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 "gtkprivate.h"
51 #include "gtkbuildable.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;
118 GdkWindow *grip_window;
122 gchar *wmclass_class;
130 guint keys_changed_handler;
132 guint16 configure_request_count;
134 /* The following flags are initially TRUE (before a window is mapped).
135 * They cause us to compute a configure request that involves
136 * default-only parameters. Once mapped, we set them to FALSE.
137 * Then we set them to TRUE again on unmap (for position)
138 * and on unrealize (for size).
140 guint need_default_position : 1;
141 guint need_default_size : 1;
143 guint above_initially : 1;
144 guint accept_focus : 1;
145 guint below_initially : 1;
146 guint builder_visible : 1;
147 guint configure_notify_received : 1;
150 guint destroy_with_parent : 1;
151 guint focus_on_map : 1;
152 guint fullscreen_initially : 1;
153 guint gravity : 5; /* GdkGravity */
155 guint has_user_ref_count : 1;
157 guint has_toplevel_focus : 1;
158 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
160 guint maximize_initially : 1;
161 guint mnemonics_visible : 1;
162 guint mnemonics_visible_set : 1;
164 guint opacity_set : 1;
166 guint reset_type_hint : 1;
168 guint skips_pager : 1;
169 guint skips_taskbar : 1;
170 guint stick_initially : 1;
171 guint transient_parent_group : 1;
172 guint type : 4; /* GtkWindowType */
173 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
174 * one of the original eight. If not,
176 * GDK_WINDOW_TYPE_HINT_NORMAL
179 guint has_resize_grip : 1;
180 guint resize_grip_visible : 1; /* don't use, just for "resize-
181 * grip-visible" notification
209 PROP_DESTROY_WITH_PARENT,
214 PROP_SKIP_TASKBAR_HINT,
215 PROP_SKIP_PAGER_HINT,
224 PROP_HAS_RESIZE_GRIP,
225 PROP_RESIZE_GRIP_VISIBLE,
227 /* Readonly properties */
229 PROP_HAS_TOPLEVEL_FOCUS,
231 /* Writeonly properties */
234 PROP_MNEMONICS_VISIBLE,
244 guint using_default_icon : 1;
245 guint using_parent_icon : 1;
246 guint using_themed_icon : 1;
250 GdkGeometry geometry; /* Last set of geometry hints we set */
251 GdkWindowHints flags;
252 GdkRectangle configure_request;
253 } GtkWindowLastGeometryInfo;
255 struct _GtkWindowGeometryInfo
257 /* Properties that the app has set on the window
259 GdkGeometry geometry; /* Geometry hints */
261 GtkWidget *widget; /* subwidget to which hints apply */
262 /* from last gtk_window_resize () - if > 0, indicates that
263 * we should resize to this size.
268 /* From last gtk_window_move () prior to mapping -
269 * only used if initial_pos_set
274 /* Default size - used only the FIRST time we map a window,
279 /* whether to use initial_x, initial_y */
280 guint initial_pos_set : 1;
281 /* CENTER_ALWAYS or other position constraint changed since
282 * we sent the last configure request.
284 guint position_constraints_changed : 1;
286 /* if true, default_width, height should be multiplied by the
287 * increments and affect the geometry widget only
289 guint default_is_geometry : 1;
291 /* if true, resize_width, height should be multiplied by the
292 * increments and affect the geometry widget only
294 guint resize_is_geometry : 1;
296 GtkWindowLastGeometryInfo last;
299 #define GTK_WINDOW_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW_GROUP, GtkWindowGroupPrivate))
301 struct _GtkDeviceGrabInfo
305 guint block_others : 1;
308 struct _GtkWindowGroupPrivate
310 GSList *device_grabs;
313 static void gtk_window_dispose (GObject *object);
314 static void gtk_window_finalize (GObject *object);
315 static void gtk_window_destroy (GtkWidget *widget);
316 static void gtk_window_show (GtkWidget *widget);
317 static void gtk_window_hide (GtkWidget *widget);
318 static void gtk_window_map (GtkWidget *widget);
319 static void gtk_window_unmap (GtkWidget *widget);
320 static void gtk_window_realize (GtkWidget *widget);
321 static void gtk_window_unrealize (GtkWidget *widget);
322 static void gtk_window_size_allocate (GtkWidget *widget,
323 GtkAllocation *allocation);
324 static gint gtk_window_event (GtkWidget *widget,
326 static gboolean gtk_window_map_event (GtkWidget *widget,
328 static gboolean gtk_window_frame_event (GtkWindow *window,
330 static gint gtk_window_configure_event (GtkWidget *widget,
331 GdkEventConfigure *event);
332 static gint gtk_window_key_press_event (GtkWidget *widget,
334 static gint gtk_window_key_release_event (GtkWidget *widget,
336 static gint gtk_window_button_press_event (GtkWidget *widget,
337 GdkEventButton *event);
338 static gint gtk_window_enter_notify_event (GtkWidget *widget,
339 GdkEventCrossing *event);
340 static gint gtk_window_leave_notify_event (GtkWidget *widget,
341 GdkEventCrossing *event);
342 static gint gtk_window_focus_in_event (GtkWidget *widget,
343 GdkEventFocus *event);
344 static gint gtk_window_focus_out_event (GtkWidget *widget,
345 GdkEventFocus *event);
346 static gint gtk_window_client_event (GtkWidget *widget,
347 GdkEventClient *event);
348 static gboolean gtk_window_state_event (GtkWidget *widget,
349 GdkEventWindowState *event);
350 static void gtk_window_check_resize (GtkContainer *container);
351 static gint gtk_window_focus (GtkWidget *widget,
352 GtkDirectionType direction);
353 static void gtk_window_real_set_focus (GtkWindow *window,
355 static void gtk_window_direction_changed (GtkWidget *widget,
356 GtkTextDirection prev_dir);
357 static void gtk_window_state_changed (GtkWidget *widget,
358 GtkStateType previous_state);
360 static void gtk_window_real_activate_default (GtkWindow *window);
361 static void gtk_window_real_activate_focus (GtkWindow *window);
362 static void gtk_window_move_focus (GtkWindow *window,
363 GtkDirectionType dir);
364 static void gtk_window_keys_changed (GtkWindow *window);
365 static gint gtk_window_draw (GtkWidget *widget,
367 static void gtk_window_unset_transient_for (GtkWindow *window);
368 static void gtk_window_transient_parent_realized (GtkWidget *parent,
370 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
373 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
375 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
378 static void gtk_window_move_resize (GtkWindow *window);
379 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
381 GdkGeometry *geometry_b,
383 static void gtk_window_constrain_size (GtkWindow *window,
384 GdkGeometry *geometry,
390 static void gtk_window_constrain_position (GtkWindow *window,
395 static void gtk_window_compute_hints (GtkWindow *window,
396 GdkGeometry *new_geometry,
398 static void gtk_window_compute_configure_request (GtkWindow *window,
399 GdkRectangle *request,
400 GdkGeometry *geometry,
403 static void gtk_window_set_default_size_internal (GtkWindow *window,
404 gboolean change_width,
406 gboolean change_height,
408 gboolean is_geometry);
410 static void update_themed_icon (GtkIconTheme *theme,
412 static GList *icon_list_from_theme (GtkWidget *widget,
414 static void gtk_window_realize_icon (GtkWindow *window);
415 static void gtk_window_unrealize_icon (GtkWindow *window);
416 static void resize_grip_create_window (GtkWindow *window);
417 static void resize_grip_destroy_window (GtkWindow *window);
418 static void update_grip_visibility (GtkWindow *window);
420 static void gtk_window_notify_keys_changed (GtkWindow *window);
421 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
422 static void gtk_window_free_key_hash (GtkWindow *window);
423 static void gtk_window_on_composited_changed (GdkScreen *screen,
426 static GSList *toplevel_list = NULL;
427 static guint window_signals[LAST_SIGNAL] = { 0 };
428 static GList *default_icon_list = NULL;
429 static gchar *default_icon_name = NULL;
430 static guint default_icon_serial = 0;
431 static gboolean disable_startup_notification = FALSE;
432 static gboolean sent_startup_notification = FALSE;
434 static GQuark quark_gtk_embedded = 0;
435 static GQuark quark_gtk_window_key_hash = 0;
436 static GQuark quark_gtk_window_icon_info = 0;
437 static GQuark quark_gtk_buildable_accels = 0;
439 static GtkBuildableIface *parent_buildable_iface;
441 static void gtk_window_set_property (GObject *object,
445 static void gtk_window_get_property (GObject *object,
451 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
452 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
455 const GValue *value);
456 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
457 GtkBuilder *builder);
458 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
461 const gchar *tagname,
462 GMarkupParser *parser,
464 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
467 const gchar *tagname,
471 static void gtk_window_get_preferred_width (GtkWidget *widget,
474 static void gtk_window_get_preferred_height (GtkWidget *widget,
478 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
479 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
480 gtk_window_buildable_interface_init))
483 add_tab_bindings (GtkBindingSet *binding_set,
484 GdkModifierType modifiers,
485 GtkDirectionType direction)
487 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
489 GTK_TYPE_DIRECTION_TYPE, direction);
490 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
492 GTK_TYPE_DIRECTION_TYPE, direction);
496 add_arrow_bindings (GtkBindingSet *binding_set,
498 GtkDirectionType direction)
500 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
502 gtk_binding_entry_add_signal (binding_set, keysym, 0,
504 GTK_TYPE_DIRECTION_TYPE, direction);
505 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
507 GTK_TYPE_DIRECTION_TYPE, direction);
508 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
510 GTK_TYPE_DIRECTION_TYPE, direction);
511 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
513 GTK_TYPE_DIRECTION_TYPE, direction);
517 extract_time_from_startup_id (const gchar* startup_id)
519 gchar *timestr = g_strrstr (startup_id, "_TIME");
520 guint32 retval = GDK_CURRENT_TIME;
527 /* Skip past the "_TIME" part */
531 timestamp = strtoul (timestr, &end, 0);
532 if (end != timestr && errno == 0)
540 startup_id_is_fake (const gchar* startup_id)
542 return strncmp (startup_id, "_TIME", 5) == 0;
546 gtk_window_class_init (GtkWindowClass *klass)
548 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
549 GtkWidgetClass *widget_class;
550 GtkContainerClass *container_class;
551 GtkBindingSet *binding_set;
553 widget_class = (GtkWidgetClass*) klass;
554 container_class = (GtkContainerClass*) klass;
556 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
557 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
558 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
559 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
561 gobject_class->dispose = gtk_window_dispose;
562 gobject_class->finalize = gtk_window_finalize;
564 gobject_class->set_property = gtk_window_set_property;
565 gobject_class->get_property = gtk_window_get_property;
567 widget_class->destroy = gtk_window_destroy;
568 widget_class->show = gtk_window_show;
569 widget_class->hide = gtk_window_hide;
570 widget_class->map = gtk_window_map;
571 widget_class->map_event = gtk_window_map_event;
572 widget_class->unmap = gtk_window_unmap;
573 widget_class->realize = gtk_window_realize;
574 widget_class->unrealize = gtk_window_unrealize;
575 widget_class->size_allocate = gtk_window_size_allocate;
576 widget_class->configure_event = gtk_window_configure_event;
577 widget_class->key_press_event = gtk_window_key_press_event;
578 widget_class->key_release_event = gtk_window_key_release_event;
579 widget_class->enter_notify_event = gtk_window_enter_notify_event;
580 widget_class->leave_notify_event = gtk_window_leave_notify_event;
581 widget_class->focus_in_event = gtk_window_focus_in_event;
582 widget_class->button_press_event = gtk_window_button_press_event;
583 widget_class->focus_out_event = gtk_window_focus_out_event;
584 widget_class->client_event = gtk_window_client_event;
585 widget_class->focus = gtk_window_focus;
586 widget_class->draw = gtk_window_draw;
587 widget_class->get_preferred_width = gtk_window_get_preferred_width;
588 widget_class->get_preferred_height = gtk_window_get_preferred_height;
589 widget_class->window_state_event = gtk_window_state_event;
590 widget_class->direction_changed = gtk_window_direction_changed;
591 widget_class->state_changed = gtk_window_state_changed;
593 container_class->check_resize = gtk_window_check_resize;
595 klass->set_focus = gtk_window_real_set_focus;
596 klass->frame_event = gtk_window_frame_event;
598 klass->activate_default = gtk_window_real_activate_default;
599 klass->activate_focus = gtk_window_real_activate_focus;
600 klass->move_focus = gtk_window_move_focus;
601 klass->keys_changed = gtk_window_keys_changed;
603 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
606 g_object_class_install_property (gobject_class,
608 g_param_spec_enum ("type",
610 P_("The type of the window"),
611 GTK_TYPE_WINDOW_TYPE,
613 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
615 g_object_class_install_property (gobject_class,
617 g_param_spec_string ("title",
619 P_("The title of the window"),
621 GTK_PARAM_READWRITE));
623 g_object_class_install_property (gobject_class,
625 g_param_spec_string ("role",
627 P_("Unique identifier for the window to be used when restoring a session"),
629 GTK_PARAM_READWRITE));
632 * GtkWindow:startup-id:
634 * The :startup-id is a write-only property for setting window's
635 * startup notification identifier. See gtk_window_set_startup_id()
640 g_object_class_install_property (gobject_class,
642 g_param_spec_string ("startup-id",
644 P_("Unique startup identifier for the window used by startup-notification"),
646 GTK_PARAM_WRITABLE));
648 g_object_class_install_property (gobject_class,
650 g_param_spec_boolean ("resizable",
652 P_("If TRUE, users can resize the window"),
654 GTK_PARAM_READWRITE));
656 g_object_class_install_property (gobject_class,
658 g_param_spec_boolean ("modal",
660 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
662 GTK_PARAM_READWRITE));
664 g_object_class_install_property (gobject_class,
666 g_param_spec_enum ("window-position",
667 P_("Window Position"),
668 P_("The initial position of the window"),
669 GTK_TYPE_WINDOW_POSITION,
671 GTK_PARAM_READWRITE));
673 g_object_class_install_property (gobject_class,
675 g_param_spec_int ("default-width",
677 P_("The default width of the window, used when initially showing the window"),
681 GTK_PARAM_READWRITE));
683 g_object_class_install_property (gobject_class,
685 g_param_spec_int ("default-height",
686 P_("Default Height"),
687 P_("The default height of the window, used when initially showing the window"),
691 GTK_PARAM_READWRITE));
693 g_object_class_install_property (gobject_class,
694 PROP_DESTROY_WITH_PARENT,
695 g_param_spec_boolean ("destroy-with-parent",
696 P_("Destroy with Parent"),
697 P_("If this window should be destroyed when the parent is destroyed"),
699 GTK_PARAM_READWRITE));
701 g_object_class_install_property (gobject_class,
703 g_param_spec_object ("icon",
705 P_("Icon for this window"),
707 GTK_PARAM_READWRITE));
708 g_object_class_install_property (gobject_class,
709 PROP_MNEMONICS_VISIBLE,
710 g_param_spec_boolean ("mnemonics-visible",
711 P_("Mnemonics Visible"),
712 P_("Whether mnemonics are currently visible in this window"),
714 GTK_PARAM_READWRITE));
717 * GtkWindow:icon-name:
719 * The :icon-name property specifies the name of the themed icon to
720 * use as the window icon. See #GtkIconTheme for more details.
724 g_object_class_install_property (gobject_class,
726 g_param_spec_string ("icon-name",
728 P_("Name of the themed icon for this window"),
730 GTK_PARAM_READWRITE));
732 g_object_class_install_property (gobject_class,
734 g_param_spec_object ("screen",
736 P_("The screen where this window will be displayed"),
738 GTK_PARAM_READWRITE));
740 g_object_class_install_property (gobject_class,
742 g_param_spec_boolean ("is-active",
744 P_("Whether the toplevel is the current active window"),
746 GTK_PARAM_READABLE));
748 g_object_class_install_property (gobject_class,
749 PROP_HAS_TOPLEVEL_FOCUS,
750 g_param_spec_boolean ("has-toplevel-focus",
751 P_("Focus in Toplevel"),
752 P_("Whether the input focus is within this GtkWindow"),
754 GTK_PARAM_READABLE));
756 g_object_class_install_property (gobject_class,
758 g_param_spec_enum ("type-hint",
760 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
761 GDK_TYPE_WINDOW_TYPE_HINT,
762 GDK_WINDOW_TYPE_HINT_NORMAL,
763 GTK_PARAM_READWRITE));
765 g_object_class_install_property (gobject_class,
766 PROP_SKIP_TASKBAR_HINT,
767 g_param_spec_boolean ("skip-taskbar-hint",
769 P_("TRUE if the window should not be in the task bar."),
771 GTK_PARAM_READWRITE));
773 g_object_class_install_property (gobject_class,
774 PROP_SKIP_PAGER_HINT,
775 g_param_spec_boolean ("skip-pager-hint",
777 P_("TRUE if the window should not be in the pager."),
779 GTK_PARAM_READWRITE));
781 g_object_class_install_property (gobject_class,
783 g_param_spec_boolean ("urgency-hint",
785 P_("TRUE if the window should be brought to the user's attention."),
787 GTK_PARAM_READWRITE));
790 * GtkWindow:accept-focus:
792 * Whether the window should receive the input focus.
796 g_object_class_install_property (gobject_class,
798 g_param_spec_boolean ("accept-focus",
800 P_("TRUE if the window should receive the input focus."),
802 GTK_PARAM_READWRITE));
805 * GtkWindow:focus-on-map:
807 * Whether the window should receive the input focus when mapped.
811 g_object_class_install_property (gobject_class,
813 g_param_spec_boolean ("focus-on-map",
815 P_("TRUE if the window should receive the input focus when mapped."),
817 GTK_PARAM_READWRITE));
820 * GtkWindow:decorated:
822 * Whether the window should be decorated by the window manager.
826 g_object_class_install_property (gobject_class,
828 g_param_spec_boolean ("decorated",
830 P_("Whether the window should be decorated by the window manager"),
832 GTK_PARAM_READWRITE));
835 * GtkWindow:deletable:
837 * Whether the window frame should have a close button.
841 g_object_class_install_property (gobject_class,
843 g_param_spec_boolean ("deletable",
845 P_("Whether the window frame should have a close button"),
847 GTK_PARAM_READWRITE));
850 * GtkWindow:has-resize-grip
852 * Whether the window has a corner resize grip.
854 * Note that the resize grip is only shown if the window is
855 * actually resizable and not maximized. Use
856 * #GtkWindow:resize-grip-visible to find out if the resize
857 * grip is currently shown.
861 g_object_class_install_property (gobject_class,
862 PROP_HAS_RESIZE_GRIP,
863 g_param_spec_boolean ("has-resize-grip",
865 P_("Specifies whether the window should have a resize grip"),
867 GTK_PARAM_READWRITE));
870 * GtkWindow: resize-grip-visible:
872 * Whether a corner resize grip is currently shown.
876 g_object_class_install_property (gobject_class,
877 PROP_RESIZE_GRIP_VISIBLE,
878 g_param_spec_boolean ("resize-grip-visible",
879 P_("Resize grip is visible"),
880 P_("Specifies whether the window's resize grip is visible."),
882 GTK_PARAM_READABLE));
888 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
889 * more details about window gravity.
893 g_object_class_install_property (gobject_class,
895 g_param_spec_enum ("gravity",
897 P_("The window gravity of the window"),
899 GDK_GRAVITY_NORTH_WEST,
900 GTK_PARAM_READWRITE));
904 * GtkWindow:transient-for:
906 * The transient parent of the window. See gtk_window_set_transient_for() for
907 * more details about transient windows.
911 g_object_class_install_property (gobject_class,
913 g_param_spec_object ("transient-for",
914 P_("Transient for Window"),
915 P_("The transient parent of the dialog"),
917 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
922 * The requested opacity of the window. See gtk_window_set_opacity() for
923 * more details about window opacity.
927 g_object_class_install_property (gobject_class,
929 g_param_spec_double ("opacity",
930 P_("Opacity for Window"),
931 P_("The opacity of the window, from 0 to 1"),
935 GTK_PARAM_READWRITE));
940 gtk_widget_class_install_style_property (widget_class,
941 g_param_spec_int ("resize-grip-width",
942 P_("Width of resize grip"),
943 P_("Width of resize grip"),
944 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
946 gtk_widget_class_install_style_property (widget_class,
947 g_param_spec_int ("resize-grip-height",
948 P_("Height of resize grip"),
949 P_("Height of resize grip"),
950 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
955 window_signals[SET_FOCUS] =
956 g_signal_new (I_("set-focus"),
957 G_TYPE_FROM_CLASS (gobject_class),
959 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
961 _gtk_marshal_VOID__OBJECT,
965 window_signals[FRAME_EVENT] =
966 g_signal_new (I_("frame-event"),
967 G_TYPE_FROM_CLASS (gobject_class),
969 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
970 _gtk_boolean_handled_accumulator, NULL,
971 _gtk_marshal_BOOLEAN__BOXED,
976 * GtkWindow::activate-focus:
977 * @window: the window which received the signal
979 * The ::activate-focus signal is a
980 * <link linkend="keybinding-signals">keybinding signal</link>
981 * which gets emitted when the user activates the currently
982 * focused widget of @window.
984 window_signals[ACTIVATE_FOCUS] =
985 g_signal_new (I_("activate-focus"),
986 G_TYPE_FROM_CLASS (gobject_class),
987 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
988 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
990 _gtk_marshal_VOID__VOID,
995 * GtkWindow::activate-default:
996 * @window: the window which received the signal
998 * The ::activate-default signal is a
999 * <link linkend="keybinding-signals">keybinding signal</link>
1000 * which gets emitted when the user activates the default widget
1003 window_signals[ACTIVATE_DEFAULT] =
1004 g_signal_new (I_("activate-default"),
1005 G_TYPE_FROM_CLASS (gobject_class),
1006 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1007 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1009 _gtk_marshal_VOID__VOID,
1014 * GtkWindow::keys-changed:
1015 * @window: the window which received the signal
1017 * The ::keys-changed signal gets emitted when the set of accelerators
1018 * or mnemonics that are associated with @window changes.
1020 window_signals[KEYS_CHANGED] =
1021 g_signal_new (I_("keys-changed"),
1022 G_TYPE_FROM_CLASS (gobject_class),
1024 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1026 _gtk_marshal_VOID__VOID,
1034 binding_set = gtk_binding_set_by_class (klass);
1036 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1037 "activate-focus", 0);
1038 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1039 "activate-focus", 0);
1041 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1042 "activate-default", 0);
1043 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1044 "activate-default", 0);
1045 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1046 "activate-default", 0);
1048 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1049 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1050 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1051 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1053 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1054 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1055 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1056 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1060 gtk_window_init (GtkWindow *window)
1062 GtkWindowPrivate *priv;
1064 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1067 priv = window->priv;
1069 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1070 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1072 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1074 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1077 priv->wmclass_name = g_strdup (g_get_prgname ());
1078 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1079 priv->wm_role = NULL;
1080 priv->geometry_info = NULL;
1081 priv->type = GTK_WINDOW_TOPLEVEL;
1082 priv->focus_widget = NULL;
1083 priv->default_widget = NULL;
1084 priv->configure_request_count = 0;
1085 priv->resizable = TRUE;
1086 priv->configure_notify_received = FALSE;
1087 priv->position = GTK_WIN_POS_NONE;
1088 priv->need_default_size = TRUE;
1089 priv->need_default_position = TRUE;
1090 priv->modal = FALSE;
1092 priv->has_frame = FALSE;
1093 priv->frame_left = 0;
1094 priv->frame_right = 0;
1095 priv->frame_top = 0;
1096 priv->frame_bottom = 0;
1097 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1098 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1099 priv->decorated = TRUE;
1100 priv->mnemonic_modifier = GDK_MOD1_MASK;
1101 priv->screen = gdk_screen_get_default ();
1103 priv->accept_focus = TRUE;
1104 priv->focus_on_map = TRUE;
1105 priv->deletable = TRUE;
1106 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1107 priv->opacity = 1.0;
1108 priv->startup_id = NULL;
1109 priv->has_resize_grip = TRUE;
1110 priv->mnemonics_visible = TRUE;
1112 g_object_ref_sink (window);
1113 priv->has_user_ref_count = TRUE;
1114 toplevel_list = g_slist_prepend (toplevel_list, window);
1116 gtk_decorated_window_init (window);
1118 g_signal_connect (priv->screen, "composited-changed",
1119 G_CALLBACK (gtk_window_on_composited_changed), window);
1123 gtk_window_set_property (GObject *object,
1125 const GValue *value,
1128 GtkWindow *window = GTK_WINDOW (object);
1129 GtkWindowPrivate *priv = window->priv;
1134 priv->type = g_value_get_enum (value);
1137 gtk_window_set_title (window, g_value_get_string (value));
1140 gtk_window_set_role (window, g_value_get_string (value));
1142 case PROP_STARTUP_ID:
1143 gtk_window_set_startup_id (window, g_value_get_string (value));
1145 case PROP_RESIZABLE:
1146 gtk_window_set_resizable (window, g_value_get_boolean (value));
1149 gtk_window_set_modal (window, g_value_get_boolean (value));
1152 gtk_window_set_position (window, g_value_get_enum (value));
1154 case PROP_DEFAULT_WIDTH:
1155 gtk_window_set_default_size_internal (window,
1156 TRUE, g_value_get_int (value),
1159 case PROP_DEFAULT_HEIGHT:
1160 gtk_window_set_default_size_internal (window,
1162 TRUE, g_value_get_int (value), FALSE);
1164 case PROP_DESTROY_WITH_PARENT:
1165 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1168 gtk_window_set_icon (window,
1169 g_value_get_object (value));
1171 case PROP_ICON_NAME:
1172 gtk_window_set_icon_name (window, g_value_get_string (value));
1175 gtk_window_set_screen (window, g_value_get_object (value));
1177 case PROP_TYPE_HINT:
1178 gtk_window_set_type_hint (window,
1179 g_value_get_enum (value));
1181 case PROP_SKIP_TASKBAR_HINT:
1182 gtk_window_set_skip_taskbar_hint (window,
1183 g_value_get_boolean (value));
1185 case PROP_SKIP_PAGER_HINT:
1186 gtk_window_set_skip_pager_hint (window,
1187 g_value_get_boolean (value));
1189 case PROP_URGENCY_HINT:
1190 gtk_window_set_urgency_hint (window,
1191 g_value_get_boolean (value));
1193 case PROP_ACCEPT_FOCUS:
1194 gtk_window_set_accept_focus (window,
1195 g_value_get_boolean (value));
1197 case PROP_FOCUS_ON_MAP:
1198 gtk_window_set_focus_on_map (window,
1199 g_value_get_boolean (value));
1201 case PROP_DECORATED:
1202 gtk_window_set_decorated (window, g_value_get_boolean (value));
1204 case PROP_DELETABLE:
1205 gtk_window_set_deletable (window, g_value_get_boolean (value));
1208 gtk_window_set_gravity (window, g_value_get_enum (value));
1210 case PROP_TRANSIENT_FOR:
1211 gtk_window_set_transient_for (window, g_value_get_object (value));
1214 gtk_window_set_opacity (window, g_value_get_double (value));
1216 case PROP_HAS_RESIZE_GRIP:
1217 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1219 case PROP_MNEMONICS_VISIBLE:
1220 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1223 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1229 gtk_window_get_property (GObject *object,
1234 GtkWindow *window = GTK_WINDOW (object);
1235 GtkWindowPrivate *priv = window->priv;
1239 GtkWindowGeometryInfo *info;
1241 g_value_set_enum (value, priv->type);
1244 g_value_set_string (value, priv->wm_role);
1247 g_value_set_string (value, priv->title);
1249 case PROP_RESIZABLE:
1250 g_value_set_boolean (value, priv->resizable);
1253 g_value_set_boolean (value, priv->modal);
1256 g_value_set_enum (value, priv->position);
1258 case PROP_DEFAULT_WIDTH:
1259 info = gtk_window_get_geometry_info (window, FALSE);
1261 g_value_set_int (value, -1);
1263 g_value_set_int (value, info->default_width);
1265 case PROP_DEFAULT_HEIGHT:
1266 info = gtk_window_get_geometry_info (window, FALSE);
1268 g_value_set_int (value, -1);
1270 g_value_set_int (value, info->default_height);
1272 case PROP_DESTROY_WITH_PARENT:
1273 g_value_set_boolean (value, priv->destroy_with_parent);
1276 g_value_set_object (value, gtk_window_get_icon (window));
1278 case PROP_ICON_NAME:
1279 g_value_set_string (value, gtk_window_get_icon_name (window));
1282 g_value_set_object (value, priv->screen);
1284 case PROP_IS_ACTIVE:
1285 g_value_set_boolean (value, priv->is_active);
1287 case PROP_HAS_TOPLEVEL_FOCUS:
1288 g_value_set_boolean (value, priv->has_toplevel_focus);
1290 case PROP_TYPE_HINT:
1291 g_value_set_enum (value, priv->type_hint);
1293 case PROP_SKIP_TASKBAR_HINT:
1294 g_value_set_boolean (value,
1295 gtk_window_get_skip_taskbar_hint (window));
1297 case PROP_SKIP_PAGER_HINT:
1298 g_value_set_boolean (value,
1299 gtk_window_get_skip_pager_hint (window));
1301 case PROP_URGENCY_HINT:
1302 g_value_set_boolean (value,
1303 gtk_window_get_urgency_hint (window));
1305 case PROP_ACCEPT_FOCUS:
1306 g_value_set_boolean (value,
1307 gtk_window_get_accept_focus (window));
1309 case PROP_FOCUS_ON_MAP:
1310 g_value_set_boolean (value,
1311 gtk_window_get_focus_on_map (window));
1313 case PROP_DECORATED:
1314 g_value_set_boolean (value, gtk_window_get_decorated (window));
1316 case PROP_DELETABLE:
1317 g_value_set_boolean (value, gtk_window_get_deletable (window));
1320 g_value_set_enum (value, gtk_window_get_gravity (window));
1322 case PROP_TRANSIENT_FOR:
1323 g_value_set_object (value, gtk_window_get_transient_for (window));
1326 g_value_set_double (value, gtk_window_get_opacity (window));
1328 case PROP_HAS_RESIZE_GRIP:
1329 g_value_set_boolean (value, priv->has_resize_grip);
1331 case PROP_RESIZE_GRIP_VISIBLE:
1332 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1334 case PROP_MNEMONICS_VISIBLE:
1335 g_value_set_boolean (value, priv->mnemonics_visible);
1338 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1344 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1346 parent_buildable_iface = g_type_interface_peek_parent (iface);
1347 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1348 iface->parser_finished = gtk_window_buildable_parser_finished;
1349 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1350 iface->custom_finished = gtk_window_buildable_custom_finished;
1354 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1355 GtkBuilder *builder,
1357 const GValue *value)
1359 GtkWindow *window = GTK_WINDOW (buildable);
1360 GtkWindowPrivate *priv = window->priv;
1362 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1363 priv->builder_visible = TRUE;
1365 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1369 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1370 GtkBuilder *builder)
1372 GtkWindow *window = GTK_WINDOW (buildable);
1373 GtkWindowPrivate *priv = window->priv;
1377 if (priv->builder_visible)
1378 gtk_widget_show (GTK_WIDGET (buildable));
1380 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1381 for (l = accels; l; l = l->next)
1383 object = gtk_builder_get_object (builder, l->data);
1386 g_warning ("Unknown accel group %s specified in window %s",
1387 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1390 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1391 GTK_ACCEL_GROUP (object));
1395 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1397 parent_buildable_iface->parser_finished (buildable, builder);
1403 } GSListSubParserData;
1406 window_start_element (GMarkupParseContext *context,
1407 const gchar *element_name,
1408 const gchar **names,
1409 const gchar **values,
1414 GSListSubParserData *data = (GSListSubParserData*)user_data;
1416 if (strcmp (element_name, "group") == 0)
1418 for (i = 0; names[i]; i++)
1420 if (strcmp (names[i], "name") == 0)
1421 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1424 else if (strcmp (element_name, "accel-groups") == 0)
1427 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1432 static const GMarkupParser window_parser =
1434 window_start_element
1438 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1439 GtkBuilder *builder,
1441 const gchar *tagname,
1442 GMarkupParser *parser,
1445 GSListSubParserData *parser_data;
1447 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1448 tagname, parser, data))
1451 if (strcmp (tagname, "accel-groups") == 0)
1453 parser_data = g_slice_new0 (GSListSubParserData);
1454 parser_data->items = NULL;
1455 parser_data->object = G_OBJECT (buildable);
1457 *parser = window_parser;
1458 *data = parser_data;
1466 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1467 GtkBuilder *builder,
1469 const gchar *tagname,
1472 GSListSubParserData *data;
1474 parent_buildable_iface->custom_finished (buildable, builder, child,
1475 tagname, user_data);
1477 if (strcmp (tagname, "accel-groups") != 0)
1480 data = (GSListSubParserData*)user_data;
1482 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1483 data->items, (GDestroyNotify) g_slist_free);
1485 g_slice_free (GSListSubParserData, data);
1490 * @type: type of window
1492 * Creates a new #GtkWindow, which is a toplevel window that can
1493 * contain other widgets. Nearly always, the type of the window should
1494 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1495 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1496 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1497 * dialogs, though in some other toolkits dialogs are called "popups".
1498 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1499 * On X11, popup windows are not controlled by the <link
1500 * linkend="gtk-X11-arch">window manager</link>.
1502 * If you simply want an undecorated window (no window borders), use
1503 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1505 * Return value: a new #GtkWindow.
1508 gtk_window_new (GtkWindowType type)
1510 GtkWindowPrivate *priv;
1513 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1515 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1516 priv = window->priv;
1520 return GTK_WIDGET (window);
1524 * gtk_window_set_title:
1525 * @window: a #GtkWindow
1526 * @title: title of the window
1528 * Sets the title of the #GtkWindow. The title of a window will be
1529 * displayed in its title bar; on the X Window System, the title bar
1530 * is rendered by the <link linkend="gtk-X11-arch">window
1531 * manager</link>, so exactly how the title appears to users may vary
1532 * according to a user's exact configuration. The title should help a
1533 * user distinguish this window from other windows they may have
1534 * open. A good title might include the application name and current
1535 * document filename, for example.
1539 gtk_window_set_title (GtkWindow *window,
1542 GtkWindowPrivate *priv;
1546 g_return_if_fail (GTK_IS_WINDOW (window));
1548 priv = window->priv;
1549 widget = GTK_WIDGET (window);
1551 new_title = g_strdup (title);
1552 g_free (priv->title);
1553 priv->title = new_title;
1555 if (gtk_widget_get_realized (widget))
1557 gdk_window_set_title (gtk_widget_get_window (widget),
1560 gtk_decorated_window_set_title (window, title);
1563 g_object_notify (G_OBJECT (window), "title");
1567 * gtk_window_get_title:
1568 * @window: a #GtkWindow
1570 * Retrieves the title of the window. See gtk_window_set_title().
1572 * Return value: the title of the window, or %NULL if none has
1573 * been set explicitely. The returned string is owned by the widget
1574 * and must not be modified or freed.
1576 G_CONST_RETURN gchar *
1577 gtk_window_get_title (GtkWindow *window)
1579 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1581 return window->priv->title;
1585 * gtk_window_set_wmclass:
1586 * @window: a #GtkWindow
1587 * @wmclass_name: window name hint
1588 * @wmclass_class: window class hint
1590 * Don't use this function. It sets the X Window System "class" and
1591 * "name" hints for a window. According to the ICCCM, you should
1592 * always set these to the same value for all windows in an
1593 * application, and GTK+ sets them to that value by default, so calling
1594 * this function is sort of pointless. However, you may want to call
1595 * gtk_window_set_role() on each window in your application, for the
1596 * benefit of the session manager. Setting the role allows the window
1597 * manager to restore window positions when loading a saved session.
1601 gtk_window_set_wmclass (GtkWindow *window,
1602 const gchar *wmclass_name,
1603 const gchar *wmclass_class)
1605 GtkWindowPrivate *priv;
1607 g_return_if_fail (GTK_IS_WINDOW (window));
1609 priv = window->priv;
1611 g_free (priv->wmclass_name);
1612 priv->wmclass_name = g_strdup (wmclass_name);
1614 g_free (priv->wmclass_class);
1615 priv->wmclass_class = g_strdup (wmclass_class);
1617 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1618 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1622 * gtk_window_set_role:
1623 * @window: a #GtkWindow
1624 * @role: unique identifier for the window to be used when restoring a session
1626 * This function is only useful on X11, not with other GTK+ targets.
1628 * In combination with the window title, the window role allows a
1629 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1630 * same" window when an application is restarted. So for example you
1631 * might set the "toolbox" role on your app's toolbox window, so that
1632 * when the user restarts their session, the window manager can put
1633 * the toolbox back in the same place.
1635 * If a window already has a unique title, you don't need to set the
1636 * role, since the WM can use the title to identify the window when
1637 * restoring the session.
1641 gtk_window_set_role (GtkWindow *window,
1644 GtkWindowPrivate *priv;
1647 g_return_if_fail (GTK_IS_WINDOW (window));
1649 priv = window->priv;
1651 new_role = g_strdup (role);
1652 g_free (priv->wm_role);
1653 priv->wm_role = new_role;
1655 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1656 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1659 g_object_notify (G_OBJECT (window), "role");
1663 * gtk_window_set_startup_id:
1664 * @window: a #GtkWindow
1665 * @startup_id: a string with startup-notification identifier
1667 * Startup notification identifiers are used by desktop environment to
1668 * track application startup, to provide user feedback and other
1669 * features. This function changes the corresponding property on the
1670 * underlying GdkWindow. Normally, startup identifier is managed
1671 * automatically and you should only use this function in special cases
1672 * like transferring focus from other processes. You should use this
1673 * function before calling gtk_window_present() or any equivalent
1674 * function generating a window map event.
1676 * This function is only useful on X11, not with other GTK+ targets.
1681 gtk_window_set_startup_id (GtkWindow *window,
1682 const gchar *startup_id)
1684 GtkWindowPrivate *priv;
1687 g_return_if_fail (GTK_IS_WINDOW (window));
1689 priv = window->priv;
1690 widget = GTK_WIDGET (window);
1692 g_free (priv->startup_id);
1693 priv->startup_id = g_strdup (startup_id);
1695 if (gtk_widget_get_realized (widget))
1697 GdkWindow *gdk_window;
1698 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1700 gdk_window = gtk_widget_get_window (widget);
1702 #ifdef GDK_WINDOWING_X11
1703 if (timestamp != GDK_CURRENT_TIME)
1704 gdk_x11_window_set_user_time (gdk_window, timestamp);
1707 /* Here we differentiate real and "fake" startup notification IDs,
1708 * constructed on purpose just to pass interaction timestamp
1710 if (startup_id_is_fake (priv->startup_id))
1711 gtk_window_present_with_time (window, timestamp);
1714 gdk_window_set_startup_id (gdk_window,
1717 /* If window is mapped, terminate the startup-notification too */
1718 if (gtk_widget_get_mapped (widget) &&
1719 !disable_startup_notification)
1720 gdk_notify_startup_complete_with_id (priv->startup_id);
1724 g_object_notify (G_OBJECT (window), "startup-id");
1728 * gtk_window_get_role:
1729 * @window: a #GtkWindow
1731 * Returns the role of the window. See gtk_window_set_role() for
1732 * further explanation.
1734 * Return value: the role of the window if set, or %NULL. The
1735 * returned is owned by the widget and must not be modified
1738 G_CONST_RETURN gchar *
1739 gtk_window_get_role (GtkWindow *window)
1741 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1743 return window->priv->wm_role;
1747 * gtk_window_set_focus:
1748 * @window: a #GtkWindow
1749 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1750 * any focus widget for the toplevel window.
1752 * If @focus is not the current focus widget, and is focusable, sets
1753 * it as the focus widget for the window. If @focus is %NULL, unsets
1754 * the focus widget for this window. To set the focus to a particular
1755 * widget in the toplevel, it is usually more convenient to use
1756 * gtk_widget_grab_focus() instead of this function.
1759 gtk_window_set_focus (GtkWindow *window,
1762 GtkWindowPrivate *priv;
1765 g_return_if_fail (GTK_IS_WINDOW (window));
1767 priv = window->priv;
1771 g_return_if_fail (GTK_IS_WIDGET (focus));
1772 g_return_if_fail (gtk_widget_get_can_focus (focus));
1776 gtk_widget_grab_focus (focus);
1779 /* Clear the existing focus chain, so that when we focus into
1780 * the window again, we start at the beginnning.
1782 GtkWidget *widget = priv->focus_widget;
1785 while ((parent = gtk_widget_get_parent (widget)))
1788 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1792 _gtk_window_internal_set_focus (window, NULL);
1797 _gtk_window_internal_set_focus (GtkWindow *window,
1800 GtkWindowPrivate *priv;
1802 g_return_if_fail (GTK_IS_WINDOW (window));
1804 priv = window->priv;
1806 if ((priv->focus_widget != focus) ||
1807 (focus && !gtk_widget_has_focus (focus)))
1808 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1812 * gtk_window_set_default:
1813 * @window: a #GtkWindow
1814 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1815 * default widget for the toplevel.
1817 * The default widget is the widget that's activated when the user
1818 * presses Enter in a dialog (for example). This function sets or
1819 * unsets the default widget for a #GtkWindow about. When setting
1820 * (rather than unsetting) the default widget it's generally easier to
1821 * call gtk_widget_grab_focus() on the widget. Before making a widget
1822 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1823 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1826 gtk_window_set_default (GtkWindow *window,
1827 GtkWidget *default_widget)
1829 GtkWindowPrivate *priv;
1831 g_return_if_fail (GTK_IS_WINDOW (window));
1833 priv = window->priv;
1836 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1838 if (priv->default_widget != default_widget)
1840 GtkWidget *old_default_widget = NULL;
1843 g_object_ref (default_widget);
1845 if (priv->default_widget)
1847 old_default_widget = priv->default_widget;
1849 if (priv->focus_widget != priv->default_widget ||
1850 !gtk_widget_get_receives_default (priv->default_widget))
1851 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1853 gtk_widget_queue_draw (priv->default_widget);
1856 priv->default_widget = default_widget;
1858 if (priv->default_widget)
1860 if (priv->focus_widget == NULL ||
1861 !gtk_widget_get_receives_default (priv->focus_widget))
1862 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1864 gtk_widget_queue_draw (priv->default_widget);
1867 if (old_default_widget)
1868 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1872 g_object_notify (G_OBJECT (default_widget), "has-default");
1873 g_object_unref (default_widget);
1879 * gtk_window_get_default_widget:
1880 * @window: a #GtkWindow
1882 * Returns the default widget for @window. See gtk_window_set_default()
1885 * Returns: (transfer none): the default widget, or %NULL if there is none.
1890 gtk_window_get_default_widget (GtkWindow *window)
1892 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1894 return window->priv->default_widget;
1898 handle_keys_changed (gpointer data)
1900 GtkWindow *window = GTK_WINDOW (data);
1901 GtkWindowPrivate *priv = window->priv;
1903 if (priv->keys_changed_handler)
1905 g_source_remove (priv->keys_changed_handler);
1906 priv->keys_changed_handler = 0;
1909 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1915 gtk_window_notify_keys_changed (GtkWindow *window)
1917 GtkWindowPrivate *priv = window->priv;
1919 if (!priv->keys_changed_handler)
1920 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1924 * gtk_window_add_accel_group:
1925 * @window: window to attach accelerator group to
1926 * @accel_group: a #GtkAccelGroup
1928 * Associate @accel_group with @window, such that calling
1929 * gtk_accel_groups_activate() on @window will activate accelerators
1933 gtk_window_add_accel_group (GtkWindow *window,
1934 GtkAccelGroup *accel_group)
1936 g_return_if_fail (GTK_IS_WINDOW (window));
1937 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1939 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1940 g_signal_connect_object (accel_group, "accel-changed",
1941 G_CALLBACK (gtk_window_notify_keys_changed),
1942 window, G_CONNECT_SWAPPED);
1943 gtk_window_notify_keys_changed (window);
1947 * gtk_window_remove_accel_group:
1948 * @window: a #GtkWindow
1949 * @accel_group: a #GtkAccelGroup
1951 * Reverses the effects of gtk_window_add_accel_group().
1954 gtk_window_remove_accel_group (GtkWindow *window,
1955 GtkAccelGroup *accel_group)
1957 g_return_if_fail (GTK_IS_WINDOW (window));
1958 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1960 g_signal_handlers_disconnect_by_func (accel_group,
1961 gtk_window_notify_keys_changed,
1963 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1964 gtk_window_notify_keys_changed (window);
1967 static GtkMnemonicHash *
1968 gtk_window_get_mnemonic_hash (GtkWindow *window,
1971 GtkWindowPrivate *private = window->priv;
1973 if (!private->mnemonic_hash && create)
1974 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1976 return private->mnemonic_hash;
1980 * gtk_window_add_mnemonic:
1981 * @window: a #GtkWindow
1982 * @keyval: the mnemonic
1983 * @target: the widget that gets activated by the mnemonic
1985 * Adds a mnemonic to this window.
1988 gtk_window_add_mnemonic (GtkWindow *window,
1992 g_return_if_fail (GTK_IS_WINDOW (window));
1993 g_return_if_fail (GTK_IS_WIDGET (target));
1995 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1997 gtk_window_notify_keys_changed (window);
2001 * gtk_window_remove_mnemonic:
2002 * @window: a #GtkWindow
2003 * @keyval: the mnemonic
2004 * @target: the widget that gets activated by the mnemonic
2006 * Removes a mnemonic from this window.
2009 gtk_window_remove_mnemonic (GtkWindow *window,
2013 g_return_if_fail (GTK_IS_WINDOW (window));
2014 g_return_if_fail (GTK_IS_WIDGET (target));
2016 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2018 gtk_window_notify_keys_changed (window);
2022 * gtk_window_mnemonic_activate:
2023 * @window: a #GtkWindow
2024 * @keyval: the mnemonic
2025 * @modifier: the modifiers
2026 * @returns: %TRUE if the activation is done.
2028 * Activates the targets associated with the mnemonic.
2031 gtk_window_mnemonic_activate (GtkWindow *window,
2033 GdkModifierType modifier)
2035 GtkWindowPrivate *priv;
2037 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2039 priv = window->priv;
2041 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2043 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2045 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2052 * gtk_window_set_mnemonic_modifier:
2053 * @window: a #GtkWindow
2054 * @modifier: the modifier mask used to activate
2055 * mnemonics on this window.
2057 * Sets the mnemonic modifier for this window.
2060 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2061 GdkModifierType modifier)
2063 GtkWindowPrivate *priv;
2065 g_return_if_fail (GTK_IS_WINDOW (window));
2066 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2068 priv = window->priv;
2070 priv->mnemonic_modifier = modifier;
2071 gtk_window_notify_keys_changed (window);
2075 * gtk_window_get_mnemonic_modifier:
2076 * @window: a #GtkWindow
2078 * Returns the mnemonic modifier for this window. See
2079 * gtk_window_set_mnemonic_modifier().
2081 * Return value: the modifier mask used to activate
2082 * mnemonics on this window.
2085 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2087 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2089 return window->priv->mnemonic_modifier;
2093 * gtk_window_set_position:
2094 * @window: a #GtkWindow.
2095 * @position: a position constraint.
2097 * Sets a position constraint for this window. If the old or new
2098 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2099 * the window to be repositioned to satisfy the new constraint.
2102 gtk_window_set_position (GtkWindow *window,
2103 GtkWindowPosition position)
2105 GtkWindowPrivate *priv;
2107 g_return_if_fail (GTK_IS_WINDOW (window));
2109 priv = window->priv;
2111 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2112 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2114 GtkWindowGeometryInfo *info;
2116 info = gtk_window_get_geometry_info (window, TRUE);
2118 /* this flag causes us to re-request the CENTER_ALWAYS
2119 * constraint in gtk_window_move_resize(), see
2120 * comment in that function.
2122 info->position_constraints_changed = TRUE;
2124 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2127 priv->position = position;
2129 g_object_notify (G_OBJECT (window), "window-position");
2133 * gtk_window_activate_focus:
2134 * @window: a #GtkWindow
2136 * Activates the current focused widget within the window.
2138 * Return value: %TRUE if a widget got activated.
2141 gtk_window_activate_focus (GtkWindow *window)
2143 GtkWindowPrivate *priv;
2145 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2147 priv = window->priv;
2149 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2150 return gtk_widget_activate (priv->focus_widget);
2156 * gtk_window_get_focus:
2157 * @window: a #GtkWindow
2159 * Retrieves the current focused widget within the window.
2160 * Note that this is the widget that would have the focus
2161 * if the toplevel window focused; if the toplevel window
2162 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2163 * not be %TRUE for the widget.
2165 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2168 gtk_window_get_focus (GtkWindow *window)
2170 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2172 return window->priv->focus_widget;
2176 * gtk_window_activate_default:
2177 * @window: a #GtkWindow
2179 * Activates the default widget for the window, unless the current
2180 * focused widget has been configured to receive the default action
2181 * (see gtk_widget_set_receives_default()), in which case the
2182 * focused widget is activated.
2184 * Return value: %TRUE if a widget got activated.
2187 gtk_window_activate_default (GtkWindow *window)
2189 GtkWindowPrivate *priv;
2191 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2193 priv = window->priv;
2195 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2196 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2197 return gtk_widget_activate (priv->default_widget);
2198 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2199 return gtk_widget_activate (priv->focus_widget);
2205 * gtk_window_set_modal:
2206 * @window: a #GtkWindow
2207 * @modal: whether the window is modal
2209 * Sets a window modal or non-modal. Modal windows prevent interaction
2210 * with other windows in the same application. To keep modal dialogs
2211 * on top of main application windows, use
2212 * gtk_window_set_transient_for() to make the dialog transient for the
2213 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2214 * will then disallow lowering the dialog below the parent.
2219 gtk_window_set_modal (GtkWindow *window,
2222 GtkWindowPrivate *priv;
2225 g_return_if_fail (GTK_IS_WINDOW (window));
2227 priv = window->priv;
2229 modal = modal != FALSE;
2230 if (priv->modal == modal)
2233 priv->modal = modal;
2234 widget = GTK_WIDGET (window);
2236 /* adjust desired modality state */
2237 if (gtk_widget_get_realized (widget))
2240 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2242 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2245 if (gtk_widget_get_visible (widget))
2248 gtk_grab_add (widget);
2250 gtk_grab_remove (widget);
2253 g_object_notify (G_OBJECT (window), "modal");
2257 * gtk_window_get_modal:
2258 * @window: a #GtkWindow
2260 * Returns whether the window is modal. See gtk_window_set_modal().
2262 * Return value: %TRUE if the window is set to be modal and
2263 * establishes a grab when shown
2266 gtk_window_get_modal (GtkWindow *window)
2268 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2270 return window->priv->modal;
2274 * gtk_window_list_toplevels:
2276 * Returns a list of all existing toplevel windows. The widgets
2277 * in the list are not individually referenced. If you want
2278 * to iterate through the list and perform actions involving
2279 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2280 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2281 * then unref all the widgets afterwards.
2283 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2286 gtk_window_list_toplevels (void)
2291 for (slist = toplevel_list; slist; slist = slist->next)
2292 list = g_list_prepend (list, slist->data);
2298 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2300 GList *embedded_windows;
2302 g_return_if_fail (GTK_IS_WINDOW (window));
2304 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2305 if (embedded_windows)
2306 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2307 embedded_windows = g_list_prepend (embedded_windows,
2308 GUINT_TO_POINTER (xid));
2310 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2313 (GDestroyNotify) g_list_free : NULL);
2317 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2319 GList *embedded_windows;
2322 g_return_if_fail (GTK_IS_WINDOW (window));
2324 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2325 if (embedded_windows)
2326 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2328 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2331 embedded_windows = g_list_remove_link (embedded_windows, node);
2332 g_list_free_1 (node);
2335 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2338 (GDestroyNotify) g_list_free : NULL);
2342 gtk_window_dispose (GObject *object)
2344 GtkWindow *window = GTK_WINDOW (object);
2346 gtk_window_set_focus (window, NULL);
2347 gtk_window_set_default (window, NULL);
2349 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2353 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2355 gtk_widget_destroy (GTK_WIDGET (child));
2359 connect_parent_destroyed (GtkWindow *window)
2361 GtkWindowPrivate *priv = window->priv;
2363 if (priv->transient_parent)
2365 g_signal_connect (priv->transient_parent,
2367 G_CALLBACK (parent_destroyed_callback),
2373 disconnect_parent_destroyed (GtkWindow *window)
2375 GtkWindowPrivate *priv = window->priv;
2377 if (priv->transient_parent)
2379 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2380 parent_destroyed_callback,
2386 gtk_window_transient_parent_realized (GtkWidget *parent,
2389 if (gtk_widget_get_realized (window))
2390 gdk_window_set_transient_for (gtk_widget_get_window (window),
2391 gtk_widget_get_window (parent));
2395 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2398 if (gtk_widget_get_realized (window))
2399 gdk_property_delete (gtk_widget_get_window (window),
2400 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2404 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2408 gtk_window_set_screen (window, parent->priv->screen);
2412 gtk_window_unset_transient_for (GtkWindow *window)
2414 GtkWindowPrivate *priv = window->priv;
2416 if (priv->transient_parent)
2418 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2419 gtk_window_transient_parent_realized,
2421 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2422 gtk_window_transient_parent_unrealized,
2424 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2425 gtk_window_transient_parent_screen_changed,
2427 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2428 gtk_widget_destroyed,
2429 &priv->transient_parent);
2431 if (priv->destroy_with_parent)
2432 disconnect_parent_destroyed (window);
2434 priv->transient_parent = NULL;
2436 if (priv->transient_parent_group)
2438 priv->transient_parent_group = FALSE;
2439 gtk_window_group_remove_window (priv->group,
2446 * gtk_window_set_transient_for:
2447 * @window: a #GtkWindow
2448 * @parent: (allow-none): parent window, or %NULL
2450 * Dialog windows should be set transient for the main application
2451 * window they were spawned from. This allows <link
2452 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2453 * dialog on top of the main window, or center the dialog over the
2454 * main window. gtk_dialog_new_with_buttons() and other convenience
2455 * functions in GTK+ will sometimes call
2456 * gtk_window_set_transient_for() on your behalf.
2458 * Passing %NULL for @parent unsets the current transient window.
2460 * On Windows, this function puts the child window on top of the parent,
2461 * much as the window manager would have done on X.
2464 gtk_window_set_transient_for (GtkWindow *window,
2467 GtkWindowPrivate *priv;
2469 g_return_if_fail (GTK_IS_WINDOW (window));
2470 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2471 g_return_if_fail (window != parent);
2473 priv = window->priv;
2475 if (priv->transient_parent)
2477 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2478 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2479 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2480 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2481 GTK_WIDGET (window));
2483 gtk_window_unset_transient_for (window);
2486 priv->transient_parent = parent;
2490 g_signal_connect (parent, "destroy",
2491 G_CALLBACK (gtk_widget_destroyed),
2492 &priv->transient_parent);
2493 g_signal_connect (parent, "realize",
2494 G_CALLBACK (gtk_window_transient_parent_realized),
2496 g_signal_connect (parent, "unrealize",
2497 G_CALLBACK (gtk_window_transient_parent_unrealized),
2499 g_signal_connect (parent, "notify::screen",
2500 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2503 gtk_window_set_screen (window, parent->priv->screen);
2505 if (priv->destroy_with_parent)
2506 connect_parent_destroyed (window);
2508 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2509 gtk_widget_get_realized (GTK_WIDGET (parent)))
2510 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2511 GTK_WIDGET (window));
2513 if (parent->priv->group)
2515 gtk_window_group_add_window (parent->priv->group, window);
2516 priv->transient_parent_group = TRUE;
2522 * gtk_window_get_transient_for:
2523 * @window: a #GtkWindow
2525 * Fetches the transient parent for this window. See
2526 * gtk_window_set_transient_for().
2528 * Return value: (transfer none): the transient parent for this window, or %NULL
2529 * if no transient parent has been set.
2532 gtk_window_get_transient_for (GtkWindow *window)
2534 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2536 return window->priv->transient_parent;
2540 * gtk_window_set_opacity:
2541 * @window: a #GtkWindow
2542 * @opacity: desired opacity, between 0 and 1
2544 * Request the windowing system to make @window partially transparent,
2545 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2546 * of the opacity parameter are clamped to the [0,1] range.) On X11
2547 * this has any effect only on X screens with a compositing manager
2548 * running. See gtk_widget_is_composited(). On Windows it should work
2551 * Note that setting a window's opacity after the window has been
2552 * shown causes it to flicker once on Windows.
2557 gtk_window_set_opacity (GtkWindow *window,
2560 GtkWindowPrivate *priv;
2562 g_return_if_fail (GTK_IS_WINDOW (window));
2564 priv = window->priv;
2568 else if (opacity > 1.0)
2571 priv->opacity_set = TRUE;
2572 priv->opacity = opacity;
2574 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2575 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2580 * gtk_window_get_opacity:
2581 * @window: a #GtkWindow
2583 * Fetches the requested opacity for this window. See
2584 * gtk_window_set_opacity().
2586 * Return value: the requested opacity for this window.
2591 gtk_window_get_opacity (GtkWindow *window)
2593 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2595 return window->priv->opacity;
2599 * gtk_window_set_type_hint:
2600 * @window: a #GtkWindow
2601 * @hint: the window type
2603 * By setting the type hint for the window, you allow the window
2604 * manager to decorate and handle the window in a way which is
2605 * suitable to the function of the window in your application.
2607 * This function should be called before the window becomes visible.
2609 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2610 * will sometimes call gtk_window_set_type_hint() on your behalf.
2614 gtk_window_set_type_hint (GtkWindow *window,
2615 GdkWindowTypeHint hint)
2617 GtkWindowPrivate *priv;
2619 g_return_if_fail (GTK_IS_WINDOW (window));
2620 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2622 priv = window->priv;
2624 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2625 priv->gdk_type_hint = hint;
2627 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2629 priv->reset_type_hint = TRUE;
2630 priv->type_hint = hint;
2634 * gtk_window_get_type_hint:
2635 * @window: a #GtkWindow
2637 * Gets the type hint for this window. See gtk_window_set_type_hint().
2639 * Return value: the type hint for @window.
2642 gtk_window_get_type_hint (GtkWindow *window)
2644 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2646 return window->priv->type_hint;
2650 * gtk_window_set_skip_taskbar_hint:
2651 * @window: a #GtkWindow
2652 * @setting: %TRUE to keep this window from appearing in the task bar
2654 * Windows may set a hint asking the desktop environment not to display
2655 * the window in the task bar. This function sets this hint.
2660 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2663 GtkWindowPrivate *priv;
2665 g_return_if_fail (GTK_IS_WINDOW (window));
2667 priv = window->priv;
2669 setting = setting != FALSE;
2671 if (priv->skips_taskbar != setting)
2673 priv->skips_taskbar = setting;
2674 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2675 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2676 priv->skips_taskbar);
2677 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2682 * gtk_window_get_skip_taskbar_hint:
2683 * @window: a #GtkWindow
2685 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2687 * Return value: %TRUE if window shouldn't be in taskbar
2692 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2694 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2696 return window->priv->skips_taskbar;
2700 * gtk_window_set_skip_pager_hint:
2701 * @window: a #GtkWindow
2702 * @setting: %TRUE to keep this window from appearing in the pager
2704 * Windows may set a hint asking the desktop environment not to display
2705 * the window in the pager. This function sets this hint.
2706 * (A "pager" is any desktop navigation tool such as a workspace
2707 * switcher that displays a thumbnail representation of the windows
2713 gtk_window_set_skip_pager_hint (GtkWindow *window,
2716 GtkWindowPrivate *priv;
2718 g_return_if_fail (GTK_IS_WINDOW (window));
2720 priv = window->priv;
2722 setting = setting != FALSE;
2724 if (priv->skips_pager != setting)
2726 priv->skips_pager = setting;
2727 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2728 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2730 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2735 * gtk_window_get_skip_pager_hint:
2736 * @window: a #GtkWindow
2738 * Gets the value set by gtk_window_set_skip_pager_hint().
2740 * Return value: %TRUE if window shouldn't be in pager
2745 gtk_window_get_skip_pager_hint (GtkWindow *window)
2747 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2749 return window->priv->skips_pager;
2753 * gtk_window_set_urgency_hint:
2754 * @window: a #GtkWindow
2755 * @setting: %TRUE to mark this window as urgent
2757 * Windows may set a hint asking the desktop environment to draw
2758 * the users attention to the window. This function sets this hint.
2763 gtk_window_set_urgency_hint (GtkWindow *window,
2766 GtkWindowPrivate *priv;
2768 g_return_if_fail (GTK_IS_WINDOW (window));
2770 priv = window->priv;
2772 setting = setting != FALSE;
2774 if (priv->urgent != setting)
2776 priv->urgent = setting;
2777 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2778 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2780 g_object_notify (G_OBJECT (window), "urgency-hint");
2785 * gtk_window_get_urgency_hint:
2786 * @window: a #GtkWindow
2788 * Gets the value set by gtk_window_set_urgency_hint()
2790 * Return value: %TRUE if window is urgent
2795 gtk_window_get_urgency_hint (GtkWindow *window)
2797 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2799 return window->priv->urgent;
2803 * gtk_window_set_accept_focus:
2804 * @window: a #GtkWindow
2805 * @setting: %TRUE to let this window receive input focus
2807 * Windows may set a hint asking the desktop environment not to receive
2808 * the input focus. This function sets this hint.
2813 gtk_window_set_accept_focus (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->accept_focus != setting)
2826 priv->accept_focus = setting;
2827 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2828 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2829 priv->accept_focus);
2830 g_object_notify (G_OBJECT (window), "accept-focus");
2835 * gtk_window_get_accept_focus:
2836 * @window: a #GtkWindow
2838 * Gets the value set by gtk_window_set_accept_focus().
2840 * Return value: %TRUE if window should receive the input focus
2845 gtk_window_get_accept_focus (GtkWindow *window)
2847 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2849 return window->priv->accept_focus;
2853 * gtk_window_set_focus_on_map:
2854 * @window: a #GtkWindow
2855 * @setting: %TRUE to let this window receive input focus on map
2857 * Windows may set a hint asking the desktop environment not to receive
2858 * the input focus when the window is mapped. This function sets this
2864 gtk_window_set_focus_on_map (GtkWindow *window,
2867 GtkWindowPrivate *priv;
2869 g_return_if_fail (GTK_IS_WINDOW (window));
2871 priv = window->priv;
2873 setting = setting != FALSE;
2875 if (priv->focus_on_map != setting)
2877 priv->focus_on_map = setting;
2878 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2879 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2880 priv->focus_on_map);
2881 g_object_notify (G_OBJECT (window), "focus-on-map");
2886 * gtk_window_get_focus_on_map:
2887 * @window: a #GtkWindow
2889 * Gets the value set by gtk_window_set_focus_on_map().
2891 * Return value: %TRUE if window should receive the input focus when
2897 gtk_window_get_focus_on_map (GtkWindow *window)
2899 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2901 return window->priv->focus_on_map;
2905 * gtk_window_set_destroy_with_parent:
2906 * @window: a #GtkWindow
2907 * @setting: whether to destroy @window with its transient parent
2909 * If @setting is %TRUE, then destroying the transient parent of @window
2910 * will also destroy @window itself. This is useful for dialogs that
2911 * shouldn't persist beyond the lifetime of the main window they're
2912 * associated with, for example.
2915 gtk_window_set_destroy_with_parent (GtkWindow *window,
2918 GtkWindowPrivate *priv;
2920 g_return_if_fail (GTK_IS_WINDOW (window));
2922 priv = window->priv;
2924 if (priv->destroy_with_parent == (setting != FALSE))
2927 if (priv->destroy_with_parent)
2929 disconnect_parent_destroyed (window);
2933 connect_parent_destroyed (window);
2936 priv->destroy_with_parent = setting;
2938 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2942 * gtk_window_get_destroy_with_parent:
2943 * @window: a #GtkWindow
2945 * Returns whether the window will be destroyed with its transient parent. See
2946 * gtk_window_set_destroy_with_parent ().
2948 * Return value: %TRUE if the window will be destroyed with its transient parent.
2951 gtk_window_get_destroy_with_parent (GtkWindow *window)
2953 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2955 return window->priv->destroy_with_parent;
2958 static GtkWindowGeometryInfo*
2959 gtk_window_get_geometry_info (GtkWindow *window,
2962 GtkWindowPrivate *priv = window->priv;
2963 GtkWindowGeometryInfo *info;
2965 info = priv->geometry_info;
2966 if (!info && create)
2968 info = g_new0 (GtkWindowGeometryInfo, 1);
2970 info->default_width = -1;
2971 info->default_height = -1;
2972 info->resize_width = -1;
2973 info->resize_height = -1;
2974 info->initial_x = 0;
2975 info->initial_y = 0;
2976 info->initial_pos_set = FALSE;
2977 info->default_is_geometry = FALSE;
2978 info->position_constraints_changed = FALSE;
2979 info->last.configure_request.x = 0;
2980 info->last.configure_request.y = 0;
2981 info->last.configure_request.width = -1;
2982 info->last.configure_request.height = -1;
2983 info->widget = NULL;
2985 priv->geometry_info = info;
2992 * gtk_window_set_geometry_hints:
2993 * @window: a #GtkWindow
2994 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
2995 * @geometry: (allow-none): struct containing geometry information or %NULL
2996 * @geom_mask: mask indicating which struct fields should be paid attention to
2998 * This function sets up hints about how a window can be resized by
2999 * the user. You can set a minimum and maximum size; allowed resize
3000 * increments (e.g. for xterm, you can only resize by the size of a
3001 * character); aspect ratios; and more. See the #GdkGeometry struct.
3005 gtk_window_set_geometry_hints (GtkWindow *window,
3006 GtkWidget *geometry_widget,
3007 GdkGeometry *geometry,
3008 GdkWindowHints geom_mask)
3010 GtkWindowGeometryInfo *info;
3012 g_return_if_fail (GTK_IS_WINDOW (window));
3013 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3015 info = gtk_window_get_geometry_info (window, TRUE);
3018 g_signal_handlers_disconnect_by_func (info->widget,
3019 gtk_widget_destroyed,
3022 info->widget = geometry_widget;
3024 g_signal_connect (geometry_widget, "destroy",
3025 G_CALLBACK (gtk_widget_destroyed),
3029 info->geometry = *geometry;
3031 /* We store gravity in priv->gravity not in the hints. */
3032 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3034 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3036 gtk_window_set_gravity (window, geometry->win_gravity);
3039 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3043 * gtk_window_set_decorated:
3044 * @window: a #GtkWindow
3045 * @setting: %TRUE to decorate the window
3047 * By default, windows are decorated with a title bar, resize
3048 * controls, etc. Some <link linkend="gtk-X11-arch">window
3049 * managers</link> allow GTK+ to disable these decorations, creating a
3050 * borderless window. If you set the decorated property to %FALSE
3051 * using this function, GTK+ will do its best to convince the window
3052 * manager not to decorate the window. Depending on the system, this
3053 * function may not have any effect when called on a window that is
3054 * already visible, so you should call it before calling gtk_window_show().
3056 * On Windows, this function always works, since there's no window manager
3061 gtk_window_set_decorated (GtkWindow *window,
3064 GtkWindowPrivate *priv;
3065 GdkWindow *gdk_window;
3067 g_return_if_fail (GTK_IS_WINDOW (window));
3069 priv = window->priv;
3071 setting = setting != FALSE;
3073 if (setting == priv->decorated)
3076 priv->decorated = setting;
3078 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3081 if (priv->decorated)
3082 gdk_window_set_decorations (gdk_window,
3085 gdk_window_set_decorations (gdk_window,
3089 g_object_notify (G_OBJECT (window), "decorated");
3093 * gtk_window_get_decorated:
3094 * @window: a #GtkWindow
3096 * Returns whether the window has been set to have decorations
3097 * such as a title bar via gtk_window_set_decorated().
3099 * Return value: %TRUE if the window has been set to have decorations
3102 gtk_window_get_decorated (GtkWindow *window)
3104 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3106 return window->priv->decorated;
3110 * gtk_window_set_deletable:
3111 * @window: a #GtkWindow
3112 * @setting: %TRUE to decorate the window as deletable
3114 * By default, windows have a close button in the window frame. Some
3115 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3116 * disable this button. If you set the deletable property to %FALSE
3117 * using this function, GTK+ will do its best to convince the window
3118 * manager not to show a close button. Depending on the system, this
3119 * function may not have any effect when called on a window that is
3120 * already visible, so you should call it before calling gtk_window_show().
3122 * On Windows, this function always works, since there's no window manager
3128 gtk_window_set_deletable (GtkWindow *window,
3131 GtkWindowPrivate *priv;
3132 GdkWindow *gdk_window;
3134 g_return_if_fail (GTK_IS_WINDOW (window));
3136 priv = window->priv;
3138 setting = setting != FALSE;
3140 if (setting == priv->deletable)
3143 priv->deletable = setting;
3145 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3148 if (priv->deletable)
3149 gdk_window_set_functions (gdk_window,
3152 gdk_window_set_functions (gdk_window,
3153 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3156 g_object_notify (G_OBJECT (window), "deletable");
3160 * gtk_window_get_deletable:
3161 * @window: a #GtkWindow
3163 * Returns whether the window has been set to have a close button
3164 * via gtk_window_set_deletable().
3166 * Return value: %TRUE if the window has been set to have a close button
3171 gtk_window_get_deletable (GtkWindow *window)
3173 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3175 return window->priv->deletable;
3178 static GtkWindowIconInfo*
3179 get_icon_info (GtkWindow *window)
3181 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3185 free_icon_info (GtkWindowIconInfo *info)
3187 g_free (info->icon_name);
3188 g_slice_free (GtkWindowIconInfo, info);
3192 static GtkWindowIconInfo*
3193 ensure_icon_info (GtkWindow *window)
3195 GtkWindowIconInfo *info;
3197 info = get_icon_info (window);
3201 info = g_slice_new0 (GtkWindowIconInfo);
3202 g_object_set_qdata_full (G_OBJECT (window),
3203 quark_gtk_window_icon_info,
3205 (GDestroyNotify)free_icon_info);
3212 icon_list_from_theme (GtkWidget *widget,
3217 GtkIconTheme *icon_theme;
3222 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3224 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3227 for (i = 0; sizes[i]; i++)
3230 * We need an EWMH extension to handle scalable icons
3231 * by passing their name to the WM. For now just use a
3235 icon = gtk_icon_theme_load_icon (icon_theme, name,
3238 icon = gtk_icon_theme_load_icon (icon_theme, name,
3241 list = g_list_append (list, icon);
3251 gtk_window_realize_icon (GtkWindow *window)
3253 GtkWindowPrivate *priv = window->priv;
3255 GtkWindowIconInfo *info;
3256 GdkWindow *gdk_window;
3259 widget = GTK_WIDGET (window);
3260 gdk_window = gtk_widget_get_window (widget);
3262 g_return_if_fail (gdk_window != NULL);
3264 /* no point setting an icon on override-redirect */
3265 if (priv->type == GTK_WINDOW_POPUP)
3270 info = ensure_icon_info (window);
3275 info->using_default_icon = FALSE;
3276 info->using_parent_icon = FALSE;
3277 info->using_themed_icon = FALSE;
3279 icon_list = info->icon_list;
3281 /* Look up themed icon */
3282 if (icon_list == NULL && info->icon_name)
3284 icon_list = icon_list_from_theme (widget, info->icon_name);
3286 info->using_themed_icon = TRUE;
3289 /* Inherit from transient parent */
3290 if (icon_list == NULL && priv->transient_parent)
3292 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3294 info->using_parent_icon = TRUE;
3297 /* Inherit from default */
3298 if (icon_list == NULL)
3300 icon_list = default_icon_list;
3302 info->using_default_icon = TRUE;
3305 /* Look up themed icon */
3306 if (icon_list == NULL && default_icon_name)
3308 icon_list = icon_list_from_theme (widget, default_icon_name);
3309 info->using_default_icon = TRUE;
3310 info->using_themed_icon = TRUE;
3313 info->realized = TRUE;
3315 if (info->using_themed_icon)
3317 GtkIconTheme *icon_theme;
3319 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3320 g_list_free (icon_list);
3322 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3323 g_signal_connect (icon_theme, "changed",
3324 G_CALLBACK (update_themed_icon), window);
3329 gtk_window_unrealize_icon (GtkWindow *window)
3331 GtkWindowIconInfo *info;
3333 info = get_icon_info (window);
3338 if (info->using_themed_icon)
3340 GtkIconTheme *icon_theme;
3342 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3344 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3347 /* We don't clear the properties on the window, just figure the
3348 * window is going away.
3351 info->realized = FALSE;
3356 * gtk_window_set_icon_list:
3357 * @window: a #GtkWindow
3358 * @list: (element-type GdkPixbuf) (transfer container): list of #GdkPixbuf
3360 * Sets up the icon representing a #GtkWindow. The icon is used when
3361 * the window is minimized (also known as iconified). Some window
3362 * managers or desktop environments may also place it in the window
3363 * frame, or display it in other contexts.
3365 * gtk_window_set_icon_list() allows you to pass in the same icon in
3366 * several hand-drawn sizes. The list should contain the natural sizes
3367 * your icon is available in; that is, don't scale the image before
3368 * passing it to GTK+. Scaling is postponed until the last minute,
3369 * when the desired final size is known, to allow best quality.
3371 * By passing several sizes, you may improve the final image quality
3372 * of the icon, by reducing or eliminating automatic image scaling.
3374 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3375 * larger images (64x64, 128x128) if you have them.
3377 * See also gtk_window_set_default_icon_list() to set the icon
3378 * for all windows in your application in one go.
3380 * Note that transient windows (those who have been set transient for another
3381 * window using gtk_window_set_transient_for()) will inherit their
3382 * icon from their transient parent. So there's no need to explicitly
3383 * set the icon on transient windows.
3386 gtk_window_set_icon_list (GtkWindow *window,
3389 GtkWindowIconInfo *info;
3391 g_return_if_fail (GTK_IS_WINDOW (window));
3393 info = ensure_icon_info (window);
3395 if (info->icon_list == list) /* check for NULL mostly */
3398 g_list_foreach (list,
3399 (GFunc) g_object_ref, NULL);
3401 g_list_foreach (info->icon_list,
3402 (GFunc) g_object_unref, NULL);
3404 g_list_free (info->icon_list);
3406 info->icon_list = g_list_copy (list);
3408 g_object_notify (G_OBJECT (window), "icon");
3410 gtk_window_unrealize_icon (window);
3412 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3413 gtk_window_realize_icon (window);
3415 /* We could try to update our transient children, but I don't think
3416 * it's really worth it. If we did it, the best way would probably
3417 * be to have children connect to notify::icon-list
3422 * gtk_window_get_icon_list:
3423 * @window: a #GtkWindow
3425 * Retrieves the list of icons set by gtk_window_set_icon_list().
3426 * The list is copied, but the reference count on each
3427 * member won't be incremented.
3429 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3432 gtk_window_get_icon_list (GtkWindow *window)
3434 GtkWindowIconInfo *info;
3436 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3438 info = get_icon_info (window);
3441 return g_list_copy (info->icon_list);
3447 * gtk_window_set_icon:
3448 * @window: a #GtkWindow
3449 * @icon: (allow-none): icon image, or %NULL
3451 * Sets up the icon representing a #GtkWindow. This icon is used when
3452 * the window is minimized (also known as iconified). Some window
3453 * managers or desktop environments may also place it in the window
3454 * frame, or display it in other contexts.
3456 * The icon should be provided in whatever size it was naturally
3457 * drawn; that is, don't scale the image before passing it to
3458 * GTK+. Scaling is postponed until the last minute, when the desired
3459 * final size is known, to allow best quality.
3461 * If you have your icon hand-drawn in multiple sizes, use
3462 * gtk_window_set_icon_list(). Then the best size will be used.
3464 * This function is equivalent to calling gtk_window_set_icon_list()
3465 * with a 1-element list.
3467 * See also gtk_window_set_default_icon_list() to set the icon
3468 * for all windows in your application in one go.
3471 gtk_window_set_icon (GtkWindow *window,
3476 g_return_if_fail (GTK_IS_WINDOW (window));
3477 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3482 list = g_list_append (list, icon);
3484 gtk_window_set_icon_list (window, list);
3490 update_themed_icon (GtkIconTheme *icon_theme,
3493 g_object_notify (G_OBJECT (window), "icon");
3495 gtk_window_unrealize_icon (window);
3497 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3498 gtk_window_realize_icon (window);
3502 * gtk_window_set_icon_name:
3503 * @window: a #GtkWindow
3504 * @name: (allow-none): the name of the themed icon
3506 * Sets the icon for the window from a named themed icon. See
3507 * the docs for #GtkIconTheme for more details.
3509 * Note that this has nothing to do with the WM_ICON_NAME
3510 * property which is mentioned in the ICCCM.
3515 gtk_window_set_icon_name (GtkWindow *window,
3518 GtkWindowIconInfo *info;
3521 g_return_if_fail (GTK_IS_WINDOW (window));
3523 info = ensure_icon_info (window);
3525 if (g_strcmp0 (info->icon_name, name) == 0)
3528 tmp = info->icon_name;
3529 info->icon_name = g_strdup (name);
3532 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3533 g_list_free (info->icon_list);
3534 info->icon_list = NULL;
3536 update_themed_icon (NULL, window);
3538 g_object_notify (G_OBJECT (window), "icon-name");
3542 * gtk_window_get_icon_name:
3543 * @window: a #GtkWindow
3545 * Returns the name of the themed icon for the window,
3546 * see gtk_window_set_icon_name().
3548 * Returns: the icon name or %NULL if the window has
3554 gtk_window_get_icon_name (GtkWindow *window)
3556 GtkWindowIconInfo *info;
3558 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3560 info = ensure_icon_info (window);
3562 return info->icon_name;
3566 * gtk_window_get_icon:
3567 * @window: a #GtkWindow
3569 * Gets the value set by gtk_window_set_icon() (or if you've
3570 * called gtk_window_set_icon_list(), gets the first icon in
3573 * Return value: (transfer none): icon for window
3576 gtk_window_get_icon (GtkWindow *window)
3578 GtkWindowIconInfo *info;
3580 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3582 info = get_icon_info (window);
3583 if (info && info->icon_list)
3584 return GDK_PIXBUF (info->icon_list->data);
3589 /* Load pixbuf, printing warning on failure if error == NULL
3592 load_pixbuf_verbosely (const char *filename,
3595 GError *local_err = NULL;
3598 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3606 g_warning ("Error loading icon from file '%s':\n\t%s",
3607 filename, local_err->message);
3608 g_error_free (local_err);
3616 * gtk_window_set_icon_from_file:
3617 * @window: a #GtkWindow
3618 * @filename: location of icon file
3619 * @err: (allow-none): location to store error, or %NULL.
3621 * Sets the icon for @window.
3622 * Warns on failure if @err is %NULL.
3624 * This function is equivalent to calling gtk_window_set_icon()
3625 * with a pixbuf created by loading the image from @filename.
3627 * Returns: %TRUE if setting the icon succeeded.
3632 gtk_window_set_icon_from_file (GtkWindow *window,
3633 const gchar *filename,
3636 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3640 gtk_window_set_icon (window, pixbuf);
3641 g_object_unref (pixbuf);
3650 * gtk_window_set_default_icon_list:
3651 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3653 * Sets an icon list to be used as fallback for windows that haven't
3654 * had gtk_window_set_icon_list() called on them to set up a
3655 * window-specific icon list. This function allows you to set up the
3656 * icon for all windows in your app at once.
3658 * See gtk_window_set_icon_list() for more details.
3662 gtk_window_set_default_icon_list (GList *list)
3666 if (list == default_icon_list)
3669 /* Update serial so we don't used cached pixmaps/masks
3671 default_icon_serial++;
3673 g_list_foreach (list,
3674 (GFunc) g_object_ref, NULL);
3676 g_list_foreach (default_icon_list,
3677 (GFunc) g_object_unref, NULL);
3679 g_list_free (default_icon_list);
3681 default_icon_list = g_list_copy (list);
3683 /* Update all toplevels */
3684 toplevels = gtk_window_list_toplevels ();
3685 tmp_list = toplevels;
3686 while (tmp_list != NULL)
3688 GtkWindowIconInfo *info;
3689 GtkWindow *w = tmp_list->data;
3691 info = get_icon_info (w);
3692 if (info && info->using_default_icon)
3694 gtk_window_unrealize_icon (w);
3695 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3696 gtk_window_realize_icon (w);
3699 tmp_list = tmp_list->next;
3701 g_list_free (toplevels);
3705 * gtk_window_set_default_icon:
3708 * Sets an icon to be used as fallback for windows that haven't
3709 * had gtk_window_set_icon() called on them from a pixbuf.
3714 gtk_window_set_default_icon (GdkPixbuf *icon)
3718 g_return_if_fail (GDK_IS_PIXBUF (icon));
3720 list = g_list_prepend (NULL, icon);
3721 gtk_window_set_default_icon_list (list);
3726 * gtk_window_set_default_icon_name:
3727 * @name: the name of the themed icon
3729 * Sets an icon to be used as fallback for windows that haven't
3730 * had gtk_window_set_icon_list() called on them from a named
3731 * themed icon, see gtk_window_set_icon_name().
3736 gtk_window_set_default_icon_name (const gchar *name)
3741 /* Update serial so we don't used cached pixmaps/masks
3743 default_icon_serial++;
3745 g_free (default_icon_name);
3746 default_icon_name = g_strdup (name);
3748 g_list_foreach (default_icon_list,
3749 (GFunc) g_object_unref, NULL);
3751 g_list_free (default_icon_list);
3752 default_icon_list = NULL;
3754 /* Update all toplevels */
3755 toplevels = gtk_window_list_toplevels ();
3756 tmp_list = toplevels;
3757 while (tmp_list != NULL)
3759 GtkWindowIconInfo *info;
3760 GtkWindow *w = tmp_list->data;
3762 info = get_icon_info (w);
3763 if (info && info->using_default_icon && info->using_themed_icon)
3765 gtk_window_unrealize_icon (w);
3766 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3767 gtk_window_realize_icon (w);
3770 tmp_list = tmp_list->next;
3772 g_list_free (toplevels);
3776 * gtk_window_get_default_icon_name:
3778 * Returns the fallback icon name for windows that has been set
3779 * with gtk_window_set_default_icon_name(). The returned
3780 * string is owned by GTK+ and should not be modified. It
3781 * is only valid until the next call to
3782 * gtk_window_set_default_icon_name().
3784 * Returns: the fallback icon name for windows
3789 gtk_window_get_default_icon_name (void)
3791 return default_icon_name;
3795 * gtk_window_set_default_icon_from_file:
3796 * @filename: location of icon file
3797 * @err: (allow-none): location to store error, or %NULL.
3799 * Sets an icon to be used as fallback for windows that haven't
3800 * had gtk_window_set_icon_list() called on them from a file
3801 * on disk. Warns on failure if @err is %NULL.
3803 * Returns: %TRUE if setting the icon succeeded.
3808 gtk_window_set_default_icon_from_file (const gchar *filename,
3811 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3815 gtk_window_set_default_icon (pixbuf);
3816 g_object_unref (pixbuf);
3825 * gtk_window_get_default_icon_list:
3827 * Gets the value set by gtk_window_set_default_icon_list().
3828 * The list is a copy and should be freed with g_list_free(),
3829 * but the pixbufs in the list have not had their reference count
3832 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3835 gtk_window_get_default_icon_list (void)
3837 return g_list_copy (default_icon_list);
3841 gtk_window_set_default_size_internal (GtkWindow *window,
3842 gboolean change_width,
3844 gboolean change_height,
3846 gboolean is_geometry)
3848 GtkWindowGeometryInfo *info;
3850 g_return_if_fail (change_width == FALSE || width >= -1);
3851 g_return_if_fail (change_height == FALSE || height >= -1);
3853 info = gtk_window_get_geometry_info (window, TRUE);
3855 g_object_freeze_notify (G_OBJECT (window));
3857 info->default_is_geometry = is_geometry != FALSE;
3867 info->default_width = width;
3869 g_object_notify (G_OBJECT (window), "default-width");
3880 info->default_height = height;
3882 g_object_notify (G_OBJECT (window), "default-height");
3885 g_object_thaw_notify (G_OBJECT (window));
3887 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3891 * gtk_window_set_default_size:
3892 * @window: a #GtkWindow
3893 * @width: width in pixels, or -1 to unset the default width
3894 * @height: height in pixels, or -1 to unset the default height
3896 * Sets the default size of a window. If the window's "natural" size
3897 * (its size request) is larger than the default, the default will be
3898 * ignored. More generally, if the default size does not obey the
3899 * geometry hints for the window (gtk_window_set_geometry_hints() can
3900 * be used to set these explicitly), the default size will be clamped
3901 * to the nearest permitted size.
3903 * Unlike gtk_widget_set_size_request(), which sets a size request for
3904 * a widget and thus would keep users from shrinking the window, this
3905 * function only sets the initial size, just as if the user had
3906 * resized the window themselves. Users can still shrink the window
3907 * again as they normally would. Setting a default size of -1 means to
3908 * use the "natural" default size (the size request of the window).
3910 * For more control over a window's initial size and how resizing works,
3911 * investigate gtk_window_set_geometry_hints().
3913 * For some uses, gtk_window_resize() is a more appropriate function.
3914 * gtk_window_resize() changes the current size of the window, rather
3915 * than the size to be used on initial display. gtk_window_resize() always
3916 * affects the window itself, not the geometry widget.
3918 * The default size of a window only affects the first time a window is
3919 * shown; if a window is hidden and re-shown, it will remember the size
3920 * it had prior to hiding, rather than using the default size.
3922 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3923 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3926 gtk_window_set_default_size (GtkWindow *window,
3930 g_return_if_fail (GTK_IS_WINDOW (window));
3931 g_return_if_fail (width >= -1);
3932 g_return_if_fail (height >= -1);
3934 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3938 * gtk_window_set_default_geometry:
3939 * @window: a #GtkWindow
3940 * @width: width in resize increments, or -1 to unset the default width
3941 * @height: height in resize increments, or -1 to unset the default height
3943 * Like gtk_window_set_default_size(), but @width and @height are interpreted
3944 * in terms of the base size and increment set with
3945 * gtk_window_set_geometry_hints.
3950 gtk_window_set_default_geometry (GtkWindow *window,
3954 g_return_if_fail (GTK_IS_WINDOW (window));
3955 g_return_if_fail (width >= -1);
3956 g_return_if_fail (height >= -1);
3958 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
3962 * gtk_window_get_default_size:
3963 * @window: a #GtkWindow
3964 * @width: (out) (allow-none): location to store the default width, or %NULL
3965 * @height: (out) (allow-none): location to store the default height, or %NULL
3967 * Gets the default size of the window. A value of -1 for the width or
3968 * height indicates that a default size has not been explicitly set
3969 * for that dimension, so the "natural" size of the window will be
3974 gtk_window_get_default_size (GtkWindow *window,
3978 GtkWindowGeometryInfo *info;
3980 g_return_if_fail (GTK_IS_WINDOW (window));
3982 info = gtk_window_get_geometry_info (window, FALSE);
3985 *width = info ? info->default_width : -1;
3988 *height = info ? info->default_height : -1;
3992 * gtk_window_resize:
3993 * @window: a #GtkWindow
3994 * @width: width in pixels to resize the window to
3995 * @height: height in pixels to resize the window to
3997 * Resizes the window as if the user had done so, obeying geometry
3998 * constraints. The default geometry constraint is that windows may
3999 * not be smaller than their size request; to override this
4000 * constraint, call gtk_widget_set_size_request() to set the window's
4001 * request to a smaller value.
4003 * If gtk_window_resize() is called before showing a window for the
4004 * first time, it overrides any default size set with
4005 * gtk_window_set_default_size().
4007 * Windows may not be resized smaller than 1 by 1 pixels.
4011 gtk_window_resize (GtkWindow *window,
4015 GtkWindowGeometryInfo *info;
4017 g_return_if_fail (GTK_IS_WINDOW (window));
4018 g_return_if_fail (width > 0);
4019 g_return_if_fail (height > 0);
4021 info = gtk_window_get_geometry_info (window, TRUE);
4023 info->resize_width = width;
4024 info->resize_height = height;
4025 info->resize_is_geometry = FALSE;
4027 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4031 * gtk_window_resize_to_geometry:
4032 * @window: a #GtkWindow
4033 * @width: width in resize increments to resize the window to
4034 * @height: height in resize increments to resize the window to
4036 * Like gtk_window_resize(), but @width and @height are interpreted
4037 * in terms of the base size and increment set with
4038 * gtk_window_set_geometry_hints.
4043 gtk_window_resize_to_geometry (GtkWindow *window,
4047 GtkWindowGeometryInfo *info;
4049 g_return_if_fail (GTK_IS_WINDOW (window));
4050 g_return_if_fail (width > 0);
4051 g_return_if_fail (height > 0);
4053 info = gtk_window_get_geometry_info (window, TRUE);
4055 info->resize_width = width;
4056 info->resize_height = height;
4057 info->resize_is_geometry = TRUE;
4059 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4063 * gtk_window_get_size:
4064 * @window: a #GtkWindow
4065 * @width: (out) (allow-none): return location for width, or %NULL
4066 * @height: (out) (allow-none): return location for height, or %NULL
4068 * Obtains the current size of @window. If @window is not onscreen,
4069 * it returns the size GTK+ will suggest to the <link
4070 * linkend="gtk-X11-arch">window manager</link> for the initial window
4071 * size (but this is not reliably the same as the size the window
4072 * manager will actually select). The size obtained by
4073 * gtk_window_get_size() is the last size received in a
4074 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4075 * rather than querying the X server for the size. As a result, if you
4076 * call gtk_window_resize() then immediately call
4077 * gtk_window_get_size(), the size won't have taken effect yet. After
4078 * the window manager processes the resize request, GTK+ receives
4079 * notification that the size has changed via a configure event, and
4080 * the size of the window gets updated.
4082 * Note 1: Nearly any use of this function creates a race condition,
4083 * because the size of the window may change between the time that you
4084 * get the size and the time that you perform some action assuming
4085 * that size is the current size. To avoid race conditions, connect to
4086 * "configure-event" on the window and adjust your size-dependent
4087 * state to match the size delivered in the #GdkEventConfigure.
4089 * Note 2: The returned size does <emphasis>not</emphasis> include the
4090 * size of the window manager decorations (aka the window frame or
4091 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4092 * method of determining their size.
4094 * Note 3: If you are getting a window size in order to position
4095 * the window onscreen, there may be a better way. The preferred
4096 * way is to simply set the window's semantic type with
4097 * gtk_window_set_type_hint(), which allows the window manager to
4098 * e.g. center dialogs. Also, if you set the transient parent of
4099 * dialogs with gtk_window_set_transient_for() window managers
4100 * will often center the dialog over its parent window. It's
4101 * much preferred to let the window manager handle these
4102 * things rather than doing it yourself, because all apps will
4103 * behave consistently and according to user prefs if the window
4104 * manager handles it. Also, the window manager can take the size
4105 * of the window decorations/border into account, while your
4106 * application cannot.
4108 * In any case, if you insist on application-specified window
4109 * positioning, there's <emphasis>still</emphasis> a better way than
4110 * doing it yourself - gtk_window_set_position() will frequently
4111 * handle the details for you.
4115 gtk_window_get_size (GtkWindow *window,
4121 g_return_if_fail (GTK_IS_WINDOW (window));
4123 if (width == NULL && height == NULL)
4126 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4128 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4129 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4133 GdkRectangle configure_request;
4135 gtk_window_compute_configure_request (window,
4139 w = configure_request.width;
4140 h = configure_request.height;
4151 * @window: a #GtkWindow
4152 * @x: X coordinate to move window to
4153 * @y: Y coordinate to move window to
4155 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4156 * @window to the given position. Window managers are free to ignore
4157 * this; most window managers ignore requests for initial window
4158 * positions (instead using a user-defined placement algorithm) and
4159 * honor requests after the window has already been shown.
4161 * Note: the position is the position of the gravity-determined
4162 * reference point for the window. The gravity determines two things:
4163 * first, the location of the reference point in root window
4164 * coordinates; and second, which point on the window is positioned at
4165 * the reference point.
4167 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4168 * point is simply the @x, @y supplied to gtk_window_move(). The
4169 * top-left corner of the window decorations (aka window frame or
4170 * border) will be placed at @x, @y. Therefore, to position a window
4171 * at the top left of the screen, you want to use the default gravity
4172 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4174 * To position a window at the bottom right corner of the screen, you
4175 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4176 * point is at @x + the window width and @y + the window height, and
4177 * the bottom-right corner of the window border will be placed at that
4178 * reference point. So, to place a window in the bottom right corner
4179 * you would first set gravity to south east, then write:
4180 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4181 * gdk_screen_height () - window_height)</literal> (note that this
4182 * example does not take multi-head scenarios into account).
4184 * The Extended Window Manager Hints specification at <ulink
4185 * url="http://www.freedesktop.org/Standards/wm-spec">
4186 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4187 * nice table of gravities in the "implementation notes" section.
4189 * The gtk_window_get_position() documentation may also be relevant.
4192 gtk_window_move (GtkWindow *window,
4196 GtkWindowPrivate *priv;
4197 GtkWindowGeometryInfo *info;
4200 g_return_if_fail (GTK_IS_WINDOW (window));
4202 priv = window->priv;
4203 widget = GTK_WIDGET (window);
4205 info = gtk_window_get_geometry_info (window, TRUE);
4207 if (gtk_widget_get_mapped (widget))
4209 GtkAllocation allocation;
4211 gtk_widget_get_allocation (widget, &allocation);
4213 /* we have now sent a request with this position
4214 * with currently-active constraints, so toggle flag.
4216 info->position_constraints_changed = FALSE;
4218 /* we only constrain if mapped - if not mapped,
4219 * then gtk_window_compute_configure_request()
4220 * will apply the constraints later, and we
4221 * don't want to lose information about
4222 * what position the user set before then.
4223 * i.e. if you do a move() then turn off POS_CENTER
4224 * then show the window, your move() will work.
4226 gtk_window_constrain_position (window,
4227 allocation.width, allocation.height,
4230 /* Note that this request doesn't go through our standard request
4231 * framework, e.g. doesn't increment configure_request_count,
4232 * doesn't set info->last, etc.; that's because
4233 * we don't save the info needed to arrive at this same request
4236 * To gtk_window_move_resize(), this will end up looking exactly
4237 * the same as the position being changed by the window
4241 /* FIXME are we handling gravity properly for framed windows? */
4243 gdk_window_move (priv->frame,
4244 x - priv->frame_left,
4245 y - priv->frame_top);
4247 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)),
4252 /* Save this position to apply on mapping */
4253 info->initial_x = x;
4254 info->initial_y = y;
4255 info->initial_pos_set = TRUE;
4260 * gtk_window_get_position:
4261 * @window: a #GtkWindow
4262 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4263 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4265 * This function returns the position you need to pass to
4266 * gtk_window_move() to keep @window in its current position. This
4267 * means that the meaning of the returned value varies with window
4268 * gravity. See gtk_window_move() for more details.
4270 * If you haven't changed the window gravity, its gravity will be
4271 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4272 * gets the position of the top-left corner of the window manager
4273 * frame for the window. gtk_window_move() sets the position of this
4274 * same top-left corner.
4276 * gtk_window_get_position() is not 100% reliable because the X Window System
4277 * does not specify a way to obtain the geometry of the
4278 * decorations placed on a window by the window manager.
4279 * Thus GTK+ is using a "best guess" that works with most
4282 * Moreover, nearly all window managers are historically broken with
4283 * respect to their handling of window gravity. So moving a window to
4284 * its current position as returned by gtk_window_get_position() tends
4285 * to result in moving the window slightly. Window managers are
4286 * slowly getting better over time.
4288 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4289 * frame is not relevant, and thus gtk_window_get_position() will
4290 * always produce accurate results. However you can't use static
4291 * gravity to do things like place a window in a corner of the screen,
4292 * because static gravity ignores the window manager decorations.
4294 * If you are saving and restoring your application's window
4295 * positions, you should know that it's impossible for applications to
4296 * do this without getting it somewhat wrong because applications do
4297 * not have sufficient knowledge of window manager state. The Correct
4298 * Mechanism is to support the session management protocol (see the
4299 * "GnomeClient" object in the GNOME libraries for example) and allow
4300 * the window manager to save your window sizes and positions.
4305 gtk_window_get_position (GtkWindow *window,
4309 GtkWindowPrivate *priv;
4311 GdkWindow *gdk_window;
4313 g_return_if_fail (GTK_IS_WINDOW (window));
4315 priv = window->priv;
4316 widget = GTK_WIDGET (window);
4317 gdk_window = gtk_widget_get_window (widget);
4319 if (priv->gravity == GDK_GRAVITY_STATIC)
4321 if (gtk_widget_get_mapped (widget))
4323 /* This does a server round-trip, which is sort of wrong;
4324 * but a server round-trip is inevitable for
4325 * gdk_window_get_frame_extents() in the usual
4326 * NorthWestGravity case below, so not sure what else to
4327 * do. We should likely be consistent about whether we get
4328 * the client-side info or the server-side info.
4330 gdk_window_get_origin (gdk_window, root_x, root_y);
4334 GdkRectangle configure_request;
4336 gtk_window_compute_configure_request (window,
4340 *root_x = configure_request.x;
4341 *root_y = configure_request.y;
4346 GdkRectangle frame_extents;
4351 if (gtk_widget_get_mapped (widget))
4354 gdk_window_get_frame_extents (priv->frame, &frame_extents);
4356 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4357 x = frame_extents.x;
4358 y = frame_extents.y;
4359 gtk_window_get_size (window, &w, &h);
4363 /* We just say the frame has 0 size on all sides.
4364 * Not sure what else to do.
4366 gtk_window_compute_configure_request (window,
4369 x = frame_extents.x;
4370 y = frame_extents.y;
4371 w = frame_extents.width;
4372 h = frame_extents.height;
4375 switch (priv->gravity)
4377 case GDK_GRAVITY_NORTH:
4378 case GDK_GRAVITY_CENTER:
4379 case GDK_GRAVITY_SOUTH:
4380 /* Find center of frame. */
4381 x += frame_extents.width / 2;
4382 /* Center client window on that point. */
4386 case GDK_GRAVITY_SOUTH_EAST:
4387 case GDK_GRAVITY_EAST:
4388 case GDK_GRAVITY_NORTH_EAST:
4389 /* Find right edge of frame */
4390 x += frame_extents.width;
4391 /* Align left edge of client at that point. */
4398 switch (priv->gravity)
4400 case GDK_GRAVITY_WEST:
4401 case GDK_GRAVITY_CENTER:
4402 case GDK_GRAVITY_EAST:
4403 /* Find center of frame. */
4404 y += frame_extents.height / 2;
4405 /* Center client window there. */
4408 case GDK_GRAVITY_SOUTH_WEST:
4409 case GDK_GRAVITY_SOUTH:
4410 case GDK_GRAVITY_SOUTH_EAST:
4411 /* Find south edge of frame */
4412 y += frame_extents.height;
4413 /* Place bottom edge of client there */
4428 * gtk_window_reshow_with_initial_size:
4429 * @window: a #GtkWindow
4431 * Hides @window, then reshows it, resetting the
4432 * default size and position of the window. Used
4433 * by GUI builders only.
4436 gtk_window_reshow_with_initial_size (GtkWindow *window)
4440 g_return_if_fail (GTK_IS_WINDOW (window));
4442 widget = GTK_WIDGET (window);
4444 gtk_widget_hide (widget);
4445 gtk_widget_unrealize (widget);
4446 gtk_widget_show (widget);
4450 gtk_window_destroy (GtkWidget *widget)
4452 GtkWindow *window = GTK_WINDOW (widget);
4453 GtkWindowPrivate *priv = window->priv;
4455 toplevel_list = g_slist_remove (toplevel_list, window);
4457 if (priv->transient_parent)
4458 gtk_window_set_transient_for (window, NULL);
4460 /* frees the icons */
4461 gtk_window_set_icon_list (window, NULL);
4463 if (priv->has_user_ref_count)
4465 priv->has_user_ref_count = FALSE;
4466 g_object_unref (window);
4470 gtk_window_group_remove_window (priv->group, window);
4472 gtk_window_free_key_hash (window);
4474 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4478 gtk_window_finalize (GObject *object)
4480 GtkWindow *window = GTK_WINDOW (object);
4481 GtkWindowPrivate *priv = window->priv;
4482 GtkMnemonicHash *mnemonic_hash;
4484 g_free (priv->title);
4485 g_free (priv->wmclass_name);
4486 g_free (priv->wmclass_class);
4487 g_free (priv->wm_role);
4489 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4491 _gtk_mnemonic_hash_free (mnemonic_hash);
4493 if (priv->geometry_info)
4495 if (priv->geometry_info->widget)
4496 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4497 gtk_widget_destroyed,
4498 &priv->geometry_info->widget);
4499 g_free (priv->geometry_info);
4502 if (priv->keys_changed_handler)
4504 g_source_remove (priv->keys_changed_handler);
4505 priv->keys_changed_handler = 0;
4509 g_signal_handlers_disconnect_by_func (priv->screen,
4510 gtk_window_on_composited_changed, window);
4512 g_free (priv->startup_id);
4514 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4518 gtk_window_show (GtkWidget *widget)
4520 GtkWindow *window = GTK_WINDOW (widget);
4521 GtkWindowPrivate *priv = window->priv;
4522 GtkContainer *container = GTK_CONTAINER (window);
4523 gboolean need_resize;
4525 _gtk_widget_set_visible_flag (widget, TRUE);
4527 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4528 _gtk_container_set_need_resize (container, FALSE);
4532 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4533 GtkAllocation allocation = { 0, 0 };
4534 GdkRectangle configure_request;
4535 GdkGeometry new_geometry;
4537 gboolean was_realized;
4539 /* We are going to go ahead and perform this configure request
4540 * and then emulate a configure notify by going ahead and
4541 * doing a size allocate. Sort of a synchronous
4542 * mini-copy of gtk_window_move_resize() here.
4544 gtk_window_compute_configure_request (window,
4549 /* We update this because we are going to go ahead
4550 * and gdk_window_resize() below, rather than
4553 info->last.configure_request.width = configure_request.width;
4554 info->last.configure_request.height = configure_request.height;
4556 /* and allocate the window - this is normally done
4557 * in move_resize in response to configure notify
4559 allocation.width = configure_request.width;
4560 allocation.height = configure_request.height;
4561 gtk_widget_size_allocate (widget, &allocation);
4563 /* Then we guarantee we have a realize */
4564 was_realized = FALSE;
4565 if (!gtk_widget_get_realized (widget))
4567 gtk_widget_realize (widget);
4568 was_realized = TRUE;
4571 /* Must be done after the windows are realized,
4572 * so that the decorations can be read
4574 gtk_decorated_window_calculate_frame_size (window);
4576 /* We only send configure request if we didn't just finish
4577 * creating the window; if we just created the window
4578 * then we created it with widget->allocation anyhow.
4581 gdk_window_move_resize (gtk_widget_get_window (widget),
4582 configure_request.x,
4583 configure_request.y,
4584 configure_request.width,
4585 configure_request.height);
4588 gtk_container_check_resize (container);
4590 gtk_widget_map (widget);
4592 /* Try to make sure that we have some focused widget
4594 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4595 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4598 gtk_grab_add (widget);
4602 gtk_window_hide (GtkWidget *widget)
4604 GtkWindow *window = GTK_WINDOW (widget);
4605 GtkWindowPrivate *priv = window->priv;
4607 _gtk_widget_set_visible_flag (widget, FALSE);
4608 gtk_widget_unmap (widget);
4611 gtk_grab_remove (widget);
4615 gtk_window_map (GtkWidget *widget)
4618 GtkWindow *window = GTK_WINDOW (widget);
4619 GtkWindowPrivate *priv = window->priv;
4620 GdkWindow *toplevel;
4621 GdkWindow *gdk_window;
4622 gboolean auto_mnemonics;
4624 gdk_window = gtk_widget_get_window (widget);
4626 gtk_widget_set_mapped (widget, TRUE);
4628 child = gtk_bin_get_child (&(window->bin));
4630 gtk_widget_get_visible (child) &&
4631 !gtk_widget_get_mapped (child))
4632 gtk_widget_map (child);
4635 toplevel = priv->frame;
4637 toplevel = gdk_window;
4639 if (priv->maximize_initially)
4640 gdk_window_maximize (toplevel);
4642 gdk_window_unmaximize (toplevel);
4644 if (priv->stick_initially)
4645 gdk_window_stick (toplevel);
4647 gdk_window_unstick (toplevel);
4649 if (priv->iconify_initially)
4650 gdk_window_iconify (toplevel);
4652 gdk_window_deiconify (toplevel);
4654 if (priv->fullscreen_initially)
4655 gdk_window_fullscreen (toplevel);
4657 gdk_window_unfullscreen (toplevel);
4659 gdk_window_set_keep_above (toplevel, priv->above_initially);
4661 gdk_window_set_keep_below (toplevel, priv->below_initially);
4663 /* No longer use the default settings */
4664 priv->need_default_size = FALSE;
4665 priv->need_default_position = FALSE;
4667 if (priv->reset_type_hint)
4669 /* We should only reset the type hint when the application
4670 * used gtk_window_set_type_hint() to change the hint.
4671 * Some applications use X directly to change the properties;
4672 * in that case, we shouldn't overwrite what they did.
4674 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4675 priv->reset_type_hint = FALSE;
4678 gdk_window_show (gdk_window);
4681 gdk_window_show (priv->frame);
4683 if (priv->grip_window)
4684 gdk_window_show (priv->grip_window);
4686 if (!disable_startup_notification)
4688 /* Do we have a custom startup-notification id? */
4689 if (priv->startup_id != NULL)
4691 /* Make sure we have a "real" id */
4692 if (!startup_id_is_fake (priv->startup_id))
4693 gdk_notify_startup_complete_with_id (priv->startup_id);
4695 g_free (priv->startup_id);
4696 priv->startup_id = NULL;
4698 else if (!sent_startup_notification)
4700 sent_startup_notification = TRUE;
4701 gdk_notify_startup_complete ();
4705 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4706 * (as in the case of popup menus), then hide mnemonics initially
4708 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4709 &auto_mnemonics, NULL);
4710 if (auto_mnemonics && !priv->mnemonics_visible_set)
4711 gtk_window_set_mnemonics_visible (window, FALSE);
4715 gtk_window_map_event (GtkWidget *widget,
4718 if (!gtk_widget_get_mapped (widget))
4720 /* we should be be unmapped, but are getting a MapEvent, this may happen
4721 * to toplevel XWindows if mapping was intercepted by a window manager
4722 * and an unmap request occoured while the MapRequestEvent was still
4723 * being handled. we work around this situaiton here by re-requesting
4724 * the window being unmapped. more details can be found in:
4725 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4727 gdk_window_hide (gtk_widget_get_window (widget));
4733 gtk_window_unmap (GtkWidget *widget)
4735 GtkWindow *window = GTK_WINDOW (widget);
4736 GtkWindowPrivate *priv = window->priv;
4737 GtkWindowGeometryInfo *info;
4738 GdkWindow *gdk_window;
4739 GdkWindowState state;
4741 gdk_window = gtk_widget_get_window (widget);
4743 gtk_widget_set_mapped (widget, FALSE);
4745 gdk_window_withdraw (priv->frame);
4747 gdk_window_withdraw (gdk_window);
4749 priv->configure_request_count = 0;
4750 priv->configure_notify_received = FALSE;
4752 /* on unmap, we reset the default positioning of the window,
4753 * so it's placed again, but we don't reset the default
4754 * size of the window, so it's remembered.
4756 priv->need_default_position = TRUE;
4758 info = gtk_window_get_geometry_info (window, FALSE);
4761 info->initial_pos_set = FALSE;
4762 info->position_constraints_changed = FALSE;
4765 state = gdk_window_get_state (gdk_window);
4766 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4767 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4768 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4769 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4770 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4774 gtk_window_realize (GtkWidget *widget)
4776 GtkAllocation allocation;
4779 GdkWindow *parent_window;
4780 GdkWindow *gdk_window;
4781 GdkWindowAttr attributes;
4782 gint attributes_mask;
4783 GtkWindowPrivate *priv;
4785 window = GTK_WINDOW (widget);
4786 priv = window->priv;
4788 gtk_widget_get_allocation (widget, &allocation);
4790 /* ensure widget tree is properly size allocated */
4791 if (allocation.x == -1 &&
4792 allocation.y == -1 &&
4793 allocation.width == 1 &&
4794 allocation.height == 1)
4796 GtkRequisition requisition;
4800 allocation.width = 200;
4801 allocation.height = 200;
4803 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4804 if (requisition.width || requisition.height)
4806 /* non-empty window */
4807 allocation.width = requisition.width;
4808 allocation.height = requisition.height;
4810 gtk_widget_size_allocate (widget, &allocation);
4812 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4814 g_return_if_fail (!gtk_widget_get_realized (widget));
4817 gtk_widget_set_realized (widget, TRUE);
4821 case GTK_WINDOW_TOPLEVEL:
4822 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4824 case GTK_WINDOW_POPUP:
4825 attributes.window_type = GDK_WINDOW_TEMP;
4828 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4832 attributes.title = priv->title;
4833 attributes.wmclass_name = priv->wmclass_name;
4834 attributes.wmclass_class = priv->wmclass_class;
4835 attributes.wclass = GDK_INPUT_OUTPUT;
4836 attributes.visual = gtk_widget_get_visual (widget);
4838 if (priv->has_frame)
4840 gtk_widget_get_allocation (widget, &allocation);
4841 attributes.width = allocation.width + priv->frame_left + priv->frame_right;
4842 attributes.height = allocation.height + priv->frame_top + priv->frame_bottom;
4843 attributes.event_mask = (GDK_EXPOSURE_MASK |
4844 GDK_KEY_PRESS_MASK |
4845 GDK_ENTER_NOTIFY_MASK |
4846 GDK_LEAVE_NOTIFY_MASK |
4847 GDK_FOCUS_CHANGE_MASK |
4848 GDK_STRUCTURE_MASK |
4849 GDK_BUTTON_MOTION_MASK |
4850 GDK_POINTER_MOTION_HINT_MASK |
4851 GDK_BUTTON_PRESS_MASK |
4852 GDK_BUTTON_RELEASE_MASK);
4854 attributes_mask = GDK_WA_VISUAL;
4856 priv->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4857 &attributes, attributes_mask);
4859 if (priv->opacity_set)
4860 gdk_window_set_opacity (priv->frame, priv->opacity);
4862 gdk_window_set_user_data (priv->frame, widget);
4864 attributes.window_type = GDK_WINDOW_CHILD;
4865 attributes.x = priv->frame_left;
4866 attributes.y = priv->frame_top;
4868 attributes_mask = GDK_WA_X | GDK_WA_Y;
4870 parent_window = priv->frame;
4872 g_signal_connect (window,
4874 G_CALLBACK (gtk_window_event),
4879 attributes_mask = 0;
4880 parent_window = gtk_widget_get_root_window (widget);
4883 gtk_widget_get_allocation (widget, &allocation);
4884 attributes.width = allocation.width;
4885 attributes.height = allocation.height;
4886 attributes.event_mask = gtk_widget_get_events (widget);
4887 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4888 GDK_KEY_PRESS_MASK |
4889 GDK_KEY_RELEASE_MASK |
4890 GDK_ENTER_NOTIFY_MASK |
4891 GDK_LEAVE_NOTIFY_MASK |
4892 GDK_FOCUS_CHANGE_MASK |
4893 GDK_STRUCTURE_MASK);
4894 attributes.type_hint = priv->type_hint;
4896 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4897 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4898 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4900 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4901 gtk_widget_set_window (widget, gdk_window);
4903 if (!priv->has_frame && priv->opacity_set)
4904 gdk_window_set_opacity (gdk_window, priv->opacity);
4906 gdk_window_enable_synchronized_configure (gdk_window);
4908 gdk_window_set_user_data (gdk_window, window);
4910 gtk_widget_style_attach (widget);
4911 style = gtk_widget_get_style (widget);
4912 gtk_style_set_background (style, gdk_window, GTK_STATE_NORMAL);
4914 gtk_style_set_background (style, priv->frame, GTK_STATE_NORMAL);
4916 if (priv->transient_parent &&
4917 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
4918 gdk_window_set_transient_for (gdk_window,
4919 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
4922 gdk_window_set_role (gdk_window, priv->wm_role);
4924 if (!priv->decorated)
4925 gdk_window_set_decorations (gdk_window, 0);
4927 if (!priv->deletable)
4928 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4930 if (gtk_window_get_skip_pager_hint (window))
4931 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
4933 if (gtk_window_get_skip_taskbar_hint (window))
4934 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
4936 if (gtk_window_get_accept_focus (window))
4937 gdk_window_set_accept_focus (gdk_window, TRUE);
4939 gdk_window_set_accept_focus (gdk_window, FALSE);
4941 if (gtk_window_get_focus_on_map (window))
4942 gdk_window_set_focus_on_map (gdk_window, TRUE);
4944 gdk_window_set_focus_on_map (gdk_window, FALSE);
4947 gdk_window_set_modal_hint (gdk_window, TRUE);
4949 gdk_window_set_modal_hint (gdk_window, FALSE);
4951 if (priv->startup_id)
4953 #ifdef GDK_WINDOWING_X11
4954 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4955 if (timestamp != GDK_CURRENT_TIME)
4956 gdk_x11_window_set_user_time (gdk_window, timestamp);
4958 if (!startup_id_is_fake (priv->startup_id))
4959 gdk_window_set_startup_id (gdk_window, priv->startup_id);
4963 gtk_window_realize_icon (window);
4965 if (priv->has_resize_grip)
4966 resize_grip_create_window (window);
4970 gtk_window_unrealize (GtkWidget *widget)
4972 GtkWindow *window = GTK_WINDOW (widget);
4973 GtkWindowPrivate *priv = window->priv;
4974 GtkWindowGeometryInfo *info;
4976 /* On unrealize, we reset the size of the window such
4977 * that we will re-apply the default sizing stuff
4978 * next time we show the window.
4980 * Default positioning is reset on unmap, instead of unrealize.
4982 priv->need_default_size = TRUE;
4983 info = gtk_window_get_geometry_info (window, FALSE);
4986 info->resize_width = -1;
4987 info->resize_height = -1;
4988 info->last.configure_request.x = 0;
4989 info->last.configure_request.y = 0;
4990 info->last.configure_request.width = -1;
4991 info->last.configure_request.height = -1;
4992 /* be sure we reset geom hints on re-realize */
4993 info->last.flags = 0;
4998 gdk_window_set_user_data (priv->frame, NULL);
4999 gdk_window_destroy (priv->frame);
5004 gtk_window_unrealize_icon (window);
5006 if (priv->grip_window != NULL)
5007 resize_grip_destroy_window (window);
5009 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5012 static GdkWindowEdge
5013 get_grip_edge (GtkWidget *widget)
5015 return gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR
5016 ? GDK_WINDOW_EDGE_SOUTH_EAST
5017 : GDK_WINDOW_EDGE_SOUTH_WEST;
5021 get_drag_edge (GtkWidget *widget,
5022 GdkWindowEdge *edge)
5024 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5025 gboolean hresizable;
5026 gboolean vresizable;
5027 GtkTextDirection dir;
5028 GtkWindowGeometryInfo *info;
5033 info = priv->geometry_info;
5036 GdkWindowHints flags = info->last.flags;
5037 GdkGeometry *geometry = &info->last.geometry;
5039 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5041 hresizable = geometry->min_width < geometry->max_width;
5042 vresizable = geometry->min_height < geometry->max_height;
5046 dir = gtk_widget_get_direction (widget);
5048 if (hresizable && vresizable)
5049 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5050 else if (hresizable)
5051 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5052 else if (vresizable)
5053 *edge = GDK_WINDOW_EDGE_SOUTH;
5061 set_grip_cursor (GtkWindow *window)
5063 GtkWidget *widget = GTK_WIDGET (window);
5064 GtkWindowPrivate *priv = window->priv;
5066 if (priv->grip_window == NULL)
5069 if (gtk_widget_is_sensitive (widget))
5072 GdkDisplay *display;
5073 GdkCursorType cursor_type;
5076 cursor_type = GDK_LEFT_PTR;
5078 if (get_drag_edge (widget, &edge))
5082 case GDK_WINDOW_EDGE_EAST:
5083 cursor_type = GDK_RIGHT_SIDE;
5085 case GDK_WINDOW_EDGE_SOUTH_EAST:
5086 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5088 case GDK_WINDOW_EDGE_SOUTH:
5089 cursor_type = GDK_BOTTOM_SIDE;
5091 case GDK_WINDOW_EDGE_SOUTH_WEST:
5092 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5094 case GDK_WINDOW_EDGE_WEST:
5095 cursor_type = GDK_LEFT_SIDE;
5101 display = gtk_widget_get_display (widget);
5102 cursor = gdk_cursor_new_for_display (display, cursor_type);
5103 gdk_window_set_cursor (priv->grip_window, cursor);
5104 gdk_cursor_unref (cursor);
5107 gdk_window_set_cursor (priv->grip_window, NULL);
5111 set_grip_shape (GtkWindow *window)
5113 GtkWindowPrivate *priv = window->priv;
5114 cairo_region_t *region;
5115 cairo_surface_t *surface;
5117 double width, height;
5119 if (priv->grip_window == NULL)
5122 width = gdk_window_get_width (priv->grip_window);
5123 height = gdk_window_get_height (priv->grip_window);
5124 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5126 cr = cairo_create (surface);
5127 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5129 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5130 if (get_grip_edge (GTK_WIDGET (window)) == GDK_WINDOW_EDGE_SOUTH_EAST)
5132 cairo_move_to (cr, width, 0.0);
5133 cairo_line_to (cr, width, height);
5134 cairo_line_to (cr, 0.0, height);
5138 cairo_move_to (cr, 0.0, 0.0);
5139 cairo_line_to (cr, width, height);
5140 cairo_line_to (cr, 0.0, height);
5142 cairo_close_path (cr);
5145 region = gdk_cairo_region_create_from_surface (surface);
5146 cairo_surface_destroy (surface);
5148 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5149 cairo_region_destroy (region);
5153 set_grip_position (GtkWindow *window)
5155 GtkWindowPrivate *priv = window->priv;
5158 if (priv->grip_window == NULL)
5161 gtk_window_get_resize_grip_area (window, &rect);
5162 gdk_window_raise (priv->grip_window);
5163 gdk_window_move_resize (priv->grip_window,
5165 rect.width, rect.height);
5169 gtk_window_size_allocate (GtkWidget *widget,
5170 GtkAllocation *allocation)
5172 GtkWindow *window = GTK_WINDOW (widget);
5173 GtkWindowPrivate *priv = window->priv;
5174 GtkAllocation child_allocation;
5178 gtk_widget_set_allocation (widget, allocation);
5180 child = gtk_bin_get_child (&(window->bin));
5181 if (child && gtk_widget_get_visible (child))
5183 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5184 child_allocation.x = border_width;
5185 child_allocation.y = border_width;
5186 child_allocation.width =
5187 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5188 child_allocation.height =
5189 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5191 gtk_widget_size_allocate (child, &child_allocation);
5194 if (gtk_widget_get_realized (widget))
5197 gdk_window_resize (priv->frame,
5198 allocation->width + priv->frame_left + priv->frame_right,
5199 allocation->height + priv->frame_top + priv->frame_bottom);
5200 update_grip_visibility (window);
5201 set_grip_position (window);
5206 gtk_window_event (GtkWidget *widget, GdkEvent *event)
5208 GtkWindow *window = GTK_WINDOW (widget);
5209 GtkWindowPrivate *priv = window->priv;
5210 gboolean return_val;
5212 if (priv->frame && (event->any.window == priv->frame))
5214 if ((event->type != GDK_KEY_PRESS) &&
5215 (event->type != GDK_KEY_RELEASE) &&
5216 (event->type != GDK_FOCUS_CHANGE))
5218 g_signal_stop_emission_by_name (widget, "event");
5220 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
5225 g_object_unref (event->any.window);
5226 event->any.window = g_object_ref (gtk_widget_get_window (widget));
5234 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
5236 GtkWindowPrivate *priv = window->priv;
5237 GdkEventConfigure *configure_event;
5240 switch (event->type)
5243 configure_event = (GdkEventConfigure *)event;
5245 /* Invalidate the decorations */
5248 rect.width = configure_event->width;
5249 rect.height = configure_event->height;
5251 gdk_window_invalidate_rect (priv->frame, &rect, FALSE);
5253 /* Pass on the (modified) configure event */
5254 configure_event->width -= priv->frame_left + priv->frame_right;
5255 configure_event->height -= priv->frame_top + priv->frame_bottom;
5256 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
5265 gtk_window_configure_event (GtkWidget *widget,
5266 GdkEventConfigure *event)
5268 GtkAllocation allocation;
5269 GtkWindow *window = GTK_WINDOW (widget);
5270 GtkWindowPrivate *priv = window->priv;
5271 gboolean expected_reply = priv->configure_request_count > 0;
5273 /* priv->configure_request_count incremented for each
5274 * configure request, and decremented to a min of 0 for
5275 * each configure notify.
5277 * All it means is that we know we will get at least
5278 * priv->configure_request_count more configure notifies.
5279 * We could get more configure notifies than that; some
5280 * of the configure notifies we get may be unrelated to
5281 * the configure requests. But we will get at least
5282 * priv->configure_request_count notifies.
5285 if (priv->configure_request_count > 0)
5287 priv->configure_request_count -= 1;
5288 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5291 /* As an optimization, we avoid a resize when possible.
5293 * The only times we can avoid a resize are:
5294 * - we know only the position changed, not the size
5295 * - we know we have made more requests and so will get more
5296 * notifies and can wait to resize when we get them
5298 gtk_widget_get_allocation (widget, &allocation);
5299 if (!expected_reply &&
5300 (allocation.width == event->width &&
5301 allocation.height == event->height))
5303 gdk_window_configure_finished (gtk_widget_get_window (widget));
5308 * If we do need to resize, we do that by:
5309 * - filling in widget->allocation with the new size
5310 * - setting configure_notify_received to TRUE
5311 * for use in gtk_window_move_resize()
5312 * - queueing a resize, leading to invocation of
5313 * gtk_window_move_resize() in an idle handler
5317 priv->configure_notify_received = TRUE;
5319 allocation.width = event->width;
5320 allocation.height = event->height;
5321 gtk_widget_set_allocation (widget, &allocation);
5323 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5325 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5331 gtk_window_state_event (GtkWidget *widget,
5332 GdkEventWindowState *event)
5334 update_grip_visibility (GTK_WINDOW (widget));
5340 gtk_window_direction_changed (GtkWidget *widget,
5341 GtkTextDirection prev_dir)
5343 GtkWindow *window = GTK_WINDOW (widget);
5345 set_grip_cursor (window);
5346 set_grip_position (window);
5347 set_grip_shape (window);
5351 gtk_window_state_changed (GtkWidget *widget,
5352 GtkStateType previous_state)
5354 GtkWindow *window = GTK_WINDOW (widget);
5356 update_grip_visibility (window);
5360 resize_grip_create_window (GtkWindow *window)
5363 GtkWindowPrivate *priv;
5364 GdkWindowAttr attributes;
5365 gint attributes_mask;
5368 priv = window->priv;
5369 widget = GTK_WIDGET (window);
5371 g_return_if_fail (gtk_widget_get_realized (widget));
5372 g_return_if_fail (priv->grip_window == NULL);
5374 gtk_window_get_resize_grip_area (window, &rect);
5376 attributes.x = rect.x;
5377 attributes.y = rect.y;
5378 attributes.width = rect.width;
5379 attributes.height = rect.height;
5380 attributes.window_type = GDK_WINDOW_CHILD;
5381 attributes.wclass = GDK_INPUT_OUTPUT;
5382 attributes.event_mask = gtk_widget_get_events (widget) |
5384 GDK_BUTTON_PRESS_MASK;
5386 attributes_mask = GDK_WA_X | GDK_WA_Y;
5388 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5392 gdk_window_set_user_data (priv->grip_window, widget);
5394 gdk_window_raise (priv->grip_window);
5396 set_grip_shape (window);
5397 update_grip_visibility (window);
5401 resize_grip_destroy_window (GtkWindow *window)
5403 GtkWindowPrivate *priv = window->priv;
5405 gdk_window_set_user_data (priv->grip_window, NULL);
5406 gdk_window_destroy (priv->grip_window);
5407 priv->grip_window = NULL;
5408 update_grip_visibility (window);
5412 * gtk_window_set_has_resize_grip:
5413 * @window: a #GtkWindow
5414 * @value: %TRUE to allow a resize grip
5416 * Sets whether @window has a corner resize grip.
5418 * Note that the resize grip is only shown if the window
5419 * is actually resizable and not maximized. Use
5420 * gtk_window_resize_grip_is_visible() to find out if the
5421 * resize grip is currently shown.
5426 gtk_window_set_has_resize_grip (GtkWindow *window,
5429 GtkWidget *widget = GTK_WIDGET (window);
5430 GtkWindowPrivate *priv = window->priv;
5432 value = value != FALSE;
5434 if (value != priv->has_resize_grip)
5436 priv->has_resize_grip = value;
5437 gtk_widget_queue_draw (widget);
5439 if (gtk_widget_get_realized (widget))
5441 if (priv->has_resize_grip && priv->grip_window == NULL)
5442 resize_grip_create_window (window);
5443 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5444 resize_grip_destroy_window (window);
5447 g_object_notify (G_OBJECT (window), "has-resize-grip");
5452 update_grip_visibility (GtkWindow *window)
5454 GtkWindowPrivate *priv = window->priv;
5457 val = gtk_window_resize_grip_is_visible (window);
5459 if (priv->grip_window != NULL)
5463 gdk_window_show (priv->grip_window);
5464 set_grip_cursor (window);
5468 gdk_window_hide (priv->grip_window);
5472 if (priv->resize_grip_visible != val)
5474 priv->resize_grip_visible = val;
5476 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5481 * gtk_window_resize_grip_is_visible:
5482 * @window: a #GtkWindow
5484 * Determines whether a resize grip is visible for the specified window.
5486 * Returns %TRUE if a resize grip exists and is visible.
5491 gtk_window_resize_grip_is_visible (GtkWindow *window)
5494 GtkWindowPrivate *priv;
5495 GdkWindowEdge *edge;
5497 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5499 priv = window->priv;
5500 widget = GTK_WIDGET (window);
5502 if (priv->type == GTK_WINDOW_POPUP)
5505 if (!priv->resizable)
5508 if (gtk_widget_get_realized (widget))
5510 GdkWindowState state;
5512 state = gdk_window_get_state (gtk_widget_get_window (widget));
5514 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5518 if (!get_drag_edge (widget, &edge))
5521 return window->priv->has_resize_grip;
5525 * gtk_window_get_has_resize_grip:
5526 * @window: a #GtkWindow
5528 * Determines whether the window may have a resize grip.
5530 * Returns: %TRUE if the window has a resize grip.
5535 gtk_window_get_has_resize_grip (GtkWindow *window)
5537 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5539 return window->priv->has_resize_grip;
5543 * gtk_window_get_resize_grip_area:
5544 * @window: a #GtkWindow
5545 * @rect: a pointer to a #GdkRectangle which we should store the
5548 * If a window has a resize grip, this will retrieve the grip
5549 * position, width and height into the specified #GdkRectangle.
5551 * Returns: %TRUE if the resize grip's area was retrieved.
5556 gtk_window_get_resize_grip_area (GtkWindow *window,
5559 GtkWidget *widget = GTK_WIDGET (window);
5560 GtkAllocation allocation;
5565 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5567 if (!window->priv->has_resize_grip)
5570 gtk_widget_get_allocation (widget, &allocation);
5571 style = gtk_widget_get_style (widget);
5573 gtk_widget_style_get (widget,
5574 "resize-grip-width", &grip_width,
5575 "resize-grip-height", &grip_height,
5578 if (grip_width > allocation.width)
5579 grip_width = allocation.width;
5581 if (grip_height > allocation.height)
5582 grip_height = allocation.height;
5584 rect->width = grip_width;
5585 rect->height = grip_height;
5586 rect->y = allocation.y + allocation.height - grip_height;
5588 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5589 rect->x = allocation.x + allocation.width - grip_width;
5591 rect->x = allocation.x;
5596 /* the accel_key and accel_mods fields of the key have to be setup
5597 * upon calling this function. it'll then return whether that key
5598 * is at all used as accelerator, and if so will OR in the
5599 * accel_flags member of the key.
5602 _gtk_window_query_nonaccels (GtkWindow *window,
5604 GdkModifierType accel_mods)
5606 GtkWindowPrivate *priv;
5608 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5610 priv = window->priv;
5612 /* movement keys are considered locked accels */
5615 static const guint bindings[] = {
5616 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,
5617 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,
5621 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5622 if (bindings[i] == accel_key)
5626 /* mnemonics are considered locked accels */
5627 if (accel_mods == priv->mnemonic_modifier)
5629 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5630 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5638 * gtk_window_propagate_key_event:
5639 * @window: a #GtkWindow
5640 * @event: a #GdkEventKey
5642 * Propagate a key press or release event to the focus widget and
5643 * up the focus container chain until a widget handles @event.
5644 * This is normally called by the default ::key_press_event and
5645 * ::key_release_event handlers for toplevel windows,
5646 * however in some cases it may be useful to call this directly when
5647 * overriding the standard key handling for a toplevel window.
5649 * Return value: %TRUE if a widget in the focus chain handled the event.
5654 gtk_window_propagate_key_event (GtkWindow *window,
5657 GtkWindowPrivate *priv;
5658 gboolean handled = FALSE;
5659 GtkWidget *widget, *focus;
5661 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5663 priv = window->priv;
5664 widget = GTK_WIDGET (window);
5666 focus = priv->focus_widget;
5668 g_object_ref (focus);
5671 focus && focus != widget &&
5672 gtk_widget_get_toplevel (focus) == widget)
5676 if (gtk_widget_is_sensitive (focus))
5677 handled = gtk_widget_event (focus, (GdkEvent*) event);
5679 parent = gtk_widget_get_parent (focus);
5681 g_object_ref (parent);
5683 g_object_unref (focus);
5689 g_object_unref (focus);
5695 gtk_window_key_press_event (GtkWidget *widget,
5698 GtkWindow *window = GTK_WINDOW (widget);
5699 gboolean handled = FALSE;
5701 /* handle mnemonics and accelerators */
5703 handled = gtk_window_activate_key (window, event);
5705 /* handle focus widget key events */
5707 handled = gtk_window_propagate_key_event (window, event);
5709 /* Chain up, invokes binding set */
5711 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5717 gtk_window_key_release_event (GtkWidget *widget,
5720 GtkWindow *window = GTK_WINDOW (widget);
5721 gboolean handled = FALSE;
5723 /* handle focus widget key events */
5725 handled = gtk_window_propagate_key_event (window, event);
5727 /* Chain up, invokes binding set */
5729 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5735 gtk_window_button_press_event (GtkWidget *widget,
5736 GdkEventButton *event)
5738 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5741 if (event->window == priv->grip_window)
5743 if (get_drag_edge (widget, &edge))
5744 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5758 gtk_window_real_activate_default (GtkWindow *window)
5760 gtk_window_activate_default (window);
5764 gtk_window_real_activate_focus (GtkWindow *window)
5766 gtk_window_activate_focus (window);
5770 gtk_window_move_focus (GtkWindow *window,
5771 GtkDirectionType dir)
5773 gtk_widget_child_focus (GTK_WIDGET (window), dir);
5775 if (!gtk_container_get_focus_child (GTK_CONTAINER (window)))
5776 gtk_window_set_focus (window, NULL);
5780 gtk_window_enter_notify_event (GtkWidget *widget,
5781 GdkEventCrossing *event)
5787 gtk_window_leave_notify_event (GtkWidget *widget,
5788 GdkEventCrossing *event)
5794 do_focus_change (GtkWidget *widget,
5798 GdkDeviceManager *device_manager;
5801 g_object_ref (widget);
5803 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5804 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5805 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5806 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5808 for (d = devices; d; d = d->next)
5810 GdkDevice *dev = d->data;
5813 if (dev->source != GDK_SOURCE_KEYBOARD)
5816 /* Skip non-master keyboards that haven't
5817 * selected for events from this window
5819 window = gtk_widget_get_window (widget);
5820 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5821 window && !gdk_window_get_device_events (window, dev))
5824 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5826 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5827 fevent->focus_change.window = window;
5829 g_object_ref (window);
5830 fevent->focus_change.in = in;
5831 gdk_event_set_device (fevent, dev);
5833 gtk_widget_send_focus_change (widget, fevent);
5835 gdk_event_free (fevent);
5838 g_list_free (devices);
5839 g_object_unref (widget);
5843 gtk_window_focus_in_event (GtkWidget *widget,
5844 GdkEventFocus *event)
5846 GtkWindow *window = GTK_WINDOW (widget);
5848 /* It appears spurious focus in events can occur when
5849 * the window is hidden. So we'll just check to see if
5850 * the window is visible before actually handling the
5853 if (gtk_widget_get_visible (widget))
5855 _gtk_window_set_has_toplevel_focus (window, TRUE);
5856 _gtk_window_set_is_active (window, TRUE);
5863 gtk_window_focus_out_event (GtkWidget *widget,
5864 GdkEventFocus *event)
5866 GtkWindow *window = GTK_WINDOW (widget);
5867 gboolean auto_mnemonics;
5869 _gtk_window_set_has_toplevel_focus (window, FALSE);
5870 _gtk_window_set_is_active (window, FALSE);
5872 /* set the mnemonic-visible property to false */
5873 g_object_get (gtk_widget_get_settings (widget),
5874 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5876 gtk_window_set_mnemonics_visible (window, FALSE);
5881 static GdkAtom atom_rcfiles = GDK_NONE;
5882 static GdkAtom atom_iconthemes = GDK_NONE;
5885 send_client_message_to_embedded_windows (GtkWidget *widget,
5886 GdkAtom message_type)
5888 GList *embedded_windows;
5890 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5891 if (embedded_windows)
5893 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5896 for (i = 0; i < 5; i++)
5897 send_event->client.data.l[i] = 0;
5898 send_event->client.data_format = 32;
5899 send_event->client.message_type = message_type;
5901 while (embedded_windows)
5903 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
5904 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5905 embedded_windows = embedded_windows->next;
5908 gdk_event_free (send_event);
5913 gtk_window_client_event (GtkWidget *widget,
5914 GdkEventClient *event)
5918 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5919 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5922 if (event->message_type == atom_rcfiles)
5924 send_client_message_to_embedded_windows (widget, atom_rcfiles);
5925 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
5928 if (event->message_type == atom_iconthemes)
5930 send_client_message_to_embedded_windows (widget, atom_iconthemes);
5931 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
5938 gtk_window_check_resize (GtkContainer *container)
5940 if (gtk_widget_get_visible (GTK_WIDGET (container)))
5941 gtk_window_move_resize (GTK_WINDOW (container));
5945 gtk_window_focus (GtkWidget *widget,
5946 GtkDirectionType direction)
5948 GtkWindowPrivate *priv;
5951 GtkContainer *container;
5953 GtkWidget *old_focus_child;
5956 container = GTK_CONTAINER (widget);
5957 window = GTK_WINDOW (widget);
5958 priv = window->priv;
5959 bin = GTK_BIN (widget);
5961 old_focus_child = gtk_container_get_focus_child (container);
5963 /* We need a special implementation here to deal properly with wrapping
5964 * around in the tab chain without the danger of going into an
5967 if (old_focus_child)
5969 if (gtk_widget_child_focus (old_focus_child, direction))
5973 if (priv->focus_widget)
5975 if (direction == GTK_DIR_LEFT ||
5976 direction == GTK_DIR_RIGHT ||
5977 direction == GTK_DIR_UP ||
5978 direction == GTK_DIR_DOWN)
5983 /* Wrapped off the end, clear the focus setting for the toplpevel */
5984 parent = gtk_widget_get_parent (priv->focus_widget);
5987 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5988 parent = gtk_widget_get_parent (parent);
5991 gtk_window_set_focus (GTK_WINDOW (container), NULL);
5994 /* Now try to focus the first widget in the window */
5995 child = gtk_bin_get_child (bin);
5998 if (gtk_widget_child_focus (child, direction))
6006 gtk_window_real_set_focus (GtkWindow *window,
6009 GtkWindowPrivate *priv = window->priv;
6010 GtkWidget *old_focus = priv->focus_widget;
6011 gboolean had_default = FALSE;
6012 gboolean focus_had_default = FALSE;
6013 gboolean old_focus_had_default = FALSE;
6017 g_object_ref (old_focus);
6018 g_object_freeze_notify (G_OBJECT (old_focus));
6019 old_focus_had_default = gtk_widget_has_default (old_focus);
6023 g_object_ref (focus);
6024 g_object_freeze_notify (G_OBJECT (focus));
6025 focus_had_default = gtk_widget_has_default (focus);
6028 if (priv->default_widget)
6029 had_default = gtk_widget_has_default (priv->default_widget);
6031 if (priv->focus_widget)
6033 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6034 (priv->focus_widget != priv->default_widget))
6036 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6037 gtk_widget_queue_draw (priv->focus_widget);
6039 if (priv->default_widget)
6040 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6043 priv->focus_widget = NULL;
6045 if (priv->has_focus)
6046 do_focus_change (old_focus, FALSE);
6048 g_object_notify (G_OBJECT (old_focus), "is-focus");
6051 /* The above notifications may have set a new focus widget,
6052 * if so, we don't want to override it.
6054 if (focus && !priv->focus_widget)
6056 priv->focus_widget = focus;
6058 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6059 (priv->focus_widget != priv->default_widget))
6061 if (gtk_widget_get_can_default (priv->focus_widget))
6062 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6064 if (priv->default_widget)
6065 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6068 if (priv->has_focus)
6069 do_focus_change (priv->focus_widget, TRUE);
6071 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6074 /* If the default widget changed, a redraw will have been queued
6075 * on the old and new default widgets by gtk_window_set_default(), so
6076 * we only have to worry about the case where it didn't change.
6077 * We'll sometimes queue a draw twice on the new widget but that
6080 if (priv->default_widget &&
6081 (had_default != gtk_widget_has_default (priv->default_widget)))
6082 gtk_widget_queue_draw (priv->default_widget);
6086 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6087 gtk_widget_queue_draw (old_focus);
6089 g_object_thaw_notify (G_OBJECT (old_focus));
6090 g_object_unref (old_focus);
6094 if (focus_had_default != gtk_widget_has_default (focus))
6095 gtk_widget_queue_draw (focus);
6097 g_object_thaw_notify (G_OBJECT (focus));
6098 g_object_unref (focus);
6104 gtk_window_get_preferred_width (GtkWidget *widget,
6112 window = GTK_WINDOW (widget);
6113 child = gtk_bin_get_child (GTK_BIN (window));
6115 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6116 *minimum_size = border_width * 2;
6117 *natural_size = border_width * 2;
6119 if (child && gtk_widget_get_visible (child))
6121 gint child_min, child_nat;
6122 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6124 *minimum_size += child_min;
6125 *natural_size += child_nat;
6130 gtk_window_get_preferred_height (GtkWidget *widget,
6138 window = GTK_WINDOW (widget);
6139 child = gtk_bin_get_child (GTK_BIN (window));
6141 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6142 *minimum_size = border_width * 2;
6143 *natural_size = border_width * 2;
6145 if (child && gtk_widget_get_visible (child))
6147 gint child_min, child_nat;
6148 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6150 *minimum_size += child_min;
6151 *natural_size += child_nat;
6157 * _gtk_window_unset_focus_and_default:
6158 * @window: a #GtkWindow
6159 * @widget: a widget inside of @window
6161 * Checks whether the focus and default widgets of @window are
6162 * @widget or a descendent of @widget, and if so, unset them.
6165 _gtk_window_unset_focus_and_default (GtkWindow *window,
6169 GtkWindowPrivate *priv = window->priv;
6173 g_object_ref (window);
6174 g_object_ref (widget);
6176 parent = gtk_widget_get_parent (widget);
6177 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6179 child = priv->focus_widget;
6181 while (child && child != widget)
6182 child = gtk_widget_get_parent (child);
6184 if (child == widget)
6185 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6188 child = priv->default_widget;
6190 while (child && child != widget)
6191 child = gtk_widget_get_parent (child);
6193 if (child == widget)
6194 gtk_window_set_default (window, NULL);
6196 g_object_unref (widget);
6197 g_object_unref (window);
6200 /*********************************
6201 * Functions related to resizing *
6202 *********************************/
6205 geometry_size_to_pixels (GdkGeometry *geometry,
6210 gint base_width = 0;
6211 gint base_height = 0;
6213 gint min_height = 0;
6215 gint height_inc = 1;
6217 if (flags & GDK_HINT_BASE_SIZE)
6219 base_width = geometry->base_width;
6220 base_height = geometry->base_height;
6222 if (flags & GDK_HINT_MIN_SIZE)
6224 min_width = geometry->min_width;
6225 min_height = geometry->min_height;
6227 if (flags & GDK_HINT_RESIZE_INC)
6229 width_inc = geometry->width_inc;
6230 height_inc = geometry->height_inc;
6234 *width = MAX (*width * width_inc + base_width, min_width);
6236 *height = MAX (*height * height_inc + base_height, min_height);
6239 /* This function doesn't constrain to geometry hints */
6241 gtk_window_compute_configure_request_size (GtkWindow *window,
6242 GdkGeometry *geometry,
6247 GtkWindowPrivate *priv = window->priv;
6248 GtkRequisition requisition;
6249 GtkWindowGeometryInfo *info;
6253 * - we've done a size request
6256 widget = GTK_WIDGET (window);
6258 info = gtk_window_get_geometry_info (window, FALSE);
6260 if (priv->need_default_size)
6262 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6264 /* Default to requisition */
6265 *width = requisition.width;
6266 *height = requisition.height;
6268 /* If window is empty so requests 0, default to random nonzero size */
6269 if (*width == 0 && *height == 0)
6275 /* Override requisition with default size */
6279 if (info->default_width > 0)
6280 *width = info->default_width;
6281 if (info->default_height > 0)
6282 *height = info->default_height;
6284 if (info->default_is_geometry)
6285 geometry_size_to_pixels (geometry, flags,
6286 info->default_width > 0 ? width : NULL,
6287 info->default_height > 0 ? height : NULL);
6292 GtkAllocation allocation;
6294 gtk_widget_get_allocation (widget, &allocation);
6296 /* Default to keeping current size */
6297 *width = allocation.width;
6298 *height = allocation.height;
6301 /* Override any size with gtk_window_resize() values */
6304 if (info->resize_width > 0)
6305 *width = info->resize_width;
6306 if (info->resize_height > 0)
6307 *height = info->resize_height;
6309 if (info->resize_is_geometry)
6310 geometry_size_to_pixels (geometry, flags,
6311 info->resize_width > 0 ? width : NULL,
6312 info->resize_height > 0 ? height : NULL);
6315 /* Don't ever request zero width or height, its not supported by
6316 gdk. The size allocation code will round it to 1 anyway but if
6317 we do it then the value returned from this function will is
6318 not comparable to the size allocation read from the GtkWindow. */
6319 *width = MAX (*width, 1);
6320 *height = MAX (*height, 1);
6323 static GtkWindowPosition
6324 get_effective_position (GtkWindow *window)
6326 GtkWindowPrivate *priv = window->priv;
6327 GtkWindowPosition pos = priv->position;
6329 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6330 (priv->transient_parent == NULL ||
6331 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6332 pos = GTK_WIN_POS_NONE;
6338 get_center_monitor_of_window (GtkWindow *window)
6340 /* We could try to sort out the relative positions of the monitors and
6341 * stuff, or we could just be losers and assume you have a row
6342 * or column of monitors.
6344 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6348 get_monitor_containing_pointer (GtkWindow *window)
6352 GdkScreen *window_screen;
6353 GdkScreen *pointer_screen;
6354 GdkDisplay *display;
6355 GdkDeviceManager *device_manager;
6358 window_screen = gtk_window_check_screen (window);
6359 display = gdk_screen_get_display (window_screen);
6360 device_manager = gdk_display_get_device_manager (display);
6361 pointer = gdk_device_manager_get_client_pointer (device_manager);
6363 gdk_display_get_device_state (display, pointer,
6367 if (pointer_screen == window_screen)
6368 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6376 center_window_on_monitor (GtkWindow *window,
6382 GdkRectangle monitor;
6385 monitor_num = get_monitor_containing_pointer (window);
6387 if (monitor_num == -1)
6388 monitor_num = get_center_monitor_of_window (window);
6390 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6391 monitor_num, &monitor);
6393 *x = (monitor.width - w) / 2 + monitor.x;
6394 *y = (monitor.height - h) / 2 + monitor.y;
6396 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6397 * and WM decorations.
6411 if (extent > clamp_extent)
6413 *base = clamp_base + clamp_extent/2 - extent/2;
6414 else if (*base < clamp_base)
6416 else if (*base + extent > clamp_base + clamp_extent)
6417 *base = clamp_base + clamp_extent - extent;
6421 clamp_window_to_rectangle (gint *x,
6425 const GdkRectangle *rect)
6427 #ifdef DEBUGGING_OUTPUT
6428 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);
6431 /* If it is too large, center it. If it fits on the monitor but is
6432 * partially outside, move it to the closest edge. Do this
6433 * separately in x and y directions.
6435 clamp (x, w, rect->x, rect->width);
6436 clamp (y, h, rect->y, rect->height);
6437 #ifdef DEBUGGING_OUTPUT
6438 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6444 gtk_window_compute_configure_request (GtkWindow *window,
6445 GdkRectangle *request,
6446 GdkGeometry *geometry,
6449 GtkWindowPrivate *priv = window->priv;
6450 GdkGeometry new_geometry;
6454 GtkWindowPosition pos;
6455 GtkWidget *parent_widget;
6456 GtkWindowGeometryInfo *info;
6460 widget = GTK_WIDGET (window);
6462 screen = gtk_window_check_screen (window);
6464 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6465 gtk_window_compute_configure_request_size (window,
6466 &new_geometry, new_flags,
6467 (guint *)&w, (guint *)&h);
6469 gtk_window_constrain_size (window,
6470 &new_geometry, new_flags,
6474 parent_widget = (GtkWidget*) priv->transient_parent;
6476 pos = get_effective_position (window);
6477 info = gtk_window_get_geometry_info (window, FALSE);
6479 /* by default, don't change position requested */
6482 x = info->last.configure_request.x;
6483 y = info->last.configure_request.y;
6492 if (priv->need_default_position)
6495 /* FIXME this all interrelates with window gravity.
6496 * For most of them I think we want to set GRAVITY_CENTER.
6498 * Not sure how to go about that.
6503 /* here we are only handling CENTER_ALWAYS
6504 * as it relates to default positioning,
6505 * where it's equivalent to simply CENTER
6507 case GTK_WIN_POS_CENTER_ALWAYS:
6508 case GTK_WIN_POS_CENTER:
6509 center_window_on_monitor (window, w, h, &x, &y);
6512 case GTK_WIN_POS_CENTER_ON_PARENT:
6514 GtkAllocation allocation;
6515 GdkWindow *gdk_window;
6517 GdkRectangle monitor;
6520 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6522 gdk_window = gtk_widget_get_window (parent_widget);
6524 if (gdk_window != NULL)
6525 monitor_num = gdk_screen_get_monitor_at_window (screen,
6530 gdk_window_get_origin (gdk_window,
6533 gtk_widget_get_allocation (parent_widget, &allocation);
6534 x = ox + (allocation.width - w) / 2;
6535 y = oy + (allocation.height - h) / 2;
6537 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6538 * WM decorations. If parent wasn't on a monitor, just
6541 if (monitor_num >= 0)
6543 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6544 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6549 case GTK_WIN_POS_MOUSE:
6551 gint screen_width = gdk_screen_get_width (screen);
6552 gint screen_height = gdk_screen_get_height (screen);
6554 GdkRectangle monitor;
6555 GdkDisplay *display;
6556 GdkDeviceManager *device_manager;
6558 GdkScreen *pointer_screen;
6561 display = gdk_screen_get_display (screen);
6562 device_manager = gdk_display_get_device_manager (display);
6563 pointer = gdk_device_manager_get_client_pointer (device_manager);
6565 gdk_display_get_device_state (display, pointer,
6569 if (pointer_screen == screen)
6570 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6576 x = CLAMP (x, 0, screen_width - w);
6577 y = CLAMP (y, 0, screen_height - h);
6579 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6580 * WM decorations. Don't try to figure out what's going
6581 * on if the mouse wasn't inside a monitor.
6583 if (monitor_num >= 0)
6585 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6586 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6594 } /* if (priv->need_default_position) */
6596 if (priv->need_default_position && info &&
6597 info->initial_pos_set)
6599 x = info->initial_x;
6600 y = info->initial_y;
6601 gtk_window_constrain_position (window, w, h, &x, &y);
6607 request->height = h;
6610 *geometry = new_geometry;
6616 gtk_window_constrain_position (GtkWindow *window,
6622 GtkWindowPrivate *priv = window->priv;
6624 /* See long comments in gtk_window_move_resize()
6625 * on when it's safe to call this function.
6627 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6629 gint center_x, center_y;
6631 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6639 gtk_window_move_resize (GtkWindow *window)
6643 * First we determine whether any information has changed that would
6644 * cause us to revise our last configure request. If we would send
6645 * a different configure request from last time, then
6646 * configure_request_size_changed = TRUE or
6647 * configure_request_pos_changed = TRUE. configure_request_size_changed
6648 * may be true due to new hints, a gtk_window_resize(), or whatever.
6649 * configure_request_pos_changed may be true due to gtk_window_set_position()
6650 * or gtk_window_move().
6652 * If the configure request has changed, we send off a new one. To
6653 * ensure GTK+ invariants are maintained (resize queue does what it
6654 * should), we go ahead and size_allocate the requested size in this
6657 * If the configure request has not changed, we don't ever resend
6658 * it, because it could mean fighting the user or window manager.
6661 * To prepare the configure request, we come up with a base size/pos:
6662 * - the one from gtk_window_move()/gtk_window_resize()
6663 * - else default_width, default_height if we haven't ever
6665 * - else the size request if we haven't ever been mapped,
6666 * as a substitute default size
6667 * - else the current size of the window, as received from
6668 * configure notifies (i.e. the current allocation)
6670 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6671 * the position request to be centered.
6673 GtkWindowPrivate *priv = window->priv;
6674 GtkAllocation allocation;
6676 GtkContainer *container;
6677 GtkWindowGeometryInfo *info;
6678 GdkGeometry new_geometry;
6679 GdkWindow *gdk_window;
6681 GdkRectangle new_request;
6682 gboolean configure_request_size_changed;
6683 gboolean configure_request_pos_changed;
6684 gboolean hints_changed; /* do we need to send these again */
6685 GtkWindowLastGeometryInfo saved_last_info;
6687 widget = GTK_WIDGET (window);
6688 gdk_window = gtk_widget_get_window (widget);
6689 container = GTK_CONTAINER (widget);
6690 info = gtk_window_get_geometry_info (window, TRUE);
6692 configure_request_size_changed = FALSE;
6693 configure_request_pos_changed = FALSE;
6695 gtk_window_compute_configure_request (window, &new_request,
6696 &new_geometry, &new_flags);
6698 /* This check implies the invariant that we never set info->last
6699 * without setting the hints and sending off a configure request.
6701 * If we change info->last without sending the request, we may
6704 if (info->last.configure_request.x != new_request.x ||
6705 info->last.configure_request.y != new_request.y)
6706 configure_request_pos_changed = TRUE;
6708 if ((info->last.configure_request.width != new_request.width ||
6709 info->last.configure_request.height != new_request.height))
6710 configure_request_size_changed = TRUE;
6712 hints_changed = FALSE;
6714 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6715 &new_geometry, new_flags))
6717 hints_changed = TRUE;
6720 /* Position Constraints
6721 * ====================
6723 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6724 * a default. The other POS_ values are used only when the
6725 * window is shown, not after that.
6727 * However, we can't implement a position constraint as
6728 * "anytime the window size changes, center the window"
6729 * because this may well end up fighting the WM or user. In
6730 * fact it gets in an infinite loop with at least one WM.
6732 * Basically, applications are in no way in a position to
6733 * constrain the position of a window, with one exception:
6734 * override redirect windows. (Really the intended purpose
6735 * of CENTER_ALWAYS anyhow, I would think.)
6737 * So the way we implement this "constraint" is to say that when WE
6738 * cause a move or resize, i.e. we make a configure request changing
6739 * window size, we recompute the CENTER_ALWAYS position to reflect
6740 * the new window size, and include it in our request. Also, if we
6741 * just turned on CENTER_ALWAYS we snap to center with a new
6742 * request. Otherwise, if we are just NOTIFIED of a move or resize
6743 * done by someone else e.g. the window manager, we do NOT send a
6744 * new configure request.
6746 * For override redirect windows, this works fine; all window
6747 * sizes are from our configure requests. For managed windows,
6748 * it is at least semi-sane, though who knows what the
6749 * app author is thinking.
6752 /* This condition should be kept in sync with the condition later on
6753 * that determines whether we send a configure request. i.e. we
6754 * should do this position constraining anytime we were going to
6755 * send a configure request anyhow, plus when constraints have
6758 if (configure_request_pos_changed ||
6759 configure_request_size_changed ||
6761 info->position_constraints_changed)
6763 /* We request the constrained position if:
6764 * - we were changing position, and need to clamp
6765 * the change to the constraint
6766 * - we're changing the size anyway
6767 * - set_position() was called to toggle CENTER_ALWAYS on
6770 gtk_window_constrain_position (window,
6776 /* Update whether we need to request a move */
6777 if (info->last.configure_request.x != new_request.x ||
6778 info->last.configure_request.y != new_request.y)
6779 configure_request_pos_changed = TRUE;
6781 configure_request_pos_changed = FALSE;
6785 if (priv->type == GTK_WINDOW_TOPLEVEL)
6787 int notify_x, notify_y;
6789 /* this is the position from the last configure notify */
6790 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6792 g_message ("--- %s ---\n"
6793 "last : %d,%d\t%d x %d\n"
6794 "this : %d,%d\t%d x %d\n"
6795 "alloc : %d,%d\t%d x %d\n"
6797 "resize: \t%d x %d\n"
6798 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6799 "configure_notify_received: %d\n"
6800 "configure_request_count: %d\n"
6801 "position_constraints_changed: %d\n",
6802 priv->title ? priv->title : "(no title)",
6803 info->last.configure_request.x,
6804 info->last.configure_request.y,
6805 info->last.configure_request.width,
6806 info->last.configure_request.height,
6812 widget->allocation.width,
6813 widget->allocation.height,
6814 widget->requisition.width,
6815 widget->requisition.height,
6817 info->resize_height,
6818 configure_request_pos_changed,
6819 configure_request_size_changed,
6821 priv->configure_notify_received,
6822 priv->configure_request_count,
6823 info->position_constraints_changed);
6827 saved_last_info = info->last;
6828 info->last.geometry = new_geometry;
6829 info->last.flags = new_flags;
6830 info->last.configure_request = new_request;
6832 /* need to set PPosition so the WM will look at our position,
6833 * but we don't want to count PPosition coming and going as a hints
6834 * change for future iterations. So we saved info->last prior to
6838 /* Also, if the initial position was explicitly set, then we always
6839 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6843 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6844 * this is an initial map
6847 if ((configure_request_pos_changed ||
6848 info->initial_pos_set ||
6849 (priv->need_default_position &&
6850 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6851 (new_flags & GDK_HINT_POS) == 0)
6853 new_flags |= GDK_HINT_POS;
6854 hints_changed = TRUE;
6857 /* Set hints if necessary
6860 gdk_window_set_geometry_hints (gdk_window,
6864 gtk_widget_get_allocation (widget, &allocation);
6866 /* handle resizing/moving and widget tree allocation
6868 if (priv->configure_notify_received)
6870 /* If we have received a configure event since
6871 * the last time in this function, we need to
6872 * accept our new size and size_allocate child widgets.
6873 * (see gtk_window_configure_event() for more details).
6875 * 1 or more configure notifies may have been received.
6876 * Also, configure_notify_received will only be TRUE
6877 * if all expected configure notifies have been received
6878 * (one per configure request), as an optimization.
6881 priv->configure_notify_received = FALSE;
6883 /* gtk_window_configure_event() filled in widget->allocation */
6884 gtk_widget_size_allocate (widget, &allocation);
6886 set_grip_position (window);
6887 update_grip_visibility (window);
6889 gdk_window_process_updates (gdk_window, TRUE);
6891 gdk_window_configure_finished (gdk_window);
6893 /* If the configure request changed, it means that
6895 * 1) coincidentally changed hints or widget properties
6896 * impacting the configure request before getting
6897 * a configure notify, or
6898 * 2) some broken widget is changing its size request
6899 * during size allocation, resulting in
6900 * a false appearance of changed configure request.
6902 * For 1), we could just go ahead and ask for the
6903 * new size right now, but doing that for 2)
6904 * might well be fighting the user (and can even
6905 * trigger a loop). Since we really don't want to
6906 * do that, we requeue a resize in hopes that
6907 * by the time it gets handled, the child has seen
6908 * the light and is willing to go along with the
6909 * new size. (this happens for the zvt widget, since
6910 * the size_allocate() above will have stored the
6911 * requisition corresponding to the new size in the
6914 * This doesn't buy us anything for 1), but it shouldn't
6915 * hurt us too badly, since it is what would have
6916 * happened if we had gotten the configure event before
6917 * the new size had been set.
6920 if (configure_request_size_changed ||
6921 configure_request_pos_changed)
6923 /* Don't change the recorded last info after all, because we
6924 * haven't actually updated to the new info yet - we decided
6925 * to postpone our configure request until later.
6927 info->last = saved_last_info;
6929 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6932 return; /* Bail out, we didn't really process the move/resize */
6934 else if ((configure_request_size_changed || hints_changed) &&
6935 (allocation.width != new_request.width || allocation.height != new_request.height))
6938 /* We are in one of the following situations:
6939 * A. configure_request_size_changed
6940 * our requisition has changed and we need a different window size,
6941 * so we request it from the window manager.
6942 * B. !configure_request_size_changed && hints_changed
6943 * the window manager rejects our size, but we have just changed the
6944 * window manager hints, so there's a chance our request will
6945 * be honoured this time, so we try again.
6947 * However, if the new requisition is the same as the current allocation,
6948 * we don't request it again, since we won't get a ConfigureNotify back from
6949 * the window manager unless it decides to change our requisition. If
6950 * we don't get the ConfigureNotify back, the resize queue will never be run.
6953 /* Now send the configure request */
6954 if (configure_request_pos_changed)
6958 gdk_window_move_resize (priv->frame,
6959 new_request.x - priv->frame_left,
6960 new_request.y - priv->frame_top,
6961 new_request.width + priv->frame_left + priv->frame_right,
6962 new_request.height + priv->frame_top + priv->frame_bottom);
6963 gdk_window_resize (gdk_window,
6964 new_request.width, new_request.height);
6967 gdk_window_move_resize (gdk_window,
6968 new_request.x, new_request.y,
6969 new_request.width, new_request.height);
6971 else /* only size changed */
6974 gdk_window_resize (priv->frame,
6975 new_request.width + priv->frame_left + priv->frame_right,
6976 new_request.height + priv->frame_top + priv->frame_bottom);
6977 gdk_window_resize (gdk_window,
6978 new_request.width, new_request.height);
6981 if (priv->type == GTK_WINDOW_POPUP)
6983 GtkAllocation allocation;
6985 /* Directly size allocate for override redirect (popup) windows. */
6988 allocation.width = new_request.width;
6989 allocation.height = new_request.height;
6991 gtk_widget_size_allocate (widget, &allocation);
6993 gdk_window_process_updates (gdk_window, TRUE);
6995 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6996 gtk_widget_queue_draw (widget);
7000 /* Increment the number of have-not-yet-received-notify requests */
7001 priv->configure_request_count += 1;
7002 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7004 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7005 * configure event in response to our resizing request.
7006 * the configure event will cause a new resize with
7007 * ->configure_notify_received=TRUE.
7008 * until then, we want to
7009 * - discard expose events
7010 * - coalesce resizes for our children
7011 * - defer any window resizes until the configure event arrived
7012 * to achieve this, we queue a resize for the window, but remove its
7013 * resizing handler, so resizing will not be handled from the next
7014 * idle handler but when the configure event arrives.
7016 * FIXME: we should also dequeue the pending redraws here, since
7017 * we handle those ourselves upon ->configure_notify_received==TRUE.
7019 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7021 gtk_widget_queue_resize_no_redraw (widget);
7022 _gtk_container_dequeue_resize_handler (container);
7028 /* Handle any position changes.
7030 if (configure_request_pos_changed)
7034 gdk_window_move (priv->frame,
7035 new_request.x - priv->frame_left,
7036 new_request.y - priv->frame_top);
7039 gdk_window_move (gdk_window,
7040 new_request.x, new_request.y);
7043 /* And run the resize queue.
7045 gtk_container_resize_children (container);
7048 /* We have now processed a move/resize since the last position
7049 * constraint change, setting of the initial position, or resize.
7050 * (Not resetting these flags here can lead to infinite loops for
7051 * GTK_RESIZE_IMMEDIATE containers)
7053 info->position_constraints_changed = FALSE;
7054 info->initial_pos_set = FALSE;
7055 info->resize_width = -1;
7056 info->resize_height = -1;
7059 /* Compare two sets of Geometry hints for equality.
7062 gtk_window_compare_hints (GdkGeometry *geometry_a,
7064 GdkGeometry *geometry_b,
7067 if (flags_a != flags_b)
7070 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7071 (geometry_a->min_width != geometry_b->min_width ||
7072 geometry_a->min_height != geometry_b->min_height))
7075 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7076 (geometry_a->max_width != geometry_b->max_width ||
7077 geometry_a->max_height != geometry_b->max_height))
7080 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7081 (geometry_a->base_width != geometry_b->base_width ||
7082 geometry_a->base_height != geometry_b->base_height))
7085 if ((flags_a & GDK_HINT_ASPECT) &&
7086 (geometry_a->min_aspect != geometry_b->min_aspect ||
7087 geometry_a->max_aspect != geometry_b->max_aspect))
7090 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7091 (geometry_a->width_inc != geometry_b->width_inc ||
7092 geometry_a->height_inc != geometry_b->height_inc))
7095 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7096 geometry_a->win_gravity != geometry_b->win_gravity)
7103 _gtk_window_constrain_size (GtkWindow *window,
7109 GtkWindowPrivate *priv;
7110 GtkWindowGeometryInfo *info;
7112 g_return_if_fail (GTK_IS_WINDOW (window));
7114 priv = window->priv;
7116 info = priv->geometry_info;
7119 GdkWindowHints flags = info->last.flags;
7120 GdkGeometry *geometry = &info->last.geometry;
7122 gtk_window_constrain_size (window,
7133 gtk_window_constrain_size (GtkWindow *window,
7134 GdkGeometry *geometry,
7141 gdk_window_constrain_size (geometry, flags, width, height,
7142 new_width, new_height);
7145 /* Compute the set of geometry hints and flags for a window
7146 * based on the application set geometry, and requisition
7147 * of the window. gtk_widget_get_preferred_size() must have been
7151 gtk_window_compute_hints (GtkWindow *window,
7152 GdkGeometry *new_geometry,
7155 GtkWindowPrivate *priv = window->priv;
7157 gint extra_width = 0;
7158 gint extra_height = 0;
7159 GtkWindowGeometryInfo *geometry_info;
7160 GtkRequisition requisition;
7162 widget = GTK_WIDGET (window);
7164 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7165 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7169 *new_flags = geometry_info->mask;
7170 *new_geometry = geometry_info->geometry;
7177 if (geometry_info && geometry_info->widget)
7179 /* If the geometry widget is set, then the hints really apply to that
7180 * widget. This is pretty much meaningless unless the window layout
7181 * is such that the rest of the window adds fixed size borders to
7182 * the geometry widget. Our job is to figure the size of the borders;
7183 * We do that by asking how big the toplevel would be if the
7184 * geometry widget was *really big*.
7187 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7188 * |GGGGG B| in the border can confuse things
7194 * |AAAAAAAAA | When the geometry widget is large, things are
7195 * |GGGGGGGGGGB| clearer.
7200 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7201 GtkRequisition requisition;
7202 int current_width, current_height;
7204 _gtk_widget_override_size_request (geometry_info->widget,
7205 TEMPORARY_SIZE, TEMPORARY_SIZE,
7206 ¤t_width, ¤t_height);
7207 gtk_widget_get_preferred_size (widget,
7208 &requisition, NULL);
7209 _gtk_widget_restore_size_request (geometry_info->widget,
7210 current_width, current_height);
7212 extra_width = requisition.width - TEMPORARY_SIZE;
7213 extra_height = requisition.height - TEMPORARY_SIZE;
7215 if (extra_width < 0 || extra_width < 0)
7217 g_warning("Toplevel size doesn't seem to directly depend on the "
7218 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7219 "The geometry widget might not be in the window, or it might not "
7220 "be packed into the window appropriately");
7221 extra_width = MAX(extra_width, 0);
7222 extra_height = MAX(extra_height, 0);
7224 #undef TEMPORARY_SIZE
7227 /* We don't want to set GDK_HINT_POS in here, we just set it
7228 * in gtk_window_move_resize() when we want the position
7232 if (*new_flags & GDK_HINT_BASE_SIZE)
7234 new_geometry->base_width += extra_width;
7235 new_geometry->base_height += extra_height;
7239 /* For simplicity, we always set the base hint, even when we
7240 * don't expect it to have any visible effect.
7241 * (Note: geometry_size_to_pixels() depends on this.)
7243 *new_flags |= GDK_HINT_BASE_SIZE;
7245 new_geometry->base_width = extra_width;
7246 new_geometry->base_height = extra_height;
7248 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7249 * base size is the minimum size */
7250 if (*new_flags & GDK_HINT_MIN_SIZE)
7252 if (new_geometry->min_width > 0)
7253 new_geometry->base_width += new_geometry->min_width;
7254 if (new_geometry->min_height > 0)
7255 new_geometry->base_height += new_geometry->min_height;
7259 if (*new_flags & GDK_HINT_MIN_SIZE)
7261 if (new_geometry->min_width < 0)
7262 new_geometry->min_width = requisition.width;
7264 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7266 if (new_geometry->min_height < 0)
7267 new_geometry->min_height = requisition.height;
7269 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7273 *new_flags |= GDK_HINT_MIN_SIZE;
7275 new_geometry->min_width = requisition.width;
7276 new_geometry->min_height = requisition.height;
7279 if (*new_flags & GDK_HINT_MAX_SIZE)
7281 if (new_geometry->max_width < 0)
7282 new_geometry->max_width = requisition.width;
7284 new_geometry->max_width += extra_width;
7286 if (new_geometry->max_height < 0)
7287 new_geometry->max_height = requisition.height;
7289 new_geometry->max_height += extra_height;
7291 else if (!priv->resizable)
7293 *new_flags |= GDK_HINT_MAX_SIZE;
7295 new_geometry->max_width = requisition.width;
7296 new_geometry->max_height = requisition.height;
7299 *new_flags |= GDK_HINT_WIN_GRAVITY;
7300 new_geometry->win_gravity = priv->gravity;
7303 /***********************
7304 * Redrawing functions *
7305 ***********************/
7308 gtk_window_draw (GtkWidget *widget,
7311 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7312 gboolean ret = FALSE;
7314 if (!gtk_widget_get_app_paintable (widget))
7315 gtk_paint_flat_box (gtk_widget_get_style (widget),
7318 GTK_SHADOW_NONE, widget, "base",
7320 gtk_widget_get_allocated_width (widget),
7321 gtk_widget_get_allocated_height (widget));
7323 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7324 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7326 if (priv->grip_window != NULL &&
7327 gtk_cairo_should_draw_window (cr, priv->grip_window))
7332 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7333 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7334 gtk_paint_resize_grip (gtk_widget_get_style (widget),
7336 gtk_widget_get_state (widget),
7339 get_grip_edge (widget),
7341 rect.width, rect.height);
7349 * gtk_window_set_has_frame:
7350 * @window: a #GtkWindow
7351 * @setting: a boolean
7353 * (Note: this is a special-purpose function for the framebuffer port,
7354 * that causes GTK+ to draw its own window border. For most applications,
7355 * you want gtk_window_set_decorated() instead, which tells the window
7356 * manager whether to draw the window border.)
7358 * If this function is called on a window with setting of %TRUE, before
7359 * it is realized or showed, it will have a "frame" window around
7360 * @window->window, accessible in @window->frame. Using the signal
7361 * frame_event you can receive all events targeted at the frame.
7363 * This function is used by the linux-fb port to implement managed
7364 * windows, but it could conceivably be used by X-programs that
7365 * want to do their own window decorations.
7369 gtk_window_set_has_frame (GtkWindow *window,
7372 GtkWindowPrivate *priv;
7374 g_return_if_fail (GTK_IS_WINDOW (window));
7375 g_return_if_fail (!gtk_widget_get_realized (GTK_WIDGET (window)));
7377 priv = window->priv;
7379 priv->has_frame = setting != FALSE;
7383 * gtk_window_get_has_frame:
7384 * @window: a #GtkWindow
7386 * Accessor for whether the window has a frame window exterior to
7387 * @window->window. Gets the value set by gtk_window_set_has_frame ().
7389 * Return value: %TRUE if a frame has been added to the window
7390 * via gtk_window_set_has_frame().
7393 gtk_window_get_has_frame (GtkWindow *window)
7395 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7397 return window->priv->has_frame;
7401 * gtk_window_set_frame_dimensions:
7402 * @window: a #GtkWindow that has a frame
7403 * @left: The width of the left border
7404 * @top: The height of the top border
7405 * @right: The width of the right border
7406 * @bottom: The height of the bottom border
7408 * (Note: this is a special-purpose function intended for the framebuffer
7409 * port; see gtk_window_set_has_frame(). It will have no effect on the
7410 * window border drawn by the window manager, which is the normal
7411 * case when using the X Window system.)
7413 * For windows with frames (see gtk_window_set_has_frame()) this function
7414 * can be used to change the size of the frame border.
7417 gtk_window_set_frame_dimensions (GtkWindow *window,
7423 GtkWindowPrivate *priv;
7424 GtkAllocation allocation;
7427 g_return_if_fail (GTK_IS_WINDOW (window));
7429 priv = window->priv;
7430 widget = GTK_WIDGET (window);
7432 if (priv->frame_left == left &&
7433 priv->frame_top == top &&
7434 priv->frame_right == right &&
7435 priv->frame_bottom == bottom)
7438 priv->frame_left = left;
7439 priv->frame_top = top;
7440 priv->frame_right = right;
7441 priv->frame_bottom = bottom;
7443 if (gtk_widget_get_realized (widget) && priv->frame)
7445 gtk_widget_get_allocation (widget, &allocation);
7447 gint width = allocation.width + left + right;
7448 gint height = allocation.height + top + bottom;
7449 gdk_window_resize (priv->frame, width, height);
7450 gtk_decorated_window_move_resize_window (window,
7458 * gtk_window_present:
7459 * @window: a #GtkWindow
7461 * Presents a window to the user. This may mean raising the window
7462 * in the stacking order, deiconifying it, moving it to the current
7463 * desktop, and/or giving it the keyboard focus, possibly dependent
7464 * on the user's platform, window manager, and preferences.
7466 * If @window is hidden, this function calls gtk_widget_show()
7469 * This function should be used when the user tries to open a window
7470 * that's already open. Say for example the preferences dialog is
7471 * currently open, and the user chooses Preferences from the menu
7472 * a second time; use gtk_window_present() to move the already-open dialog
7473 * where the user can see it.
7475 * If you are calling this function in response to a user interaction,
7476 * it is preferable to use gtk_window_present_with_time().
7480 gtk_window_present (GtkWindow *window)
7482 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7486 * gtk_window_present_with_time:
7487 * @window: a #GtkWindow
7488 * @timestamp: the timestamp of the user interaction (typically a
7489 * button or key press event) which triggered this call
7491 * Presents a window to the user in response to a user interaction.
7492 * If you need to present a window without a timestamp, use
7493 * gtk_window_present(). See gtk_window_present() for details.
7498 gtk_window_present_with_time (GtkWindow *window,
7502 GdkWindow *gdk_window;
7504 g_return_if_fail (GTK_IS_WINDOW (window));
7506 widget = GTK_WIDGET (window);
7508 if (gtk_widget_get_visible (widget))
7510 gdk_window = gtk_widget_get_window (widget);
7512 g_assert (gdk_window != NULL);
7514 gdk_window_show (gdk_window);
7516 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7517 if (timestamp == GDK_CURRENT_TIME)
7519 #ifdef GDK_WINDOWING_X11
7520 GdkDisplay *display;
7522 display = gtk_widget_get_display (GTK_WIDGET (window));
7523 timestamp = gdk_x11_display_get_user_time (display);
7525 timestamp = gtk_get_current_event_time ();
7529 gdk_window_focus (gdk_window, timestamp);
7533 gtk_widget_show (widget);
7538 * gtk_window_iconify:
7539 * @window: a #GtkWindow
7541 * Asks to iconify (i.e. minimize) the specified @window. Note that
7542 * you shouldn't assume the window is definitely iconified afterward,
7543 * because other entities (e.g. the user or <link
7544 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7545 * again, or there may not be a window manager in which case
7546 * iconification isn't possible, etc. But normally the window will end
7547 * up iconified. Just don't write code that crashes if not.
7549 * It's permitted to call this function before showing a window,
7550 * in which case the window will be iconified before it ever appears
7553 * You can track iconification via the "window-state-event" signal
7558 gtk_window_iconify (GtkWindow *window)
7560 GtkWindowPrivate *priv;
7562 GdkWindow *toplevel;
7564 g_return_if_fail (GTK_IS_WINDOW (window));
7566 priv = window->priv;
7567 widget = GTK_WIDGET (window);
7569 priv->iconify_initially = TRUE;
7572 toplevel = priv->frame;
7574 toplevel = gtk_widget_get_window (widget);
7576 if (toplevel != NULL)
7577 gdk_window_iconify (toplevel);
7581 * gtk_window_deiconify:
7582 * @window: a #GtkWindow
7584 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7585 * that you shouldn't assume the window is definitely deiconified
7586 * afterward, because other entities (e.g. the user or <link
7587 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7588 * again before your code which assumes deiconification gets to run.
7590 * You can track iconification via the "window-state-event" signal
7594 gtk_window_deiconify (GtkWindow *window)
7596 GtkWindowPrivate *priv;
7598 GdkWindow *toplevel;
7600 g_return_if_fail (GTK_IS_WINDOW (window));
7602 priv = window->priv;
7603 widget = GTK_WIDGET (window);
7605 priv->iconify_initially = FALSE;
7608 toplevel = priv->frame;
7610 toplevel = gtk_widget_get_window (widget);
7612 if (toplevel != NULL)
7613 gdk_window_deiconify (toplevel);
7618 * @window: a #GtkWindow
7620 * Asks to stick @window, which means that it will appear on all user
7621 * desktops. Note that you shouldn't assume the window is definitely
7622 * stuck afterward, because other entities (e.g. the user or <link
7623 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7624 * again, and some window managers do not support sticking
7625 * windows. But normally the window will end up stuck. Just don't
7626 * write code that crashes if not.
7628 * It's permitted to call this function before showing a window.
7630 * You can track stickiness via the "window-state-event" signal
7635 gtk_window_stick (GtkWindow *window)
7637 GtkWindowPrivate *priv;
7639 GdkWindow *toplevel;
7641 g_return_if_fail (GTK_IS_WINDOW (window));
7643 priv = window->priv;
7644 widget = GTK_WIDGET (window);
7646 priv->stick_initially = TRUE;
7649 toplevel = priv->frame;
7651 toplevel = gtk_widget_get_window (widget);
7653 if (toplevel != NULL)
7654 gdk_window_stick (toplevel);
7658 * gtk_window_unstick:
7659 * @window: a #GtkWindow
7661 * Asks to unstick @window, which means that it will appear on only
7662 * one of the user's desktops. Note that you shouldn't assume the
7663 * window is definitely unstuck afterward, because other entities
7664 * (e.g. the user or <link linkend="gtk-X11-arch">window
7665 * manager</link>) could stick it again. But normally the window will
7666 * end up stuck. Just don't write code that crashes if not.
7668 * You can track stickiness via the "window-state-event" signal
7673 gtk_window_unstick (GtkWindow *window)
7675 GtkWindowPrivate *priv;
7677 GdkWindow *toplevel;
7679 g_return_if_fail (GTK_IS_WINDOW (window));
7681 priv = window->priv;
7682 widget = GTK_WIDGET (window);
7684 priv->stick_initially = FALSE;
7687 toplevel = priv->frame;
7689 toplevel = gtk_widget_get_window (widget);
7691 if (toplevel != NULL)
7692 gdk_window_unstick (toplevel);
7696 * gtk_window_maximize:
7697 * @window: a #GtkWindow
7699 * Asks to maximize @window, so that it becomes full-screen. Note that
7700 * you shouldn't assume the window is definitely maximized afterward,
7701 * because other entities (e.g. the user or <link
7702 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7703 * again, and not all window managers support maximization. But
7704 * normally the window will end up maximized. Just don't write code
7705 * that crashes if not.
7707 * It's permitted to call this function before showing a window,
7708 * in which case the window will be maximized when it appears onscreen
7711 * You can track maximization via the "window-state-event" signal
7716 gtk_window_maximize (GtkWindow *window)
7718 GtkWindowPrivate *priv;
7720 GdkWindow *toplevel;
7722 g_return_if_fail (GTK_IS_WINDOW (window));
7724 priv = window->priv;
7725 widget = GTK_WIDGET (window);
7727 priv->maximize_initially = TRUE;
7730 toplevel = priv->frame;
7732 toplevel = gtk_widget_get_window (widget);
7734 if (toplevel != NULL)
7735 gdk_window_maximize (toplevel);
7739 * gtk_window_unmaximize:
7740 * @window: a #GtkWindow
7742 * Asks to unmaximize @window. Note that you shouldn't assume the
7743 * window is definitely unmaximized afterward, because other entities
7744 * (e.g. the user or <link linkend="gtk-X11-arch">window
7745 * manager</link>) could maximize it again, and not all window
7746 * managers honor requests to unmaximize. But normally the window will
7747 * end up unmaximized. Just don't write code that crashes if not.
7749 * You can track maximization via the "window-state-event" signal
7754 gtk_window_unmaximize (GtkWindow *window)
7756 GtkWindowPrivate *priv;
7758 GdkWindow *toplevel;
7760 g_return_if_fail (GTK_IS_WINDOW (window));
7762 priv = window->priv;
7763 widget = GTK_WIDGET (window);
7765 priv->maximize_initially = FALSE;
7768 toplevel = priv->frame;
7770 toplevel = gtk_widget_get_window (widget);
7772 if (toplevel != NULL)
7773 gdk_window_unmaximize (toplevel);
7777 * gtk_window_fullscreen:
7778 * @window: a #GtkWindow
7780 * Asks to place @window in the fullscreen state. Note that you
7781 * shouldn't assume the window is definitely full screen afterward,
7782 * because other entities (e.g. the user or <link
7783 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7784 * again, and not all window managers honor requests to fullscreen
7785 * windows. But normally the window will end up fullscreen. Just
7786 * don't write code that crashes if not.
7788 * You can track the fullscreen state via the "window-state-event" signal
7794 gtk_window_fullscreen (GtkWindow *window)
7796 GtkWindowPrivate *priv;
7798 GdkWindow *toplevel;
7800 g_return_if_fail (GTK_IS_WINDOW (window));
7802 priv = window->priv;
7803 widget = GTK_WIDGET (window);
7805 priv->fullscreen_initially = TRUE;
7808 toplevel = priv->frame;
7810 toplevel = gtk_widget_get_window (widget);
7812 if (toplevel != NULL)
7813 gdk_window_fullscreen (toplevel);
7817 * gtk_window_unfullscreen:
7818 * @window: a #GtkWindow
7820 * Asks to toggle off the fullscreen state for @window. Note that you
7821 * shouldn't assume the window is definitely not full screen
7822 * afterward, because other entities (e.g. the user or <link
7823 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7824 * again, and not all window managers honor requests to unfullscreen
7825 * windows. But normally the window will end up restored to its normal
7826 * state. Just don't write code that crashes if not.
7828 * You can track the fullscreen state via the "window-state-event" signal
7834 gtk_window_unfullscreen (GtkWindow *window)
7837 GdkWindow *toplevel;
7838 GtkWindowPrivate *priv;
7840 g_return_if_fail (GTK_IS_WINDOW (window));
7842 priv = window->priv;
7843 widget = GTK_WIDGET (window);
7845 priv->fullscreen_initially = FALSE;
7848 toplevel = priv->frame;
7850 toplevel = gtk_widget_get_window (widget);
7852 if (toplevel != NULL)
7853 gdk_window_unfullscreen (toplevel);
7857 * gtk_window_set_keep_above:
7858 * @window: a #GtkWindow
7859 * @setting: whether to keep @window above other windows
7861 * Asks to keep @window above, so that it stays on top. Note that
7862 * you shouldn't assume the window is definitely above afterward,
7863 * because other entities (e.g. the user or <link
7864 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7865 * and not all window managers support keeping windows above. But
7866 * normally the window will end kept above. Just don't write code
7867 * that crashes if not.
7869 * It's permitted to call this function before showing a window,
7870 * in which case the window will be kept above when it appears onscreen
7873 * You can track the above state via the "window-state-event" signal
7876 * Note that, according to the <ulink
7877 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7878 * Manager Hints</ulink> specification, the above state is mainly meant
7879 * for user preferences and should not be used by applications e.g. for
7880 * drawing attention to their dialogs.
7885 gtk_window_set_keep_above (GtkWindow *window,
7889 GtkWindowPrivate *priv;
7890 GdkWindow *toplevel;
7892 g_return_if_fail (GTK_IS_WINDOW (window));
7894 priv = window->priv;
7895 widget = GTK_WIDGET (window);
7897 priv->above_initially = setting != FALSE;
7899 priv->below_initially = FALSE;
7902 toplevel = priv->frame;
7904 toplevel = gtk_widget_get_window (widget);
7906 if (toplevel != NULL)
7907 gdk_window_set_keep_above (toplevel, setting);
7911 * gtk_window_set_keep_below:
7912 * @window: a #GtkWindow
7913 * @setting: whether to keep @window below other windows
7915 * Asks to keep @window below, so that it stays in bottom. Note that
7916 * you shouldn't assume the window is definitely below afterward,
7917 * because other entities (e.g. the user or <link
7918 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7919 * and not all window managers support putting windows below. But
7920 * normally the window will be kept below. Just don't write code
7921 * that crashes if not.
7923 * It's permitted to call this function before showing a window,
7924 * in which case the window will be kept below when it appears onscreen
7927 * You can track the below state via the "window-state-event" signal
7930 * Note that, according to the <ulink
7931 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7932 * Manager Hints</ulink> specification, the above state is mainly meant
7933 * for user preferences and should not be used by applications e.g. for
7934 * drawing attention to their dialogs.
7939 gtk_window_set_keep_below (GtkWindow *window,
7943 GtkWindowPrivate *priv;
7944 GdkWindow *toplevel;
7946 g_return_if_fail (GTK_IS_WINDOW (window));
7948 priv = window->priv;
7949 widget = GTK_WIDGET (window);
7951 priv->below_initially = setting != FALSE;
7953 priv->above_initially = FALSE;
7956 toplevel = priv->frame;
7958 toplevel = gtk_widget_get_window (widget);
7960 if (toplevel != NULL)
7961 gdk_window_set_keep_below (toplevel, setting);
7965 * gtk_window_set_resizable:
7966 * @window: a #GtkWindow
7967 * @resizable: %TRUE if the user can resize this window
7969 * Sets whether the user can resize a window. Windows are user resizable
7973 gtk_window_set_resizable (GtkWindow *window,
7976 GtkWindowPrivate *priv;
7978 g_return_if_fail (GTK_IS_WINDOW (window));
7980 priv = window->priv;
7982 resizable = (resizable != FALSE);
7984 if (priv->resizable != resizable)
7986 priv->resizable = (resizable != FALSE);
7988 update_grip_visibility (window);
7990 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7992 g_object_notify (G_OBJECT (window), "resizable");
7997 * gtk_window_get_resizable:
7998 * @window: a #GtkWindow
8000 * Gets the value set by gtk_window_set_resizable().
8002 * Return value: %TRUE if the user can resize the window
8005 gtk_window_get_resizable (GtkWindow *window)
8007 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8009 return window->priv->resizable;
8013 * gtk_window_set_gravity:
8014 * @window: a #GtkWindow
8015 * @gravity: window gravity
8017 * Window gravity defines the meaning of coordinates passed to
8018 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8021 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8022 * typically "do what you mean."
8026 gtk_window_set_gravity (GtkWindow *window,
8029 GtkWindowPrivate *priv;
8031 g_return_if_fail (GTK_IS_WINDOW (window));
8033 priv = window->priv;
8035 if (gravity != priv->gravity)
8037 priv->gravity = gravity;
8039 /* gtk_window_move_resize() will adapt gravity
8041 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8043 g_object_notify (G_OBJECT (window), "gravity");
8048 * gtk_window_get_gravity:
8049 * @window: a #GtkWindow
8051 * Gets the value set by gtk_window_set_gravity().
8053 * Return value: (transfer none): window gravity
8056 gtk_window_get_gravity (GtkWindow *window)
8058 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8060 return window->priv->gravity;
8064 * gtk_window_begin_resize_drag:
8065 * @window: a #GtkWindow
8066 * @button: mouse button that initiated the drag
8067 * @edge: position of the resize control
8068 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8069 * @root_y: Y position where the user clicked to initiate the drag
8070 * @timestamp: timestamp from the click event that initiated the drag
8072 * Starts resizing a window. This function is used if an application
8073 * has window resizing controls. When GDK can support it, the resize
8074 * will be done using the standard mechanism for the <link
8075 * linkend="gtk-X11-arch">window manager</link> or windowing
8076 * system. Otherwise, GDK will try to emulate window resizing,
8077 * potentially not all that well, depending on the windowing system.
8081 gtk_window_begin_resize_drag (GtkWindow *window,
8088 GtkWindowPrivate *priv;
8090 GdkWindow *toplevel;
8092 g_return_if_fail (GTK_IS_WINDOW (window));
8093 widget = GTK_WIDGET (window);
8094 g_return_if_fail (gtk_widget_get_visible (widget));
8096 priv = window->priv;
8099 toplevel = priv->frame;
8101 toplevel = gtk_widget_get_window (widget);
8103 gdk_window_begin_resize_drag (toplevel,
8110 * gtk_window_get_frame_dimensions:
8111 * @window: a #GtkWindow
8112 * @left: (out) (allow-none): location to store the width of the frame at the left, or %NULL
8113 * @top: (out) (allow-none): location to store the height of the frame at the top, or %NULL
8114 * @right: (out) (allow-none): location to store the width of the frame at the returns, or %NULL
8115 * @bottom: (out) (allow-none): location to store the height of the frame at the bottom, or %NULL
8117 * (Note: this is a special-purpose function intended for the
8118 * framebuffer port; see gtk_window_set_has_frame(). It will not
8119 * return the size of the window border drawn by the <link
8120 * linkend="gtk-X11-arch">window manager</link>, which is the normal
8121 * case when using a windowing system. See
8122 * gdk_window_get_frame_extents() to get the standard window border
8125 * Retrieves the dimensions of the frame window for this toplevel.
8126 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
8129 gtk_window_get_frame_dimensions (GtkWindow *window,
8135 GtkWindowPrivate *priv;
8137 g_return_if_fail (GTK_IS_WINDOW (window));
8139 priv = window->priv;
8142 *left = priv->frame_left;
8144 *top = priv->frame_top;
8146 *right = priv->frame_right;
8148 *bottom = priv->frame_bottom;
8152 * gtk_window_begin_move_drag:
8153 * @window: a #GtkWindow
8154 * @button: mouse button that initiated the drag
8155 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8156 * @root_y: Y position where the user clicked to initiate the drag
8157 * @timestamp: timestamp from the click event that initiated the drag
8159 * Starts moving a window. This function is used if an application has
8160 * window movement grips. When GDK can support it, the window movement
8161 * will be done using the standard mechanism for the <link
8162 * linkend="gtk-X11-arch">window manager</link> or windowing
8163 * system. Otherwise, GDK will try to emulate window movement,
8164 * potentially not all that well, depending on the windowing system.
8168 gtk_window_begin_move_drag (GtkWindow *window,
8174 GtkWindowPrivate *priv;
8176 GdkWindow *toplevel;
8178 g_return_if_fail (GTK_IS_WINDOW (window));
8179 widget = GTK_WIDGET (window);
8180 g_return_if_fail (gtk_widget_get_visible (widget));
8182 priv = window->priv;
8185 toplevel = priv->frame;
8187 toplevel = gtk_widget_get_window (widget);
8189 gdk_window_begin_move_drag (toplevel,
8196 * gtk_window_set_screen:
8197 * @window: a #GtkWindow.
8198 * @screen: a #GdkScreen.
8200 * Sets the #GdkScreen where the @window is displayed; if
8201 * the window is already mapped, it will be unmapped, and
8202 * then remapped on the new screen.
8207 gtk_window_set_screen (GtkWindow *window,
8210 GtkWindowPrivate *priv;
8212 GdkScreen *previous_screen;
8213 gboolean was_mapped;
8215 g_return_if_fail (GTK_IS_WINDOW (window));
8216 g_return_if_fail (GDK_IS_SCREEN (screen));
8218 priv = window->priv;
8220 if (screen == priv->screen)
8223 widget = GTK_WIDGET (window);
8225 previous_screen = priv->screen;
8226 was_mapped = gtk_widget_get_mapped (widget);
8229 gtk_widget_unmap (widget);
8230 if (gtk_widget_get_realized (widget))
8231 gtk_widget_unrealize (widget);
8233 gtk_window_free_key_hash (window);
8234 priv->screen = screen;
8235 gtk_widget_reset_rc_styles (widget);
8236 if (screen != previous_screen)
8238 g_signal_handlers_disconnect_by_func (previous_screen,
8239 gtk_window_on_composited_changed, window);
8240 g_signal_connect (screen, "composited-changed",
8241 G_CALLBACK (gtk_window_on_composited_changed), window);
8243 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8244 _gtk_widget_propagate_composited_changed (widget);
8246 g_object_notify (G_OBJECT (window), "screen");
8249 gtk_widget_map (widget);
8253 gtk_window_on_composited_changed (GdkScreen *screen,
8256 gtk_widget_queue_draw (GTK_WIDGET (window));
8258 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8262 gtk_window_check_screen (GtkWindow *window)
8264 GtkWindowPrivate *priv = window->priv;
8267 return priv->screen;
8270 g_warning ("Screen for GtkWindow not set; you must always set\n"
8271 "a screen for a GtkWindow before using the window");
8277 * gtk_window_get_screen:
8278 * @window: a #GtkWindow.
8280 * Returns the #GdkScreen associated with @window.
8282 * Return value: (transfer none): a #GdkScreen.
8287 gtk_window_get_screen (GtkWindow *window)
8289 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8291 return window->priv->screen;
8295 * gtk_window_is_active:
8296 * @window: a #GtkWindow
8298 * Returns whether the window is part of the current active toplevel.
8299 * (That is, the toplevel window receiving keystrokes.)
8300 * The return value is %TRUE if the window is active toplevel
8301 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8302 * You might use this function if you wanted to draw a widget
8303 * differently in an active window from a widget in an inactive window.
8304 * See gtk_window_has_toplevel_focus()
8306 * Return value: %TRUE if the window part of the current active window.
8311 gtk_window_is_active (GtkWindow *window)
8313 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8315 return window->priv->is_active;
8319 * gtk_window_has_toplevel_focus:
8320 * @window: a #GtkWindow
8322 * Returns whether the input focus is within this GtkWindow.
8323 * For real toplevel windows, this is identical to gtk_window_is_active(),
8324 * but for embedded windows, like #GtkPlug, the results will differ.
8326 * Return value: %TRUE if the input focus is within this GtkWindow
8331 gtk_window_has_toplevel_focus (GtkWindow *window)
8333 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8335 return window->priv->has_toplevel_focus;
8339 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8341 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8345 gtk_window_group_get_type (void)
8347 static GType window_group_type = 0;
8349 if (!window_group_type)
8351 const GTypeInfo window_group_info =
8353 sizeof (GtkWindowGroupClass),
8354 NULL, /* base_init */
8355 NULL, /* base_finalize */
8356 (GClassInitFunc) gtk_window_group_class_init,
8357 NULL, /* class_finalize */
8358 NULL, /* class_data */
8359 sizeof (GtkWindowGroup),
8360 0, /* n_preallocs */
8361 (GInstanceInitFunc) NULL,
8364 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
8365 &window_group_info, 0);
8368 return window_group_type;
8372 * gtk_window_group_new:
8374 * Creates a new #GtkWindowGroup object. Grabs added with
8375 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8377 * Return value: a new #GtkWindowGroup.
8380 gtk_window_group_new (void)
8382 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8386 window_group_cleanup_grabs (GtkWindowGroup *group,
8389 GtkWindowGroupPrivate *priv;
8390 GtkDeviceGrabInfo *info;
8392 GSList *to_remove = NULL;
8394 tmp_list = group->grabs;
8397 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8398 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8399 tmp_list = tmp_list->next;
8404 gtk_grab_remove (to_remove->data);
8405 g_object_unref (to_remove->data);
8406 to_remove = g_slist_delete_link (to_remove, to_remove);
8409 priv = GTK_WINDOW_GROUP_GET_PRIVATE (group);
8410 tmp_list = priv->device_grabs;
8414 info = tmp_list->data;
8416 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8417 to_remove = g_slist_prepend (to_remove, info);
8419 tmp_list = tmp_list->next;
8424 info = to_remove->data;
8426 gtk_device_grab_remove (info->widget, info->device);
8427 to_remove = g_slist_delete_link (to_remove, to_remove);
8432 * gtk_window_group_add_window:
8433 * @window_group: a #GtkWindowGroup
8434 * @window: the #GtkWindow to add
8436 * Adds a window to a #GtkWindowGroup.
8439 gtk_window_group_add_window (GtkWindowGroup *window_group,
8442 GtkWindowPrivate *priv;
8444 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8445 g_return_if_fail (GTK_IS_WINDOW (window));
8447 priv = window->priv;
8449 if (priv->group != window_group)
8451 g_object_ref (window);
8452 g_object_ref (window_group);
8455 gtk_window_group_remove_window (priv->group, window);
8457 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8459 priv->group = window_group;
8461 g_object_unref (window);
8466 * gtk_window_group_remove_window:
8467 * @window_group: a #GtkWindowGroup
8468 * @window: the #GtkWindow to remove
8470 * Removes a window from a #GtkWindowGroup.
8473 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8476 GtkWindowPrivate *priv;
8478 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8479 g_return_if_fail (GTK_IS_WINDOW (window));
8480 priv = window->priv;
8481 g_return_if_fail (priv->group == window_group);
8483 g_object_ref (window);
8485 window_group_cleanup_grabs (window_group, window);
8488 g_object_unref (window_group);
8489 g_object_unref (window);
8493 * gtk_window_group_list_windows:
8494 * @window_group: a #GtkWindowGroup
8496 * Returns a list of the #GtkWindows that belong to @window_group.
8498 * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
8499 * windows inside the group.
8504 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8506 GList *toplevels, *toplevel, *group_windows;
8508 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8510 group_windows = NULL;
8511 toplevels = gtk_window_list_toplevels ();
8513 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8515 GtkWindow *window = toplevel->data;
8517 if (window_group == window->priv->group)
8518 group_windows = g_list_prepend (group_windows, window);
8521 return g_list_reverse (group_windows);
8525 * gtk_window_get_group:
8526 * @window: (allow-none): a #GtkWindow, or %NULL
8528 * Returns the group for @window or the default group, if
8529 * @window is %NULL or if @window does not have an explicit
8532 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8537 gtk_window_get_group (GtkWindow *window)
8539 if (window && window->priv->group)
8540 return window->priv->group;
8543 static GtkWindowGroup *default_group = NULL;
8546 default_group = gtk_window_group_new ();
8548 return default_group;
8553 * gtk_window_has_group:
8554 * @window: a #GtkWindow
8556 * Returns whether @window has an explicit window group.
8558 * Return value: %TRUE if @window has an explicit window group.
8563 gtk_window_has_group (GtkWindow *window)
8565 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8567 return window->priv->group != NULL;
8571 * gtk_window_group_get_current_grab:
8572 * @window_group: a #GtkWindowGroup
8574 * Gets the current grab widget of the given group,
8575 * see gtk_grab_add().
8577 * Returns: the current grab widget of the group
8582 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8584 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8586 if (window_group->grabs)
8587 return GTK_WIDGET (window_group->grabs->data);
8592 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8595 gboolean block_others)
8597 GtkWindowGroupPrivate *priv;
8598 GtkDeviceGrabInfo *info;
8600 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8602 info = g_slice_new0 (GtkDeviceGrabInfo);
8603 info->widget = widget;
8604 info->device = device;
8605 info->block_others = block_others;
8607 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8611 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8615 GtkWindowGroupPrivate *priv;
8616 GtkDeviceGrabInfo *info;
8617 GSList *list, *node = NULL;
8618 GdkDevice *other_device;
8620 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8621 other_device = gdk_device_get_associated_device (device);
8622 list = priv->device_grabs;
8628 if (info->widget == widget &&
8629 (info->device == device ||
8630 info->device == other_device))
8643 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8644 g_slice_free (GtkDeviceGrabInfo, info);
8649 * gtk_window_group_get_current_device_grab:
8650 * @window_group: a #GtkWindowGroup
8651 * @device: a #GdkDevice
8653 * Returns the current grab widget for @device, or %NULL if none.
8655 * Returns: The grab widget, or %NULL
8660 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8663 GtkWindowGroupPrivate *priv;
8664 GtkDeviceGrabInfo *info;
8665 GdkDevice *other_device;
8668 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8669 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8671 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8672 list = priv->device_grabs;
8673 other_device = gdk_device_get_associated_device (device);
8680 if (info->device == device ||
8681 info->device == other_device)
8682 return info->widget;
8689 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8693 GtkWindowGroupPrivate *priv;
8694 GtkDeviceGrabInfo *info;
8695 GdkDevice *other_device;
8698 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8699 other_device = gdk_device_get_associated_device (device);
8700 list = priv->device_grabs;
8707 /* Look for blocking grabs on other device pairs
8708 * that have the passed widget within the GTK+ grab.
8710 if (info->block_others &&
8711 info->device != device &&
8712 info->device != other_device &&
8713 (info->widget == widget ||
8714 gtk_widget_is_ancestor (widget, info->widget)))
8722 Derived from XParseGeometry() in XFree86
8724 Copyright 1985, 1986, 1987,1998 The Open Group
8726 All Rights Reserved.
8728 The above copyright notice and this permission notice shall be included
8729 in all copies or substantial portions of the Software.
8731 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8732 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8733 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8734 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8735 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8736 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8737 OTHER DEALINGS IN THE SOFTWARE.
8739 Except as contained in this notice, the name of The Open Group shall
8740 not be used in advertising or otherwise to promote the sale, use or
8741 other dealings in this Software without prior written authorization
8742 from The Open Group.
8747 * XParseGeometry parses strings of the form
8748 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8749 * width, height, xoffset, and yoffset are unsigned integers.
8750 * Example: "=80x24+300-49"
8751 * The equal sign is optional.
8752 * It returns a bitmask that indicates which of the four values
8753 * were actually found in the string. For each value found,
8754 * the corresponding argument is updated; for each value
8755 * not found, the corresponding argument is left unchanged.
8758 /* The following code is from Xlib, and is minimally modified, so we
8759 * can track any upstream changes if required. Don't change this
8760 * code. Or if you do, put in a huge comment marking which thing
8765 read_int (gchar *string,
8773 else if (*string == '-')
8779 for (; (*string >= '0') && (*string <= '9'); string++)
8781 result = (result * 10) + (*string - '0');
8793 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8794 * value (x, y, width, height) was found in the parsed string.
8796 #define NoValue 0x0000
8797 #define XValue 0x0001
8798 #define YValue 0x0002
8799 #define WidthValue 0x0004
8800 #define HeightValue 0x0008
8801 #define AllValues 0x000F
8802 #define XNegative 0x0010
8803 #define YNegative 0x0020
8805 /* Try not to reformat/modify, so we can compare/sync with X sources */
8807 gtk_XParseGeometry (const char *string,
8810 unsigned int *width,
8811 unsigned int *height)
8815 unsigned int tempWidth, tempHeight;
8817 char *nextCharacter;
8819 /* These initializations are just to silence gcc */
8825 if ( (string == NULL) || (*string == '\0')) return(mask);
8827 string++; /* ignore possible '=' at beg of geometry spec */
8829 strind = (char *)string;
8830 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8831 tempWidth = read_int(strind, &nextCharacter);
8832 if (strind == nextCharacter)
8834 strind = nextCharacter;
8838 if (*strind == 'x' || *strind == 'X') {
8840 tempHeight = read_int(strind, &nextCharacter);
8841 if (strind == nextCharacter)
8843 strind = nextCharacter;
8844 mask |= HeightValue;
8847 if ((*strind == '+') || (*strind == '-')) {
8848 if (*strind == '-') {
8850 tempX = -read_int(strind, &nextCharacter);
8851 if (strind == nextCharacter)
8853 strind = nextCharacter;
8859 tempX = read_int(strind, &nextCharacter);
8860 if (strind == nextCharacter)
8862 strind = nextCharacter;
8865 if ((*strind == '+') || (*strind == '-')) {
8866 if (*strind == '-') {
8868 tempY = -read_int(strind, &nextCharacter);
8869 if (strind == nextCharacter)
8871 strind = nextCharacter;
8878 tempY = read_int(strind, &nextCharacter);
8879 if (strind == nextCharacter)
8881 strind = nextCharacter;
8887 /* If strind isn't at the end of the string the it's an invalid
8888 geometry specification. */
8890 if (*strind != '\0') return (0);
8896 if (mask & WidthValue)
8898 if (mask & HeightValue)
8899 *height = tempHeight;
8904 * gtk_window_parse_geometry:
8905 * @window: a #GtkWindow
8906 * @geometry: geometry string
8908 * Parses a standard X Window System geometry string - see the
8909 * manual page for X (type 'man X') for details on this.
8910 * gtk_window_parse_geometry() does work on all GTK+ ports
8911 * including Win32 but is primarily intended for an X environment.
8913 * If either a size or a position can be extracted from the
8914 * geometry string, gtk_window_parse_geometry() returns %TRUE
8915 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8916 * to resize/move the window.
8918 * If gtk_window_parse_geometry() returns %TRUE, it will also
8919 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8920 * indicating to the window manager that the size/position of
8921 * the window was user-specified. This causes most window
8922 * managers to honor the geometry.
8924 * Note that for gtk_window_parse_geometry() to work as expected, it has
8925 * to be called when the window has its "final" size, i.e. after calling
8926 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8929 * #include <gtk/gtk.h>
8932 * fill_with_content (GtkWidget *vbox)
8934 * /* fill with content... */
8938 * main (int argc, char *argv[])
8940 * GtkWidget *window, *vbox;
8941 * GdkGeometry size_hints = {
8942 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8945 * gtk_init (&argc, &argv);
8947 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8948 * vbox = gtk_vbox_new (FALSE, 0);
8950 * gtk_container_add (GTK_CONTAINER (window), vbox);
8951 * fill_with_content (vbox);
8952 * gtk_widget_show_all (vbox);
8954 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8957 * GDK_HINT_MIN_SIZE |
8958 * GDK_HINT_BASE_SIZE |
8959 * GDK_HINT_RESIZE_INC);
8963 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8964 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8967 * gtk_widget_show_all (window);
8974 * Return value: %TRUE if string was parsed successfully
8977 gtk_window_parse_geometry (GtkWindow *window,
8978 const gchar *geometry)
8980 gint result, x = 0, y = 0;
8984 gboolean size_set, pos_set;
8987 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8988 g_return_val_if_fail (geometry != NULL, FALSE);
8990 child = gtk_bin_get_child (GTK_BIN (window));
8991 if (!child || !gtk_widget_get_visible (child))
8992 g_warning ("gtk_window_parse_geometry() called on a window with no "
8993 "visible children; the window should be set up before "
8994 "gtk_window_parse_geometry() is called.");
8996 screen = gtk_window_check_screen (window);
8998 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9001 if ((result & WidthValue) || (result & HeightValue))
9003 gtk_window_set_default_size_internal (window,
9004 TRUE, result & WidthValue ? w : -1,
9005 TRUE, result & HeightValue ? h : -1,
9010 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9012 grav = GDK_GRAVITY_NORTH_WEST;
9014 if ((result & XNegative) && (result & YNegative))
9015 grav = GDK_GRAVITY_SOUTH_EAST;
9016 else if (result & XNegative)
9017 grav = GDK_GRAVITY_NORTH_EAST;
9018 else if (result & YNegative)
9019 grav = GDK_GRAVITY_SOUTH_WEST;
9021 if ((result & XValue) == 0)
9024 if ((result & YValue) == 0)
9027 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9028 grav == GDK_GRAVITY_SOUTH_EAST)
9029 y = gdk_screen_get_height (screen) - h + y;
9031 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9032 grav == GDK_GRAVITY_NORTH_EAST)
9033 x = gdk_screen_get_width (screen) - w + x;
9035 /* we don't let you put a window offscreen; maybe some people would
9036 * prefer to be able to, but it's kind of a bogus thing to do.
9045 if ((result & XValue) || (result & YValue))
9047 gtk_window_set_gravity (window, grav);
9048 gtk_window_move (window, x, y);
9052 if (size_set || pos_set)
9054 /* Set USSize, USPosition hints */
9055 GtkWindowGeometryInfo *info;
9057 info = gtk_window_get_geometry_info (window, TRUE);
9060 info->mask |= GDK_HINT_USER_POS;
9062 info->mask |= GDK_HINT_USER_SIZE;
9069 gtk_window_mnemonic_hash_foreach (guint keyval,
9075 GtkWindowKeysForeachFunc func;
9079 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9083 _gtk_window_keys_foreach (GtkWindow *window,
9084 GtkWindowKeysForeachFunc func,
9088 GtkMnemonicHash *mnemonic_hash;
9092 GtkWindowKeysForeachFunc func;
9096 info.window = window;
9098 info.func_data = func_data;
9100 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9102 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9103 gtk_window_mnemonic_hash_foreach, &info);
9105 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9108 GtkAccelGroup *group = groups->data;
9111 for (i = 0; i < group->priv->n_accels; i++)
9113 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9116 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9119 groups = groups->next;
9124 gtk_window_keys_changed (GtkWindow *window)
9126 gtk_window_free_key_hash (window);
9127 gtk_window_get_key_hash (window);
9130 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9132 struct _GtkWindowKeyEntry
9136 guint is_mnemonic : 1;
9140 window_key_entry_destroy (gpointer data)
9142 g_slice_free (GtkWindowKeyEntry, data);
9146 add_to_key_hash (GtkWindow *window,
9148 GdkModifierType modifiers,
9149 gboolean is_mnemonic,
9152 GtkKeyHash *key_hash = data;
9154 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9156 entry->keyval = keyval;
9157 entry->modifiers = modifiers;
9158 entry->is_mnemonic = is_mnemonic;
9160 /* GtkAccelGroup stores lowercased accelerators. To deal
9161 * with this, if <Shift> was specified, uppercase.
9163 if (modifiers & GDK_SHIFT_MASK)
9165 if (keyval == GDK_KEY_Tab)
9166 keyval = GDK_KEY_ISO_Left_Tab;
9168 keyval = gdk_keyval_to_upper (keyval);
9171 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9175 gtk_window_get_key_hash (GtkWindow *window)
9177 GdkScreen *screen = gtk_window_check_screen (window);
9178 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9183 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9184 (GDestroyNotify)window_key_entry_destroy);
9185 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9186 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9192 gtk_window_free_key_hash (GtkWindow *window)
9194 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9197 _gtk_key_hash_free (key_hash);
9198 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9203 * gtk_window_activate_key:
9204 * @window: a #GtkWindow
9205 * @event: a #GdkEventKey
9207 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9208 * called by the default ::key_press_event handler for toplevel windows,
9209 * however in some cases it may be useful to call this directly when
9210 * overriding the standard key handling for a toplevel window.
9212 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9217 gtk_window_activate_key (GtkWindow *window,
9220 GtkKeyHash *key_hash;
9221 GtkWindowKeyEntry *found_entry = NULL;
9222 gboolean enable_mnemonics;
9223 gboolean enable_accels;
9225 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9226 g_return_val_if_fail (event != NULL, FALSE);
9228 key_hash = gtk_window_get_key_hash (window);
9233 GSList *entries = _gtk_key_hash_lookup (key_hash,
9234 event->hardware_keycode,
9236 gtk_accelerator_get_default_mod_mask (),
9239 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9240 "gtk-enable-mnemonics", &enable_mnemonics,
9241 "gtk-enable-accels", &enable_accels,
9244 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9246 GtkWindowKeyEntry *entry = tmp_list->data;
9247 if (entry->is_mnemonic)
9249 if (enable_mnemonics)
9251 found_entry = entry;
9257 if (enable_accels && !found_entry)
9259 found_entry = entry;
9264 g_slist_free (entries);
9269 if (found_entry->is_mnemonic)
9271 if (enable_mnemonics)
9272 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9273 found_entry->modifiers);
9278 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9279 found_entry->modifiers);
9287 window_update_has_focus (GtkWindow *window)
9289 GtkWindowPrivate *priv = window->priv;
9290 GtkWidget *widget = GTK_WIDGET (window);
9291 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9293 if (has_focus != priv->has_focus)
9295 priv->has_focus = has_focus;
9299 if (priv->focus_widget &&
9300 priv->focus_widget != widget &&
9301 !gtk_widget_has_focus (priv->focus_widget))
9302 do_focus_change (priv->focus_widget, TRUE);
9306 if (priv->focus_widget &&
9307 priv->focus_widget != widget &&
9308 gtk_widget_has_focus (priv->focus_widget))
9309 do_focus_change (priv->focus_widget, FALSE);
9315 * _gtk_window_set_is_active:
9316 * @window: a #GtkWindow
9317 * @is_active: %TRUE if the window is in the currently active toplevel
9319 * Internal function that sets whether the #GtkWindow is part
9320 * of the currently active toplevel window (taking into account inter-process
9324 _gtk_window_set_is_active (GtkWindow *window,
9327 GtkWindowPrivate *priv;
9329 g_return_if_fail (GTK_IS_WINDOW (window));
9331 priv = window->priv;
9333 is_active = is_active != FALSE;
9335 if (is_active != priv->is_active)
9337 priv->is_active = is_active;
9338 window_update_has_focus (window);
9340 g_object_notify (G_OBJECT (window), "is-active");
9345 * _gtk_window_set_is_toplevel:
9346 * @window: a #GtkWindow
9347 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9348 * parent of the root window); %FALSE if it is not (for example, for an
9349 * in-process, parented GtkPlug)
9351 * Internal function used by #GtkPlug when it gets parented/unparented by a
9352 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9353 * global list of toplevel windows.
9356 _gtk_window_set_is_toplevel (GtkWindow *window,
9357 gboolean is_toplevel)
9361 widget = GTK_WIDGET (window);
9363 if (gtk_widget_is_toplevel (widget))
9364 g_assert (g_slist_find (toplevel_list, window) != NULL);
9366 g_assert (g_slist_find (toplevel_list, window) == NULL);
9368 if (is_toplevel == gtk_widget_is_toplevel (widget))
9373 _gtk_widget_set_is_toplevel (widget, TRUE);
9374 toplevel_list = g_slist_prepend (toplevel_list, window);
9378 _gtk_widget_set_is_toplevel (widget, FALSE);
9379 toplevel_list = g_slist_remove (toplevel_list, window);
9384 * _gtk_window_set_has_toplevel_focus:
9385 * @window: a #GtkWindow
9386 * @has_toplevel_focus: %TRUE if the in
9388 * Internal function that sets whether the keyboard focus for the
9389 * toplevel window (taking into account inter-process embedding.)
9392 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9393 gboolean has_toplevel_focus)
9395 GtkWindowPrivate *priv;
9397 g_return_if_fail (GTK_IS_WINDOW (window));
9399 priv = window->priv;
9401 has_toplevel_focus = has_toplevel_focus != FALSE;
9403 if (has_toplevel_focus != priv->has_toplevel_focus)
9405 priv->has_toplevel_focus = has_toplevel_focus;
9406 window_update_has_focus (window);
9408 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9413 * gtk_window_set_auto_startup_notification:
9414 * @setting: %TRUE to automatically do startup notification
9416 * By default, after showing the first #GtkWindow, GTK+ calls
9417 * gdk_notify_startup_complete(). Call this function to disable
9418 * the automatic startup notification. You might do this if your
9419 * first window is a splash screen, and you want to delay notification
9420 * until after your real main window has been shown, for example.
9422 * In that example, you would disable startup notification
9423 * temporarily, show your splash screen, then re-enable it so that
9424 * showing the main window would automatically result in notification.
9429 gtk_window_set_auto_startup_notification (gboolean setting)
9431 disable_startup_notification = !setting;
9435 * gtk_window_get_window_type:
9436 * @window: a #GtkWindow
9438 * Gets the type of the window. See #GtkWindowType.
9440 * Return value: the type of the window
9445 gtk_window_get_window_type (GtkWindow *window)
9447 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9449 return window->priv->type;
9453 * gtk_window_get_mnemonics_visible:
9454 * @window: a #GtkWindow
9456 * Gets the value of the #GtkWindow:mnemonics-visible property.
9458 * Returns: %TRUE if mnemonics are supposed to be visible
9464 gtk_window_get_mnemonics_visible (GtkWindow *window)
9466 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9468 return window->priv->mnemonics_visible;
9472 * gtk_window_set_mnemonics_visible:
9473 * @window: a #GtkWindow
9474 * @setting: the new value
9476 * Sets the #GtkWindow:mnemonics-visible property.
9481 gtk_window_set_mnemonics_visible (GtkWindow *window,
9484 GtkWindowPrivate *priv;
9486 g_return_if_fail (GTK_IS_WINDOW (window));
9488 priv = window->priv;
9490 setting = setting != FALSE;
9492 if (priv->mnemonics_visible != setting)
9494 priv->mnemonics_visible = setting;
9495 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9498 priv->mnemonics_visible_set = TRUE;
9502 _gtk_window_get_wmclass (GtkWindow *window,
9503 gchar **wmclass_name,
9504 gchar **wmclass_class)
9506 GtkWindowPrivate *priv = window->priv;
9508 *wmclass_name = priv->wmclass_name;
9509 *wmclass_class = priv->wmclass_class;