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 gboolean has_resize_grip;
119 GdkWindow *grip_window;
123 gchar *wmclass_class;
131 guint keys_changed_handler;
133 /* Don't use this value, it's only used for determining when
134 * to fire notify events on the "resize-grip-visible" property.
136 gboolean resize_grip_visible;
138 guint16 configure_request_count;
140 /* The following flags are initially TRUE (before a window is mapped).
141 * They cause us to compute a configure request that involves
142 * default-only parameters. Once mapped, we set them to FALSE.
143 * Then we set them to TRUE again on unmap (for position)
144 * and on unrealize (for size).
146 guint need_default_position : 1;
147 guint need_default_size : 1;
149 guint above_initially : 1;
150 guint accept_focus : 1;
151 guint below_initially : 1;
152 guint builder_visible : 1;
153 guint configure_notify_received : 1;
156 guint destroy_with_parent : 1;
157 guint focus_on_map : 1;
158 guint fullscreen_initially : 1;
159 guint gravity : 5; /* GdkGravity */
161 guint has_user_ref_count : 1;
163 guint has_toplevel_focus : 1;
164 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
166 guint maximize_initially : 1;
167 guint mnemonics_visible : 1;
168 guint mnemonics_visible_set : 1;
170 guint opacity_set : 1;
172 guint reset_type_hint : 1;
174 guint skips_pager : 1;
175 guint skips_taskbar : 1;
176 guint stick_initially : 1;
177 guint transient_parent_group : 1;
178 guint type : 4; /* GtkWindowType */
179 guint type_hint : 3; /* GdkWindowTypeHint if the hint is one of the original eight. If not, then
180 * it contains GDK_WINDOW_TYPE_HINT_NORMAL */
207 PROP_DESTROY_WITH_PARENT,
212 PROP_SKIP_TASKBAR_HINT,
213 PROP_SKIP_PAGER_HINT,
222 PROP_HAS_RESIZE_GRIP,
223 PROP_RESIZE_GRIP_VISIBLE,
225 /* Readonly properties */
227 PROP_HAS_TOPLEVEL_FOCUS,
229 /* Writeonly properties */
232 PROP_MNEMONICS_VISIBLE,
242 guint using_default_icon : 1;
243 guint using_parent_icon : 1;
244 guint using_themed_icon : 1;
248 GdkGeometry geometry; /* Last set of geometry hints we set */
249 GdkWindowHints flags;
250 GdkRectangle configure_request;
251 } GtkWindowLastGeometryInfo;
253 struct _GtkWindowGeometryInfo
255 /* Properties that the app has set on the window
257 GdkGeometry geometry; /* Geometry hints */
259 GtkWidget *widget; /* subwidget to which hints apply */
260 /* from last gtk_window_resize () - if > 0, indicates that
261 * we should resize to this size.
266 /* From last gtk_window_move () prior to mapping -
267 * only used if initial_pos_set
272 /* Default size - used only the FIRST time we map a window,
277 /* whether to use initial_x, initial_y */
278 guint initial_pos_set : 1;
279 /* CENTER_ALWAYS or other position constraint changed since
280 * we sent the last configure request.
282 guint position_constraints_changed : 1;
284 /* if true, default_width, height should be multiplied by the
285 * increments and affect the geometry widget only
287 guint default_is_geometry : 1;
289 /* if true, resize_width, height should be multiplied by the
290 * increments and affect the geometry widget only
292 guint resize_is_geometry : 1;
294 GtkWindowLastGeometryInfo last;
297 #define GTK_WINDOW_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW_GROUP, GtkWindowGroupPrivate))
299 struct _GtkDeviceGrabInfo
303 guint block_others : 1;
306 struct _GtkWindowGroupPrivate
308 GSList *device_grabs;
311 static void gtk_window_dispose (GObject *object);
312 static void gtk_window_finalize (GObject *object);
313 static void gtk_window_destroy (GtkWidget *widget);
314 static void gtk_window_show (GtkWidget *widget);
315 static void gtk_window_hide (GtkWidget *widget);
316 static void gtk_window_map (GtkWidget *widget);
317 static void gtk_window_unmap (GtkWidget *widget);
318 static void gtk_window_realize (GtkWidget *widget);
319 static void gtk_window_unrealize (GtkWidget *widget);
320 static void gtk_window_size_allocate (GtkWidget *widget,
321 GtkAllocation *allocation);
322 static gint gtk_window_event (GtkWidget *widget,
324 static gboolean gtk_window_map_event (GtkWidget *widget,
326 static gboolean gtk_window_frame_event (GtkWindow *window,
328 static gint gtk_window_configure_event (GtkWidget *widget,
329 GdkEventConfigure *event);
330 static gint gtk_window_key_press_event (GtkWidget *widget,
332 static gint gtk_window_key_release_event (GtkWidget *widget,
334 static gint gtk_window_button_press_event (GtkWidget *widget,
335 GdkEventButton *event);
336 static gint gtk_window_enter_notify_event (GtkWidget *widget,
337 GdkEventCrossing *event);
338 static gint gtk_window_leave_notify_event (GtkWidget *widget,
339 GdkEventCrossing *event);
340 static gint gtk_window_focus_in_event (GtkWidget *widget,
341 GdkEventFocus *event);
342 static gint gtk_window_focus_out_event (GtkWidget *widget,
343 GdkEventFocus *event);
344 static gint gtk_window_client_event (GtkWidget *widget,
345 GdkEventClient *event);
346 static gboolean gtk_window_state_event (GtkWidget *widget,
347 GdkEventWindowState *event);
348 static void gtk_window_check_resize (GtkContainer *container);
349 static gint gtk_window_focus (GtkWidget *widget,
350 GtkDirectionType direction);
351 static void gtk_window_real_set_focus (GtkWindow *window,
353 static void gtk_window_direction_changed (GtkWidget *widget,
354 GtkTextDirection prev_dir);
355 static void gtk_window_state_changed (GtkWidget *widget,
356 GtkStateType previous_state);
358 static void gtk_window_real_activate_default (GtkWindow *window);
359 static void gtk_window_real_activate_focus (GtkWindow *window);
360 static void gtk_window_move_focus (GtkWindow *window,
361 GtkDirectionType dir);
362 static void gtk_window_keys_changed (GtkWindow *window);
363 static gint gtk_window_draw (GtkWidget *widget,
365 static void gtk_window_unset_transient_for (GtkWindow *window);
366 static void gtk_window_transient_parent_realized (GtkWidget *parent,
368 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
371 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
373 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
376 static void gtk_window_move_resize (GtkWindow *window);
377 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
379 GdkGeometry *geometry_b,
381 static void gtk_window_constrain_size (GtkWindow *window,
382 GdkGeometry *geometry,
388 static void gtk_window_constrain_position (GtkWindow *window,
393 static void gtk_window_compute_hints (GtkWindow *window,
394 GdkGeometry *new_geometry,
396 static void gtk_window_compute_configure_request (GtkWindow *window,
397 GdkRectangle *request,
398 GdkGeometry *geometry,
401 static void gtk_window_set_default_size_internal (GtkWindow *window,
402 gboolean change_width,
404 gboolean change_height,
406 gboolean is_geometry);
408 static void update_themed_icon (GtkIconTheme *theme,
410 static GList *icon_list_from_theme (GtkWidget *widget,
412 static void gtk_window_realize_icon (GtkWindow *window);
413 static void gtk_window_unrealize_icon (GtkWindow *window);
414 static void resize_grip_create_window (GtkWindow *window);
415 static void resize_grip_destroy_window (GtkWindow *window);
416 static void update_grip_visibility (GtkWindow *window);
418 static void gtk_window_notify_keys_changed (GtkWindow *window);
419 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
420 static void gtk_window_free_key_hash (GtkWindow *window);
421 static void gtk_window_on_composited_changed (GdkScreen *screen,
424 static GSList *toplevel_list = NULL;
425 static guint window_signals[LAST_SIGNAL] = { 0 };
426 static GList *default_icon_list = NULL;
427 static gchar *default_icon_name = NULL;
428 static guint default_icon_serial = 0;
429 static gboolean disable_startup_notification = FALSE;
430 static gboolean sent_startup_notification = FALSE;
432 static GQuark quark_gtk_embedded = 0;
433 static GQuark quark_gtk_window_key_hash = 0;
434 static GQuark quark_gtk_window_icon_info = 0;
435 static GQuark quark_gtk_buildable_accels = 0;
437 static GtkBuildableIface *parent_buildable_iface;
439 static void gtk_window_set_property (GObject *object,
443 static void gtk_window_get_property (GObject *object,
449 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
450 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
453 const GValue *value);
454 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
455 GtkBuilder *builder);
456 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
459 const gchar *tagname,
460 GMarkupParser *parser,
462 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
465 const gchar *tagname,
469 static void gtk_window_get_preferred_width (GtkWidget *widget,
472 static void gtk_window_get_preferred_height (GtkWidget *widget,
476 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
477 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
478 gtk_window_buildable_interface_init))
481 add_tab_bindings (GtkBindingSet *binding_set,
482 GdkModifierType modifiers,
483 GtkDirectionType direction)
485 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
487 GTK_TYPE_DIRECTION_TYPE, direction);
488 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
490 GTK_TYPE_DIRECTION_TYPE, direction);
494 add_arrow_bindings (GtkBindingSet *binding_set,
496 GtkDirectionType direction)
498 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
500 gtk_binding_entry_add_signal (binding_set, keysym, 0,
502 GTK_TYPE_DIRECTION_TYPE, direction);
503 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
505 GTK_TYPE_DIRECTION_TYPE, direction);
506 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
508 GTK_TYPE_DIRECTION_TYPE, direction);
509 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
511 GTK_TYPE_DIRECTION_TYPE, direction);
515 extract_time_from_startup_id (const gchar* startup_id)
517 gchar *timestr = g_strrstr (startup_id, "_TIME");
518 guint32 retval = GDK_CURRENT_TIME;
525 /* Skip past the "_TIME" part */
529 timestamp = strtoul (timestr, &end, 0);
530 if (end != timestr && errno == 0)
538 startup_id_is_fake (const gchar* startup_id)
540 return strncmp (startup_id, "_TIME", 5) == 0;
544 gtk_window_class_init (GtkWindowClass *klass)
546 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
547 GtkWidgetClass *widget_class;
548 GtkContainerClass *container_class;
549 GtkBindingSet *binding_set;
551 widget_class = (GtkWidgetClass*) klass;
552 container_class = (GtkContainerClass*) klass;
554 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
555 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
556 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
557 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
559 gobject_class->dispose = gtk_window_dispose;
560 gobject_class->finalize = gtk_window_finalize;
562 gobject_class->set_property = gtk_window_set_property;
563 gobject_class->get_property = gtk_window_get_property;
565 widget_class->destroy = gtk_window_destroy;
566 widget_class->show = gtk_window_show;
567 widget_class->hide = gtk_window_hide;
568 widget_class->map = gtk_window_map;
569 widget_class->map_event = gtk_window_map_event;
570 widget_class->unmap = gtk_window_unmap;
571 widget_class->realize = gtk_window_realize;
572 widget_class->unrealize = gtk_window_unrealize;
573 widget_class->size_allocate = gtk_window_size_allocate;
574 widget_class->configure_event = gtk_window_configure_event;
575 widget_class->key_press_event = gtk_window_key_press_event;
576 widget_class->key_release_event = gtk_window_key_release_event;
577 widget_class->enter_notify_event = gtk_window_enter_notify_event;
578 widget_class->leave_notify_event = gtk_window_leave_notify_event;
579 widget_class->focus_in_event = gtk_window_focus_in_event;
580 widget_class->button_press_event = gtk_window_button_press_event;
581 widget_class->focus_out_event = gtk_window_focus_out_event;
582 widget_class->client_event = gtk_window_client_event;
583 widget_class->focus = gtk_window_focus;
584 widget_class->draw = gtk_window_draw;
585 widget_class->get_preferred_width = gtk_window_get_preferred_width;
586 widget_class->get_preferred_height = gtk_window_get_preferred_height;
587 widget_class->window_state_event = gtk_window_state_event;
588 widget_class->direction_changed = gtk_window_direction_changed;
589 widget_class->state_changed = gtk_window_state_changed;
591 container_class->check_resize = gtk_window_check_resize;
593 klass->set_focus = gtk_window_real_set_focus;
594 klass->frame_event = gtk_window_frame_event;
596 klass->activate_default = gtk_window_real_activate_default;
597 klass->activate_focus = gtk_window_real_activate_focus;
598 klass->move_focus = gtk_window_move_focus;
599 klass->keys_changed = gtk_window_keys_changed;
601 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
604 g_object_class_install_property (gobject_class,
606 g_param_spec_enum ("type",
608 P_("The type of the window"),
609 GTK_TYPE_WINDOW_TYPE,
611 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
613 g_object_class_install_property (gobject_class,
615 g_param_spec_string ("title",
617 P_("The title of the window"),
619 GTK_PARAM_READWRITE));
621 g_object_class_install_property (gobject_class,
623 g_param_spec_string ("role",
625 P_("Unique identifier for the window to be used when restoring a session"),
627 GTK_PARAM_READWRITE));
630 * GtkWindow:startup-id:
632 * The :startup-id is a write-only property for setting window's
633 * startup notification identifier. See gtk_window_set_startup_id()
638 g_object_class_install_property (gobject_class,
640 g_param_spec_string ("startup-id",
642 P_("Unique startup identifier for the window used by startup-notification"),
644 GTK_PARAM_WRITABLE));
646 g_object_class_install_property (gobject_class,
648 g_param_spec_boolean ("resizable",
650 P_("If TRUE, users can resize the window"),
652 GTK_PARAM_READWRITE));
654 g_object_class_install_property (gobject_class,
656 g_param_spec_boolean ("modal",
658 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
660 GTK_PARAM_READWRITE));
662 g_object_class_install_property (gobject_class,
664 g_param_spec_enum ("window-position",
665 P_("Window Position"),
666 P_("The initial position of the window"),
667 GTK_TYPE_WINDOW_POSITION,
669 GTK_PARAM_READWRITE));
671 g_object_class_install_property (gobject_class,
673 g_param_spec_int ("default-width",
675 P_("The default width of the window, used when initially showing the window"),
679 GTK_PARAM_READWRITE));
681 g_object_class_install_property (gobject_class,
683 g_param_spec_int ("default-height",
684 P_("Default Height"),
685 P_("The default height of the window, used when initially showing the window"),
689 GTK_PARAM_READWRITE));
691 g_object_class_install_property (gobject_class,
692 PROP_DESTROY_WITH_PARENT,
693 g_param_spec_boolean ("destroy-with-parent",
694 P_("Destroy with Parent"),
695 P_("If this window should be destroyed when the parent is destroyed"),
697 GTK_PARAM_READWRITE));
699 g_object_class_install_property (gobject_class,
701 g_param_spec_object ("icon",
703 P_("Icon for this window"),
705 GTK_PARAM_READWRITE));
706 g_object_class_install_property (gobject_class,
707 PROP_MNEMONICS_VISIBLE,
708 g_param_spec_boolean ("mnemonics-visible",
709 P_("Mnemonics Visible"),
710 P_("Whether mnemonics are currently visible in this window"),
712 GTK_PARAM_READWRITE));
715 * GtkWindow:icon-name:
717 * The :icon-name property specifies the name of the themed icon to
718 * use as the window icon. See #GtkIconTheme for more details.
722 g_object_class_install_property (gobject_class,
724 g_param_spec_string ("icon-name",
726 P_("Name of the themed icon for this window"),
728 GTK_PARAM_READWRITE));
730 g_object_class_install_property (gobject_class,
732 g_param_spec_object ("screen",
734 P_("The screen where this window will be displayed"),
736 GTK_PARAM_READWRITE));
738 g_object_class_install_property (gobject_class,
740 g_param_spec_boolean ("is-active",
742 P_("Whether the toplevel is the current active window"),
744 GTK_PARAM_READABLE));
746 g_object_class_install_property (gobject_class,
747 PROP_HAS_TOPLEVEL_FOCUS,
748 g_param_spec_boolean ("has-toplevel-focus",
749 P_("Focus in Toplevel"),
750 P_("Whether the input focus is within this GtkWindow"),
752 GTK_PARAM_READABLE));
754 g_object_class_install_property (gobject_class,
756 g_param_spec_enum ("type-hint",
758 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
759 GDK_TYPE_WINDOW_TYPE_HINT,
760 GDK_WINDOW_TYPE_HINT_NORMAL,
761 GTK_PARAM_READWRITE));
763 g_object_class_install_property (gobject_class,
764 PROP_SKIP_TASKBAR_HINT,
765 g_param_spec_boolean ("skip-taskbar-hint",
767 P_("TRUE if the window should not be in the task bar."),
769 GTK_PARAM_READWRITE));
771 g_object_class_install_property (gobject_class,
772 PROP_SKIP_PAGER_HINT,
773 g_param_spec_boolean ("skip-pager-hint",
775 P_("TRUE if the window should not be in the pager."),
777 GTK_PARAM_READWRITE));
779 g_object_class_install_property (gobject_class,
781 g_param_spec_boolean ("urgency-hint",
783 P_("TRUE if the window should be brought to the user's attention."),
785 GTK_PARAM_READWRITE));
788 * GtkWindow:accept-focus:
790 * Whether the window should receive the input focus.
794 g_object_class_install_property (gobject_class,
796 g_param_spec_boolean ("accept-focus",
798 P_("TRUE if the window should receive the input focus."),
800 GTK_PARAM_READWRITE));
803 * GtkWindow:focus-on-map:
805 * Whether the window should receive the input focus when mapped.
809 g_object_class_install_property (gobject_class,
811 g_param_spec_boolean ("focus-on-map",
813 P_("TRUE if the window should receive the input focus when mapped."),
815 GTK_PARAM_READWRITE));
818 * GtkWindow:decorated:
820 * Whether the window should be decorated by the window manager.
824 g_object_class_install_property (gobject_class,
826 g_param_spec_boolean ("decorated",
828 P_("Whether the window should be decorated by the window manager"),
830 GTK_PARAM_READWRITE));
833 * GtkWindow:deletable:
835 * Whether the window frame should have a close button.
839 g_object_class_install_property (gobject_class,
841 g_param_spec_boolean ("deletable",
843 P_("Whether the window frame should have a close button"),
845 GTK_PARAM_READWRITE));
848 * GtkWindow:has-resize-grip
850 * Whether the window has a corner resize grip.
852 * Note that the resize grip is only shown if the window is
853 * actually resizable and not maximized. Use
854 * #GtkWindow:resize-grip-visible to find out if the resize
855 * grip is currently shown.
859 g_object_class_install_property (gobject_class,
860 PROP_HAS_RESIZE_GRIP,
861 g_param_spec_boolean ("has-resize-grip",
863 P_("Specifies whether the window should have a resize grip"),
865 GTK_PARAM_READWRITE));
868 * GtkWindow: resize-grip-visible:
870 * Whether a corner resize grip is currently shown.
874 g_object_class_install_property (gobject_class,
875 PROP_RESIZE_GRIP_VISIBLE,
876 g_param_spec_boolean ("resize-grip-visible",
877 P_("Resize grip is visible"),
878 P_("Specifies whether the window's resize grip is visible."),
880 GTK_PARAM_READABLE));
886 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
887 * more details about window gravity.
891 g_object_class_install_property (gobject_class,
893 g_param_spec_enum ("gravity",
895 P_("The window gravity of the window"),
897 GDK_GRAVITY_NORTH_WEST,
898 GTK_PARAM_READWRITE));
902 * GtkWindow:transient-for:
904 * The transient parent of the window. See gtk_window_set_transient_for() for
905 * more details about transient windows.
909 g_object_class_install_property (gobject_class,
911 g_param_spec_object ("transient-for",
912 P_("Transient for Window"),
913 P_("The transient parent of the dialog"),
915 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
920 * The requested opacity of the window. See gtk_window_set_opacity() for
921 * more details about window opacity.
925 g_object_class_install_property (gobject_class,
927 g_param_spec_double ("opacity",
928 P_("Opacity for Window"),
929 P_("The opacity of the window, from 0 to 1"),
933 GTK_PARAM_READWRITE));
938 gtk_widget_class_install_style_property (widget_class,
939 g_param_spec_int ("resize-grip-width",
940 P_("Width of resize grip"),
941 P_("Width of resize grip"),
942 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
944 gtk_widget_class_install_style_property (widget_class,
945 g_param_spec_int ("resize-grip-height",
946 P_("Height of resize grip"),
947 P_("Height of resize grip"),
948 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
953 window_signals[SET_FOCUS] =
954 g_signal_new (I_("set-focus"),
955 G_TYPE_FROM_CLASS (gobject_class),
957 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
959 _gtk_marshal_VOID__OBJECT,
963 window_signals[FRAME_EVENT] =
964 g_signal_new (I_("frame-event"),
965 G_TYPE_FROM_CLASS (gobject_class),
967 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
968 _gtk_boolean_handled_accumulator, NULL,
969 _gtk_marshal_BOOLEAN__BOXED,
974 * GtkWindow::activate-focus:
975 * @window: the window which received the signal
977 * The ::activate-focus signal is a
978 * <link linkend="keybinding-signals">keybinding signal</link>
979 * which gets emitted when the user activates the currently
980 * focused widget of @window.
982 window_signals[ACTIVATE_FOCUS] =
983 g_signal_new (I_("activate-focus"),
984 G_TYPE_FROM_CLASS (gobject_class),
985 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
986 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
988 _gtk_marshal_VOID__VOID,
993 * GtkWindow::activate-default:
994 * @window: the window which received the signal
996 * The ::activate-default signal is a
997 * <link linkend="keybinding-signals">keybinding signal</link>
998 * which gets emitted when the user activates the default widget
1001 window_signals[ACTIVATE_DEFAULT] =
1002 g_signal_new (I_("activate-default"),
1003 G_TYPE_FROM_CLASS (gobject_class),
1004 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1005 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1007 _gtk_marshal_VOID__VOID,
1012 * GtkWindow::keys-changed:
1013 * @window: the window which received the signal
1015 * The ::keys-changed signal gets emitted when the set of accelerators
1016 * or mnemonics that are associated with @window changes.
1018 window_signals[KEYS_CHANGED] =
1019 g_signal_new (I_("keys-changed"),
1020 G_TYPE_FROM_CLASS (gobject_class),
1022 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1024 _gtk_marshal_VOID__VOID,
1032 binding_set = gtk_binding_set_by_class (klass);
1034 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1035 "activate-focus", 0);
1036 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1037 "activate-focus", 0);
1039 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1040 "activate-default", 0);
1041 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1042 "activate-default", 0);
1043 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1044 "activate-default", 0);
1046 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1047 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1048 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1049 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1051 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1052 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1053 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1054 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1058 gtk_window_init (GtkWindow *window)
1060 GtkWindowPrivate *priv;
1062 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1065 priv = window->priv;
1067 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1068 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1070 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1072 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1075 priv->wmclass_name = g_strdup (g_get_prgname ());
1076 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1077 priv->wm_role = NULL;
1078 priv->geometry_info = NULL;
1079 priv->type = GTK_WINDOW_TOPLEVEL;
1080 priv->focus_widget = NULL;
1081 priv->default_widget = NULL;
1082 priv->configure_request_count = 0;
1083 priv->resizable = TRUE;
1084 priv->configure_notify_received = FALSE;
1085 priv->position = GTK_WIN_POS_NONE;
1086 priv->need_default_size = TRUE;
1087 priv->need_default_position = TRUE;
1088 priv->modal = FALSE;
1090 priv->has_frame = FALSE;
1091 priv->frame_left = 0;
1092 priv->frame_right = 0;
1093 priv->frame_top = 0;
1094 priv->frame_bottom = 0;
1095 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1096 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1097 priv->decorated = TRUE;
1098 priv->mnemonic_modifier = GDK_MOD1_MASK;
1099 priv->screen = gdk_screen_get_default ();
1101 priv->accept_focus = TRUE;
1102 priv->focus_on_map = TRUE;
1103 priv->deletable = TRUE;
1104 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1105 priv->opacity = 1.0;
1106 priv->startup_id = NULL;
1107 priv->has_resize_grip = TRUE;
1108 priv->mnemonics_visible = TRUE;
1110 g_object_ref_sink (window);
1111 priv->has_user_ref_count = TRUE;
1112 toplevel_list = g_slist_prepend (toplevel_list, window);
1114 gtk_decorated_window_init (window);
1116 g_signal_connect (priv->screen, "composited-changed",
1117 G_CALLBACK (gtk_window_on_composited_changed), window);
1121 gtk_window_set_property (GObject *object,
1123 const GValue *value,
1126 GtkWindow *window = GTK_WINDOW (object);
1127 GtkWindowPrivate *priv = window->priv;
1132 priv->type = g_value_get_enum (value);
1135 gtk_window_set_title (window, g_value_get_string (value));
1138 gtk_window_set_role (window, g_value_get_string (value));
1140 case PROP_STARTUP_ID:
1141 gtk_window_set_startup_id (window, g_value_get_string (value));
1143 case PROP_RESIZABLE:
1144 gtk_window_set_resizable (window, g_value_get_boolean (value));
1147 gtk_window_set_modal (window, g_value_get_boolean (value));
1150 gtk_window_set_position (window, g_value_get_enum (value));
1152 case PROP_DEFAULT_WIDTH:
1153 gtk_window_set_default_size_internal (window,
1154 TRUE, g_value_get_int (value),
1157 case PROP_DEFAULT_HEIGHT:
1158 gtk_window_set_default_size_internal (window,
1160 TRUE, g_value_get_int (value), FALSE);
1162 case PROP_DESTROY_WITH_PARENT:
1163 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1166 gtk_window_set_icon (window,
1167 g_value_get_object (value));
1169 case PROP_ICON_NAME:
1170 gtk_window_set_icon_name (window, g_value_get_string (value));
1173 gtk_window_set_screen (window, g_value_get_object (value));
1175 case PROP_TYPE_HINT:
1176 gtk_window_set_type_hint (window,
1177 g_value_get_enum (value));
1179 case PROP_SKIP_TASKBAR_HINT:
1180 gtk_window_set_skip_taskbar_hint (window,
1181 g_value_get_boolean (value));
1183 case PROP_SKIP_PAGER_HINT:
1184 gtk_window_set_skip_pager_hint (window,
1185 g_value_get_boolean (value));
1187 case PROP_URGENCY_HINT:
1188 gtk_window_set_urgency_hint (window,
1189 g_value_get_boolean (value));
1191 case PROP_ACCEPT_FOCUS:
1192 gtk_window_set_accept_focus (window,
1193 g_value_get_boolean (value));
1195 case PROP_FOCUS_ON_MAP:
1196 gtk_window_set_focus_on_map (window,
1197 g_value_get_boolean (value));
1199 case PROP_DECORATED:
1200 gtk_window_set_decorated (window, g_value_get_boolean (value));
1202 case PROP_DELETABLE:
1203 gtk_window_set_deletable (window, g_value_get_boolean (value));
1206 gtk_window_set_gravity (window, g_value_get_enum (value));
1208 case PROP_TRANSIENT_FOR:
1209 gtk_window_set_transient_for (window, g_value_get_object (value));
1212 gtk_window_set_opacity (window, g_value_get_double (value));
1214 case PROP_HAS_RESIZE_GRIP:
1215 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1217 case PROP_MNEMONICS_VISIBLE:
1218 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1221 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1227 gtk_window_get_property (GObject *object,
1232 GtkWindow *window = GTK_WINDOW (object);
1233 GtkWindowPrivate *priv = window->priv;
1237 GtkWindowGeometryInfo *info;
1239 g_value_set_enum (value, priv->type);
1242 g_value_set_string (value, priv->wm_role);
1245 g_value_set_string (value, priv->title);
1247 case PROP_RESIZABLE:
1248 g_value_set_boolean (value, priv->resizable);
1251 g_value_set_boolean (value, priv->modal);
1254 g_value_set_enum (value, priv->position);
1256 case PROP_DEFAULT_WIDTH:
1257 info = gtk_window_get_geometry_info (window, FALSE);
1259 g_value_set_int (value, -1);
1261 g_value_set_int (value, info->default_width);
1263 case PROP_DEFAULT_HEIGHT:
1264 info = gtk_window_get_geometry_info (window, FALSE);
1266 g_value_set_int (value, -1);
1268 g_value_set_int (value, info->default_height);
1270 case PROP_DESTROY_WITH_PARENT:
1271 g_value_set_boolean (value, priv->destroy_with_parent);
1274 g_value_set_object (value, gtk_window_get_icon (window));
1276 case PROP_ICON_NAME:
1277 g_value_set_string (value, gtk_window_get_icon_name (window));
1280 g_value_set_object (value, priv->screen);
1282 case PROP_IS_ACTIVE:
1283 g_value_set_boolean (value, priv->is_active);
1285 case PROP_HAS_TOPLEVEL_FOCUS:
1286 g_value_set_boolean (value, priv->has_toplevel_focus);
1288 case PROP_TYPE_HINT:
1289 g_value_set_enum (value, priv->type_hint);
1291 case PROP_SKIP_TASKBAR_HINT:
1292 g_value_set_boolean (value,
1293 gtk_window_get_skip_taskbar_hint (window));
1295 case PROP_SKIP_PAGER_HINT:
1296 g_value_set_boolean (value,
1297 gtk_window_get_skip_pager_hint (window));
1299 case PROP_URGENCY_HINT:
1300 g_value_set_boolean (value,
1301 gtk_window_get_urgency_hint (window));
1303 case PROP_ACCEPT_FOCUS:
1304 g_value_set_boolean (value,
1305 gtk_window_get_accept_focus (window));
1307 case PROP_FOCUS_ON_MAP:
1308 g_value_set_boolean (value,
1309 gtk_window_get_focus_on_map (window));
1311 case PROP_DECORATED:
1312 g_value_set_boolean (value, gtk_window_get_decorated (window));
1314 case PROP_DELETABLE:
1315 g_value_set_boolean (value, gtk_window_get_deletable (window));
1318 g_value_set_enum (value, gtk_window_get_gravity (window));
1320 case PROP_TRANSIENT_FOR:
1321 g_value_set_object (value, gtk_window_get_transient_for (window));
1324 g_value_set_double (value, gtk_window_get_opacity (window));
1326 case PROP_HAS_RESIZE_GRIP:
1327 g_value_set_boolean (value, priv->has_resize_grip);
1329 case PROP_RESIZE_GRIP_VISIBLE:
1330 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1332 case PROP_MNEMONICS_VISIBLE:
1333 g_value_set_boolean (value, priv->mnemonics_visible);
1336 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1342 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1344 parent_buildable_iface = g_type_interface_peek_parent (iface);
1345 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1346 iface->parser_finished = gtk_window_buildable_parser_finished;
1347 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1348 iface->custom_finished = gtk_window_buildable_custom_finished;
1352 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1353 GtkBuilder *builder,
1355 const GValue *value)
1357 GtkWindow *window = GTK_WINDOW (buildable);
1358 GtkWindowPrivate *priv = window->priv;
1360 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1361 priv->builder_visible = TRUE;
1363 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1367 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1368 GtkBuilder *builder)
1370 GtkWindow *window = GTK_WINDOW (buildable);
1371 GtkWindowPrivate *priv = window->priv;
1375 if (priv->builder_visible)
1376 gtk_widget_show (GTK_WIDGET (buildable));
1378 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1379 for (l = accels; l; l = l->next)
1381 object = gtk_builder_get_object (builder, l->data);
1384 g_warning ("Unknown accel group %s specified in window %s",
1385 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1388 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1389 GTK_ACCEL_GROUP (object));
1393 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1395 parent_buildable_iface->parser_finished (buildable, builder);
1401 } GSListSubParserData;
1404 window_start_element (GMarkupParseContext *context,
1405 const gchar *element_name,
1406 const gchar **names,
1407 const gchar **values,
1412 GSListSubParserData *data = (GSListSubParserData*)user_data;
1414 if (strcmp (element_name, "group") == 0)
1416 for (i = 0; names[i]; i++)
1418 if (strcmp (names[i], "name") == 0)
1419 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1422 else if (strcmp (element_name, "accel-groups") == 0)
1425 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1430 static const GMarkupParser window_parser =
1432 window_start_element
1436 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1437 GtkBuilder *builder,
1439 const gchar *tagname,
1440 GMarkupParser *parser,
1443 GSListSubParserData *parser_data;
1445 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1446 tagname, parser, data))
1449 if (strcmp (tagname, "accel-groups") == 0)
1451 parser_data = g_slice_new0 (GSListSubParserData);
1452 parser_data->items = NULL;
1453 parser_data->object = G_OBJECT (buildable);
1455 *parser = window_parser;
1456 *data = parser_data;
1464 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1465 GtkBuilder *builder,
1467 const gchar *tagname,
1470 GSListSubParserData *data;
1472 parent_buildable_iface->custom_finished (buildable, builder, child,
1473 tagname, user_data);
1475 if (strcmp (tagname, "accel-groups") != 0)
1478 data = (GSListSubParserData*)user_data;
1480 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1481 data->items, (GDestroyNotify) g_slist_free);
1483 g_slice_free (GSListSubParserData, data);
1488 * @type: type of window
1490 * Creates a new #GtkWindow, which is a toplevel window that can
1491 * contain other widgets. Nearly always, the type of the window should
1492 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1493 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1494 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1495 * dialogs, though in some other toolkits dialogs are called "popups".
1496 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1497 * On X11, popup windows are not controlled by the <link
1498 * linkend="gtk-X11-arch">window manager</link>.
1500 * If you simply want an undecorated window (no window borders), use
1501 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1503 * Return value: a new #GtkWindow.
1506 gtk_window_new (GtkWindowType type)
1508 GtkWindowPrivate *priv;
1511 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1513 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1514 priv = window->priv;
1518 return GTK_WIDGET (window);
1522 * gtk_window_set_title:
1523 * @window: a #GtkWindow
1524 * @title: title of the window
1526 * Sets the title of the #GtkWindow. The title of a window will be
1527 * displayed in its title bar; on the X Window System, the title bar
1528 * is rendered by the <link linkend="gtk-X11-arch">window
1529 * manager</link>, so exactly how the title appears to users may vary
1530 * according to a user's exact configuration. The title should help a
1531 * user distinguish this window from other windows they may have
1532 * open. A good title might include the application name and current
1533 * document filename, for example.
1537 gtk_window_set_title (GtkWindow *window,
1540 GtkWindowPrivate *priv;
1544 g_return_if_fail (GTK_IS_WINDOW (window));
1546 priv = window->priv;
1547 widget = GTK_WIDGET (window);
1549 new_title = g_strdup (title);
1550 g_free (priv->title);
1551 priv->title = new_title;
1553 if (gtk_widget_get_realized (widget))
1555 gdk_window_set_title (gtk_widget_get_window (widget),
1558 gtk_decorated_window_set_title (window, title);
1561 g_object_notify (G_OBJECT (window), "title");
1565 * gtk_window_get_title:
1566 * @window: a #GtkWindow
1568 * Retrieves the title of the window. See gtk_window_set_title().
1570 * Return value: the title of the window, or %NULL if none has
1571 * been set explicitely. The returned string is owned by the widget
1572 * and must not be modified or freed.
1574 G_CONST_RETURN gchar *
1575 gtk_window_get_title (GtkWindow *window)
1577 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1579 return window->priv->title;
1583 * gtk_window_set_wmclass:
1584 * @window: a #GtkWindow
1585 * @wmclass_name: window name hint
1586 * @wmclass_class: window class hint
1588 * Don't use this function. It sets the X Window System "class" and
1589 * "name" hints for a window. According to the ICCCM, you should
1590 * always set these to the same value for all windows in an
1591 * application, and GTK+ sets them to that value by default, so calling
1592 * this function is sort of pointless. However, you may want to call
1593 * gtk_window_set_role() on each window in your application, for the
1594 * benefit of the session manager. Setting the role allows the window
1595 * manager to restore window positions when loading a saved session.
1599 gtk_window_set_wmclass (GtkWindow *window,
1600 const gchar *wmclass_name,
1601 const gchar *wmclass_class)
1603 GtkWindowPrivate *priv;
1605 g_return_if_fail (GTK_IS_WINDOW (window));
1607 priv = window->priv;
1609 g_free (priv->wmclass_name);
1610 priv->wmclass_name = g_strdup (wmclass_name);
1612 g_free (priv->wmclass_class);
1613 priv->wmclass_class = g_strdup (wmclass_class);
1615 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1616 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1620 * gtk_window_set_role:
1621 * @window: a #GtkWindow
1622 * @role: unique identifier for the window to be used when restoring a session
1624 * This function is only useful on X11, not with other GTK+ targets.
1626 * In combination with the window title, the window role allows a
1627 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1628 * same" window when an application is restarted. So for example you
1629 * might set the "toolbox" role on your app's toolbox window, so that
1630 * when the user restarts their session, the window manager can put
1631 * the toolbox back in the same place.
1633 * If a window already has a unique title, you don't need to set the
1634 * role, since the WM can use the title to identify the window when
1635 * restoring the session.
1639 gtk_window_set_role (GtkWindow *window,
1642 GtkWindowPrivate *priv;
1645 g_return_if_fail (GTK_IS_WINDOW (window));
1647 priv = window->priv;
1649 new_role = g_strdup (role);
1650 g_free (priv->wm_role);
1651 priv->wm_role = new_role;
1653 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1654 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1657 g_object_notify (G_OBJECT (window), "role");
1661 * gtk_window_set_startup_id:
1662 * @window: a #GtkWindow
1663 * @startup_id: a string with startup-notification identifier
1665 * Startup notification identifiers are used by desktop environment to
1666 * track application startup, to provide user feedback and other
1667 * features. This function changes the corresponding property on the
1668 * underlying GdkWindow. Normally, startup identifier is managed
1669 * automatically and you should only use this function in special cases
1670 * like transferring focus from other processes. You should use this
1671 * function before calling gtk_window_present() or any equivalent
1672 * function generating a window map event.
1674 * This function is only useful on X11, not with other GTK+ targets.
1679 gtk_window_set_startup_id (GtkWindow *window,
1680 const gchar *startup_id)
1682 GtkWindowPrivate *priv;
1685 g_return_if_fail (GTK_IS_WINDOW (window));
1687 priv = window->priv;
1688 widget = GTK_WIDGET (window);
1690 g_free (priv->startup_id);
1691 priv->startup_id = g_strdup (startup_id);
1693 if (gtk_widget_get_realized (widget))
1695 GdkWindow *gdk_window;
1696 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1698 gdk_window = gtk_widget_get_window (widget);
1700 #ifdef GDK_WINDOWING_X11
1701 if (timestamp != GDK_CURRENT_TIME)
1702 gdk_x11_window_set_user_time (gdk_window, timestamp);
1705 /* Here we differentiate real and "fake" startup notification IDs,
1706 * constructed on purpose just to pass interaction timestamp
1708 if (startup_id_is_fake (priv->startup_id))
1709 gtk_window_present_with_time (window, timestamp);
1712 gdk_window_set_startup_id (gdk_window,
1715 /* If window is mapped, terminate the startup-notification too */
1716 if (gtk_widget_get_mapped (widget) &&
1717 !disable_startup_notification)
1718 gdk_notify_startup_complete_with_id (priv->startup_id);
1722 g_object_notify (G_OBJECT (window), "startup-id");
1726 * gtk_window_get_role:
1727 * @window: a #GtkWindow
1729 * Returns the role of the window. See gtk_window_set_role() for
1730 * further explanation.
1732 * Return value: the role of the window if set, or %NULL. The
1733 * returned is owned by the widget and must not be modified
1736 G_CONST_RETURN gchar *
1737 gtk_window_get_role (GtkWindow *window)
1739 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1741 return window->priv->wm_role;
1745 * gtk_window_set_focus:
1746 * @window: a #GtkWindow
1747 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1748 * any focus widget for the toplevel window.
1750 * If @focus is not the current focus widget, and is focusable, sets
1751 * it as the focus widget for the window. If @focus is %NULL, unsets
1752 * the focus widget for this window. To set the focus to a particular
1753 * widget in the toplevel, it is usually more convenient to use
1754 * gtk_widget_grab_focus() instead of this function.
1757 gtk_window_set_focus (GtkWindow *window,
1760 GtkWindowPrivate *priv;
1763 g_return_if_fail (GTK_IS_WINDOW (window));
1765 priv = window->priv;
1769 g_return_if_fail (GTK_IS_WIDGET (focus));
1770 g_return_if_fail (gtk_widget_get_can_focus (focus));
1774 gtk_widget_grab_focus (focus);
1777 /* Clear the existing focus chain, so that when we focus into
1778 * the window again, we start at the beginnning.
1780 GtkWidget *widget = priv->focus_widget;
1783 while ((parent = gtk_widget_get_parent (widget)))
1786 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1790 _gtk_window_internal_set_focus (window, NULL);
1795 _gtk_window_internal_set_focus (GtkWindow *window,
1798 GtkWindowPrivate *priv;
1800 g_return_if_fail (GTK_IS_WINDOW (window));
1802 priv = window->priv;
1804 if ((priv->focus_widget != focus) ||
1805 (focus && !gtk_widget_has_focus (focus)))
1806 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1810 * gtk_window_set_default:
1811 * @window: a #GtkWindow
1812 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1813 * default widget for the toplevel.
1815 * The default widget is the widget that's activated when the user
1816 * presses Enter in a dialog (for example). This function sets or
1817 * unsets the default widget for a #GtkWindow about. When setting
1818 * (rather than unsetting) the default widget it's generally easier to
1819 * call gtk_widget_grab_focus() on the widget. Before making a widget
1820 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1821 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1824 gtk_window_set_default (GtkWindow *window,
1825 GtkWidget *default_widget)
1827 GtkWindowPrivate *priv;
1829 g_return_if_fail (GTK_IS_WINDOW (window));
1831 priv = window->priv;
1834 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1836 if (priv->default_widget != default_widget)
1838 GtkWidget *old_default_widget = NULL;
1841 g_object_ref (default_widget);
1843 if (priv->default_widget)
1845 old_default_widget = priv->default_widget;
1847 if (priv->focus_widget != priv->default_widget ||
1848 !gtk_widget_get_receives_default (priv->default_widget))
1849 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1851 gtk_widget_queue_draw (priv->default_widget);
1854 priv->default_widget = default_widget;
1856 if (priv->default_widget)
1858 if (priv->focus_widget == NULL ||
1859 !gtk_widget_get_receives_default (priv->focus_widget))
1860 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1862 gtk_widget_queue_draw (priv->default_widget);
1865 if (old_default_widget)
1866 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1870 g_object_notify (G_OBJECT (default_widget), "has-default");
1871 g_object_unref (default_widget);
1877 * gtk_window_get_default_widget:
1878 * @window: a #GtkWindow
1880 * Returns the default widget for @window. See gtk_window_set_default()
1883 * Returns: (transfer none): the default widget, or %NULL if there is none.
1888 gtk_window_get_default_widget (GtkWindow *window)
1890 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1892 return window->priv->default_widget;
1896 handle_keys_changed (gpointer data)
1898 GtkWindow *window = GTK_WINDOW (data);
1899 GtkWindowPrivate *priv = window->priv;
1901 if (priv->keys_changed_handler)
1903 g_source_remove (priv->keys_changed_handler);
1904 priv->keys_changed_handler = 0;
1907 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1913 gtk_window_notify_keys_changed (GtkWindow *window)
1915 GtkWindowPrivate *priv = window->priv;
1917 if (!priv->keys_changed_handler)
1918 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1922 * gtk_window_add_accel_group:
1923 * @window: window to attach accelerator group to
1924 * @accel_group: a #GtkAccelGroup
1926 * Associate @accel_group with @window, such that calling
1927 * gtk_accel_groups_activate() on @window will activate accelerators
1931 gtk_window_add_accel_group (GtkWindow *window,
1932 GtkAccelGroup *accel_group)
1934 g_return_if_fail (GTK_IS_WINDOW (window));
1935 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1937 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1938 g_signal_connect_object (accel_group, "accel-changed",
1939 G_CALLBACK (gtk_window_notify_keys_changed),
1940 window, G_CONNECT_SWAPPED);
1941 gtk_window_notify_keys_changed (window);
1945 * gtk_window_remove_accel_group:
1946 * @window: a #GtkWindow
1947 * @accel_group: a #GtkAccelGroup
1949 * Reverses the effects of gtk_window_add_accel_group().
1952 gtk_window_remove_accel_group (GtkWindow *window,
1953 GtkAccelGroup *accel_group)
1955 g_return_if_fail (GTK_IS_WINDOW (window));
1956 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1958 g_signal_handlers_disconnect_by_func (accel_group,
1959 gtk_window_notify_keys_changed,
1961 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1962 gtk_window_notify_keys_changed (window);
1965 static GtkMnemonicHash *
1966 gtk_window_get_mnemonic_hash (GtkWindow *window,
1969 GtkWindowPrivate *private = window->priv;
1971 if (!private->mnemonic_hash && create)
1972 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1974 return private->mnemonic_hash;
1978 * gtk_window_add_mnemonic:
1979 * @window: a #GtkWindow
1980 * @keyval: the mnemonic
1981 * @target: the widget that gets activated by the mnemonic
1983 * Adds a mnemonic to this window.
1986 gtk_window_add_mnemonic (GtkWindow *window,
1990 g_return_if_fail (GTK_IS_WINDOW (window));
1991 g_return_if_fail (GTK_IS_WIDGET (target));
1993 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1995 gtk_window_notify_keys_changed (window);
1999 * gtk_window_remove_mnemonic:
2000 * @window: a #GtkWindow
2001 * @keyval: the mnemonic
2002 * @target: the widget that gets activated by the mnemonic
2004 * Removes a mnemonic from this window.
2007 gtk_window_remove_mnemonic (GtkWindow *window,
2011 g_return_if_fail (GTK_IS_WINDOW (window));
2012 g_return_if_fail (GTK_IS_WIDGET (target));
2014 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2016 gtk_window_notify_keys_changed (window);
2020 * gtk_window_mnemonic_activate:
2021 * @window: a #GtkWindow
2022 * @keyval: the mnemonic
2023 * @modifier: the modifiers
2024 * @returns: %TRUE if the activation is done.
2026 * Activates the targets associated with the mnemonic.
2029 gtk_window_mnemonic_activate (GtkWindow *window,
2031 GdkModifierType modifier)
2033 GtkWindowPrivate *priv;
2035 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2037 priv = window->priv;
2039 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2041 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2043 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2050 * gtk_window_set_mnemonic_modifier:
2051 * @window: a #GtkWindow
2052 * @modifier: the modifier mask used to activate
2053 * mnemonics on this window.
2055 * Sets the mnemonic modifier for this window.
2058 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2059 GdkModifierType modifier)
2061 GtkWindowPrivate *priv;
2063 g_return_if_fail (GTK_IS_WINDOW (window));
2064 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2066 priv = window->priv;
2068 priv->mnemonic_modifier = modifier;
2069 gtk_window_notify_keys_changed (window);
2073 * gtk_window_get_mnemonic_modifier:
2074 * @window: a #GtkWindow
2076 * Returns the mnemonic modifier for this window. See
2077 * gtk_window_set_mnemonic_modifier().
2079 * Return value: the modifier mask used to activate
2080 * mnemonics on this window.
2083 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2085 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2087 return window->priv->mnemonic_modifier;
2091 * gtk_window_set_position:
2092 * @window: a #GtkWindow.
2093 * @position: a position constraint.
2095 * Sets a position constraint for this window. If the old or new
2096 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2097 * the window to be repositioned to satisfy the new constraint.
2100 gtk_window_set_position (GtkWindow *window,
2101 GtkWindowPosition position)
2103 GtkWindowPrivate *priv;
2105 g_return_if_fail (GTK_IS_WINDOW (window));
2107 priv = window->priv;
2109 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2110 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2112 GtkWindowGeometryInfo *info;
2114 info = gtk_window_get_geometry_info (window, TRUE);
2116 /* this flag causes us to re-request the CENTER_ALWAYS
2117 * constraint in gtk_window_move_resize(), see
2118 * comment in that function.
2120 info->position_constraints_changed = TRUE;
2122 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2125 priv->position = position;
2127 g_object_notify (G_OBJECT (window), "window-position");
2131 * gtk_window_activate_focus:
2132 * @window: a #GtkWindow
2134 * Activates the current focused widget within the window.
2136 * Return value: %TRUE if a widget got activated.
2139 gtk_window_activate_focus (GtkWindow *window)
2141 GtkWindowPrivate *priv;
2143 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2145 priv = window->priv;
2147 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2148 return gtk_widget_activate (priv->focus_widget);
2154 * gtk_window_get_focus:
2155 * @window: a #GtkWindow
2157 * Retrieves the current focused widget within the window.
2158 * Note that this is the widget that would have the focus
2159 * if the toplevel window focused; if the toplevel window
2160 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2161 * not be %TRUE for the widget.
2163 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2166 gtk_window_get_focus (GtkWindow *window)
2168 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2170 return window->priv->focus_widget;
2174 * gtk_window_activate_default:
2175 * @window: a #GtkWindow
2177 * Activates the default widget for the window, unless the current
2178 * focused widget has been configured to receive the default action
2179 * (see gtk_widget_set_receives_default()), in which case the
2180 * focused widget is activated.
2182 * Return value: %TRUE if a widget got activated.
2185 gtk_window_activate_default (GtkWindow *window)
2187 GtkWindowPrivate *priv;
2189 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2191 priv = window->priv;
2193 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2194 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2195 return gtk_widget_activate (priv->default_widget);
2196 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2197 return gtk_widget_activate (priv->focus_widget);
2203 * gtk_window_set_modal:
2204 * @window: a #GtkWindow
2205 * @modal: whether the window is modal
2207 * Sets a window modal or non-modal. Modal windows prevent interaction
2208 * with other windows in the same application. To keep modal dialogs
2209 * on top of main application windows, use
2210 * gtk_window_set_transient_for() to make the dialog transient for the
2211 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2212 * will then disallow lowering the dialog below the parent.
2217 gtk_window_set_modal (GtkWindow *window,
2220 GtkWindowPrivate *priv;
2223 g_return_if_fail (GTK_IS_WINDOW (window));
2225 priv = window->priv;
2227 modal = modal != FALSE;
2228 if (priv->modal == modal)
2231 priv->modal = modal;
2232 widget = GTK_WIDGET (window);
2234 /* adjust desired modality state */
2235 if (gtk_widget_get_realized (widget))
2238 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2240 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2243 if (gtk_widget_get_visible (widget))
2246 gtk_grab_add (widget);
2248 gtk_grab_remove (widget);
2251 g_object_notify (G_OBJECT (window), "modal");
2255 * gtk_window_get_modal:
2256 * @window: a #GtkWindow
2258 * Returns whether the window is modal. See gtk_window_set_modal().
2260 * Return value: %TRUE if the window is set to be modal and
2261 * establishes a grab when shown
2264 gtk_window_get_modal (GtkWindow *window)
2266 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2268 return window->priv->modal;
2272 * gtk_window_list_toplevels:
2274 * Returns a list of all existing toplevel windows. The widgets
2275 * in the list are not individually referenced. If you want
2276 * to iterate through the list and perform actions involving
2277 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2278 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2279 * then unref all the widgets afterwards.
2281 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2284 gtk_window_list_toplevels (void)
2289 for (slist = toplevel_list; slist; slist = slist->next)
2290 list = g_list_prepend (list, slist->data);
2296 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2298 GList *embedded_windows;
2300 g_return_if_fail (GTK_IS_WINDOW (window));
2302 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2303 if (embedded_windows)
2304 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2305 embedded_windows = g_list_prepend (embedded_windows,
2306 GUINT_TO_POINTER (xid));
2308 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2311 (GDestroyNotify) g_list_free : NULL);
2315 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2317 GList *embedded_windows;
2320 g_return_if_fail (GTK_IS_WINDOW (window));
2322 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2323 if (embedded_windows)
2324 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2326 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2329 embedded_windows = g_list_remove_link (embedded_windows, node);
2330 g_list_free_1 (node);
2333 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2336 (GDestroyNotify) g_list_free : NULL);
2340 gtk_window_dispose (GObject *object)
2342 GtkWindow *window = GTK_WINDOW (object);
2344 gtk_window_set_focus (window, NULL);
2345 gtk_window_set_default (window, NULL);
2347 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2351 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2353 gtk_widget_destroy (GTK_WIDGET (child));
2357 connect_parent_destroyed (GtkWindow *window)
2359 GtkWindowPrivate *priv = window->priv;
2361 if (priv->transient_parent)
2363 g_signal_connect (priv->transient_parent,
2365 G_CALLBACK (parent_destroyed_callback),
2371 disconnect_parent_destroyed (GtkWindow *window)
2373 GtkWindowPrivate *priv = window->priv;
2375 if (priv->transient_parent)
2377 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2378 parent_destroyed_callback,
2384 gtk_window_transient_parent_realized (GtkWidget *parent,
2387 if (gtk_widget_get_realized (window))
2388 gdk_window_set_transient_for (gtk_widget_get_window (window),
2389 gtk_widget_get_window (parent));
2393 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2396 if (gtk_widget_get_realized (window))
2397 gdk_property_delete (gtk_widget_get_window (window),
2398 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2402 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2406 gtk_window_set_screen (window, parent->priv->screen);
2410 gtk_window_unset_transient_for (GtkWindow *window)
2412 GtkWindowPrivate *priv = window->priv;
2414 if (priv->transient_parent)
2416 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2417 gtk_window_transient_parent_realized,
2419 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2420 gtk_window_transient_parent_unrealized,
2422 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2423 gtk_window_transient_parent_screen_changed,
2425 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2426 gtk_widget_destroyed,
2427 &priv->transient_parent);
2429 if (priv->destroy_with_parent)
2430 disconnect_parent_destroyed (window);
2432 priv->transient_parent = NULL;
2434 if (priv->transient_parent_group)
2436 priv->transient_parent_group = FALSE;
2437 gtk_window_group_remove_window (priv->group,
2444 * gtk_window_set_transient_for:
2445 * @window: a #GtkWindow
2446 * @parent: (allow-none): parent window, or %NULL
2448 * Dialog windows should be set transient for the main application
2449 * window they were spawned from. This allows <link
2450 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2451 * dialog on top of the main window, or center the dialog over the
2452 * main window. gtk_dialog_new_with_buttons() and other convenience
2453 * functions in GTK+ will sometimes call
2454 * gtk_window_set_transient_for() on your behalf.
2456 * Passing %NULL for @parent unsets the current transient window.
2458 * On Windows, this function puts the child window on top of the parent,
2459 * much as the window manager would have done on X.
2462 gtk_window_set_transient_for (GtkWindow *window,
2465 GtkWindowPrivate *priv;
2467 g_return_if_fail (GTK_IS_WINDOW (window));
2468 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2469 g_return_if_fail (window != parent);
2471 priv = window->priv;
2473 if (priv->transient_parent)
2475 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2476 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2477 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2478 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2479 GTK_WIDGET (window));
2481 gtk_window_unset_transient_for (window);
2484 priv->transient_parent = parent;
2488 g_signal_connect (parent, "destroy",
2489 G_CALLBACK (gtk_widget_destroyed),
2490 &priv->transient_parent);
2491 g_signal_connect (parent, "realize",
2492 G_CALLBACK (gtk_window_transient_parent_realized),
2494 g_signal_connect (parent, "unrealize",
2495 G_CALLBACK (gtk_window_transient_parent_unrealized),
2497 g_signal_connect (parent, "notify::screen",
2498 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2501 gtk_window_set_screen (window, parent->priv->screen);
2503 if (priv->destroy_with_parent)
2504 connect_parent_destroyed (window);
2506 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2507 gtk_widget_get_realized (GTK_WIDGET (parent)))
2508 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2509 GTK_WIDGET (window));
2511 if (parent->priv->group)
2513 gtk_window_group_add_window (parent->priv->group, window);
2514 priv->transient_parent_group = TRUE;
2520 * gtk_window_get_transient_for:
2521 * @window: a #GtkWindow
2523 * Fetches the transient parent for this window. See
2524 * gtk_window_set_transient_for().
2526 * Return value: (transfer none): the transient parent for this window, or %NULL
2527 * if no transient parent has been set.
2530 gtk_window_get_transient_for (GtkWindow *window)
2532 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2534 return window->priv->transient_parent;
2538 * gtk_window_set_opacity:
2539 * @window: a #GtkWindow
2540 * @opacity: desired opacity, between 0 and 1
2542 * Request the windowing system to make @window partially transparent,
2543 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2544 * of the opacity parameter are clamped to the [0,1] range.) On X11
2545 * this has any effect only on X screens with a compositing manager
2546 * running. See gtk_widget_is_composited(). On Windows it should work
2549 * Note that setting a window's opacity after the window has been
2550 * shown causes it to flicker once on Windows.
2555 gtk_window_set_opacity (GtkWindow *window,
2558 GtkWindowPrivate *priv;
2560 g_return_if_fail (GTK_IS_WINDOW (window));
2562 priv = window->priv;
2566 else if (opacity > 1.0)
2569 priv->opacity_set = TRUE;
2570 priv->opacity = opacity;
2572 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2573 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2578 * gtk_window_get_opacity:
2579 * @window: a #GtkWindow
2581 * Fetches the requested opacity for this window. See
2582 * gtk_window_set_opacity().
2584 * Return value: the requested opacity for this window.
2589 gtk_window_get_opacity (GtkWindow *window)
2591 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2593 return window->priv->opacity;
2597 * gtk_window_set_type_hint:
2598 * @window: a #GtkWindow
2599 * @hint: the window type
2601 * By setting the type hint for the window, you allow the window
2602 * manager to decorate and handle the window in a way which is
2603 * suitable to the function of the window in your application.
2605 * This function should be called before the window becomes visible.
2607 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2608 * will sometimes call gtk_window_set_type_hint() on your behalf.
2612 gtk_window_set_type_hint (GtkWindow *window,
2613 GdkWindowTypeHint hint)
2615 GtkWindowPrivate *priv;
2617 g_return_if_fail (GTK_IS_WINDOW (window));
2618 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2620 priv = window->priv;
2622 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2623 priv->gdk_type_hint = hint;
2625 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2627 priv->reset_type_hint = TRUE;
2628 priv->type_hint = hint;
2632 * gtk_window_get_type_hint:
2633 * @window: a #GtkWindow
2635 * Gets the type hint for this window. See gtk_window_set_type_hint().
2637 * Return value: the type hint for @window.
2640 gtk_window_get_type_hint (GtkWindow *window)
2642 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2644 return window->priv->type_hint;
2648 * gtk_window_set_skip_taskbar_hint:
2649 * @window: a #GtkWindow
2650 * @setting: %TRUE to keep this window from appearing in the task bar
2652 * Windows may set a hint asking the desktop environment not to display
2653 * the window in the task bar. This function sets this hint.
2658 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2661 GtkWindowPrivate *priv;
2663 g_return_if_fail (GTK_IS_WINDOW (window));
2665 priv = window->priv;
2667 setting = setting != FALSE;
2669 if (priv->skips_taskbar != setting)
2671 priv->skips_taskbar = setting;
2672 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2673 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2674 priv->skips_taskbar);
2675 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2680 * gtk_window_get_skip_taskbar_hint:
2681 * @window: a #GtkWindow
2683 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2685 * Return value: %TRUE if window shouldn't be in taskbar
2690 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2692 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2694 return window->priv->skips_taskbar;
2698 * gtk_window_set_skip_pager_hint:
2699 * @window: a #GtkWindow
2700 * @setting: %TRUE to keep this window from appearing in the pager
2702 * Windows may set a hint asking the desktop environment not to display
2703 * the window in the pager. This function sets this hint.
2704 * (A "pager" is any desktop navigation tool such as a workspace
2705 * switcher that displays a thumbnail representation of the windows
2711 gtk_window_set_skip_pager_hint (GtkWindow *window,
2714 GtkWindowPrivate *priv;
2716 g_return_if_fail (GTK_IS_WINDOW (window));
2718 priv = window->priv;
2720 setting = setting != FALSE;
2722 if (priv->skips_pager != setting)
2724 priv->skips_pager = setting;
2725 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2726 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2728 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2733 * gtk_window_get_skip_pager_hint:
2734 * @window: a #GtkWindow
2736 * Gets the value set by gtk_window_set_skip_pager_hint().
2738 * Return value: %TRUE if window shouldn't be in pager
2743 gtk_window_get_skip_pager_hint (GtkWindow *window)
2745 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2747 return window->priv->skips_pager;
2751 * gtk_window_set_urgency_hint:
2752 * @window: a #GtkWindow
2753 * @setting: %TRUE to mark this window as urgent
2755 * Windows may set a hint asking the desktop environment to draw
2756 * the users attention to the window. This function sets this hint.
2761 gtk_window_set_urgency_hint (GtkWindow *window,
2764 GtkWindowPrivate *priv;
2766 g_return_if_fail (GTK_IS_WINDOW (window));
2768 priv = window->priv;
2770 setting = setting != FALSE;
2772 if (priv->urgent != setting)
2774 priv->urgent = setting;
2775 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2776 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2778 g_object_notify (G_OBJECT (window), "urgency-hint");
2783 * gtk_window_get_urgency_hint:
2784 * @window: a #GtkWindow
2786 * Gets the value set by gtk_window_set_urgency_hint()
2788 * Return value: %TRUE if window is urgent
2793 gtk_window_get_urgency_hint (GtkWindow *window)
2795 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2797 return window->priv->urgent;
2801 * gtk_window_set_accept_focus:
2802 * @window: a #GtkWindow
2803 * @setting: %TRUE to let this window receive input focus
2805 * Windows may set a hint asking the desktop environment not to receive
2806 * the input focus. This function sets this hint.
2811 gtk_window_set_accept_focus (GtkWindow *window,
2814 GtkWindowPrivate *priv;
2816 g_return_if_fail (GTK_IS_WINDOW (window));
2818 priv = window->priv;
2820 setting = setting != FALSE;
2822 if (priv->accept_focus != setting)
2824 priv->accept_focus = setting;
2825 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2826 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2827 priv->accept_focus);
2828 g_object_notify (G_OBJECT (window), "accept-focus");
2833 * gtk_window_get_accept_focus:
2834 * @window: a #GtkWindow
2836 * Gets the value set by gtk_window_set_accept_focus().
2838 * Return value: %TRUE if window should receive the input focus
2843 gtk_window_get_accept_focus (GtkWindow *window)
2845 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2847 return window->priv->accept_focus;
2851 * gtk_window_set_focus_on_map:
2852 * @window: a #GtkWindow
2853 * @setting: %TRUE to let this window receive input focus on map
2855 * Windows may set a hint asking the desktop environment not to receive
2856 * the input focus when the window is mapped. This function sets this
2862 gtk_window_set_focus_on_map (GtkWindow *window,
2865 GtkWindowPrivate *priv;
2867 g_return_if_fail (GTK_IS_WINDOW (window));
2869 priv = window->priv;
2871 setting = setting != FALSE;
2873 if (priv->focus_on_map != setting)
2875 priv->focus_on_map = setting;
2876 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2877 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2878 priv->focus_on_map);
2879 g_object_notify (G_OBJECT (window), "focus-on-map");
2884 * gtk_window_get_focus_on_map:
2885 * @window: a #GtkWindow
2887 * Gets the value set by gtk_window_set_focus_on_map().
2889 * Return value: %TRUE if window should receive the input focus when
2895 gtk_window_get_focus_on_map (GtkWindow *window)
2897 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2899 return window->priv->focus_on_map;
2903 * gtk_window_set_destroy_with_parent:
2904 * @window: a #GtkWindow
2905 * @setting: whether to destroy @window with its transient parent
2907 * If @setting is %TRUE, then destroying the transient parent of @window
2908 * will also destroy @window itself. This is useful for dialogs that
2909 * shouldn't persist beyond the lifetime of the main window they're
2910 * associated with, for example.
2913 gtk_window_set_destroy_with_parent (GtkWindow *window,
2916 GtkWindowPrivate *priv;
2918 g_return_if_fail (GTK_IS_WINDOW (window));
2920 priv = window->priv;
2922 if (priv->destroy_with_parent == (setting != FALSE))
2925 if (priv->destroy_with_parent)
2927 disconnect_parent_destroyed (window);
2931 connect_parent_destroyed (window);
2934 priv->destroy_with_parent = setting;
2936 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2940 * gtk_window_get_destroy_with_parent:
2941 * @window: a #GtkWindow
2943 * Returns whether the window will be destroyed with its transient parent. See
2944 * gtk_window_set_destroy_with_parent ().
2946 * Return value: %TRUE if the window will be destroyed with its transient parent.
2949 gtk_window_get_destroy_with_parent (GtkWindow *window)
2951 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2953 return window->priv->destroy_with_parent;
2956 static GtkWindowGeometryInfo*
2957 gtk_window_get_geometry_info (GtkWindow *window,
2960 GtkWindowPrivate *priv = window->priv;
2961 GtkWindowGeometryInfo *info;
2963 info = priv->geometry_info;
2964 if (!info && create)
2966 info = g_new0 (GtkWindowGeometryInfo, 1);
2968 info->default_width = -1;
2969 info->default_height = -1;
2970 info->resize_width = -1;
2971 info->resize_height = -1;
2972 info->initial_x = 0;
2973 info->initial_y = 0;
2974 info->initial_pos_set = FALSE;
2975 info->default_is_geometry = FALSE;
2976 info->position_constraints_changed = FALSE;
2977 info->last.configure_request.x = 0;
2978 info->last.configure_request.y = 0;
2979 info->last.configure_request.width = -1;
2980 info->last.configure_request.height = -1;
2981 info->widget = NULL;
2983 priv->geometry_info = info;
2990 * gtk_window_set_geometry_hints:
2991 * @window: a #GtkWindow
2992 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
2993 * @geometry: (allow-none): struct containing geometry information or %NULL
2994 * @geom_mask: mask indicating which struct fields should be paid attention to
2996 * This function sets up hints about how a window can be resized by
2997 * the user. You can set a minimum and maximum size; allowed resize
2998 * increments (e.g. for xterm, you can only resize by the size of a
2999 * character); aspect ratios; and more. See the #GdkGeometry struct.
3003 gtk_window_set_geometry_hints (GtkWindow *window,
3004 GtkWidget *geometry_widget,
3005 GdkGeometry *geometry,
3006 GdkWindowHints geom_mask)
3008 GtkWindowGeometryInfo *info;
3010 g_return_if_fail (GTK_IS_WINDOW (window));
3011 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3013 info = gtk_window_get_geometry_info (window, TRUE);
3016 g_signal_handlers_disconnect_by_func (info->widget,
3017 gtk_widget_destroyed,
3020 info->widget = geometry_widget;
3022 g_signal_connect (geometry_widget, "destroy",
3023 G_CALLBACK (gtk_widget_destroyed),
3027 info->geometry = *geometry;
3029 /* We store gravity in priv->gravity not in the hints. */
3030 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3032 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3034 gtk_window_set_gravity (window, geometry->win_gravity);
3037 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3041 * gtk_window_set_decorated:
3042 * @window: a #GtkWindow
3043 * @setting: %TRUE to decorate the window
3045 * By default, windows are decorated with a title bar, resize
3046 * controls, etc. Some <link linkend="gtk-X11-arch">window
3047 * managers</link> allow GTK+ to disable these decorations, creating a
3048 * borderless window. If you set the decorated property to %FALSE
3049 * using this function, GTK+ will do its best to convince the window
3050 * manager not to decorate the window. Depending on the system, this
3051 * function may not have any effect when called on a window that is
3052 * already visible, so you should call it before calling gtk_window_show().
3054 * On Windows, this function always works, since there's no window manager
3059 gtk_window_set_decorated (GtkWindow *window,
3062 GtkWindowPrivate *priv;
3063 GdkWindow *gdk_window;
3065 g_return_if_fail (GTK_IS_WINDOW (window));
3067 priv = window->priv;
3069 setting = setting != FALSE;
3071 if (setting == priv->decorated)
3074 priv->decorated = setting;
3076 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3079 if (priv->decorated)
3080 gdk_window_set_decorations (gdk_window,
3083 gdk_window_set_decorations (gdk_window,
3087 g_object_notify (G_OBJECT (window), "decorated");
3091 * gtk_window_get_decorated:
3092 * @window: a #GtkWindow
3094 * Returns whether the window has been set to have decorations
3095 * such as a title bar via gtk_window_set_decorated().
3097 * Return value: %TRUE if the window has been set to have decorations
3100 gtk_window_get_decorated (GtkWindow *window)
3102 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3104 return window->priv->decorated;
3108 * gtk_window_set_deletable:
3109 * @window: a #GtkWindow
3110 * @setting: %TRUE to decorate the window as deletable
3112 * By default, windows have a close button in the window frame. Some
3113 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3114 * disable this button. If you set the deletable property to %FALSE
3115 * using this function, GTK+ will do its best to convince the window
3116 * manager not to show a close button. Depending on the system, this
3117 * function may not have any effect when called on a window that is
3118 * already visible, so you should call it before calling gtk_window_show().
3120 * On Windows, this function always works, since there's no window manager
3126 gtk_window_set_deletable (GtkWindow *window,
3129 GtkWindowPrivate *priv;
3130 GdkWindow *gdk_window;
3132 g_return_if_fail (GTK_IS_WINDOW (window));
3134 priv = window->priv;
3136 setting = setting != FALSE;
3138 if (setting == priv->deletable)
3141 priv->deletable = setting;
3143 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3146 if (priv->deletable)
3147 gdk_window_set_functions (gdk_window,
3150 gdk_window_set_functions (gdk_window,
3151 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3154 g_object_notify (G_OBJECT (window), "deletable");
3158 * gtk_window_get_deletable:
3159 * @window: a #GtkWindow
3161 * Returns whether the window has been set to have a close button
3162 * via gtk_window_set_deletable().
3164 * Return value: %TRUE if the window has been set to have a close button
3169 gtk_window_get_deletable (GtkWindow *window)
3171 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3173 return window->priv->deletable;
3176 static GtkWindowIconInfo*
3177 get_icon_info (GtkWindow *window)
3179 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3183 free_icon_info (GtkWindowIconInfo *info)
3185 g_free (info->icon_name);
3186 g_slice_free (GtkWindowIconInfo, info);
3190 static GtkWindowIconInfo*
3191 ensure_icon_info (GtkWindow *window)
3193 GtkWindowIconInfo *info;
3195 info = get_icon_info (window);
3199 info = g_slice_new0 (GtkWindowIconInfo);
3200 g_object_set_qdata_full (G_OBJECT (window),
3201 quark_gtk_window_icon_info,
3203 (GDestroyNotify)free_icon_info);
3210 icon_list_from_theme (GtkWidget *widget,
3215 GtkIconTheme *icon_theme;
3220 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3222 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3225 for (i = 0; sizes[i]; i++)
3228 * We need an EWMH extension to handle scalable icons
3229 * by passing their name to the WM. For now just use a
3233 icon = gtk_icon_theme_load_icon (icon_theme, name,
3236 icon = gtk_icon_theme_load_icon (icon_theme, name,
3239 list = g_list_append (list, icon);
3249 gtk_window_realize_icon (GtkWindow *window)
3251 GtkWindowPrivate *priv = window->priv;
3253 GtkWindowIconInfo *info;
3254 GdkWindow *gdk_window;
3257 widget = GTK_WIDGET (window);
3258 gdk_window = gtk_widget_get_window (widget);
3260 g_return_if_fail (gdk_window != NULL);
3262 /* no point setting an icon on override-redirect */
3263 if (priv->type == GTK_WINDOW_POPUP)
3268 info = ensure_icon_info (window);
3273 info->using_default_icon = FALSE;
3274 info->using_parent_icon = FALSE;
3275 info->using_themed_icon = FALSE;
3277 icon_list = info->icon_list;
3279 /* Look up themed icon */
3280 if (icon_list == NULL && info->icon_name)
3282 icon_list = icon_list_from_theme (widget, info->icon_name);
3284 info->using_themed_icon = TRUE;
3287 /* Inherit from transient parent */
3288 if (icon_list == NULL && priv->transient_parent)
3290 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3292 info->using_parent_icon = TRUE;
3295 /* Inherit from default */
3296 if (icon_list == NULL)
3298 icon_list = default_icon_list;
3300 info->using_default_icon = TRUE;
3303 /* Look up themed icon */
3304 if (icon_list == NULL && default_icon_name)
3306 icon_list = icon_list_from_theme (widget, default_icon_name);
3307 info->using_default_icon = TRUE;
3308 info->using_themed_icon = TRUE;
3311 info->realized = TRUE;
3313 if (info->using_themed_icon)
3315 GtkIconTheme *icon_theme;
3317 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3318 g_list_free (icon_list);
3320 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3321 g_signal_connect (icon_theme, "changed",
3322 G_CALLBACK (update_themed_icon), window);
3327 gtk_window_unrealize_icon (GtkWindow *window)
3329 GtkWindowIconInfo *info;
3331 info = get_icon_info (window);
3336 if (info->using_themed_icon)
3338 GtkIconTheme *icon_theme;
3340 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3342 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3345 /* We don't clear the properties on the window, just figure the
3346 * window is going away.
3349 info->realized = FALSE;
3354 * gtk_window_set_icon_list:
3355 * @window: a #GtkWindow
3356 * @list: (element-type GdkPixbuf) (transfer container): list of #GdkPixbuf
3358 * Sets up the icon representing a #GtkWindow. The icon is used when
3359 * the window is minimized (also known as iconified). Some window
3360 * managers or desktop environments may also place it in the window
3361 * frame, or display it in other contexts.
3363 * gtk_window_set_icon_list() allows you to pass in the same icon in
3364 * several hand-drawn sizes. The list should contain the natural sizes
3365 * your icon is available in; that is, don't scale the image before
3366 * passing it to GTK+. Scaling is postponed until the last minute,
3367 * when the desired final size is known, to allow best quality.
3369 * By passing several sizes, you may improve the final image quality
3370 * of the icon, by reducing or eliminating automatic image scaling.
3372 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3373 * larger images (64x64, 128x128) if you have them.
3375 * See also gtk_window_set_default_icon_list() to set the icon
3376 * for all windows in your application in one go.
3378 * Note that transient windows (those who have been set transient for another
3379 * window using gtk_window_set_transient_for()) will inherit their
3380 * icon from their transient parent. So there's no need to explicitly
3381 * set the icon on transient windows.
3384 gtk_window_set_icon_list (GtkWindow *window,
3387 GtkWindowIconInfo *info;
3389 g_return_if_fail (GTK_IS_WINDOW (window));
3391 info = ensure_icon_info (window);
3393 if (info->icon_list == list) /* check for NULL mostly */
3396 g_list_foreach (list,
3397 (GFunc) g_object_ref, NULL);
3399 g_list_foreach (info->icon_list,
3400 (GFunc) g_object_unref, NULL);
3402 g_list_free (info->icon_list);
3404 info->icon_list = g_list_copy (list);
3406 g_object_notify (G_OBJECT (window), "icon");
3408 gtk_window_unrealize_icon (window);
3410 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3411 gtk_window_realize_icon (window);
3413 /* We could try to update our transient children, but I don't think
3414 * it's really worth it. If we did it, the best way would probably
3415 * be to have children connect to notify::icon-list
3420 * gtk_window_get_icon_list:
3421 * @window: a #GtkWindow
3423 * Retrieves the list of icons set by gtk_window_set_icon_list().
3424 * The list is copied, but the reference count on each
3425 * member won't be incremented.
3427 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3430 gtk_window_get_icon_list (GtkWindow *window)
3432 GtkWindowIconInfo *info;
3434 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3436 info = get_icon_info (window);
3439 return g_list_copy (info->icon_list);
3445 * gtk_window_set_icon:
3446 * @window: a #GtkWindow
3447 * @icon: (allow-none): icon image, or %NULL
3449 * Sets up the icon representing a #GtkWindow. This icon is used when
3450 * the window is minimized (also known as iconified). Some window
3451 * managers or desktop environments may also place it in the window
3452 * frame, or display it in other contexts.
3454 * The icon should be provided in whatever size it was naturally
3455 * drawn; that is, don't scale the image before passing it to
3456 * GTK+. Scaling is postponed until the last minute, when the desired
3457 * final size is known, to allow best quality.
3459 * If you have your icon hand-drawn in multiple sizes, use
3460 * gtk_window_set_icon_list(). Then the best size will be used.
3462 * This function is equivalent to calling gtk_window_set_icon_list()
3463 * with a 1-element list.
3465 * See also gtk_window_set_default_icon_list() to set the icon
3466 * for all windows in your application in one go.
3469 gtk_window_set_icon (GtkWindow *window,
3474 g_return_if_fail (GTK_IS_WINDOW (window));
3475 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3480 list = g_list_append (list, icon);
3482 gtk_window_set_icon_list (window, list);
3488 update_themed_icon (GtkIconTheme *icon_theme,
3491 g_object_notify (G_OBJECT (window), "icon");
3493 gtk_window_unrealize_icon (window);
3495 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3496 gtk_window_realize_icon (window);
3500 * gtk_window_set_icon_name:
3501 * @window: a #GtkWindow
3502 * @name: (allow-none): the name of the themed icon
3504 * Sets the icon for the window from a named themed icon. See
3505 * the docs for #GtkIconTheme for more details.
3507 * Note that this has nothing to do with the WM_ICON_NAME
3508 * property which is mentioned in the ICCCM.
3513 gtk_window_set_icon_name (GtkWindow *window,
3516 GtkWindowIconInfo *info;
3519 g_return_if_fail (GTK_IS_WINDOW (window));
3521 info = ensure_icon_info (window);
3523 if (g_strcmp0 (info->icon_name, name) == 0)
3526 tmp = info->icon_name;
3527 info->icon_name = g_strdup (name);
3530 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3531 g_list_free (info->icon_list);
3532 info->icon_list = NULL;
3534 update_themed_icon (NULL, window);
3536 g_object_notify (G_OBJECT (window), "icon-name");
3540 * gtk_window_get_icon_name:
3541 * @window: a #GtkWindow
3543 * Returns the name of the themed icon for the window,
3544 * see gtk_window_set_icon_name().
3546 * Returns: the icon name or %NULL if the window has
3552 gtk_window_get_icon_name (GtkWindow *window)
3554 GtkWindowIconInfo *info;
3556 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3558 info = ensure_icon_info (window);
3560 return info->icon_name;
3564 * gtk_window_get_icon:
3565 * @window: a #GtkWindow
3567 * Gets the value set by gtk_window_set_icon() (or if you've
3568 * called gtk_window_set_icon_list(), gets the first icon in
3571 * Return value: (transfer none): icon for window
3574 gtk_window_get_icon (GtkWindow *window)
3576 GtkWindowIconInfo *info;
3578 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3580 info = get_icon_info (window);
3581 if (info && info->icon_list)
3582 return GDK_PIXBUF (info->icon_list->data);
3587 /* Load pixbuf, printing warning on failure if error == NULL
3590 load_pixbuf_verbosely (const char *filename,
3593 GError *local_err = NULL;
3596 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3604 g_warning ("Error loading icon from file '%s':\n\t%s",
3605 filename, local_err->message);
3606 g_error_free (local_err);
3614 * gtk_window_set_icon_from_file:
3615 * @window: a #GtkWindow
3616 * @filename: location of icon file
3617 * @err: (allow-none): location to store error, or %NULL.
3619 * Sets the icon for @window.
3620 * Warns on failure if @err is %NULL.
3622 * This function is equivalent to calling gtk_window_set_icon()
3623 * with a pixbuf created by loading the image from @filename.
3625 * Returns: %TRUE if setting the icon succeeded.
3630 gtk_window_set_icon_from_file (GtkWindow *window,
3631 const gchar *filename,
3634 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3638 gtk_window_set_icon (window, pixbuf);
3639 g_object_unref (pixbuf);
3648 * gtk_window_set_default_icon_list:
3649 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3651 * Sets an icon list to be used as fallback for windows that haven't
3652 * had gtk_window_set_icon_list() called on them to set up a
3653 * window-specific icon list. This function allows you to set up the
3654 * icon for all windows in your app at once.
3656 * See gtk_window_set_icon_list() for more details.
3660 gtk_window_set_default_icon_list (GList *list)
3664 if (list == default_icon_list)
3667 /* Update serial so we don't used cached pixmaps/masks
3669 default_icon_serial++;
3671 g_list_foreach (list,
3672 (GFunc) g_object_ref, NULL);
3674 g_list_foreach (default_icon_list,
3675 (GFunc) g_object_unref, NULL);
3677 g_list_free (default_icon_list);
3679 default_icon_list = g_list_copy (list);
3681 /* Update all toplevels */
3682 toplevels = gtk_window_list_toplevels ();
3683 tmp_list = toplevels;
3684 while (tmp_list != NULL)
3686 GtkWindowIconInfo *info;
3687 GtkWindow *w = tmp_list->data;
3689 info = get_icon_info (w);
3690 if (info && info->using_default_icon)
3692 gtk_window_unrealize_icon (w);
3693 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3694 gtk_window_realize_icon (w);
3697 tmp_list = tmp_list->next;
3699 g_list_free (toplevels);
3703 * gtk_window_set_default_icon:
3706 * Sets an icon to be used as fallback for windows that haven't
3707 * had gtk_window_set_icon() called on them from a pixbuf.
3712 gtk_window_set_default_icon (GdkPixbuf *icon)
3716 g_return_if_fail (GDK_IS_PIXBUF (icon));
3718 list = g_list_prepend (NULL, icon);
3719 gtk_window_set_default_icon_list (list);
3724 * gtk_window_set_default_icon_name:
3725 * @name: the name of the themed icon
3727 * Sets an icon to be used as fallback for windows that haven't
3728 * had gtk_window_set_icon_list() called on them from a named
3729 * themed icon, see gtk_window_set_icon_name().
3734 gtk_window_set_default_icon_name (const gchar *name)
3739 /* Update serial so we don't used cached pixmaps/masks
3741 default_icon_serial++;
3743 g_free (default_icon_name);
3744 default_icon_name = g_strdup (name);
3746 g_list_foreach (default_icon_list,
3747 (GFunc) g_object_unref, NULL);
3749 g_list_free (default_icon_list);
3750 default_icon_list = NULL;
3752 /* Update all toplevels */
3753 toplevels = gtk_window_list_toplevels ();
3754 tmp_list = toplevels;
3755 while (tmp_list != NULL)
3757 GtkWindowIconInfo *info;
3758 GtkWindow *w = tmp_list->data;
3760 info = get_icon_info (w);
3761 if (info && info->using_default_icon && info->using_themed_icon)
3763 gtk_window_unrealize_icon (w);
3764 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3765 gtk_window_realize_icon (w);
3768 tmp_list = tmp_list->next;
3770 g_list_free (toplevels);
3774 * gtk_window_get_default_icon_name:
3776 * Returns the fallback icon name for windows that has been set
3777 * with gtk_window_set_default_icon_name(). The returned
3778 * string is owned by GTK+ and should not be modified. It
3779 * is only valid until the next call to
3780 * gtk_window_set_default_icon_name().
3782 * Returns: the fallback icon name for windows
3787 gtk_window_get_default_icon_name (void)
3789 return default_icon_name;
3793 * gtk_window_set_default_icon_from_file:
3794 * @filename: location of icon file
3795 * @err: (allow-none): location to store error, or %NULL.
3797 * Sets an icon to be used as fallback for windows that haven't
3798 * had gtk_window_set_icon_list() called on them from a file
3799 * on disk. Warns on failure if @err is %NULL.
3801 * Returns: %TRUE if setting the icon succeeded.
3806 gtk_window_set_default_icon_from_file (const gchar *filename,
3809 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3813 gtk_window_set_default_icon (pixbuf);
3814 g_object_unref (pixbuf);
3823 * gtk_window_get_default_icon_list:
3825 * Gets the value set by gtk_window_set_default_icon_list().
3826 * The list is a copy and should be freed with g_list_free(),
3827 * but the pixbufs in the list have not had their reference count
3830 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3833 gtk_window_get_default_icon_list (void)
3835 return g_list_copy (default_icon_list);
3839 gtk_window_set_default_size_internal (GtkWindow *window,
3840 gboolean change_width,
3842 gboolean change_height,
3844 gboolean is_geometry)
3846 GtkWindowGeometryInfo *info;
3848 g_return_if_fail (change_width == FALSE || width >= -1);
3849 g_return_if_fail (change_height == FALSE || height >= -1);
3851 info = gtk_window_get_geometry_info (window, TRUE);
3853 g_object_freeze_notify (G_OBJECT (window));
3855 info->default_is_geometry = is_geometry != FALSE;
3865 info->default_width = width;
3867 g_object_notify (G_OBJECT (window), "default-width");
3878 info->default_height = height;
3880 g_object_notify (G_OBJECT (window), "default-height");
3883 g_object_thaw_notify (G_OBJECT (window));
3885 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3889 * gtk_window_set_default_size:
3890 * @window: a #GtkWindow
3891 * @width: width in pixels, or -1 to unset the default width
3892 * @height: height in pixels, or -1 to unset the default height
3894 * Sets the default size of a window. If the window's "natural" size
3895 * (its size request) is larger than the default, the default will be
3896 * ignored. More generally, if the default size does not obey the
3897 * geometry hints for the window (gtk_window_set_geometry_hints() can
3898 * be used to set these explicitly), the default size will be clamped
3899 * to the nearest permitted size.
3901 * Unlike gtk_widget_set_size_request(), which sets a size request for
3902 * a widget and thus would keep users from shrinking the window, this
3903 * function only sets the initial size, just as if the user had
3904 * resized the window themselves. Users can still shrink the window
3905 * again as they normally would. Setting a default size of -1 means to
3906 * use the "natural" default size (the size request of the window).
3908 * For more control over a window's initial size and how resizing works,
3909 * investigate gtk_window_set_geometry_hints().
3911 * For some uses, gtk_window_resize() is a more appropriate function.
3912 * gtk_window_resize() changes the current size of the window, rather
3913 * than the size to be used on initial display. gtk_window_resize() always
3914 * affects the window itself, not the geometry widget.
3916 * The default size of a window only affects the first time a window is
3917 * shown; if a window is hidden and re-shown, it will remember the size
3918 * it had prior to hiding, rather than using the default size.
3920 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3921 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3924 gtk_window_set_default_size (GtkWindow *window,
3928 g_return_if_fail (GTK_IS_WINDOW (window));
3929 g_return_if_fail (width >= -1);
3930 g_return_if_fail (height >= -1);
3932 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3936 * gtk_window_set_default_geometry:
3937 * @window: a #GtkWindow
3938 * @width: width in resize increments, or -1 to unset the default width
3939 * @height: height in resize increments, or -1 to unset the default height
3941 * Like gtk_window_set_default_size(), but @width and @height are interpreted
3942 * in terms of the base size and increment set with
3943 * gtk_window_set_geometry_hints.
3948 gtk_window_set_default_geometry (GtkWindow *window,
3952 g_return_if_fail (GTK_IS_WINDOW (window));
3953 g_return_if_fail (width >= -1);
3954 g_return_if_fail (height >= -1);
3956 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
3960 * gtk_window_get_default_size:
3961 * @window: a #GtkWindow
3962 * @width: (out) (allow-none): location to store the default width, or %NULL
3963 * @height: (out) (allow-none): location to store the default height, or %NULL
3965 * Gets the default size of the window. A value of -1 for the width or
3966 * height indicates that a default size has not been explicitly set
3967 * for that dimension, so the "natural" size of the window will be
3972 gtk_window_get_default_size (GtkWindow *window,
3976 GtkWindowGeometryInfo *info;
3978 g_return_if_fail (GTK_IS_WINDOW (window));
3980 info = gtk_window_get_geometry_info (window, FALSE);
3983 *width = info ? info->default_width : -1;
3986 *height = info ? info->default_height : -1;
3990 * gtk_window_resize:
3991 * @window: a #GtkWindow
3992 * @width: width in pixels to resize the window to
3993 * @height: height in pixels to resize the window to
3995 * Resizes the window as if the user had done so, obeying geometry
3996 * constraints. The default geometry constraint is that windows may
3997 * not be smaller than their size request; to override this
3998 * constraint, call gtk_widget_set_size_request() to set the window's
3999 * request to a smaller value.
4001 * If gtk_window_resize() is called before showing a window for the
4002 * first time, it overrides any default size set with
4003 * gtk_window_set_default_size().
4005 * Windows may not be resized smaller than 1 by 1 pixels.
4009 gtk_window_resize (GtkWindow *window,
4013 GtkWindowGeometryInfo *info;
4015 g_return_if_fail (GTK_IS_WINDOW (window));
4016 g_return_if_fail (width > 0);
4017 g_return_if_fail (height > 0);
4019 info = gtk_window_get_geometry_info (window, TRUE);
4021 info->resize_width = width;
4022 info->resize_height = height;
4023 info->resize_is_geometry = FALSE;
4025 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4029 * gtk_window_resize_to_geometry:
4030 * @window: a #GtkWindow
4031 * @width: width in resize increments to resize the window to
4032 * @height: height in resize increments to resize the window to
4034 * Like gtk_window_resize(), but @width and @height are interpreted
4035 * in terms of the base size and increment set with
4036 * gtk_window_set_geometry_hints.
4041 gtk_window_resize_to_geometry (GtkWindow *window,
4045 GtkWindowGeometryInfo *info;
4047 g_return_if_fail (GTK_IS_WINDOW (window));
4048 g_return_if_fail (width > 0);
4049 g_return_if_fail (height > 0);
4051 info = gtk_window_get_geometry_info (window, TRUE);
4053 info->resize_width = width;
4054 info->resize_height = height;
4055 info->resize_is_geometry = TRUE;
4057 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4061 * gtk_window_get_size:
4062 * @window: a #GtkWindow
4063 * @width: (out) (allow-none): return location for width, or %NULL
4064 * @height: (out) (allow-none): return location for height, or %NULL
4066 * Obtains the current size of @window. If @window is not onscreen,
4067 * it returns the size GTK+ will suggest to the <link
4068 * linkend="gtk-X11-arch">window manager</link> for the initial window
4069 * size (but this is not reliably the same as the size the window
4070 * manager will actually select). The size obtained by
4071 * gtk_window_get_size() is the last size received in a
4072 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4073 * rather than querying the X server for the size. As a result, if you
4074 * call gtk_window_resize() then immediately call
4075 * gtk_window_get_size(), the size won't have taken effect yet. After
4076 * the window manager processes the resize request, GTK+ receives
4077 * notification that the size has changed via a configure event, and
4078 * the size of the window gets updated.
4080 * Note 1: Nearly any use of this function creates a race condition,
4081 * because the size of the window may change between the time that you
4082 * get the size and the time that you perform some action assuming
4083 * that size is the current size. To avoid race conditions, connect to
4084 * "configure-event" on the window and adjust your size-dependent
4085 * state to match the size delivered in the #GdkEventConfigure.
4087 * Note 2: The returned size does <emphasis>not</emphasis> include the
4088 * size of the window manager decorations (aka the window frame or
4089 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4090 * method of determining their size.
4092 * Note 3: If you are getting a window size in order to position
4093 * the window onscreen, there may be a better way. The preferred
4094 * way is to simply set the window's semantic type with
4095 * gtk_window_set_type_hint(), which allows the window manager to
4096 * e.g. center dialogs. Also, if you set the transient parent of
4097 * dialogs with gtk_window_set_transient_for() window managers
4098 * will often center the dialog over its parent window. It's
4099 * much preferred to let the window manager handle these
4100 * things rather than doing it yourself, because all apps will
4101 * behave consistently and according to user prefs if the window
4102 * manager handles it. Also, the window manager can take the size
4103 * of the window decorations/border into account, while your
4104 * application cannot.
4106 * In any case, if you insist on application-specified window
4107 * positioning, there's <emphasis>still</emphasis> a better way than
4108 * doing it yourself - gtk_window_set_position() will frequently
4109 * handle the details for you.
4113 gtk_window_get_size (GtkWindow *window,
4119 g_return_if_fail (GTK_IS_WINDOW (window));
4121 if (width == NULL && height == NULL)
4124 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4126 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4127 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4131 GdkRectangle configure_request;
4133 gtk_window_compute_configure_request (window,
4137 w = configure_request.width;
4138 h = configure_request.height;
4149 * @window: a #GtkWindow
4150 * @x: X coordinate to move window to
4151 * @y: Y coordinate to move window to
4153 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4154 * @window to the given position. Window managers are free to ignore
4155 * this; most window managers ignore requests for initial window
4156 * positions (instead using a user-defined placement algorithm) and
4157 * honor requests after the window has already been shown.
4159 * Note: the position is the position of the gravity-determined
4160 * reference point for the window. The gravity determines two things:
4161 * first, the location of the reference point in root window
4162 * coordinates; and second, which point on the window is positioned at
4163 * the reference point.
4165 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4166 * point is simply the @x, @y supplied to gtk_window_move(). The
4167 * top-left corner of the window decorations (aka window frame or
4168 * border) will be placed at @x, @y. Therefore, to position a window
4169 * at the top left of the screen, you want to use the default gravity
4170 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4172 * To position a window at the bottom right corner of the screen, you
4173 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4174 * point is at @x + the window width and @y + the window height, and
4175 * the bottom-right corner of the window border will be placed at that
4176 * reference point. So, to place a window in the bottom right corner
4177 * you would first set gravity to south east, then write:
4178 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4179 * gdk_screen_height () - window_height)</literal> (note that this
4180 * example does not take multi-head scenarios into account).
4182 * The Extended Window Manager Hints specification at <ulink
4183 * url="http://www.freedesktop.org/Standards/wm-spec">
4184 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4185 * nice table of gravities in the "implementation notes" section.
4187 * The gtk_window_get_position() documentation may also be relevant.
4190 gtk_window_move (GtkWindow *window,
4194 GtkWindowPrivate *priv;
4195 GtkWindowGeometryInfo *info;
4198 g_return_if_fail (GTK_IS_WINDOW (window));
4200 priv = window->priv;
4201 widget = GTK_WIDGET (window);
4203 info = gtk_window_get_geometry_info (window, TRUE);
4205 if (gtk_widget_get_mapped (widget))
4207 GtkAllocation allocation;
4209 gtk_widget_get_allocation (widget, &allocation);
4211 /* we have now sent a request with this position
4212 * with currently-active constraints, so toggle flag.
4214 info->position_constraints_changed = FALSE;
4216 /* we only constrain if mapped - if not mapped,
4217 * then gtk_window_compute_configure_request()
4218 * will apply the constraints later, and we
4219 * don't want to lose information about
4220 * what position the user set before then.
4221 * i.e. if you do a move() then turn off POS_CENTER
4222 * then show the window, your move() will work.
4224 gtk_window_constrain_position (window,
4225 allocation.width, allocation.height,
4228 /* Note that this request doesn't go through our standard request
4229 * framework, e.g. doesn't increment configure_request_count,
4230 * doesn't set info->last, etc.; that's because
4231 * we don't save the info needed to arrive at this same request
4234 * To gtk_window_move_resize(), this will end up looking exactly
4235 * the same as the position being changed by the window
4239 /* FIXME are we handling gravity properly for framed windows? */
4241 gdk_window_move (priv->frame,
4242 x - priv->frame_left,
4243 y - priv->frame_top);
4245 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)),
4250 /* Save this position to apply on mapping */
4251 info->initial_x = x;
4252 info->initial_y = y;
4253 info->initial_pos_set = TRUE;
4258 * gtk_window_get_position:
4259 * @window: a #GtkWindow
4260 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4261 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4263 * This function returns the position you need to pass to
4264 * gtk_window_move() to keep @window in its current position. This
4265 * means that the meaning of the returned value varies with window
4266 * gravity. See gtk_window_move() for more details.
4268 * If you haven't changed the window gravity, its gravity will be
4269 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4270 * gets the position of the top-left corner of the window manager
4271 * frame for the window. gtk_window_move() sets the position of this
4272 * same top-left corner.
4274 * gtk_window_get_position() is not 100% reliable because the X Window System
4275 * does not specify a way to obtain the geometry of the
4276 * decorations placed on a window by the window manager.
4277 * Thus GTK+ is using a "best guess" that works with most
4280 * Moreover, nearly all window managers are historically broken with
4281 * respect to their handling of window gravity. So moving a window to
4282 * its current position as returned by gtk_window_get_position() tends
4283 * to result in moving the window slightly. Window managers are
4284 * slowly getting better over time.
4286 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4287 * frame is not relevant, and thus gtk_window_get_position() will
4288 * always produce accurate results. However you can't use static
4289 * gravity to do things like place a window in a corner of the screen,
4290 * because static gravity ignores the window manager decorations.
4292 * If you are saving and restoring your application's window
4293 * positions, you should know that it's impossible for applications to
4294 * do this without getting it somewhat wrong because applications do
4295 * not have sufficient knowledge of window manager state. The Correct
4296 * Mechanism is to support the session management protocol (see the
4297 * "GnomeClient" object in the GNOME libraries for example) and allow
4298 * the window manager to save your window sizes and positions.
4303 gtk_window_get_position (GtkWindow *window,
4307 GtkWindowPrivate *priv;
4309 GdkWindow *gdk_window;
4311 g_return_if_fail (GTK_IS_WINDOW (window));
4313 priv = window->priv;
4314 widget = GTK_WIDGET (window);
4315 gdk_window = gtk_widget_get_window (widget);
4317 if (priv->gravity == GDK_GRAVITY_STATIC)
4319 if (gtk_widget_get_mapped (widget))
4321 /* This does a server round-trip, which is sort of wrong;
4322 * but a server round-trip is inevitable for
4323 * gdk_window_get_frame_extents() in the usual
4324 * NorthWestGravity case below, so not sure what else to
4325 * do. We should likely be consistent about whether we get
4326 * the client-side info or the server-side info.
4328 gdk_window_get_origin (gdk_window, root_x, root_y);
4332 GdkRectangle configure_request;
4334 gtk_window_compute_configure_request (window,
4338 *root_x = configure_request.x;
4339 *root_y = configure_request.y;
4344 GdkRectangle frame_extents;
4349 if (gtk_widget_get_mapped (widget))
4352 gdk_window_get_frame_extents (priv->frame, &frame_extents);
4354 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4355 x = frame_extents.x;
4356 y = frame_extents.y;
4357 gtk_window_get_size (window, &w, &h);
4361 /* We just say the frame has 0 size on all sides.
4362 * Not sure what else to do.
4364 gtk_window_compute_configure_request (window,
4367 x = frame_extents.x;
4368 y = frame_extents.y;
4369 w = frame_extents.width;
4370 h = frame_extents.height;
4373 switch (priv->gravity)
4375 case GDK_GRAVITY_NORTH:
4376 case GDK_GRAVITY_CENTER:
4377 case GDK_GRAVITY_SOUTH:
4378 /* Find center of frame. */
4379 x += frame_extents.width / 2;
4380 /* Center client window on that point. */
4384 case GDK_GRAVITY_SOUTH_EAST:
4385 case GDK_GRAVITY_EAST:
4386 case GDK_GRAVITY_NORTH_EAST:
4387 /* Find right edge of frame */
4388 x += frame_extents.width;
4389 /* Align left edge of client at that point. */
4396 switch (priv->gravity)
4398 case GDK_GRAVITY_WEST:
4399 case GDK_GRAVITY_CENTER:
4400 case GDK_GRAVITY_EAST:
4401 /* Find center of frame. */
4402 y += frame_extents.height / 2;
4403 /* Center client window there. */
4406 case GDK_GRAVITY_SOUTH_WEST:
4407 case GDK_GRAVITY_SOUTH:
4408 case GDK_GRAVITY_SOUTH_EAST:
4409 /* Find south edge of frame */
4410 y += frame_extents.height;
4411 /* Place bottom edge of client there */
4426 * gtk_window_reshow_with_initial_size:
4427 * @window: a #GtkWindow
4429 * Hides @window, then reshows it, resetting the
4430 * default size and position of the window. Used
4431 * by GUI builders only.
4434 gtk_window_reshow_with_initial_size (GtkWindow *window)
4438 g_return_if_fail (GTK_IS_WINDOW (window));
4440 widget = GTK_WIDGET (window);
4442 gtk_widget_hide (widget);
4443 gtk_widget_unrealize (widget);
4444 gtk_widget_show (widget);
4448 gtk_window_destroy (GtkWidget *widget)
4450 GtkWindow *window = GTK_WINDOW (widget);
4451 GtkWindowPrivate *priv = window->priv;
4453 toplevel_list = g_slist_remove (toplevel_list, window);
4455 if (priv->transient_parent)
4456 gtk_window_set_transient_for (window, NULL);
4458 /* frees the icons */
4459 gtk_window_set_icon_list (window, NULL);
4461 if (priv->has_user_ref_count)
4463 priv->has_user_ref_count = FALSE;
4464 g_object_unref (window);
4468 gtk_window_group_remove_window (priv->group, window);
4470 gtk_window_free_key_hash (window);
4472 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4476 gtk_window_finalize (GObject *object)
4478 GtkWindow *window = GTK_WINDOW (object);
4479 GtkWindowPrivate *priv = window->priv;
4480 GtkMnemonicHash *mnemonic_hash;
4482 g_free (priv->title);
4483 g_free (priv->wmclass_name);
4484 g_free (priv->wmclass_class);
4485 g_free (priv->wm_role);
4487 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4489 _gtk_mnemonic_hash_free (mnemonic_hash);
4491 if (priv->geometry_info)
4493 if (priv->geometry_info->widget)
4494 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4495 gtk_widget_destroyed,
4496 &priv->geometry_info->widget);
4497 g_free (priv->geometry_info);
4500 if (priv->keys_changed_handler)
4502 g_source_remove (priv->keys_changed_handler);
4503 priv->keys_changed_handler = 0;
4507 g_signal_handlers_disconnect_by_func (priv->screen,
4508 gtk_window_on_composited_changed, window);
4510 g_free (priv->startup_id);
4512 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4516 gtk_window_show (GtkWidget *widget)
4518 GtkWindow *window = GTK_WINDOW (widget);
4519 GtkWindowPrivate *priv = window->priv;
4520 GtkContainer *container = GTK_CONTAINER (window);
4521 gboolean need_resize;
4523 _gtk_widget_set_visible_flag (widget, TRUE);
4525 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4526 _gtk_container_set_need_resize (container, FALSE);
4530 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4531 GtkAllocation allocation = { 0, 0 };
4532 GdkRectangle configure_request;
4533 GdkGeometry new_geometry;
4535 gboolean was_realized;
4537 /* We are going to go ahead and perform this configure request
4538 * and then emulate a configure notify by going ahead and
4539 * doing a size allocate. Sort of a synchronous
4540 * mini-copy of gtk_window_move_resize() here.
4542 gtk_window_compute_configure_request (window,
4547 /* We update this because we are going to go ahead
4548 * and gdk_window_resize() below, rather than
4551 info->last.configure_request.width = configure_request.width;
4552 info->last.configure_request.height = configure_request.height;
4554 /* and allocate the window - this is normally done
4555 * in move_resize in response to configure notify
4557 allocation.width = configure_request.width;
4558 allocation.height = configure_request.height;
4559 gtk_widget_size_allocate (widget, &allocation);
4561 /* Then we guarantee we have a realize */
4562 was_realized = FALSE;
4563 if (!gtk_widget_get_realized (widget))
4565 gtk_widget_realize (widget);
4566 was_realized = TRUE;
4569 /* Must be done after the windows are realized,
4570 * so that the decorations can be read
4572 gtk_decorated_window_calculate_frame_size (window);
4574 /* We only send configure request if we didn't just finish
4575 * creating the window; if we just created the window
4576 * then we created it with widget->allocation anyhow.
4579 gdk_window_move_resize (gtk_widget_get_window (widget),
4580 configure_request.x,
4581 configure_request.y,
4582 configure_request.width,
4583 configure_request.height);
4586 gtk_container_check_resize (container);
4588 gtk_widget_map (widget);
4590 /* Try to make sure that we have some focused widget
4592 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4593 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4596 gtk_grab_add (widget);
4600 gtk_window_hide (GtkWidget *widget)
4602 GtkWindow *window = GTK_WINDOW (widget);
4603 GtkWindowPrivate *priv = window->priv;
4605 _gtk_widget_set_visible_flag (widget, FALSE);
4606 gtk_widget_unmap (widget);
4609 gtk_grab_remove (widget);
4613 gtk_window_map (GtkWidget *widget)
4616 GtkWindow *window = GTK_WINDOW (widget);
4617 GtkWindowPrivate *priv = window->priv;
4618 GdkWindow *toplevel;
4619 GdkWindow *gdk_window;
4620 gboolean auto_mnemonics;
4622 gdk_window = gtk_widget_get_window (widget);
4624 gtk_widget_set_mapped (widget, TRUE);
4626 child = gtk_bin_get_child (&(window->bin));
4628 gtk_widget_get_visible (child) &&
4629 !gtk_widget_get_mapped (child))
4630 gtk_widget_map (child);
4633 toplevel = priv->frame;
4635 toplevel = gdk_window;
4637 if (priv->maximize_initially)
4638 gdk_window_maximize (toplevel);
4640 gdk_window_unmaximize (toplevel);
4642 if (priv->stick_initially)
4643 gdk_window_stick (toplevel);
4645 gdk_window_unstick (toplevel);
4647 if (priv->iconify_initially)
4648 gdk_window_iconify (toplevel);
4650 gdk_window_deiconify (toplevel);
4652 if (priv->fullscreen_initially)
4653 gdk_window_fullscreen (toplevel);
4655 gdk_window_unfullscreen (toplevel);
4657 gdk_window_set_keep_above (toplevel, priv->above_initially);
4659 gdk_window_set_keep_below (toplevel, priv->below_initially);
4661 /* No longer use the default settings */
4662 priv->need_default_size = FALSE;
4663 priv->need_default_position = FALSE;
4665 if (priv->reset_type_hint)
4667 /* We should only reset the type hint when the application
4668 * used gtk_window_set_type_hint() to change the hint.
4669 * Some applications use X directly to change the properties;
4670 * in that case, we shouldn't overwrite what they did.
4672 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4673 priv->reset_type_hint = FALSE;
4676 gdk_window_show (gdk_window);
4679 gdk_window_show (priv->frame);
4681 if (priv->grip_window)
4682 gdk_window_show (priv->grip_window);
4684 if (!disable_startup_notification)
4686 /* Do we have a custom startup-notification id? */
4687 if (priv->startup_id != NULL)
4689 /* Make sure we have a "real" id */
4690 if (!startup_id_is_fake (priv->startup_id))
4691 gdk_notify_startup_complete_with_id (priv->startup_id);
4693 g_free (priv->startup_id);
4694 priv->startup_id = NULL;
4696 else if (!sent_startup_notification)
4698 sent_startup_notification = TRUE;
4699 gdk_notify_startup_complete ();
4703 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4704 * (as in the case of popup menus), then hide mnemonics initially
4706 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4707 &auto_mnemonics, NULL);
4708 if (auto_mnemonics && !priv->mnemonics_visible_set)
4709 gtk_window_set_mnemonics_visible (window, FALSE);
4713 gtk_window_map_event (GtkWidget *widget,
4716 if (!gtk_widget_get_mapped (widget))
4718 /* we should be be unmapped, but are getting a MapEvent, this may happen
4719 * to toplevel XWindows if mapping was intercepted by a window manager
4720 * and an unmap request occoured while the MapRequestEvent was still
4721 * being handled. we work around this situaiton here by re-requesting
4722 * the window being unmapped. more details can be found in:
4723 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4725 gdk_window_hide (gtk_widget_get_window (widget));
4731 gtk_window_unmap (GtkWidget *widget)
4733 GtkWindow *window = GTK_WINDOW (widget);
4734 GtkWindowPrivate *priv = window->priv;
4735 GtkWindowGeometryInfo *info;
4736 GdkWindow *gdk_window;
4737 GdkWindowState state;
4739 gdk_window = gtk_widget_get_window (widget);
4741 gtk_widget_set_mapped (widget, FALSE);
4743 gdk_window_withdraw (priv->frame);
4745 gdk_window_withdraw (gdk_window);
4747 priv->configure_request_count = 0;
4748 priv->configure_notify_received = FALSE;
4750 /* on unmap, we reset the default positioning of the window,
4751 * so it's placed again, but we don't reset the default
4752 * size of the window, so it's remembered.
4754 priv->need_default_position = TRUE;
4756 info = gtk_window_get_geometry_info (window, FALSE);
4759 info->initial_pos_set = FALSE;
4760 info->position_constraints_changed = FALSE;
4763 state = gdk_window_get_state (gdk_window);
4764 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4765 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4766 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4767 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4768 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4772 gtk_window_realize (GtkWidget *widget)
4774 GtkAllocation allocation;
4777 GdkWindow *parent_window;
4778 GdkWindow *gdk_window;
4779 GdkWindowAttr attributes;
4780 gint attributes_mask;
4781 GtkWindowPrivate *priv;
4783 window = GTK_WINDOW (widget);
4784 priv = window->priv;
4786 gtk_widget_get_allocation (widget, &allocation);
4788 /* ensure widget tree is properly size allocated */
4789 if (allocation.x == -1 &&
4790 allocation.y == -1 &&
4791 allocation.width == 1 &&
4792 allocation.height == 1)
4794 GtkRequisition requisition;
4798 allocation.width = 200;
4799 allocation.height = 200;
4801 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4802 if (requisition.width || requisition.height)
4804 /* non-empty window */
4805 allocation.width = requisition.width;
4806 allocation.height = requisition.height;
4808 gtk_widget_size_allocate (widget, &allocation);
4810 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4812 g_return_if_fail (!gtk_widget_get_realized (widget));
4815 gtk_widget_set_realized (widget, TRUE);
4819 case GTK_WINDOW_TOPLEVEL:
4820 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4822 case GTK_WINDOW_POPUP:
4823 attributes.window_type = GDK_WINDOW_TEMP;
4826 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4830 attributes.title = priv->title;
4831 attributes.wmclass_name = priv->wmclass_name;
4832 attributes.wmclass_class = priv->wmclass_class;
4833 attributes.wclass = GDK_INPUT_OUTPUT;
4834 attributes.visual = gtk_widget_get_visual (widget);
4836 if (priv->has_frame)
4838 gtk_widget_get_allocation (widget, &allocation);
4839 attributes.width = allocation.width + priv->frame_left + priv->frame_right;
4840 attributes.height = allocation.height + priv->frame_top + priv->frame_bottom;
4841 attributes.event_mask = (GDK_EXPOSURE_MASK |
4842 GDK_KEY_PRESS_MASK |
4843 GDK_ENTER_NOTIFY_MASK |
4844 GDK_LEAVE_NOTIFY_MASK |
4845 GDK_FOCUS_CHANGE_MASK |
4846 GDK_STRUCTURE_MASK |
4847 GDK_BUTTON_MOTION_MASK |
4848 GDK_POINTER_MOTION_HINT_MASK |
4849 GDK_BUTTON_PRESS_MASK |
4850 GDK_BUTTON_RELEASE_MASK);
4852 attributes_mask = GDK_WA_VISUAL;
4854 priv->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4855 &attributes, attributes_mask);
4857 if (priv->opacity_set)
4858 gdk_window_set_opacity (priv->frame, priv->opacity);
4860 gdk_window_set_user_data (priv->frame, widget);
4862 attributes.window_type = GDK_WINDOW_CHILD;
4863 attributes.x = priv->frame_left;
4864 attributes.y = priv->frame_top;
4866 attributes_mask = GDK_WA_X | GDK_WA_Y;
4868 parent_window = priv->frame;
4870 g_signal_connect (window,
4872 G_CALLBACK (gtk_window_event),
4877 attributes_mask = 0;
4878 parent_window = gtk_widget_get_root_window (widget);
4881 gtk_widget_get_allocation (widget, &allocation);
4882 attributes.width = allocation.width;
4883 attributes.height = allocation.height;
4884 attributes.event_mask = gtk_widget_get_events (widget);
4885 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4886 GDK_KEY_PRESS_MASK |
4887 GDK_KEY_RELEASE_MASK |
4888 GDK_ENTER_NOTIFY_MASK |
4889 GDK_LEAVE_NOTIFY_MASK |
4890 GDK_FOCUS_CHANGE_MASK |
4891 GDK_STRUCTURE_MASK);
4892 attributes.type_hint = priv->type_hint;
4894 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4895 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4896 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4898 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4899 gtk_widget_set_window (widget, gdk_window);
4901 if (!priv->has_frame && priv->opacity_set)
4902 gdk_window_set_opacity (gdk_window, priv->opacity);
4904 gdk_window_enable_synchronized_configure (gdk_window);
4906 gdk_window_set_user_data (gdk_window, window);
4908 gtk_widget_style_attach (widget);
4909 style = gtk_widget_get_style (widget);
4910 gtk_style_set_background (style, gdk_window, GTK_STATE_NORMAL);
4912 gtk_style_set_background (style, priv->frame, GTK_STATE_NORMAL);
4914 if (priv->transient_parent &&
4915 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
4916 gdk_window_set_transient_for (gdk_window,
4917 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
4920 gdk_window_set_role (gdk_window, priv->wm_role);
4922 if (!priv->decorated)
4923 gdk_window_set_decorations (gdk_window, 0);
4925 if (!priv->deletable)
4926 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4928 if (gtk_window_get_skip_pager_hint (window))
4929 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
4931 if (gtk_window_get_skip_taskbar_hint (window))
4932 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
4934 if (gtk_window_get_accept_focus (window))
4935 gdk_window_set_accept_focus (gdk_window, TRUE);
4937 gdk_window_set_accept_focus (gdk_window, FALSE);
4939 if (gtk_window_get_focus_on_map (window))
4940 gdk_window_set_focus_on_map (gdk_window, TRUE);
4942 gdk_window_set_focus_on_map (gdk_window, FALSE);
4945 gdk_window_set_modal_hint (gdk_window, TRUE);
4947 gdk_window_set_modal_hint (gdk_window, FALSE);
4949 if (priv->startup_id)
4951 #ifdef GDK_WINDOWING_X11
4952 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4953 if (timestamp != GDK_CURRENT_TIME)
4954 gdk_x11_window_set_user_time (gdk_window, timestamp);
4956 if (!startup_id_is_fake (priv->startup_id))
4957 gdk_window_set_startup_id (gdk_window, priv->startup_id);
4961 gtk_window_realize_icon (window);
4963 if (priv->has_resize_grip)
4964 resize_grip_create_window (window);
4968 gtk_window_unrealize (GtkWidget *widget)
4970 GtkWindow *window = GTK_WINDOW (widget);
4971 GtkWindowPrivate *priv = window->priv;
4972 GtkWindowGeometryInfo *info;
4974 /* On unrealize, we reset the size of the window such
4975 * that we will re-apply the default sizing stuff
4976 * next time we show the window.
4978 * Default positioning is reset on unmap, instead of unrealize.
4980 priv->need_default_size = TRUE;
4981 info = gtk_window_get_geometry_info (window, FALSE);
4984 info->resize_width = -1;
4985 info->resize_height = -1;
4986 info->last.configure_request.x = 0;
4987 info->last.configure_request.y = 0;
4988 info->last.configure_request.width = -1;
4989 info->last.configure_request.height = -1;
4990 /* be sure we reset geom hints on re-realize */
4991 info->last.flags = 0;
4996 gdk_window_set_user_data (priv->frame, NULL);
4997 gdk_window_destroy (priv->frame);
5002 gtk_window_unrealize_icon (window);
5004 if (priv->grip_window != NULL)
5005 resize_grip_destroy_window (window);
5007 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5010 static GdkWindowEdge
5011 get_grip_edge (GtkWidget *widget)
5013 return gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR
5014 ? GDK_WINDOW_EDGE_SOUTH_EAST
5015 : GDK_WINDOW_EDGE_SOUTH_WEST;
5018 static GdkWindowEdge
5019 get_drag_edge (GtkWidget *widget)
5021 GdkGeometry geometry;
5023 gboolean hresizable;
5024 gboolean vresizable;
5025 GtkTextDirection dir;
5028 gtk_window_compute_hints (GTK_WINDOW (widget), &geometry, &flags);
5030 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5032 hresizable = geometry.min_width < geometry.max_width;
5033 vresizable = geometry.min_height < geometry.max_height;
5041 dir = gtk_widget_get_direction (widget);
5043 if (hresizable && vresizable)
5044 edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5045 else if (hresizable)
5046 edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5047 else if (vresizable)
5048 edge = GDK_WINDOW_EDGE_SOUTH;
5050 edge = (GdkWindowEdge)-1;
5056 set_grip_cursor (GtkWindow *window)
5058 GtkWidget *widget = GTK_WIDGET (window);
5059 GtkWindowPrivate *priv = window->priv;
5061 GdkDisplay *display;
5062 GdkCursorType cursor_type;
5065 if (priv->grip_window == NULL)
5068 if (gtk_widget_is_sensitive (widget))
5070 edge = get_drag_edge (widget);
5073 case GDK_WINDOW_EDGE_EAST:
5074 cursor_type = GDK_RIGHT_SIDE;
5076 case GDK_WINDOW_EDGE_SOUTH_EAST:
5077 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5079 case GDK_WINDOW_EDGE_SOUTH:
5080 cursor_type = GDK_BOTTOM_SIDE;
5082 case GDK_WINDOW_EDGE_SOUTH_WEST:
5083 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5085 case GDK_WINDOW_EDGE_WEST:
5086 cursor_type = GDK_LEFT_SIDE;
5089 cursor_type = GDK_LEFT_PTR;
5093 display = gtk_widget_get_display (widget);
5094 cursor = gdk_cursor_new_for_display (display, cursor_type);
5095 gdk_window_set_cursor (priv->grip_window, cursor);
5096 gdk_cursor_unref (cursor);
5099 gdk_window_set_cursor (priv->grip_window, NULL);
5103 set_grip_shape (GtkWindow *window)
5105 GtkWindowPrivate *priv = window->priv;
5106 cairo_region_t *region;
5107 cairo_surface_t *surface;
5109 double width, height;
5111 if (priv->grip_window == NULL)
5114 width = gdk_window_get_width (priv->grip_window);
5115 height = gdk_window_get_height (priv->grip_window);
5116 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5118 cr = cairo_create (surface);
5119 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5121 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5122 if (get_grip_edge (GTK_WIDGET (window)) == GDK_WINDOW_EDGE_SOUTH_EAST)
5124 cairo_move_to (cr, width, 0.0);
5125 cairo_line_to (cr, width, height);
5126 cairo_line_to (cr, 0.0, height);
5130 cairo_move_to (cr, 0.0, 0.0);
5131 cairo_line_to (cr, width, height);
5132 cairo_line_to (cr, 0.0, height);
5134 cairo_close_path (cr);
5137 region = gdk_cairo_region_create_from_surface (surface);
5138 cairo_surface_destroy (surface);
5140 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5141 cairo_region_destroy (region);
5145 set_grip_position (GtkWindow *window)
5147 GtkWindowPrivate *priv = window->priv;
5150 if (priv->grip_window == NULL)
5153 gtk_window_get_resize_grip_area (window, &rect);
5154 gdk_window_raise (priv->grip_window);
5155 gdk_window_move_resize (priv->grip_window,
5157 rect.width, rect.height);
5161 gtk_window_size_allocate (GtkWidget *widget,
5162 GtkAllocation *allocation)
5164 GtkWindow *window = GTK_WINDOW (widget);
5165 GtkWindowPrivate *priv = window->priv;
5166 GtkAllocation child_allocation;
5170 gtk_widget_set_allocation (widget, allocation);
5172 child = gtk_bin_get_child (&(window->bin));
5173 if (child && gtk_widget_get_visible (child))
5175 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5176 child_allocation.x = border_width;
5177 child_allocation.y = border_width;
5178 child_allocation.width =
5179 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5180 child_allocation.height =
5181 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5183 gtk_widget_size_allocate (child, &child_allocation);
5186 if (gtk_widget_get_realized (widget))
5189 gdk_window_resize (priv->frame,
5190 allocation->width + priv->frame_left + priv->frame_right,
5191 allocation->height + priv->frame_top + priv->frame_bottom);
5192 set_grip_position (window);
5197 gtk_window_event (GtkWidget *widget, GdkEvent *event)
5199 GtkWindow *window = GTK_WINDOW (widget);
5200 GtkWindowPrivate *priv = window->priv;
5201 gboolean return_val;
5203 if (priv->frame && (event->any.window == priv->frame))
5205 if ((event->type != GDK_KEY_PRESS) &&
5206 (event->type != GDK_KEY_RELEASE) &&
5207 (event->type != GDK_FOCUS_CHANGE))
5209 g_signal_stop_emission_by_name (widget, "event");
5211 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
5216 g_object_unref (event->any.window);
5217 event->any.window = g_object_ref (gtk_widget_get_window (widget));
5225 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
5227 GtkWindowPrivate *priv = window->priv;
5228 GdkEventConfigure *configure_event;
5231 switch (event->type)
5234 configure_event = (GdkEventConfigure *)event;
5236 /* Invalidate the decorations */
5239 rect.width = configure_event->width;
5240 rect.height = configure_event->height;
5242 gdk_window_invalidate_rect (priv->frame, &rect, FALSE);
5244 /* Pass on the (modified) configure event */
5245 configure_event->width -= priv->frame_left + priv->frame_right;
5246 configure_event->height -= priv->frame_top + priv->frame_bottom;
5247 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
5256 gtk_window_configure_event (GtkWidget *widget,
5257 GdkEventConfigure *event)
5259 GtkAllocation allocation;
5260 GtkWindow *window = GTK_WINDOW (widget);
5261 GtkWindowPrivate *priv = window->priv;
5262 gboolean expected_reply = priv->configure_request_count > 0;
5264 /* priv->configure_request_count incremented for each
5265 * configure request, and decremented to a min of 0 for
5266 * each configure notify.
5268 * All it means is that we know we will get at least
5269 * priv->configure_request_count more configure notifies.
5270 * We could get more configure notifies than that; some
5271 * of the configure notifies we get may be unrelated to
5272 * the configure requests. But we will get at least
5273 * priv->configure_request_count notifies.
5276 if (priv->configure_request_count > 0)
5278 priv->configure_request_count -= 1;
5279 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5282 /* As an optimization, we avoid a resize when possible.
5284 * The only times we can avoid a resize are:
5285 * - we know only the position changed, not the size
5286 * - we know we have made more requests and so will get more
5287 * notifies and can wait to resize when we get them
5289 gtk_widget_get_allocation (widget, &allocation);
5290 if (!expected_reply &&
5291 (allocation.width == event->width &&
5292 allocation.height == event->height))
5294 gdk_window_configure_finished (gtk_widget_get_window (widget));
5299 * If we do need to resize, we do that by:
5300 * - filling in widget->allocation with the new size
5301 * - setting configure_notify_received to TRUE
5302 * for use in gtk_window_move_resize()
5303 * - queueing a resize, leading to invocation of
5304 * gtk_window_move_resize() in an idle handler
5308 priv->configure_notify_received = TRUE;
5310 allocation.width = event->width;
5311 allocation.height = event->height;
5312 gtk_widget_set_allocation (widget, &allocation);
5314 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5316 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5322 gtk_window_state_event (GtkWidget *widget,
5323 GdkEventWindowState *event)
5325 update_grip_visibility (GTK_WINDOW (widget));
5331 gtk_window_direction_changed (GtkWidget *widget,
5332 GtkTextDirection prev_dir)
5334 GtkWindow *window = GTK_WINDOW (widget);
5336 set_grip_cursor (window);
5337 set_grip_position (window);
5338 set_grip_shape (window);
5342 gtk_window_state_changed (GtkWidget *widget,
5343 GtkStateType previous_state)
5345 GtkWindow *window = GTK_WINDOW (widget);
5347 set_grip_cursor (window);
5348 update_grip_visibility (window);
5352 resize_grip_create_window (GtkWindow *window)
5355 GtkWindowPrivate *priv;
5356 GdkWindowAttr attributes;
5357 gint attributes_mask;
5360 priv = window->priv;
5361 widget = GTK_WIDGET (window);
5363 g_return_if_fail (gtk_widget_get_realized (widget));
5364 g_return_if_fail (priv->grip_window == NULL);
5366 gtk_window_get_resize_grip_area (window, &rect);
5368 attributes.x = rect.x;
5369 attributes.y = rect.y;
5370 attributes.width = rect.width;
5371 attributes.height = rect.height;
5372 attributes.window_type = GDK_WINDOW_CHILD;
5373 attributes.wclass = GDK_INPUT_OUTPUT;
5374 attributes.event_mask = gtk_widget_get_events (widget) |
5376 GDK_BUTTON_PRESS_MASK;
5378 attributes_mask = GDK_WA_X | GDK_WA_Y;
5380 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5384 gdk_window_set_user_data (priv->grip_window, widget);
5386 gdk_window_raise (priv->grip_window);
5388 set_grip_cursor (window);
5389 set_grip_shape (window);
5390 update_grip_visibility (window);
5394 resize_grip_destroy_window (GtkWindow *window)
5396 GtkWindowPrivate *priv = window->priv;
5398 gdk_window_set_user_data (priv->grip_window, NULL);
5399 gdk_window_destroy (priv->grip_window);
5400 priv->grip_window = NULL;
5401 update_grip_visibility (window);
5405 * gtk_window_set_has_resize_grip:
5406 * @window: a #GtkWindow
5407 * @value: %TRUE to allow a resize grip
5409 * Sets whether @window has a corner resize grip.
5411 * Note that the resize grip is only shown if the window
5412 * is actually resizable and not maximized. Use
5413 * gtk_window_resize_grip_is_visible() to find out if the
5414 * resize grip is currently shown.
5419 gtk_window_set_has_resize_grip (GtkWindow *window,
5422 GtkWidget *widget = GTK_WIDGET (window);
5423 GtkWindowPrivate *priv = window->priv;
5425 value = value != FALSE;
5427 if (value != priv->has_resize_grip)
5429 priv->has_resize_grip = value;
5430 gtk_widget_queue_draw (widget);
5432 if (gtk_widget_get_realized (widget))
5434 if (priv->has_resize_grip && priv->grip_window == NULL)
5435 resize_grip_create_window (window);
5436 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5437 resize_grip_destroy_window (window);
5440 g_object_notify (G_OBJECT (window), "has-resize-grip");
5445 update_grip_visibility (GtkWindow *window)
5447 GtkWindowPrivate *priv = window->priv;
5450 val = gtk_window_resize_grip_is_visible (window);
5452 if (priv->grip_window != NULL)
5455 gdk_window_show (priv->grip_window);
5457 gdk_window_hide (priv->grip_window);
5460 if (priv->resize_grip_visible != val)
5462 priv->resize_grip_visible = val;
5464 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5469 * gtk_window_resize_grip_is_visible:
5470 * @window: a #GtkWindow
5472 * Determines whether a resize grip is visible for the specified window.
5474 * Returns %TRUE if a resize grip exists and is visible.
5479 gtk_window_resize_grip_is_visible (GtkWindow *window)
5481 GtkWindowPrivate *priv;
5483 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5485 priv = window->priv;
5487 if (priv->type == GTK_WINDOW_POPUP)
5490 if (!priv->resizable)
5493 if (gtk_widget_get_realized (GTK_WIDGET (window)))
5495 GdkWindowState state;
5497 state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)));
5499 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5503 return window->priv->has_resize_grip;
5507 * gtk_window_get_has_resize_grip:
5508 * @window: a #GtkWindow
5510 * Determines whether the window may have a resize grip.
5512 * Returns: %TRUE if the window has a resize grip.
5517 gtk_window_get_has_resize_grip (GtkWindow *window)
5519 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5521 return window->priv->has_resize_grip;
5525 * gtk_window_get_resize_grip_area:
5526 * @window: a #GtkWindow
5527 * @rect: a pointer to a #GdkRectangle which we should store the
5530 * If a window has a resize grip, this will retrieve the grip
5531 * position, width and height into the specified #GdkRectangle.
5533 * Returns: %TRUE if the resize grip's area was retrieved.
5538 gtk_window_get_resize_grip_area (GtkWindow *window,
5541 GtkWidget *widget = GTK_WIDGET (window);
5542 GtkAllocation allocation;
5547 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5549 if (!window->priv->has_resize_grip)
5552 gtk_widget_get_allocation (widget, &allocation);
5553 style = gtk_widget_get_style (widget);
5555 gtk_widget_style_get (widget,
5556 "resize-grip-width", &grip_width,
5557 "resize-grip-height", &grip_height,
5560 if (grip_width > allocation.width)
5561 grip_width = allocation.width;
5563 if (grip_height > allocation.height)
5564 grip_height = allocation.height;
5566 rect->width = grip_width;
5567 rect->height = grip_height;
5568 rect->y = allocation.y + allocation.height - grip_height;
5570 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5571 rect->x = allocation.x + allocation.width - grip_width;
5573 rect->x = allocation.x;
5578 /* the accel_key and accel_mods fields of the key have to be setup
5579 * upon calling this function. it'll then return whether that key
5580 * is at all used as accelerator, and if so will OR in the
5581 * accel_flags member of the key.
5584 _gtk_window_query_nonaccels (GtkWindow *window,
5586 GdkModifierType accel_mods)
5588 GtkWindowPrivate *priv;
5590 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5592 priv = window->priv;
5594 /* movement keys are considered locked accels */
5597 static const guint bindings[] = {
5598 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,
5599 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,
5603 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5604 if (bindings[i] == accel_key)
5608 /* mnemonics are considered locked accels */
5609 if (accel_mods == priv->mnemonic_modifier)
5611 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5612 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5620 * gtk_window_propagate_key_event:
5621 * @window: a #GtkWindow
5622 * @event: a #GdkEventKey
5624 * Propagate a key press or release event to the focus widget and
5625 * up the focus container chain until a widget handles @event.
5626 * This is normally called by the default ::key_press_event and
5627 * ::key_release_event handlers for toplevel windows,
5628 * however in some cases it may be useful to call this directly when
5629 * overriding the standard key handling for a toplevel window.
5631 * Return value: %TRUE if a widget in the focus chain handled the event.
5636 gtk_window_propagate_key_event (GtkWindow *window,
5639 GtkWindowPrivate *priv;
5640 gboolean handled = FALSE;
5641 GtkWidget *widget, *focus;
5643 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5645 priv = window->priv;
5646 widget = GTK_WIDGET (window);
5648 focus = priv->focus_widget;
5650 g_object_ref (focus);
5653 focus && focus != widget &&
5654 gtk_widget_get_toplevel (focus) == widget)
5658 if (gtk_widget_is_sensitive (focus))
5659 handled = gtk_widget_event (focus, (GdkEvent*) event);
5661 parent = gtk_widget_get_parent (focus);
5663 g_object_ref (parent);
5665 g_object_unref (focus);
5671 g_object_unref (focus);
5677 gtk_window_key_press_event (GtkWidget *widget,
5680 GtkWindow *window = GTK_WINDOW (widget);
5681 gboolean handled = FALSE;
5683 /* handle mnemonics and accelerators */
5685 handled = gtk_window_activate_key (window, event);
5687 /* handle focus widget key events */
5689 handled = gtk_window_propagate_key_event (window, event);
5691 /* Chain up, invokes binding set */
5693 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5699 gtk_window_key_release_event (GtkWidget *widget,
5702 GtkWindow *window = GTK_WINDOW (widget);
5703 gboolean handled = FALSE;
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_release_event (widget, event);
5717 gtk_window_button_press_event (GtkWidget *widget,
5718 GdkEventButton *event)
5720 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5722 if (event->window == priv->grip_window)
5724 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5725 get_drag_edge (widget),
5738 gtk_window_real_activate_default (GtkWindow *window)
5740 gtk_window_activate_default (window);
5744 gtk_window_real_activate_focus (GtkWindow *window)
5746 gtk_window_activate_focus (window);
5750 gtk_window_move_focus (GtkWindow *window,
5751 GtkDirectionType dir)
5753 gtk_widget_child_focus (GTK_WIDGET (window), dir);
5755 if (!gtk_container_get_focus_child (GTK_CONTAINER (window)))
5756 gtk_window_set_focus (window, NULL);
5760 gtk_window_enter_notify_event (GtkWidget *widget,
5761 GdkEventCrossing *event)
5767 gtk_window_leave_notify_event (GtkWidget *widget,
5768 GdkEventCrossing *event)
5774 do_focus_change (GtkWidget *widget,
5778 GdkDeviceManager *device_manager;
5781 g_object_ref (widget);
5783 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5784 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5785 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5786 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5788 for (d = devices; d; d = d->next)
5790 GdkDevice *dev = d->data;
5793 if (dev->source != GDK_SOURCE_KEYBOARD)
5796 /* Skip non-master keyboards that haven't
5797 * selected for events from this window
5799 window = gtk_widget_get_window (widget);
5800 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5801 window && !gdk_window_get_device_events (window, dev))
5804 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5806 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5807 fevent->focus_change.window = window;
5809 g_object_ref (window);
5810 fevent->focus_change.in = in;
5811 gdk_event_set_device (fevent, dev);
5813 gtk_widget_send_focus_change (widget, fevent);
5815 gdk_event_free (fevent);
5818 g_list_free (devices);
5819 g_object_unref (widget);
5823 gtk_window_focus_in_event (GtkWidget *widget,
5824 GdkEventFocus *event)
5826 GtkWindow *window = GTK_WINDOW (widget);
5828 /* It appears spurious focus in events can occur when
5829 * the window is hidden. So we'll just check to see if
5830 * the window is visible before actually handling the
5833 if (gtk_widget_get_visible (widget))
5835 _gtk_window_set_has_toplevel_focus (window, TRUE);
5836 _gtk_window_set_is_active (window, TRUE);
5843 gtk_window_focus_out_event (GtkWidget *widget,
5844 GdkEventFocus *event)
5846 GtkWindow *window = GTK_WINDOW (widget);
5847 gboolean auto_mnemonics;
5849 _gtk_window_set_has_toplevel_focus (window, FALSE);
5850 _gtk_window_set_is_active (window, FALSE);
5852 /* set the mnemonic-visible property to false */
5853 g_object_get (gtk_widget_get_settings (widget),
5854 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5856 gtk_window_set_mnemonics_visible (window, FALSE);
5861 static GdkAtom atom_rcfiles = GDK_NONE;
5862 static GdkAtom atom_iconthemes = GDK_NONE;
5865 send_client_message_to_embedded_windows (GtkWidget *widget,
5866 GdkAtom message_type)
5868 GList *embedded_windows;
5870 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5871 if (embedded_windows)
5873 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5876 for (i = 0; i < 5; i++)
5877 send_event->client.data.l[i] = 0;
5878 send_event->client.data_format = 32;
5879 send_event->client.message_type = message_type;
5881 while (embedded_windows)
5883 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
5884 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5885 embedded_windows = embedded_windows->next;
5888 gdk_event_free (send_event);
5893 gtk_window_client_event (GtkWidget *widget,
5894 GdkEventClient *event)
5898 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5899 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5902 if (event->message_type == atom_rcfiles)
5904 send_client_message_to_embedded_windows (widget, atom_rcfiles);
5905 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
5908 if (event->message_type == atom_iconthemes)
5910 send_client_message_to_embedded_windows (widget, atom_iconthemes);
5911 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
5918 gtk_window_check_resize (GtkContainer *container)
5920 if (gtk_widget_get_visible (GTK_WIDGET (container)))
5921 gtk_window_move_resize (GTK_WINDOW (container));
5925 gtk_window_focus (GtkWidget *widget,
5926 GtkDirectionType direction)
5928 GtkWindowPrivate *priv;
5931 GtkContainer *container;
5933 GtkWidget *old_focus_child;
5936 container = GTK_CONTAINER (widget);
5937 window = GTK_WINDOW (widget);
5938 priv = window->priv;
5939 bin = GTK_BIN (widget);
5941 old_focus_child = gtk_container_get_focus_child (container);
5943 /* We need a special implementation here to deal properly with wrapping
5944 * around in the tab chain without the danger of going into an
5947 if (old_focus_child)
5949 if (gtk_widget_child_focus (old_focus_child, direction))
5953 if (priv->focus_widget)
5955 if (direction == GTK_DIR_LEFT ||
5956 direction == GTK_DIR_RIGHT ||
5957 direction == GTK_DIR_UP ||
5958 direction == GTK_DIR_DOWN)
5963 /* Wrapped off the end, clear the focus setting for the toplpevel */
5964 parent = gtk_widget_get_parent (priv->focus_widget);
5967 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5968 parent = gtk_widget_get_parent (parent);
5971 gtk_window_set_focus (GTK_WINDOW (container), NULL);
5974 /* Now try to focus the first widget in the window */
5975 child = gtk_bin_get_child (bin);
5978 if (gtk_widget_child_focus (child, direction))
5986 gtk_window_real_set_focus (GtkWindow *window,
5989 GtkWindowPrivate *priv = window->priv;
5990 GtkWidget *old_focus = priv->focus_widget;
5991 gboolean had_default = FALSE;
5992 gboolean focus_had_default = FALSE;
5993 gboolean old_focus_had_default = FALSE;
5997 g_object_ref (old_focus);
5998 g_object_freeze_notify (G_OBJECT (old_focus));
5999 old_focus_had_default = gtk_widget_has_default (old_focus);
6003 g_object_ref (focus);
6004 g_object_freeze_notify (G_OBJECT (focus));
6005 focus_had_default = gtk_widget_has_default (focus);
6008 if (priv->default_widget)
6009 had_default = gtk_widget_has_default (priv->default_widget);
6011 if (priv->focus_widget)
6013 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6014 (priv->focus_widget != priv->default_widget))
6016 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6017 gtk_widget_queue_draw (priv->focus_widget);
6019 if (priv->default_widget)
6020 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6023 priv->focus_widget = NULL;
6025 if (priv->has_focus)
6026 do_focus_change (old_focus, FALSE);
6028 g_object_notify (G_OBJECT (old_focus), "is-focus");
6031 /* The above notifications may have set a new focus widget,
6032 * if so, we don't want to override it.
6034 if (focus && !priv->focus_widget)
6036 priv->focus_widget = focus;
6038 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6039 (priv->focus_widget != priv->default_widget))
6041 if (gtk_widget_get_can_default (priv->focus_widget))
6042 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6044 if (priv->default_widget)
6045 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6048 if (priv->has_focus)
6049 do_focus_change (priv->focus_widget, TRUE);
6051 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6054 /* If the default widget changed, a redraw will have been queued
6055 * on the old and new default widgets by gtk_window_set_default(), so
6056 * we only have to worry about the case where it didn't change.
6057 * We'll sometimes queue a draw twice on the new widget but that
6060 if (priv->default_widget &&
6061 (had_default != gtk_widget_has_default (priv->default_widget)))
6062 gtk_widget_queue_draw (priv->default_widget);
6066 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6067 gtk_widget_queue_draw (old_focus);
6069 g_object_thaw_notify (G_OBJECT (old_focus));
6070 g_object_unref (old_focus);
6074 if (focus_had_default != gtk_widget_has_default (focus))
6075 gtk_widget_queue_draw (focus);
6077 g_object_thaw_notify (G_OBJECT (focus));
6078 g_object_unref (focus);
6084 gtk_window_get_preferred_width (GtkWidget *widget,
6092 window = GTK_WINDOW (widget);
6093 child = gtk_bin_get_child (GTK_BIN (window));
6095 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6096 *minimum_size = border_width * 2;
6097 *natural_size = border_width * 2;
6099 if (child && gtk_widget_get_visible (child))
6101 gint child_min, child_nat;
6102 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6104 *minimum_size += child_min;
6105 *natural_size += child_nat;
6110 gtk_window_get_preferred_height (GtkWidget *widget,
6118 window = GTK_WINDOW (widget);
6119 child = gtk_bin_get_child (GTK_BIN (window));
6121 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6122 *minimum_size = border_width * 2;
6123 *natural_size = border_width * 2;
6125 if (child && gtk_widget_get_visible (child))
6127 gint child_min, child_nat;
6128 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6130 *minimum_size += child_min;
6131 *natural_size += child_nat;
6137 * _gtk_window_unset_focus_and_default:
6138 * @window: a #GtkWindow
6139 * @widget: a widget inside of @window
6141 * Checks whether the focus and default widgets of @window are
6142 * @widget or a descendent of @widget, and if so, unset them.
6145 _gtk_window_unset_focus_and_default (GtkWindow *window,
6149 GtkWindowPrivate *priv = window->priv;
6153 g_object_ref (window);
6154 g_object_ref (widget);
6156 parent = gtk_widget_get_parent (widget);
6157 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6159 child = priv->focus_widget;
6161 while (child && child != widget)
6162 child = gtk_widget_get_parent (child);
6164 if (child == widget)
6165 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6168 child = priv->default_widget;
6170 while (child && child != widget)
6171 child = gtk_widget_get_parent (child);
6173 if (child == widget)
6174 gtk_window_set_default (window, NULL);
6176 g_object_unref (widget);
6177 g_object_unref (window);
6180 /*********************************
6181 * Functions related to resizing *
6182 *********************************/
6185 geometry_size_to_pixels (GdkGeometry *geometry,
6190 gint base_width = 0;
6191 gint base_height = 0;
6193 gint min_height = 0;
6195 gint height_inc = 1;
6197 if (flags & GDK_HINT_BASE_SIZE)
6199 base_width = geometry->base_width;
6200 base_height = geometry->base_height;
6202 if (flags & GDK_HINT_MIN_SIZE)
6204 min_width = geometry->min_width;
6205 min_height = geometry->min_height;
6207 if (flags & GDK_HINT_RESIZE_INC)
6209 width_inc = geometry->width_inc;
6210 height_inc = geometry->height_inc;
6214 *width = MAX (*width * width_inc + base_width, min_width);
6216 *height = MAX (*height * height_inc + base_height, min_height);
6219 /* This function doesn't constrain to geometry hints */
6221 gtk_window_compute_configure_request_size (GtkWindow *window,
6222 GdkGeometry *geometry,
6227 GtkWindowPrivate *priv = window->priv;
6228 GtkRequisition requisition;
6229 GtkWindowGeometryInfo *info;
6233 * - we've done a size request
6236 widget = GTK_WIDGET (window);
6238 info = gtk_window_get_geometry_info (window, FALSE);
6240 if (priv->need_default_size)
6242 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6244 /* Default to requisition */
6245 *width = requisition.width;
6246 *height = requisition.height;
6248 /* If window is empty so requests 0, default to random nonzero size */
6249 if (*width == 0 && *height == 0)
6255 /* Override requisition with default size */
6259 if (info->default_width > 0)
6260 *width = info->default_width;
6261 if (info->default_height > 0)
6262 *height = info->default_height;
6264 if (info->default_is_geometry)
6265 geometry_size_to_pixels (geometry, flags,
6266 info->default_width > 0 ? width : NULL,
6267 info->default_height > 0 ? height : NULL);
6272 GtkAllocation allocation;
6274 gtk_widget_get_allocation (widget, &allocation);
6276 /* Default to keeping current size */
6277 *width = allocation.width;
6278 *height = allocation.height;
6281 /* Override any size with gtk_window_resize() values */
6284 if (info->resize_width > 0)
6285 *width = info->resize_width;
6286 if (info->resize_height > 0)
6287 *height = info->resize_height;
6289 if (info->resize_is_geometry)
6290 geometry_size_to_pixels (geometry, flags,
6291 info->resize_width > 0 ? width : NULL,
6292 info->resize_height > 0 ? height : NULL);
6295 /* Don't ever request zero width or height, its not supported by
6296 gdk. The size allocation code will round it to 1 anyway but if
6297 we do it then the value returned from this function will is
6298 not comparable to the size allocation read from the GtkWindow. */
6299 *width = MAX (*width, 1);
6300 *height = MAX (*height, 1);
6303 static GtkWindowPosition
6304 get_effective_position (GtkWindow *window)
6306 GtkWindowPrivate *priv = window->priv;
6307 GtkWindowPosition pos = priv->position;
6309 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6310 (priv->transient_parent == NULL ||
6311 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6312 pos = GTK_WIN_POS_NONE;
6318 get_center_monitor_of_window (GtkWindow *window)
6320 /* We could try to sort out the relative positions of the monitors and
6321 * stuff, or we could just be losers and assume you have a row
6322 * or column of monitors.
6324 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6328 get_monitor_containing_pointer (GtkWindow *window)
6332 GdkScreen *window_screen;
6333 GdkScreen *pointer_screen;
6334 GdkDisplay *display;
6335 GdkDeviceManager *device_manager;
6338 window_screen = gtk_window_check_screen (window);
6339 display = gdk_screen_get_display (window_screen);
6340 device_manager = gdk_display_get_device_manager (display);
6341 pointer = gdk_device_manager_get_client_pointer (device_manager);
6343 gdk_display_get_device_state (display, pointer,
6347 if (pointer_screen == window_screen)
6348 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6356 center_window_on_monitor (GtkWindow *window,
6362 GdkRectangle monitor;
6365 monitor_num = get_monitor_containing_pointer (window);
6367 if (monitor_num == -1)
6368 monitor_num = get_center_monitor_of_window (window);
6370 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6371 monitor_num, &monitor);
6373 *x = (monitor.width - w) / 2 + monitor.x;
6374 *y = (monitor.height - h) / 2 + monitor.y;
6376 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6377 * and WM decorations.
6391 if (extent > clamp_extent)
6393 *base = clamp_base + clamp_extent/2 - extent/2;
6394 else if (*base < clamp_base)
6396 else if (*base + extent > clamp_base + clamp_extent)
6397 *base = clamp_base + clamp_extent - extent;
6401 clamp_window_to_rectangle (gint *x,
6405 const GdkRectangle *rect)
6407 #ifdef DEBUGGING_OUTPUT
6408 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);
6411 /* If it is too large, center it. If it fits on the monitor but is
6412 * partially outside, move it to the closest edge. Do this
6413 * separately in x and y directions.
6415 clamp (x, w, rect->x, rect->width);
6416 clamp (y, h, rect->y, rect->height);
6417 #ifdef DEBUGGING_OUTPUT
6418 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6424 gtk_window_compute_configure_request (GtkWindow *window,
6425 GdkRectangle *request,
6426 GdkGeometry *geometry,
6429 GtkWindowPrivate *priv = window->priv;
6430 GdkGeometry new_geometry;
6434 GtkWindowPosition pos;
6435 GtkWidget *parent_widget;
6436 GtkWindowGeometryInfo *info;
6440 widget = GTK_WIDGET (window);
6442 screen = gtk_window_check_screen (window);
6444 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6445 gtk_window_compute_configure_request_size (window,
6446 &new_geometry, new_flags,
6447 (guint *)&w, (guint *)&h);
6449 gtk_window_constrain_size (window,
6450 &new_geometry, new_flags,
6454 parent_widget = (GtkWidget*) priv->transient_parent;
6456 pos = get_effective_position (window);
6457 info = gtk_window_get_geometry_info (window, FALSE);
6459 /* by default, don't change position requested */
6462 x = info->last.configure_request.x;
6463 y = info->last.configure_request.y;
6472 if (priv->need_default_position)
6475 /* FIXME this all interrelates with window gravity.
6476 * For most of them I think we want to set GRAVITY_CENTER.
6478 * Not sure how to go about that.
6483 /* here we are only handling CENTER_ALWAYS
6484 * as it relates to default positioning,
6485 * where it's equivalent to simply CENTER
6487 case GTK_WIN_POS_CENTER_ALWAYS:
6488 case GTK_WIN_POS_CENTER:
6489 center_window_on_monitor (window, w, h, &x, &y);
6492 case GTK_WIN_POS_CENTER_ON_PARENT:
6494 GtkAllocation allocation;
6495 GdkWindow *gdk_window;
6497 GdkRectangle monitor;
6500 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6502 gdk_window = gtk_widget_get_window (parent_widget);
6504 if (gdk_window != NULL)
6505 monitor_num = gdk_screen_get_monitor_at_window (screen,
6510 gdk_window_get_origin (gdk_window,
6513 gtk_widget_get_allocation (parent_widget, &allocation);
6514 x = ox + (allocation.width - w) / 2;
6515 y = oy + (allocation.height - h) / 2;
6517 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6518 * WM decorations. If parent wasn't on a monitor, just
6521 if (monitor_num >= 0)
6523 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6524 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6529 case GTK_WIN_POS_MOUSE:
6531 gint screen_width = gdk_screen_get_width (screen);
6532 gint screen_height = gdk_screen_get_height (screen);
6534 GdkRectangle monitor;
6535 GdkDisplay *display;
6536 GdkDeviceManager *device_manager;
6538 GdkScreen *pointer_screen;
6541 display = gdk_screen_get_display (screen);
6542 device_manager = gdk_display_get_device_manager (display);
6543 pointer = gdk_device_manager_get_client_pointer (device_manager);
6545 gdk_display_get_device_state (display, pointer,
6549 if (pointer_screen == screen)
6550 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6556 x = CLAMP (x, 0, screen_width - w);
6557 y = CLAMP (y, 0, screen_height - h);
6559 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6560 * WM decorations. Don't try to figure out what's going
6561 * on if the mouse wasn't inside a monitor.
6563 if (monitor_num >= 0)
6565 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6566 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6574 } /* if (priv->need_default_position) */
6576 if (priv->need_default_position && info &&
6577 info->initial_pos_set)
6579 x = info->initial_x;
6580 y = info->initial_y;
6581 gtk_window_constrain_position (window, w, h, &x, &y);
6587 request->height = h;
6590 *geometry = new_geometry;
6596 gtk_window_constrain_position (GtkWindow *window,
6602 GtkWindowPrivate *priv = window->priv;
6604 /* See long comments in gtk_window_move_resize()
6605 * on when it's safe to call this function.
6607 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6609 gint center_x, center_y;
6611 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6619 gtk_window_move_resize (GtkWindow *window)
6623 * First we determine whether any information has changed that would
6624 * cause us to revise our last configure request. If we would send
6625 * a different configure request from last time, then
6626 * configure_request_size_changed = TRUE or
6627 * configure_request_pos_changed = TRUE. configure_request_size_changed
6628 * may be true due to new hints, a gtk_window_resize(), or whatever.
6629 * configure_request_pos_changed may be true due to gtk_window_set_position()
6630 * or gtk_window_move().
6632 * If the configure request has changed, we send off a new one. To
6633 * ensure GTK+ invariants are maintained (resize queue does what it
6634 * should), we go ahead and size_allocate the requested size in this
6637 * If the configure request has not changed, we don't ever resend
6638 * it, because it could mean fighting the user or window manager.
6641 * To prepare the configure request, we come up with a base size/pos:
6642 * - the one from gtk_window_move()/gtk_window_resize()
6643 * - else default_width, default_height if we haven't ever
6645 * - else the size request if we haven't ever been mapped,
6646 * as a substitute default size
6647 * - else the current size of the window, as received from
6648 * configure notifies (i.e. the current allocation)
6650 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6651 * the position request to be centered.
6653 GtkWindowPrivate *priv = window->priv;
6654 GtkAllocation allocation;
6656 GtkContainer *container;
6657 GtkWindowGeometryInfo *info;
6658 GdkGeometry new_geometry;
6659 GdkWindow *gdk_window;
6661 GdkRectangle new_request;
6662 gboolean configure_request_size_changed;
6663 gboolean configure_request_pos_changed;
6664 gboolean hints_changed; /* do we need to send these again */
6665 GtkWindowLastGeometryInfo saved_last_info;
6667 widget = GTK_WIDGET (window);
6668 gdk_window = gtk_widget_get_window (widget);
6669 container = GTK_CONTAINER (widget);
6670 info = gtk_window_get_geometry_info (window, TRUE);
6672 configure_request_size_changed = FALSE;
6673 configure_request_pos_changed = FALSE;
6675 gtk_window_compute_configure_request (window, &new_request,
6676 &new_geometry, &new_flags);
6678 /* This check implies the invariant that we never set info->last
6679 * without setting the hints and sending off a configure request.
6681 * If we change info->last without sending the request, we may
6684 if (info->last.configure_request.x != new_request.x ||
6685 info->last.configure_request.y != new_request.y)
6686 configure_request_pos_changed = TRUE;
6688 if ((info->last.configure_request.width != new_request.width ||
6689 info->last.configure_request.height != new_request.height))
6690 configure_request_size_changed = TRUE;
6692 hints_changed = FALSE;
6694 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6695 &new_geometry, new_flags))
6697 hints_changed = TRUE;
6700 /* Position Constraints
6701 * ====================
6703 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6704 * a default. The other POS_ values are used only when the
6705 * window is shown, not after that.
6707 * However, we can't implement a position constraint as
6708 * "anytime the window size changes, center the window"
6709 * because this may well end up fighting the WM or user. In
6710 * fact it gets in an infinite loop with at least one WM.
6712 * Basically, applications are in no way in a position to
6713 * constrain the position of a window, with one exception:
6714 * override redirect windows. (Really the intended purpose
6715 * of CENTER_ALWAYS anyhow, I would think.)
6717 * So the way we implement this "constraint" is to say that when WE
6718 * cause a move or resize, i.e. we make a configure request changing
6719 * window size, we recompute the CENTER_ALWAYS position to reflect
6720 * the new window size, and include it in our request. Also, if we
6721 * just turned on CENTER_ALWAYS we snap to center with a new
6722 * request. Otherwise, if we are just NOTIFIED of a move or resize
6723 * done by someone else e.g. the window manager, we do NOT send a
6724 * new configure request.
6726 * For override redirect windows, this works fine; all window
6727 * sizes are from our configure requests. For managed windows,
6728 * it is at least semi-sane, though who knows what the
6729 * app author is thinking.
6732 /* This condition should be kept in sync with the condition later on
6733 * that determines whether we send a configure request. i.e. we
6734 * should do this position constraining anytime we were going to
6735 * send a configure request anyhow, plus when constraints have
6738 if (configure_request_pos_changed ||
6739 configure_request_size_changed ||
6741 info->position_constraints_changed)
6743 /* We request the constrained position if:
6744 * - we were changing position, and need to clamp
6745 * the change to the constraint
6746 * - we're changing the size anyway
6747 * - set_position() was called to toggle CENTER_ALWAYS on
6750 gtk_window_constrain_position (window,
6756 /* Update whether we need to request a move */
6757 if (info->last.configure_request.x != new_request.x ||
6758 info->last.configure_request.y != new_request.y)
6759 configure_request_pos_changed = TRUE;
6761 configure_request_pos_changed = FALSE;
6765 if (priv->type == GTK_WINDOW_TOPLEVEL)
6767 int notify_x, notify_y;
6769 /* this is the position from the last configure notify */
6770 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6772 g_message ("--- %s ---\n"
6773 "last : %d,%d\t%d x %d\n"
6774 "this : %d,%d\t%d x %d\n"
6775 "alloc : %d,%d\t%d x %d\n"
6777 "resize: \t%d x %d\n"
6778 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6779 "configure_notify_received: %d\n"
6780 "configure_request_count: %d\n"
6781 "position_constraints_changed: %d\n",
6782 priv->title ? priv->title : "(no title)",
6783 info->last.configure_request.x,
6784 info->last.configure_request.y,
6785 info->last.configure_request.width,
6786 info->last.configure_request.height,
6792 widget->allocation.width,
6793 widget->allocation.height,
6794 widget->requisition.width,
6795 widget->requisition.height,
6797 info->resize_height,
6798 configure_request_pos_changed,
6799 configure_request_size_changed,
6801 priv->configure_notify_received,
6802 priv->configure_request_count,
6803 info->position_constraints_changed);
6807 saved_last_info = info->last;
6808 info->last.geometry = new_geometry;
6809 info->last.flags = new_flags;
6810 info->last.configure_request = new_request;
6812 /* need to set PPosition so the WM will look at our position,
6813 * but we don't want to count PPosition coming and going as a hints
6814 * change for future iterations. So we saved info->last prior to
6818 /* Also, if the initial position was explicitly set, then we always
6819 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6823 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6824 * this is an initial map
6827 if ((configure_request_pos_changed ||
6828 info->initial_pos_set ||
6829 (priv->need_default_position &&
6830 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6831 (new_flags & GDK_HINT_POS) == 0)
6833 new_flags |= GDK_HINT_POS;
6834 hints_changed = TRUE;
6837 /* Set hints if necessary
6840 gdk_window_set_geometry_hints (gdk_window,
6844 gtk_widget_get_allocation (widget, &allocation);
6846 /* handle resizing/moving and widget tree allocation
6848 if (priv->configure_notify_received)
6850 /* If we have received a configure event since
6851 * the last time in this function, we need to
6852 * accept our new size and size_allocate child widgets.
6853 * (see gtk_window_configure_event() for more details).
6855 * 1 or more configure notifies may have been received.
6856 * Also, configure_notify_received will only be TRUE
6857 * if all expected configure notifies have been received
6858 * (one per configure request), as an optimization.
6861 priv->configure_notify_received = FALSE;
6863 /* gtk_window_configure_event() filled in widget->allocation */
6864 gtk_widget_size_allocate (widget, &allocation);
6866 set_grip_position (window);
6867 set_grip_cursor (window);
6868 set_grip_shape (window);
6870 gdk_window_process_updates (gdk_window, TRUE);
6872 gdk_window_configure_finished (gdk_window);
6874 /* If the configure request changed, it means that
6876 * 1) coincidentally changed hints or widget properties
6877 * impacting the configure request before getting
6878 * a configure notify, or
6879 * 2) some broken widget is changing its size request
6880 * during size allocation, resulting in
6881 * a false appearance of changed configure request.
6883 * For 1), we could just go ahead and ask for the
6884 * new size right now, but doing that for 2)
6885 * might well be fighting the user (and can even
6886 * trigger a loop). Since we really don't want to
6887 * do that, we requeue a resize in hopes that
6888 * by the time it gets handled, the child has seen
6889 * the light and is willing to go along with the
6890 * new size. (this happens for the zvt widget, since
6891 * the size_allocate() above will have stored the
6892 * requisition corresponding to the new size in the
6895 * This doesn't buy us anything for 1), but it shouldn't
6896 * hurt us too badly, since it is what would have
6897 * happened if we had gotten the configure event before
6898 * the new size had been set.
6901 if (configure_request_size_changed ||
6902 configure_request_pos_changed)
6904 /* Don't change the recorded last info after all, because we
6905 * haven't actually updated to the new info yet - we decided
6906 * to postpone our configure request until later.
6908 info->last = saved_last_info;
6910 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6913 return; /* Bail out, we didn't really process the move/resize */
6915 else if ((configure_request_size_changed || hints_changed) &&
6916 (allocation.width != new_request.width || allocation.height != new_request.height))
6919 /* We are in one of the following situations:
6920 * A. configure_request_size_changed
6921 * our requisition has changed and we need a different window size,
6922 * so we request it from the window manager.
6923 * B. !configure_request_size_changed && hints_changed
6924 * the window manager rejects our size, but we have just changed the
6925 * window manager hints, so there's a chance our request will
6926 * be honoured this time, so we try again.
6928 * However, if the new requisition is the same as the current allocation,
6929 * we don't request it again, since we won't get a ConfigureNotify back from
6930 * the window manager unless it decides to change our requisition. If
6931 * we don't get the ConfigureNotify back, the resize queue will never be run.
6934 /* Now send the configure request */
6935 if (configure_request_pos_changed)
6939 gdk_window_move_resize (priv->frame,
6940 new_request.x - priv->frame_left,
6941 new_request.y - priv->frame_top,
6942 new_request.width + priv->frame_left + priv->frame_right,
6943 new_request.height + priv->frame_top + priv->frame_bottom);
6944 gdk_window_resize (gdk_window,
6945 new_request.width, new_request.height);
6948 gdk_window_move_resize (gdk_window,
6949 new_request.x, new_request.y,
6950 new_request.width, new_request.height);
6952 else /* only size changed */
6955 gdk_window_resize (priv->frame,
6956 new_request.width + priv->frame_left + priv->frame_right,
6957 new_request.height + priv->frame_top + priv->frame_bottom);
6958 gdk_window_resize (gdk_window,
6959 new_request.width, new_request.height);
6962 if (priv->type == GTK_WINDOW_POPUP)
6964 GtkAllocation allocation;
6966 /* Directly size allocate for override redirect (popup) windows. */
6969 allocation.width = new_request.width;
6970 allocation.height = new_request.height;
6972 gtk_widget_size_allocate (widget, &allocation);
6974 gdk_window_process_updates (gdk_window, TRUE);
6976 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6977 gtk_widget_queue_draw (widget);
6981 /* Increment the number of have-not-yet-received-notify requests */
6982 priv->configure_request_count += 1;
6983 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
6985 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6986 * configure event in response to our resizing request.
6987 * the configure event will cause a new resize with
6988 * ->configure_notify_received=TRUE.
6989 * until then, we want to
6990 * - discard expose events
6991 * - coalesce resizes for our children
6992 * - defer any window resizes until the configure event arrived
6993 * to achieve this, we queue a resize for the window, but remove its
6994 * resizing handler, so resizing will not be handled from the next
6995 * idle handler but when the configure event arrives.
6997 * FIXME: we should also dequeue the pending redraws here, since
6998 * we handle those ourselves upon ->configure_notify_received==TRUE.
7000 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7002 gtk_widget_queue_resize_no_redraw (widget);
7003 _gtk_container_dequeue_resize_handler (container);
7009 /* Handle any position changes.
7011 if (configure_request_pos_changed)
7015 gdk_window_move (priv->frame,
7016 new_request.x - priv->frame_left,
7017 new_request.y - priv->frame_top);
7020 gdk_window_move (gdk_window,
7021 new_request.x, new_request.y);
7024 /* And run the resize queue.
7026 gtk_container_resize_children (container);
7029 /* We have now processed a move/resize since the last position
7030 * constraint change, setting of the initial position, or resize.
7031 * (Not resetting these flags here can lead to infinite loops for
7032 * GTK_RESIZE_IMMEDIATE containers)
7034 info->position_constraints_changed = FALSE;
7035 info->initial_pos_set = FALSE;
7036 info->resize_width = -1;
7037 info->resize_height = -1;
7040 /* Compare two sets of Geometry hints for equality.
7043 gtk_window_compare_hints (GdkGeometry *geometry_a,
7045 GdkGeometry *geometry_b,
7048 if (flags_a != flags_b)
7051 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7052 (geometry_a->min_width != geometry_b->min_width ||
7053 geometry_a->min_height != geometry_b->min_height))
7056 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7057 (geometry_a->max_width != geometry_b->max_width ||
7058 geometry_a->max_height != geometry_b->max_height))
7061 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7062 (geometry_a->base_width != geometry_b->base_width ||
7063 geometry_a->base_height != geometry_b->base_height))
7066 if ((flags_a & GDK_HINT_ASPECT) &&
7067 (geometry_a->min_aspect != geometry_b->min_aspect ||
7068 geometry_a->max_aspect != geometry_b->max_aspect))
7071 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7072 (geometry_a->width_inc != geometry_b->width_inc ||
7073 geometry_a->height_inc != geometry_b->height_inc))
7076 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7077 geometry_a->win_gravity != geometry_b->win_gravity)
7084 _gtk_window_constrain_size (GtkWindow *window,
7090 GtkWindowPrivate *priv;
7091 GtkWindowGeometryInfo *info;
7093 g_return_if_fail (GTK_IS_WINDOW (window));
7095 priv = window->priv;
7097 info = priv->geometry_info;
7100 GdkWindowHints flags = info->last.flags;
7101 GdkGeometry *geometry = &info->last.geometry;
7103 gtk_window_constrain_size (window,
7114 gtk_window_constrain_size (GtkWindow *window,
7115 GdkGeometry *geometry,
7122 gdk_window_constrain_size (geometry, flags, width, height,
7123 new_width, new_height);
7126 /* Compute the set of geometry hints and flags for a window
7127 * based on the application set geometry, and requisition
7128 * of the window. gtk_widget_get_preferred_size() must have been
7132 gtk_window_compute_hints (GtkWindow *window,
7133 GdkGeometry *new_geometry,
7136 GtkWindowPrivate *priv = window->priv;
7138 gint extra_width = 0;
7139 gint extra_height = 0;
7140 GtkWindowGeometryInfo *geometry_info;
7141 GtkRequisition requisition;
7143 widget = GTK_WIDGET (window);
7145 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7146 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7150 *new_flags = geometry_info->mask;
7151 *new_geometry = geometry_info->geometry;
7158 if (geometry_info && geometry_info->widget)
7160 /* If the geometry widget is set, then the hints really apply to that
7161 * widget. This is pretty much meaningless unless the window layout
7162 * is such that the rest of the window adds fixed size borders to
7163 * the geometry widget. Our job is to figure the size of the borders;
7164 * We do that by asking how big the toplevel would be if the
7165 * geometry widget was *really big*.
7168 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7169 * |GGGGG B| in the border can confuse things
7175 * |AAAAAAAAA | When the geometry widget is large, things are
7176 * |GGGGGGGGGGB| clearer.
7181 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7182 GtkRequisition requisition;
7183 int current_width, current_height;
7185 _gtk_widget_override_size_request (geometry_info->widget,
7186 TEMPORARY_SIZE, TEMPORARY_SIZE,
7187 ¤t_width, ¤t_height);
7188 gtk_widget_get_preferred_size (widget,
7189 &requisition, NULL);
7190 _gtk_widget_restore_size_request (geometry_info->widget,
7191 current_width, current_height);
7193 extra_width = requisition.width - TEMPORARY_SIZE;
7194 extra_height = requisition.height - TEMPORARY_SIZE;
7196 if (extra_width < 0 || extra_width < 0)
7198 g_warning("Toplevel size doesn't seem to directly depend on the "
7199 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7200 "The geometry widget might not be in the window, or it might not "
7201 "be packed into the window appropriately");
7202 extra_width = MAX(extra_width, 0);
7203 extra_height = MAX(extra_height, 0);
7205 #undef TEMPORARY_SIZE
7208 /* We don't want to set GDK_HINT_POS in here, we just set it
7209 * in gtk_window_move_resize() when we want the position
7213 if (*new_flags & GDK_HINT_BASE_SIZE)
7215 new_geometry->base_width += extra_width;
7216 new_geometry->base_height += extra_height;
7220 /* For simplicity, we always set the base hint, even when we
7221 * don't expect it to have any visible effect.
7222 * (Note: geometry_size_to_pixels() depends on this.)
7224 *new_flags |= GDK_HINT_BASE_SIZE;
7226 new_geometry->base_width = extra_width;
7227 new_geometry->base_height = extra_height;
7229 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7230 * base size is the minimum size */
7231 if (*new_flags & GDK_HINT_MIN_SIZE)
7233 if (new_geometry->min_width > 0)
7234 new_geometry->base_width += new_geometry->min_width;
7235 if (new_geometry->min_height > 0)
7236 new_geometry->base_height += new_geometry->min_height;
7240 if (*new_flags & GDK_HINT_MIN_SIZE)
7242 if (new_geometry->min_width < 0)
7243 new_geometry->min_width = requisition.width;
7245 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7247 if (new_geometry->min_height < 0)
7248 new_geometry->min_height = requisition.height;
7250 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7254 *new_flags |= GDK_HINT_MIN_SIZE;
7256 new_geometry->min_width = requisition.width;
7257 new_geometry->min_height = requisition.height;
7260 if (*new_flags & GDK_HINT_MAX_SIZE)
7262 if (new_geometry->max_width < 0)
7263 new_geometry->max_width = requisition.width;
7265 new_geometry->max_width += extra_width;
7267 if (new_geometry->max_height < 0)
7268 new_geometry->max_height = requisition.height;
7270 new_geometry->max_height += extra_height;
7272 else if (!priv->resizable)
7274 *new_flags |= GDK_HINT_MAX_SIZE;
7276 new_geometry->max_width = requisition.width;
7277 new_geometry->max_height = requisition.height;
7280 *new_flags |= GDK_HINT_WIN_GRAVITY;
7281 new_geometry->win_gravity = priv->gravity;
7284 /***********************
7285 * Redrawing functions *
7286 ***********************/
7289 gtk_window_draw (GtkWidget *widget,
7292 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7293 gboolean ret = FALSE;
7295 if (!gtk_widget_get_app_paintable (widget))
7296 gtk_paint_flat_box (gtk_widget_get_style (widget),
7299 GTK_SHADOW_NONE, widget, "base",
7301 gtk_widget_get_allocated_width (widget),
7302 gtk_widget_get_allocated_height (widget));
7304 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7305 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7307 if (priv->grip_window != NULL &&
7308 gtk_cairo_should_draw_window (cr, priv->grip_window))
7313 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7314 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7315 gtk_paint_resize_grip (gtk_widget_get_style (widget),
7317 gtk_widget_get_state (widget),
7320 get_grip_edge (widget),
7322 rect.width, rect.height);
7330 * gtk_window_set_has_frame:
7331 * @window: a #GtkWindow
7332 * @setting: a boolean
7334 * (Note: this is a special-purpose function for the framebuffer port,
7335 * that causes GTK+ to draw its own window border. For most applications,
7336 * you want gtk_window_set_decorated() instead, which tells the window
7337 * manager whether to draw the window border.)
7339 * If this function is called on a window with setting of %TRUE, before
7340 * it is realized or showed, it will have a "frame" window around
7341 * @window->window, accessible in @window->frame. Using the signal
7342 * frame_event you can receive all events targeted at the frame.
7344 * This function is used by the linux-fb port to implement managed
7345 * windows, but it could conceivably be used by X-programs that
7346 * want to do their own window decorations.
7350 gtk_window_set_has_frame (GtkWindow *window,
7353 GtkWindowPrivate *priv;
7355 g_return_if_fail (GTK_IS_WINDOW (window));
7356 g_return_if_fail (!gtk_widget_get_realized (GTK_WIDGET (window)));
7358 priv = window->priv;
7360 priv->has_frame = setting != FALSE;
7364 * gtk_window_get_has_frame:
7365 * @window: a #GtkWindow
7367 * Accessor for whether the window has a frame window exterior to
7368 * @window->window. Gets the value set by gtk_window_set_has_frame ().
7370 * Return value: %TRUE if a frame has been added to the window
7371 * via gtk_window_set_has_frame().
7374 gtk_window_get_has_frame (GtkWindow *window)
7376 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7378 return window->priv->has_frame;
7382 * gtk_window_set_frame_dimensions:
7383 * @window: a #GtkWindow that has a frame
7384 * @left: The width of the left border
7385 * @top: The height of the top border
7386 * @right: The width of the right border
7387 * @bottom: The height of the bottom border
7389 * (Note: this is a special-purpose function intended for the framebuffer
7390 * port; see gtk_window_set_has_frame(). It will have no effect on the
7391 * window border drawn by the window manager, which is the normal
7392 * case when using the X Window system.)
7394 * For windows with frames (see gtk_window_set_has_frame()) this function
7395 * can be used to change the size of the frame border.
7398 gtk_window_set_frame_dimensions (GtkWindow *window,
7404 GtkWindowPrivate *priv;
7405 GtkAllocation allocation;
7408 g_return_if_fail (GTK_IS_WINDOW (window));
7410 priv = window->priv;
7411 widget = GTK_WIDGET (window);
7413 if (priv->frame_left == left &&
7414 priv->frame_top == top &&
7415 priv->frame_right == right &&
7416 priv->frame_bottom == bottom)
7419 priv->frame_left = left;
7420 priv->frame_top = top;
7421 priv->frame_right = right;
7422 priv->frame_bottom = bottom;
7424 if (gtk_widget_get_realized (widget) && priv->frame)
7426 gtk_widget_get_allocation (widget, &allocation);
7428 gint width = allocation.width + left + right;
7429 gint height = allocation.height + top + bottom;
7430 gdk_window_resize (priv->frame, width, height);
7431 gtk_decorated_window_move_resize_window (window,
7439 * gtk_window_present:
7440 * @window: a #GtkWindow
7442 * Presents a window to the user. This may mean raising the window
7443 * in the stacking order, deiconifying it, moving it to the current
7444 * desktop, and/or giving it the keyboard focus, possibly dependent
7445 * on the user's platform, window manager, and preferences.
7447 * If @window is hidden, this function calls gtk_widget_show()
7450 * This function should be used when the user tries to open a window
7451 * that's already open. Say for example the preferences dialog is
7452 * currently open, and the user chooses Preferences from the menu
7453 * a second time; use gtk_window_present() to move the already-open dialog
7454 * where the user can see it.
7456 * If you are calling this function in response to a user interaction,
7457 * it is preferable to use gtk_window_present_with_time().
7461 gtk_window_present (GtkWindow *window)
7463 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7467 * gtk_window_present_with_time:
7468 * @window: a #GtkWindow
7469 * @timestamp: the timestamp of the user interaction (typically a
7470 * button or key press event) which triggered this call
7472 * Presents a window to the user in response to a user interaction.
7473 * If you need to present a window without a timestamp, use
7474 * gtk_window_present(). See gtk_window_present() for details.
7479 gtk_window_present_with_time (GtkWindow *window,
7483 GdkWindow *gdk_window;
7485 g_return_if_fail (GTK_IS_WINDOW (window));
7487 widget = GTK_WIDGET (window);
7489 if (gtk_widget_get_visible (widget))
7491 gdk_window = gtk_widget_get_window (widget);
7493 g_assert (gdk_window != NULL);
7495 gdk_window_show (gdk_window);
7497 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7498 if (timestamp == GDK_CURRENT_TIME)
7500 #ifdef GDK_WINDOWING_X11
7501 GdkDisplay *display;
7503 display = gtk_widget_get_display (GTK_WIDGET (window));
7504 timestamp = gdk_x11_display_get_user_time (display);
7506 timestamp = gtk_get_current_event_time ();
7510 gdk_window_focus (gdk_window, timestamp);
7514 gtk_widget_show (widget);
7519 * gtk_window_iconify:
7520 * @window: a #GtkWindow
7522 * Asks to iconify (i.e. minimize) the specified @window. Note that
7523 * you shouldn't assume the window is definitely iconified afterward,
7524 * because other entities (e.g. the user or <link
7525 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7526 * again, or there may not be a window manager in which case
7527 * iconification isn't possible, etc. But normally the window will end
7528 * up iconified. Just don't write code that crashes if not.
7530 * It's permitted to call this function before showing a window,
7531 * in which case the window will be iconified before it ever appears
7534 * You can track iconification via the "window-state-event" signal
7539 gtk_window_iconify (GtkWindow *window)
7541 GtkWindowPrivate *priv;
7543 GdkWindow *toplevel;
7545 g_return_if_fail (GTK_IS_WINDOW (window));
7547 priv = window->priv;
7548 widget = GTK_WIDGET (window);
7550 priv->iconify_initially = TRUE;
7553 toplevel = priv->frame;
7555 toplevel = gtk_widget_get_window (widget);
7557 if (toplevel != NULL)
7558 gdk_window_iconify (toplevel);
7562 * gtk_window_deiconify:
7563 * @window: a #GtkWindow
7565 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7566 * that you shouldn't assume the window is definitely deiconified
7567 * afterward, because other entities (e.g. the user or <link
7568 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7569 * again before your code which assumes deiconification gets to run.
7571 * You can track iconification via the "window-state-event" signal
7575 gtk_window_deiconify (GtkWindow *window)
7577 GtkWindowPrivate *priv;
7579 GdkWindow *toplevel;
7581 g_return_if_fail (GTK_IS_WINDOW (window));
7583 priv = window->priv;
7584 widget = GTK_WIDGET (window);
7586 priv->iconify_initially = FALSE;
7589 toplevel = priv->frame;
7591 toplevel = gtk_widget_get_window (widget);
7593 if (toplevel != NULL)
7594 gdk_window_deiconify (toplevel);
7599 * @window: a #GtkWindow
7601 * Asks to stick @window, which means that it will appear on all user
7602 * desktops. Note that you shouldn't assume the window is definitely
7603 * stuck afterward, because other entities (e.g. the user or <link
7604 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7605 * again, and some window managers do not support sticking
7606 * windows. But normally the window will end up stuck. Just don't
7607 * write code that crashes if not.
7609 * It's permitted to call this function before showing a window.
7611 * You can track stickiness via the "window-state-event" signal
7616 gtk_window_stick (GtkWindow *window)
7618 GtkWindowPrivate *priv;
7620 GdkWindow *toplevel;
7622 g_return_if_fail (GTK_IS_WINDOW (window));
7624 priv = window->priv;
7625 widget = GTK_WIDGET (window);
7627 priv->stick_initially = TRUE;
7630 toplevel = priv->frame;
7632 toplevel = gtk_widget_get_window (widget);
7634 if (toplevel != NULL)
7635 gdk_window_stick (toplevel);
7639 * gtk_window_unstick:
7640 * @window: a #GtkWindow
7642 * Asks to unstick @window, which means that it will appear on only
7643 * one of the user's desktops. Note that you shouldn't assume the
7644 * window is definitely unstuck afterward, because other entities
7645 * (e.g. the user or <link linkend="gtk-X11-arch">window
7646 * manager</link>) could stick it again. But normally the window will
7647 * end up stuck. Just don't write code that crashes if not.
7649 * You can track stickiness via the "window-state-event" signal
7654 gtk_window_unstick (GtkWindow *window)
7656 GtkWindowPrivate *priv;
7658 GdkWindow *toplevel;
7660 g_return_if_fail (GTK_IS_WINDOW (window));
7662 priv = window->priv;
7663 widget = GTK_WIDGET (window);
7665 priv->stick_initially = FALSE;
7668 toplevel = priv->frame;
7670 toplevel = gtk_widget_get_window (widget);
7672 if (toplevel != NULL)
7673 gdk_window_unstick (toplevel);
7677 * gtk_window_maximize:
7678 * @window: a #GtkWindow
7680 * Asks to maximize @window, so that it becomes full-screen. Note that
7681 * you shouldn't assume the window is definitely maximized afterward,
7682 * because other entities (e.g. the user or <link
7683 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7684 * again, and not all window managers support maximization. But
7685 * normally the window will end up maximized. Just don't write code
7686 * that crashes if not.
7688 * It's permitted to call this function before showing a window,
7689 * in which case the window will be maximized when it appears onscreen
7692 * You can track maximization via the "window-state-event" signal
7697 gtk_window_maximize (GtkWindow *window)
7699 GtkWindowPrivate *priv;
7701 GdkWindow *toplevel;
7703 g_return_if_fail (GTK_IS_WINDOW (window));
7705 priv = window->priv;
7706 widget = GTK_WIDGET (window);
7708 priv->maximize_initially = TRUE;
7711 toplevel = priv->frame;
7713 toplevel = gtk_widget_get_window (widget);
7715 if (toplevel != NULL)
7716 gdk_window_maximize (toplevel);
7720 * gtk_window_unmaximize:
7721 * @window: a #GtkWindow
7723 * Asks to unmaximize @window. Note that you shouldn't assume the
7724 * window is definitely unmaximized afterward, because other entities
7725 * (e.g. the user or <link linkend="gtk-X11-arch">window
7726 * manager</link>) could maximize it again, and not all window
7727 * managers honor requests to unmaximize. But normally the window will
7728 * end up unmaximized. Just don't write code that crashes if not.
7730 * You can track maximization via the "window-state-event" signal
7735 gtk_window_unmaximize (GtkWindow *window)
7737 GtkWindowPrivate *priv;
7739 GdkWindow *toplevel;
7741 g_return_if_fail (GTK_IS_WINDOW (window));
7743 priv = window->priv;
7744 widget = GTK_WIDGET (window);
7746 priv->maximize_initially = FALSE;
7749 toplevel = priv->frame;
7751 toplevel = gtk_widget_get_window (widget);
7753 if (toplevel != NULL)
7754 gdk_window_unmaximize (toplevel);
7758 * gtk_window_fullscreen:
7759 * @window: a #GtkWindow
7761 * Asks to place @window in the fullscreen state. Note that you
7762 * shouldn't assume the window is definitely full screen afterward,
7763 * because other entities (e.g. the user or <link
7764 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7765 * again, and not all window managers honor requests to fullscreen
7766 * windows. But normally the window will end up fullscreen. Just
7767 * don't write code that crashes if not.
7769 * You can track the fullscreen state via the "window-state-event" signal
7775 gtk_window_fullscreen (GtkWindow *window)
7777 GtkWindowPrivate *priv;
7779 GdkWindow *toplevel;
7781 g_return_if_fail (GTK_IS_WINDOW (window));
7783 priv = window->priv;
7784 widget = GTK_WIDGET (window);
7786 priv->fullscreen_initially = TRUE;
7789 toplevel = priv->frame;
7791 toplevel = gtk_widget_get_window (widget);
7793 if (toplevel != NULL)
7794 gdk_window_fullscreen (toplevel);
7798 * gtk_window_unfullscreen:
7799 * @window: a #GtkWindow
7801 * Asks to toggle off the fullscreen state for @window. Note that you
7802 * shouldn't assume the window is definitely not full screen
7803 * afterward, because other entities (e.g. the user or <link
7804 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7805 * again, and not all window managers honor requests to unfullscreen
7806 * windows. But normally the window will end up restored to its normal
7807 * state. Just don't write code that crashes if not.
7809 * You can track the fullscreen state via the "window-state-event" signal
7815 gtk_window_unfullscreen (GtkWindow *window)
7818 GdkWindow *toplevel;
7819 GtkWindowPrivate *priv;
7821 g_return_if_fail (GTK_IS_WINDOW (window));
7823 priv = window->priv;
7824 widget = GTK_WIDGET (window);
7826 priv->fullscreen_initially = FALSE;
7829 toplevel = priv->frame;
7831 toplevel = gtk_widget_get_window (widget);
7833 if (toplevel != NULL)
7834 gdk_window_unfullscreen (toplevel);
7838 * gtk_window_set_keep_above:
7839 * @window: a #GtkWindow
7840 * @setting: whether to keep @window above other windows
7842 * Asks to keep @window above, so that it stays on top. Note that
7843 * you shouldn't assume the window is definitely above afterward,
7844 * because other entities (e.g. the user or <link
7845 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7846 * and not all window managers support keeping windows above. But
7847 * normally the window will end kept above. Just don't write code
7848 * that crashes if not.
7850 * It's permitted to call this function before showing a window,
7851 * in which case the window will be kept above when it appears onscreen
7854 * You can track the above state via the "window-state-event" signal
7857 * Note that, according to the <ulink
7858 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7859 * Manager Hints</ulink> specification, the above state is mainly meant
7860 * for user preferences and should not be used by applications e.g. for
7861 * drawing attention to their dialogs.
7866 gtk_window_set_keep_above (GtkWindow *window,
7870 GtkWindowPrivate *priv;
7871 GdkWindow *toplevel;
7873 g_return_if_fail (GTK_IS_WINDOW (window));
7875 priv = window->priv;
7876 widget = GTK_WIDGET (window);
7878 priv->above_initially = setting != FALSE;
7880 priv->below_initially = FALSE;
7883 toplevel = priv->frame;
7885 toplevel = gtk_widget_get_window (widget);
7887 if (toplevel != NULL)
7888 gdk_window_set_keep_above (toplevel, setting);
7892 * gtk_window_set_keep_below:
7893 * @window: a #GtkWindow
7894 * @setting: whether to keep @window below other windows
7896 * Asks to keep @window below, so that it stays in bottom. Note that
7897 * you shouldn't assume the window is definitely below afterward,
7898 * because other entities (e.g. the user or <link
7899 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7900 * and not all window managers support putting windows below. But
7901 * normally the window will be kept below. Just don't write code
7902 * that crashes if not.
7904 * It's permitted to call this function before showing a window,
7905 * in which case the window will be kept below when it appears onscreen
7908 * You can track the below state via the "window-state-event" signal
7911 * Note that, according to the <ulink
7912 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7913 * Manager Hints</ulink> specification, the above state is mainly meant
7914 * for user preferences and should not be used by applications e.g. for
7915 * drawing attention to their dialogs.
7920 gtk_window_set_keep_below (GtkWindow *window,
7924 GtkWindowPrivate *priv;
7925 GdkWindow *toplevel;
7927 g_return_if_fail (GTK_IS_WINDOW (window));
7929 priv = window->priv;
7930 widget = GTK_WIDGET (window);
7932 priv->below_initially = setting != FALSE;
7934 priv->above_initially = FALSE;
7937 toplevel = priv->frame;
7939 toplevel = gtk_widget_get_window (widget);
7941 if (toplevel != NULL)
7942 gdk_window_set_keep_below (toplevel, setting);
7946 * gtk_window_set_resizable:
7947 * @window: a #GtkWindow
7948 * @resizable: %TRUE if the user can resize this window
7950 * Sets whether the user can resize a window. Windows are user resizable
7954 gtk_window_set_resizable (GtkWindow *window,
7957 GtkWindowPrivate *priv;
7959 g_return_if_fail (GTK_IS_WINDOW (window));
7961 priv = window->priv;
7963 priv->resizable = (resizable != FALSE);
7965 g_object_notify (G_OBJECT (window), "resizable");
7967 if (priv->grip_window != NULL)
7968 update_grip_visibility (window);
7970 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7974 * gtk_window_get_resizable:
7975 * @window: a #GtkWindow
7977 * Gets the value set by gtk_window_set_resizable().
7979 * Return value: %TRUE if the user can resize the window
7982 gtk_window_get_resizable (GtkWindow *window)
7984 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7986 return window->priv->resizable;
7990 * gtk_window_set_gravity:
7991 * @window: a #GtkWindow
7992 * @gravity: window gravity
7994 * Window gravity defines the meaning of coordinates passed to
7995 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7998 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7999 * typically "do what you mean."
8003 gtk_window_set_gravity (GtkWindow *window,
8006 GtkWindowPrivate *priv;
8008 g_return_if_fail (GTK_IS_WINDOW (window));
8010 priv = window->priv;
8012 if (gravity != priv->gravity)
8014 priv->gravity = gravity;
8016 /* gtk_window_move_resize() will adapt gravity
8018 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8020 g_object_notify (G_OBJECT (window), "gravity");
8025 * gtk_window_get_gravity:
8026 * @window: a #GtkWindow
8028 * Gets the value set by gtk_window_set_gravity().
8030 * Return value: (transfer none): window gravity
8033 gtk_window_get_gravity (GtkWindow *window)
8035 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8037 return window->priv->gravity;
8041 * gtk_window_begin_resize_drag:
8042 * @window: a #GtkWindow
8043 * @button: mouse button that initiated the drag
8044 * @edge: position of the resize control
8045 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8046 * @root_y: Y position where the user clicked to initiate the drag
8047 * @timestamp: timestamp from the click event that initiated the drag
8049 * Starts resizing a window. This function is used if an application
8050 * has window resizing controls. When GDK can support it, the resize
8051 * will be done using the standard mechanism for the <link
8052 * linkend="gtk-X11-arch">window manager</link> or windowing
8053 * system. Otherwise, GDK will try to emulate window resizing,
8054 * potentially not all that well, depending on the windowing system.
8058 gtk_window_begin_resize_drag (GtkWindow *window,
8065 GtkWindowPrivate *priv;
8067 GdkWindow *toplevel;
8069 g_return_if_fail (GTK_IS_WINDOW (window));
8070 widget = GTK_WIDGET (window);
8071 g_return_if_fail (gtk_widget_get_visible (widget));
8073 priv = window->priv;
8076 toplevel = priv->frame;
8078 toplevel = gtk_widget_get_window (widget);
8080 gdk_window_begin_resize_drag (toplevel,
8087 * gtk_window_get_frame_dimensions:
8088 * @window: a #GtkWindow
8089 * @left: (out) (allow-none): location to store the width of the frame at the left, or %NULL
8090 * @top: (out) (allow-none): location to store the height of the frame at the top, or %NULL
8091 * @right: (out) (allow-none): location to store the width of the frame at the returns, or %NULL
8092 * @bottom: (out) (allow-none): location to store the height of the frame at the bottom, or %NULL
8094 * (Note: this is a special-purpose function intended for the
8095 * framebuffer port; see gtk_window_set_has_frame(). It will not
8096 * return the size of the window border drawn by the <link
8097 * linkend="gtk-X11-arch">window manager</link>, which is the normal
8098 * case when using a windowing system. See
8099 * gdk_window_get_frame_extents() to get the standard window border
8102 * Retrieves the dimensions of the frame window for this toplevel.
8103 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
8106 gtk_window_get_frame_dimensions (GtkWindow *window,
8112 GtkWindowPrivate *priv;
8114 g_return_if_fail (GTK_IS_WINDOW (window));
8116 priv = window->priv;
8119 *left = priv->frame_left;
8121 *top = priv->frame_top;
8123 *right = priv->frame_right;
8125 *bottom = priv->frame_bottom;
8129 * gtk_window_begin_move_drag:
8130 * @window: a #GtkWindow
8131 * @button: mouse button that initiated the drag
8132 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8133 * @root_y: Y position where the user clicked to initiate the drag
8134 * @timestamp: timestamp from the click event that initiated the drag
8136 * Starts moving a window. This function is used if an application has
8137 * window movement grips. When GDK can support it, the window movement
8138 * will be done using the standard mechanism for the <link
8139 * linkend="gtk-X11-arch">window manager</link> or windowing
8140 * system. Otherwise, GDK will try to emulate window movement,
8141 * potentially not all that well, depending on the windowing system.
8145 gtk_window_begin_move_drag (GtkWindow *window,
8151 GtkWindowPrivate *priv;
8153 GdkWindow *toplevel;
8155 g_return_if_fail (GTK_IS_WINDOW (window));
8156 widget = GTK_WIDGET (window);
8157 g_return_if_fail (gtk_widget_get_visible (widget));
8159 priv = window->priv;
8162 toplevel = priv->frame;
8164 toplevel = gtk_widget_get_window (widget);
8166 gdk_window_begin_move_drag (toplevel,
8173 * gtk_window_set_screen:
8174 * @window: a #GtkWindow.
8175 * @screen: a #GdkScreen.
8177 * Sets the #GdkScreen where the @window is displayed; if
8178 * the window is already mapped, it will be unmapped, and
8179 * then remapped on the new screen.
8184 gtk_window_set_screen (GtkWindow *window,
8187 GtkWindowPrivate *priv;
8189 GdkScreen *previous_screen;
8190 gboolean was_mapped;
8192 g_return_if_fail (GTK_IS_WINDOW (window));
8193 g_return_if_fail (GDK_IS_SCREEN (screen));
8195 priv = window->priv;
8197 if (screen == priv->screen)
8200 widget = GTK_WIDGET (window);
8202 previous_screen = priv->screen;
8203 was_mapped = gtk_widget_get_mapped (widget);
8206 gtk_widget_unmap (widget);
8207 if (gtk_widget_get_realized (widget))
8208 gtk_widget_unrealize (widget);
8210 gtk_window_free_key_hash (window);
8211 priv->screen = screen;
8212 gtk_widget_reset_rc_styles (widget);
8213 if (screen != previous_screen)
8215 g_signal_handlers_disconnect_by_func (previous_screen,
8216 gtk_window_on_composited_changed, window);
8217 g_signal_connect (screen, "composited-changed",
8218 G_CALLBACK (gtk_window_on_composited_changed), window);
8220 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8221 _gtk_widget_propagate_composited_changed (widget);
8223 g_object_notify (G_OBJECT (window), "screen");
8226 gtk_widget_map (widget);
8230 gtk_window_on_composited_changed (GdkScreen *screen,
8233 gtk_widget_queue_draw (GTK_WIDGET (window));
8235 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8239 gtk_window_check_screen (GtkWindow *window)
8241 GtkWindowPrivate *priv = window->priv;
8244 return priv->screen;
8247 g_warning ("Screen for GtkWindow not set; you must always set\n"
8248 "a screen for a GtkWindow before using the window");
8254 * gtk_window_get_screen:
8255 * @window: a #GtkWindow.
8257 * Returns the #GdkScreen associated with @window.
8259 * Return value: (transfer none): a #GdkScreen.
8264 gtk_window_get_screen (GtkWindow *window)
8266 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8268 return window->priv->screen;
8272 * gtk_window_is_active:
8273 * @window: a #GtkWindow
8275 * Returns whether the window is part of the current active toplevel.
8276 * (That is, the toplevel window receiving keystrokes.)
8277 * The return value is %TRUE if the window is active toplevel
8278 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8279 * You might use this function if you wanted to draw a widget
8280 * differently in an active window from a widget in an inactive window.
8281 * See gtk_window_has_toplevel_focus()
8283 * Return value: %TRUE if the window part of the current active window.
8288 gtk_window_is_active (GtkWindow *window)
8290 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8292 return window->priv->is_active;
8296 * gtk_window_has_toplevel_focus:
8297 * @window: a #GtkWindow
8299 * Returns whether the input focus is within this GtkWindow.
8300 * For real toplevel windows, this is identical to gtk_window_is_active(),
8301 * but for embedded windows, like #GtkPlug, the results will differ.
8303 * Return value: %TRUE if the input focus is within this GtkWindow
8308 gtk_window_has_toplevel_focus (GtkWindow *window)
8310 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8312 return window->priv->has_toplevel_focus;
8316 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8318 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8322 gtk_window_group_get_type (void)
8324 static GType window_group_type = 0;
8326 if (!window_group_type)
8328 const GTypeInfo window_group_info =
8330 sizeof (GtkWindowGroupClass),
8331 NULL, /* base_init */
8332 NULL, /* base_finalize */
8333 (GClassInitFunc) gtk_window_group_class_init,
8334 NULL, /* class_finalize */
8335 NULL, /* class_data */
8336 sizeof (GtkWindowGroup),
8337 0, /* n_preallocs */
8338 (GInstanceInitFunc) NULL,
8341 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
8342 &window_group_info, 0);
8345 return window_group_type;
8349 * gtk_window_group_new:
8351 * Creates a new #GtkWindowGroup object. Grabs added with
8352 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8354 * Return value: a new #GtkWindowGroup.
8357 gtk_window_group_new (void)
8359 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8363 window_group_cleanup_grabs (GtkWindowGroup *group,
8366 GtkWindowGroupPrivate *priv;
8367 GtkDeviceGrabInfo *info;
8369 GSList *to_remove = NULL;
8371 tmp_list = group->grabs;
8374 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8375 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8376 tmp_list = tmp_list->next;
8381 gtk_grab_remove (to_remove->data);
8382 g_object_unref (to_remove->data);
8383 to_remove = g_slist_delete_link (to_remove, to_remove);
8386 priv = GTK_WINDOW_GROUP_GET_PRIVATE (group);
8387 tmp_list = priv->device_grabs;
8391 info = tmp_list->data;
8393 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8394 to_remove = g_slist_prepend (to_remove, info);
8396 tmp_list = tmp_list->next;
8401 info = to_remove->data;
8403 gtk_device_grab_remove (info->widget, info->device);
8404 to_remove = g_slist_delete_link (to_remove, to_remove);
8409 * gtk_window_group_add_window:
8410 * @window_group: a #GtkWindowGroup
8411 * @window: the #GtkWindow to add
8413 * Adds a window to a #GtkWindowGroup.
8416 gtk_window_group_add_window (GtkWindowGroup *window_group,
8419 GtkWindowPrivate *priv;
8421 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8422 g_return_if_fail (GTK_IS_WINDOW (window));
8424 priv = window->priv;
8426 if (priv->group != window_group)
8428 g_object_ref (window);
8429 g_object_ref (window_group);
8432 gtk_window_group_remove_window (priv->group, window);
8434 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8436 priv->group = window_group;
8438 g_object_unref (window);
8443 * gtk_window_group_remove_window:
8444 * @window_group: a #GtkWindowGroup
8445 * @window: the #GtkWindow to remove
8447 * Removes a window from a #GtkWindowGroup.
8450 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8453 GtkWindowPrivate *priv;
8455 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8456 g_return_if_fail (GTK_IS_WINDOW (window));
8457 priv = window->priv;
8458 g_return_if_fail (priv->group == window_group);
8460 g_object_ref (window);
8462 window_group_cleanup_grabs (window_group, window);
8465 g_object_unref (window_group);
8466 g_object_unref (window);
8470 * gtk_window_group_list_windows:
8471 * @window_group: a #GtkWindowGroup
8473 * Returns a list of the #GtkWindows that belong to @window_group.
8475 * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
8476 * windows inside the group.
8481 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8483 GList *toplevels, *toplevel, *group_windows;
8485 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8487 group_windows = NULL;
8488 toplevels = gtk_window_list_toplevels ();
8490 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8492 GtkWindow *window = toplevel->data;
8494 if (window_group == window->priv->group)
8495 group_windows = g_list_prepend (group_windows, window);
8498 return g_list_reverse (group_windows);
8502 * gtk_window_get_group:
8503 * @window: (allow-none): a #GtkWindow, or %NULL
8505 * Returns the group for @window or the default group, if
8506 * @window is %NULL or if @window does not have an explicit
8509 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8514 gtk_window_get_group (GtkWindow *window)
8516 if (window && window->priv->group)
8517 return window->priv->group;
8520 static GtkWindowGroup *default_group = NULL;
8523 default_group = gtk_window_group_new ();
8525 return default_group;
8530 * gtk_window_has_group:
8531 * @window: a #GtkWindow
8533 * Returns whether @window has an explicit window group.
8535 * Return value: %TRUE if @window has an explicit window group.
8540 gtk_window_has_group (GtkWindow *window)
8542 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8544 return window->priv->group != NULL;
8548 * gtk_window_group_get_current_grab:
8549 * @window_group: a #GtkWindowGroup
8551 * Gets the current grab widget of the given group,
8552 * see gtk_grab_add().
8554 * Returns: the current grab widget of the group
8559 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8561 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8563 if (window_group->grabs)
8564 return GTK_WIDGET (window_group->grabs->data);
8569 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8572 gboolean block_others)
8574 GtkWindowGroupPrivate *priv;
8575 GtkDeviceGrabInfo *info;
8577 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8579 info = g_slice_new0 (GtkDeviceGrabInfo);
8580 info->widget = widget;
8581 info->device = device;
8582 info->block_others = block_others;
8584 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8588 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8592 GtkWindowGroupPrivate *priv;
8593 GtkDeviceGrabInfo *info;
8594 GSList *list, *node = NULL;
8595 GdkDevice *other_device;
8597 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8598 other_device = gdk_device_get_associated_device (device);
8599 list = priv->device_grabs;
8605 if (info->widget == widget &&
8606 (info->device == device ||
8607 info->device == other_device))
8620 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8621 g_slice_free (GtkDeviceGrabInfo, info);
8626 * gtk_window_group_get_current_device_grab:
8627 * @window_group: a #GtkWindowGroup
8628 * @device: a #GdkDevice
8630 * Returns the current grab widget for @device, or %NULL if none.
8632 * Returns: The grab widget, or %NULL
8637 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8640 GtkWindowGroupPrivate *priv;
8641 GtkDeviceGrabInfo *info;
8642 GdkDevice *other_device;
8645 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8646 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8648 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8649 list = priv->device_grabs;
8650 other_device = gdk_device_get_associated_device (device);
8657 if (info->device == device ||
8658 info->device == other_device)
8659 return info->widget;
8666 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8670 GtkWindowGroupPrivate *priv;
8671 GtkDeviceGrabInfo *info;
8672 GdkDevice *other_device;
8675 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8676 other_device = gdk_device_get_associated_device (device);
8677 list = priv->device_grabs;
8684 /* Look for blocking grabs on other device pairs
8685 * that have the passed widget within the GTK+ grab.
8687 if (info->block_others &&
8688 info->device != device &&
8689 info->device != other_device &&
8690 (info->widget == widget ||
8691 gtk_widget_is_ancestor (widget, info->widget)))
8699 Derived from XParseGeometry() in XFree86
8701 Copyright 1985, 1986, 1987,1998 The Open Group
8703 All Rights Reserved.
8705 The above copyright notice and this permission notice shall be included
8706 in all copies or substantial portions of the Software.
8708 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8709 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8710 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8711 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8712 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8713 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8714 OTHER DEALINGS IN THE SOFTWARE.
8716 Except as contained in this notice, the name of The Open Group shall
8717 not be used in advertising or otherwise to promote the sale, use or
8718 other dealings in this Software without prior written authorization
8719 from The Open Group.
8724 * XParseGeometry parses strings of the form
8725 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8726 * width, height, xoffset, and yoffset are unsigned integers.
8727 * Example: "=80x24+300-49"
8728 * The equal sign is optional.
8729 * It returns a bitmask that indicates which of the four values
8730 * were actually found in the string. For each value found,
8731 * the corresponding argument is updated; for each value
8732 * not found, the corresponding argument is left unchanged.
8735 /* The following code is from Xlib, and is minimally modified, so we
8736 * can track any upstream changes if required. Don't change this
8737 * code. Or if you do, put in a huge comment marking which thing
8742 read_int (gchar *string,
8750 else if (*string == '-')
8756 for (; (*string >= '0') && (*string <= '9'); string++)
8758 result = (result * 10) + (*string - '0');
8770 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8771 * value (x, y, width, height) was found in the parsed string.
8773 #define NoValue 0x0000
8774 #define XValue 0x0001
8775 #define YValue 0x0002
8776 #define WidthValue 0x0004
8777 #define HeightValue 0x0008
8778 #define AllValues 0x000F
8779 #define XNegative 0x0010
8780 #define YNegative 0x0020
8782 /* Try not to reformat/modify, so we can compare/sync with X sources */
8784 gtk_XParseGeometry (const char *string,
8787 unsigned int *width,
8788 unsigned int *height)
8792 unsigned int tempWidth, tempHeight;
8794 char *nextCharacter;
8796 /* These initializations are just to silence gcc */
8802 if ( (string == NULL) || (*string == '\0')) return(mask);
8804 string++; /* ignore possible '=' at beg of geometry spec */
8806 strind = (char *)string;
8807 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8808 tempWidth = read_int(strind, &nextCharacter);
8809 if (strind == nextCharacter)
8811 strind = nextCharacter;
8815 if (*strind == 'x' || *strind == 'X') {
8817 tempHeight = read_int(strind, &nextCharacter);
8818 if (strind == nextCharacter)
8820 strind = nextCharacter;
8821 mask |= HeightValue;
8824 if ((*strind == '+') || (*strind == '-')) {
8825 if (*strind == '-') {
8827 tempX = -read_int(strind, &nextCharacter);
8828 if (strind == nextCharacter)
8830 strind = nextCharacter;
8836 tempX = read_int(strind, &nextCharacter);
8837 if (strind == nextCharacter)
8839 strind = nextCharacter;
8842 if ((*strind == '+') || (*strind == '-')) {
8843 if (*strind == '-') {
8845 tempY = -read_int(strind, &nextCharacter);
8846 if (strind == nextCharacter)
8848 strind = nextCharacter;
8855 tempY = read_int(strind, &nextCharacter);
8856 if (strind == nextCharacter)
8858 strind = nextCharacter;
8864 /* If strind isn't at the end of the string the it's an invalid
8865 geometry specification. */
8867 if (*strind != '\0') return (0);
8873 if (mask & WidthValue)
8875 if (mask & HeightValue)
8876 *height = tempHeight;
8881 * gtk_window_parse_geometry:
8882 * @window: a #GtkWindow
8883 * @geometry: geometry string
8885 * Parses a standard X Window System geometry string - see the
8886 * manual page for X (type 'man X') for details on this.
8887 * gtk_window_parse_geometry() does work on all GTK+ ports
8888 * including Win32 but is primarily intended for an X environment.
8890 * If either a size or a position can be extracted from the
8891 * geometry string, gtk_window_parse_geometry() returns %TRUE
8892 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8893 * to resize/move the window.
8895 * If gtk_window_parse_geometry() returns %TRUE, it will also
8896 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8897 * indicating to the window manager that the size/position of
8898 * the window was user-specified. This causes most window
8899 * managers to honor the geometry.
8901 * Note that for gtk_window_parse_geometry() to work as expected, it has
8902 * to be called when the window has its "final" size, i.e. after calling
8903 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8906 * #include <gtk/gtk.h>
8909 * fill_with_content (GtkWidget *vbox)
8911 * /* fill with content... */
8915 * main (int argc, char *argv[])
8917 * GtkWidget *window, *vbox;
8918 * GdkGeometry size_hints = {
8919 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8922 * gtk_init (&argc, &argv);
8924 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8925 * vbox = gtk_vbox_new (FALSE, 0);
8927 * gtk_container_add (GTK_CONTAINER (window), vbox);
8928 * fill_with_content (vbox);
8929 * gtk_widget_show_all (vbox);
8931 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8934 * GDK_HINT_MIN_SIZE |
8935 * GDK_HINT_BASE_SIZE |
8936 * GDK_HINT_RESIZE_INC);
8940 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8941 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8944 * gtk_widget_show_all (window);
8951 * Return value: %TRUE if string was parsed successfully
8954 gtk_window_parse_geometry (GtkWindow *window,
8955 const gchar *geometry)
8957 gint result, x = 0, y = 0;
8961 gboolean size_set, pos_set;
8964 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8965 g_return_val_if_fail (geometry != NULL, FALSE);
8967 child = gtk_bin_get_child (GTK_BIN (window));
8968 if (!child || !gtk_widget_get_visible (child))
8969 g_warning ("gtk_window_parse_geometry() called on a window with no "
8970 "visible children; the window should be set up before "
8971 "gtk_window_parse_geometry() is called.");
8973 screen = gtk_window_check_screen (window);
8975 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8978 if ((result & WidthValue) || (result & HeightValue))
8980 gtk_window_set_default_size_internal (window,
8981 TRUE, result & WidthValue ? w : -1,
8982 TRUE, result & HeightValue ? h : -1,
8987 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8989 grav = GDK_GRAVITY_NORTH_WEST;
8991 if ((result & XNegative) && (result & YNegative))
8992 grav = GDK_GRAVITY_SOUTH_EAST;
8993 else if (result & XNegative)
8994 grav = GDK_GRAVITY_NORTH_EAST;
8995 else if (result & YNegative)
8996 grav = GDK_GRAVITY_SOUTH_WEST;
8998 if ((result & XValue) == 0)
9001 if ((result & YValue) == 0)
9004 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9005 grav == GDK_GRAVITY_SOUTH_EAST)
9006 y = gdk_screen_get_height (screen) - h + y;
9008 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9009 grav == GDK_GRAVITY_NORTH_EAST)
9010 x = gdk_screen_get_width (screen) - w + x;
9012 /* we don't let you put a window offscreen; maybe some people would
9013 * prefer to be able to, but it's kind of a bogus thing to do.
9022 if ((result & XValue) || (result & YValue))
9024 gtk_window_set_gravity (window, grav);
9025 gtk_window_move (window, x, y);
9029 if (size_set || pos_set)
9031 /* Set USSize, USPosition hints */
9032 GtkWindowGeometryInfo *info;
9034 info = gtk_window_get_geometry_info (window, TRUE);
9037 info->mask |= GDK_HINT_USER_POS;
9039 info->mask |= GDK_HINT_USER_SIZE;
9046 gtk_window_mnemonic_hash_foreach (guint keyval,
9052 GtkWindowKeysForeachFunc func;
9056 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9060 _gtk_window_keys_foreach (GtkWindow *window,
9061 GtkWindowKeysForeachFunc func,
9065 GtkMnemonicHash *mnemonic_hash;
9069 GtkWindowKeysForeachFunc func;
9073 info.window = window;
9075 info.func_data = func_data;
9077 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9079 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9080 gtk_window_mnemonic_hash_foreach, &info);
9082 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9085 GtkAccelGroup *group = groups->data;
9088 for (i = 0; i < group->priv->n_accels; i++)
9090 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9093 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9096 groups = groups->next;
9101 gtk_window_keys_changed (GtkWindow *window)
9103 gtk_window_free_key_hash (window);
9104 gtk_window_get_key_hash (window);
9107 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9109 struct _GtkWindowKeyEntry
9113 guint is_mnemonic : 1;
9117 window_key_entry_destroy (gpointer data)
9119 g_slice_free (GtkWindowKeyEntry, data);
9123 add_to_key_hash (GtkWindow *window,
9125 GdkModifierType modifiers,
9126 gboolean is_mnemonic,
9129 GtkKeyHash *key_hash = data;
9131 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9133 entry->keyval = keyval;
9134 entry->modifiers = modifiers;
9135 entry->is_mnemonic = is_mnemonic;
9137 /* GtkAccelGroup stores lowercased accelerators. To deal
9138 * with this, if <Shift> was specified, uppercase.
9140 if (modifiers & GDK_SHIFT_MASK)
9142 if (keyval == GDK_KEY_Tab)
9143 keyval = GDK_KEY_ISO_Left_Tab;
9145 keyval = gdk_keyval_to_upper (keyval);
9148 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9152 gtk_window_get_key_hash (GtkWindow *window)
9154 GdkScreen *screen = gtk_window_check_screen (window);
9155 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9160 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9161 (GDestroyNotify)window_key_entry_destroy);
9162 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9163 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9169 gtk_window_free_key_hash (GtkWindow *window)
9171 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9174 _gtk_key_hash_free (key_hash);
9175 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9180 * gtk_window_activate_key:
9181 * @window: a #GtkWindow
9182 * @event: a #GdkEventKey
9184 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9185 * called by the default ::key_press_event handler for toplevel windows,
9186 * however in some cases it may be useful to call this directly when
9187 * overriding the standard key handling for a toplevel window.
9189 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9194 gtk_window_activate_key (GtkWindow *window,
9197 GtkKeyHash *key_hash;
9198 GtkWindowKeyEntry *found_entry = NULL;
9199 gboolean enable_mnemonics;
9200 gboolean enable_accels;
9202 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9203 g_return_val_if_fail (event != NULL, FALSE);
9205 key_hash = gtk_window_get_key_hash (window);
9210 GSList *entries = _gtk_key_hash_lookup (key_hash,
9211 event->hardware_keycode,
9213 gtk_accelerator_get_default_mod_mask (),
9216 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9217 "gtk-enable-mnemonics", &enable_mnemonics,
9218 "gtk-enable-accels", &enable_accels,
9221 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9223 GtkWindowKeyEntry *entry = tmp_list->data;
9224 if (entry->is_mnemonic)
9226 if (enable_mnemonics)
9228 found_entry = entry;
9234 if (enable_accels && !found_entry)
9236 found_entry = entry;
9241 g_slist_free (entries);
9246 if (found_entry->is_mnemonic)
9248 if (enable_mnemonics)
9249 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9250 found_entry->modifiers);
9255 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9256 found_entry->modifiers);
9264 window_update_has_focus (GtkWindow *window)
9266 GtkWindowPrivate *priv = window->priv;
9267 GtkWidget *widget = GTK_WIDGET (window);
9268 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9270 if (has_focus != priv->has_focus)
9272 priv->has_focus = has_focus;
9276 if (priv->focus_widget &&
9277 priv->focus_widget != widget &&
9278 !gtk_widget_has_focus (priv->focus_widget))
9279 do_focus_change (priv->focus_widget, TRUE);
9283 if (priv->focus_widget &&
9284 priv->focus_widget != widget &&
9285 gtk_widget_has_focus (priv->focus_widget))
9286 do_focus_change (priv->focus_widget, FALSE);
9292 * _gtk_window_set_is_active:
9293 * @window: a #GtkWindow
9294 * @is_active: %TRUE if the window is in the currently active toplevel
9296 * Internal function that sets whether the #GtkWindow is part
9297 * of the currently active toplevel window (taking into account inter-process
9301 _gtk_window_set_is_active (GtkWindow *window,
9304 GtkWindowPrivate *priv;
9306 g_return_if_fail (GTK_IS_WINDOW (window));
9308 priv = window->priv;
9310 is_active = is_active != FALSE;
9312 if (is_active != priv->is_active)
9314 priv->is_active = is_active;
9315 window_update_has_focus (window);
9317 g_object_notify (G_OBJECT (window), "is-active");
9322 * _gtk_window_set_is_toplevel:
9323 * @window: a #GtkWindow
9324 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9325 * parent of the root window); %FALSE if it is not (for example, for an
9326 * in-process, parented GtkPlug)
9328 * Internal function used by #GtkPlug when it gets parented/unparented by a
9329 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9330 * global list of toplevel windows.
9333 _gtk_window_set_is_toplevel (GtkWindow *window,
9334 gboolean is_toplevel)
9338 widget = GTK_WIDGET (window);
9340 if (gtk_widget_is_toplevel (widget))
9341 g_assert (g_slist_find (toplevel_list, window) != NULL);
9343 g_assert (g_slist_find (toplevel_list, window) == NULL);
9345 if (is_toplevel == gtk_widget_is_toplevel (widget))
9350 _gtk_widget_set_is_toplevel (widget, TRUE);
9351 toplevel_list = g_slist_prepend (toplevel_list, window);
9355 _gtk_widget_set_is_toplevel (widget, FALSE);
9356 toplevel_list = g_slist_remove (toplevel_list, window);
9361 * _gtk_window_set_has_toplevel_focus:
9362 * @window: a #GtkWindow
9363 * @has_toplevel_focus: %TRUE if the in
9365 * Internal function that sets whether the keyboard focus for the
9366 * toplevel window (taking into account inter-process embedding.)
9369 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9370 gboolean has_toplevel_focus)
9372 GtkWindowPrivate *priv;
9374 g_return_if_fail (GTK_IS_WINDOW (window));
9376 priv = window->priv;
9378 has_toplevel_focus = has_toplevel_focus != FALSE;
9380 if (has_toplevel_focus != priv->has_toplevel_focus)
9382 priv->has_toplevel_focus = has_toplevel_focus;
9383 window_update_has_focus (window);
9385 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9390 * gtk_window_set_auto_startup_notification:
9391 * @setting: %TRUE to automatically do startup notification
9393 * By default, after showing the first #GtkWindow, GTK+ calls
9394 * gdk_notify_startup_complete(). Call this function to disable
9395 * the automatic startup notification. You might do this if your
9396 * first window is a splash screen, and you want to delay notification
9397 * until after your real main window has been shown, for example.
9399 * In that example, you would disable startup notification
9400 * temporarily, show your splash screen, then re-enable it so that
9401 * showing the main window would automatically result in notification.
9406 gtk_window_set_auto_startup_notification (gboolean setting)
9408 disable_startup_notification = !setting;
9412 * gtk_window_get_window_type:
9413 * @window: a #GtkWindow
9415 * Gets the type of the window. See #GtkWindowType.
9417 * Return value: the type of the window
9422 gtk_window_get_window_type (GtkWindow *window)
9424 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9426 return window->priv->type;
9430 * gtk_window_get_mnemonics_visible:
9431 * @window: a #GtkWindow
9433 * Gets the value of the #GtkWindow:mnemonics-visible property.
9435 * Returns: %TRUE if mnemonics are supposed to be visible
9441 gtk_window_get_mnemonics_visible (GtkWindow *window)
9443 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9445 return window->priv->mnemonics_visible;
9449 * gtk_window_set_mnemonics_visible:
9450 * @window: a #GtkWindow
9451 * @setting: the new value
9453 * Sets the #GtkWindow:mnemonics-visible property.
9458 gtk_window_set_mnemonics_visible (GtkWindow *window,
9461 GtkWindowPrivate *priv;
9463 g_return_if_fail (GTK_IS_WINDOW (window));
9465 priv = window->priv;
9467 setting = setting != FALSE;
9469 if (priv->mnemonics_visible != setting)
9471 priv->mnemonics_visible = setting;
9472 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9475 priv->mnemonics_visible_set = TRUE;
9479 _gtk_window_get_wmclass (GtkWindow *window,
9480 gchar **wmclass_name,
9481 gchar **wmclass_class)
9483 GtkWindowPrivate *priv = window->priv;
9485 *wmclass_name = priv->wmclass_name;
9486 *wmclass_class = priv->wmclass_class;