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 "gtkbindings.h"
41 #include "gtkkeyhash.h"
43 #include "gtkmnemonichash.h"
44 #include "gtkmenubar.h"
45 #include "gtkiconfactory.h"
46 #include "gtkicontheme.h"
47 #include "gtkmarshalers.h"
49 #include "gtkbuildable.h"
50 #include "gtkwidgetprivate.h"
52 #ifdef GDK_WINDOWING_X11
59 * @short_description: Toplevel which can contain other widgets
61 * A GtkWindow is a toplevel window which can contain other widgets.
62 * Windows normally have decorations that are under the control
63 * of the windowing system and allow the user to manipulate the window
64 * (resize it, move it, close it,...).
66 * GTK+ also allows windows to have a resize grip (a small area in the lower
67 * right or left corner) which can be clicked to reszie the window. To
68 * control whether a window has a resize grip, use
69 * gtk_window_set_has_resize_grip().
71 * <refsect2 id="GtkWindow-BUILDER-UI">
72 * <title>GtkWindow as GtkBuildable</title>
74 * The GtkWindow implementation of the GtkBuildable interface supports a
75 * custom <tag class="starttag">accel-groups</tag> element, which supports
76 * any number of <tag class="starttag">group</tag> elements representing the
77 * #GtkAccelGroup objects you want to add to your window (synonymous with
78 * gtk_window_add_accel_group().
81 * <title>A UI definition fragment with accel groups</title>
82 * <programlisting><![CDATA[
83 * <object class="GtkWindow">
85 * <group name="accelgroup1"/>
91 * <object class="GtkAccelGroup" id="accelgroup1"/>
92 * ]]></programlisting>
97 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
98 typedef struct _GtkWindowGroupPrivate GtkWindowGroupPrivate;
100 struct _GtkWindowPrivate
102 GtkMnemonicHash *mnemonic_hash;
104 GtkWidget *default_widget;
105 GtkWidget *focus_widget;
106 GtkWindow *transient_parent;
107 GtkWindowGeometryInfo *geometry_info;
108 GtkWindowGroup *group;
110 GdkModifierType mnemonic_modifier;
113 GdkWindowTypeHint gdk_type_hint;
115 GtkApplication *application;
119 GdkWindow *grip_window;
123 gchar *wmclass_class;
131 guint keys_changed_handler;
133 guint16 configure_request_count;
135 /* The following flags are initially TRUE (before a window is mapped).
136 * They cause us to compute a configure request that involves
137 * default-only parameters. Once mapped, we set them to FALSE.
138 * Then we set them to TRUE again on unmap (for position)
139 * and on unrealize (for size).
141 guint need_default_position : 1;
142 guint need_default_size : 1;
144 guint above_initially : 1;
145 guint accept_focus : 1;
146 guint below_initially : 1;
147 guint builder_visible : 1;
148 guint configure_notify_received : 1;
151 guint destroy_with_parent : 1;
152 guint focus_on_map : 1;
153 guint fullscreen_initially : 1;
154 guint gravity : 5; /* GdkGravity */
156 guint has_user_ref_count : 1;
158 guint has_toplevel_focus : 1;
159 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
161 guint maximize_initially : 1;
162 guint mnemonics_visible : 1;
163 guint mnemonics_visible_set : 1;
165 guint opacity_set : 1;
167 guint reset_type_hint : 1;
169 guint skips_pager : 1;
170 guint skips_taskbar : 1;
171 guint stick_initially : 1;
172 guint transient_parent_group : 1;
173 guint type : 4; /* GtkWindowType */
174 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
175 * one of the original eight. If not,
177 * GDK_WINDOW_TYPE_HINT_NORMAL
180 guint has_resize_grip : 1;
181 guint resize_grip_visible : 1; /* don't use, just for "resize-
182 * grip-visible" notification
210 PROP_DESTROY_WITH_PARENT,
215 PROP_SKIP_TASKBAR_HINT,
216 PROP_SKIP_PAGER_HINT,
225 PROP_HAS_RESIZE_GRIP,
226 PROP_RESIZE_GRIP_VISIBLE,
228 /* Readonly properties */
230 PROP_HAS_TOPLEVEL_FOCUS,
232 /* Writeonly properties */
235 PROP_MNEMONICS_VISIBLE,
245 guint using_default_icon : 1;
246 guint using_parent_icon : 1;
247 guint using_themed_icon : 1;
251 GdkGeometry geometry; /* Last set of geometry hints we set */
252 GdkWindowHints flags;
253 GdkRectangle configure_request;
254 } GtkWindowLastGeometryInfo;
256 struct _GtkWindowGeometryInfo
258 /* Properties that the app has set on the window
260 GdkGeometry geometry; /* Geometry hints */
262 GtkWidget *widget; /* subwidget to which hints apply */
263 /* from last gtk_window_resize () - if > 0, indicates that
264 * we should resize to this size.
269 /* From last gtk_window_move () prior to mapping -
270 * only used if initial_pos_set
275 /* Default size - used only the FIRST time we map a window,
280 /* whether to use initial_x, initial_y */
281 guint initial_pos_set : 1;
282 /* CENTER_ALWAYS or other position constraint changed since
283 * we sent the last configure request.
285 guint position_constraints_changed : 1;
287 /* if true, default_width, height should be multiplied by the
288 * increments and affect the geometry widget only
290 guint default_is_geometry : 1;
292 /* if true, resize_width, height should be multiplied by the
293 * increments and affect the geometry widget only
295 guint resize_is_geometry : 1;
297 GtkWindowLastGeometryInfo last;
300 #define GTK_WINDOW_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW_GROUP, GtkWindowGroupPrivate))
302 struct _GtkDeviceGrabInfo
306 guint block_others : 1;
309 struct _GtkWindowGroupPrivate
311 GSList *device_grabs;
314 static void gtk_window_dispose (GObject *object);
315 static void gtk_window_finalize (GObject *object);
316 static void gtk_window_destroy (GtkWidget *widget);
317 static void gtk_window_show (GtkWidget *widget);
318 static void gtk_window_hide (GtkWidget *widget);
319 static void gtk_window_map (GtkWidget *widget);
320 static void gtk_window_unmap (GtkWidget *widget);
321 static void gtk_window_realize (GtkWidget *widget);
322 static void gtk_window_unrealize (GtkWidget *widget);
323 static void gtk_window_size_allocate (GtkWidget *widget,
324 GtkAllocation *allocation);
325 static gint gtk_window_event (GtkWidget *widget,
327 static gboolean gtk_window_map_event (GtkWidget *widget,
329 static gboolean gtk_window_frame_event (GtkWindow *window,
331 static gint gtk_window_configure_event (GtkWidget *widget,
332 GdkEventConfigure *event);
333 static gint gtk_window_key_press_event (GtkWidget *widget,
335 static gint gtk_window_key_release_event (GtkWidget *widget,
337 static gint gtk_window_button_press_event (GtkWidget *widget,
338 GdkEventButton *event);
339 static gint gtk_window_enter_notify_event (GtkWidget *widget,
340 GdkEventCrossing *event);
341 static gint gtk_window_leave_notify_event (GtkWidget *widget,
342 GdkEventCrossing *event);
343 static gint gtk_window_focus_in_event (GtkWidget *widget,
344 GdkEventFocus *event);
345 static gint gtk_window_focus_out_event (GtkWidget *widget,
346 GdkEventFocus *event);
347 static void gtk_window_style_updated (GtkWidget *widget);
348 static gint gtk_window_client_event (GtkWidget *widget,
349 GdkEventClient *event);
350 static gboolean gtk_window_state_event (GtkWidget *widget,
351 GdkEventWindowState *event);
352 static void gtk_window_check_resize (GtkContainer *container);
353 static gint gtk_window_focus (GtkWidget *widget,
354 GtkDirectionType direction);
355 static void gtk_window_move_focus (GtkWidget *widget,
356 GtkDirectionType dir);
357 static void gtk_window_real_set_focus (GtkWindow *window,
359 static void gtk_window_direction_changed (GtkWidget *widget,
360 GtkTextDirection prev_dir);
361 static void gtk_window_state_changed (GtkWidget *widget,
362 GtkStateType previous_state);
364 static void gtk_window_real_activate_default (GtkWindow *window);
365 static void gtk_window_real_activate_focus (GtkWindow *window);
366 static void gtk_window_keys_changed (GtkWindow *window);
367 static gint gtk_window_draw (GtkWidget *widget,
369 static void gtk_window_unset_transient_for (GtkWindow *window);
370 static void gtk_window_transient_parent_realized (GtkWidget *parent,
372 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
375 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
377 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
380 static void gtk_window_move_resize (GtkWindow *window);
381 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
383 GdkGeometry *geometry_b,
385 static void gtk_window_constrain_size (GtkWindow *window,
386 GdkGeometry *geometry,
392 static void gtk_window_constrain_position (GtkWindow *window,
397 static void gtk_window_compute_hints (GtkWindow *window,
398 GdkGeometry *new_geometry,
400 static void gtk_window_compute_configure_request (GtkWindow *window,
401 GdkRectangle *request,
402 GdkGeometry *geometry,
405 static void gtk_window_set_default_size_internal (GtkWindow *window,
406 gboolean change_width,
408 gboolean change_height,
410 gboolean is_geometry);
412 static void update_themed_icon (GtkIconTheme *theme,
414 static GList *icon_list_from_theme (GtkWidget *widget,
416 static void gtk_window_realize_icon (GtkWindow *window);
417 static void gtk_window_unrealize_icon (GtkWindow *window);
418 static void resize_grip_create_window (GtkWindow *window);
419 static void resize_grip_destroy_window (GtkWindow *window);
420 static void update_grip_visibility (GtkWindow *window);
422 static void gtk_window_notify_keys_changed (GtkWindow *window);
423 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
424 static void gtk_window_free_key_hash (GtkWindow *window);
425 static void gtk_window_on_composited_changed (GdkScreen *screen,
428 static GSList *toplevel_list = NULL;
429 static guint window_signals[LAST_SIGNAL] = { 0 };
430 static GList *default_icon_list = NULL;
431 static gchar *default_icon_name = NULL;
432 static guint default_icon_serial = 0;
433 static gboolean disable_startup_notification = FALSE;
434 static gboolean sent_startup_notification = FALSE;
436 static GQuark quark_gtk_embedded = 0;
437 static GQuark quark_gtk_window_key_hash = 0;
438 static GQuark quark_gtk_window_icon_info = 0;
439 static GQuark quark_gtk_buildable_accels = 0;
441 static GtkBuildableIface *parent_buildable_iface;
443 static void gtk_window_set_property (GObject *object,
447 static void gtk_window_get_property (GObject *object,
453 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
454 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
457 const GValue *value);
458 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
459 GtkBuilder *builder);
460 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
463 const gchar *tagname,
464 GMarkupParser *parser,
466 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
469 const gchar *tagname,
473 static void gtk_window_get_preferred_width (GtkWidget *widget,
476 static void gtk_window_get_preferred_height (GtkWidget *widget,
480 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
481 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
482 gtk_window_buildable_interface_init))
485 add_tab_bindings (GtkBindingSet *binding_set,
486 GdkModifierType modifiers,
487 GtkDirectionType direction)
489 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
491 GTK_TYPE_DIRECTION_TYPE, direction);
492 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
494 GTK_TYPE_DIRECTION_TYPE, direction);
498 add_arrow_bindings (GtkBindingSet *binding_set,
500 GtkDirectionType direction)
502 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
504 gtk_binding_entry_add_signal (binding_set, keysym, 0,
506 GTK_TYPE_DIRECTION_TYPE, direction);
507 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
509 GTK_TYPE_DIRECTION_TYPE, direction);
510 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
512 GTK_TYPE_DIRECTION_TYPE, direction);
513 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
515 GTK_TYPE_DIRECTION_TYPE, direction);
519 extract_time_from_startup_id (const gchar* startup_id)
521 gchar *timestr = g_strrstr (startup_id, "_TIME");
522 guint32 retval = GDK_CURRENT_TIME;
529 /* Skip past the "_TIME" part */
534 timestamp = g_ascii_strtoull (timestr, &end, 0);
535 if (errno == 0 && end != timestr)
543 startup_id_is_fake (const gchar* startup_id)
545 return strncmp (startup_id, "_TIME", 5) == 0;
549 gtk_window_class_init (GtkWindowClass *klass)
551 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
552 GtkWidgetClass *widget_class;
553 GtkContainerClass *container_class;
554 GtkBindingSet *binding_set;
556 widget_class = (GtkWidgetClass*) klass;
557 container_class = (GtkContainerClass*) klass;
559 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
560 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
561 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
562 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
564 gobject_class->dispose = gtk_window_dispose;
565 gobject_class->finalize = gtk_window_finalize;
567 gobject_class->set_property = gtk_window_set_property;
568 gobject_class->get_property = gtk_window_get_property;
570 widget_class->destroy = gtk_window_destroy;
571 widget_class->show = gtk_window_show;
572 widget_class->hide = gtk_window_hide;
573 widget_class->map = gtk_window_map;
574 widget_class->map_event = gtk_window_map_event;
575 widget_class->unmap = gtk_window_unmap;
576 widget_class->realize = gtk_window_realize;
577 widget_class->unrealize = gtk_window_unrealize;
578 widget_class->size_allocate = gtk_window_size_allocate;
579 widget_class->configure_event = gtk_window_configure_event;
580 widget_class->key_press_event = gtk_window_key_press_event;
581 widget_class->key_release_event = gtk_window_key_release_event;
582 widget_class->enter_notify_event = gtk_window_enter_notify_event;
583 widget_class->leave_notify_event = gtk_window_leave_notify_event;
584 widget_class->focus_in_event = gtk_window_focus_in_event;
585 widget_class->button_press_event = gtk_window_button_press_event;
586 widget_class->focus_out_event = gtk_window_focus_out_event;
587 widget_class->client_event = gtk_window_client_event;
588 widget_class->focus = gtk_window_focus;
589 widget_class->move_focus = gtk_window_move_focus;
590 widget_class->draw = gtk_window_draw;
591 widget_class->get_preferred_width = gtk_window_get_preferred_width;
592 widget_class->get_preferred_height = gtk_window_get_preferred_height;
593 widget_class->window_state_event = gtk_window_state_event;
594 widget_class->direction_changed = gtk_window_direction_changed;
595 widget_class->state_changed = gtk_window_state_changed;
596 widget_class->style_updated = gtk_window_style_updated;
598 container_class->check_resize = gtk_window_check_resize;
600 klass->set_focus = gtk_window_real_set_focus;
601 klass->frame_event = gtk_window_frame_event;
603 klass->activate_default = gtk_window_real_activate_default;
604 klass->activate_focus = gtk_window_real_activate_focus;
605 klass->keys_changed = gtk_window_keys_changed;
607 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
610 g_object_class_install_property (gobject_class,
612 g_param_spec_enum ("type",
614 P_("The type of the window"),
615 GTK_TYPE_WINDOW_TYPE,
617 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
619 g_object_class_install_property (gobject_class,
621 g_param_spec_string ("title",
623 P_("The title of the window"),
625 GTK_PARAM_READWRITE));
627 g_object_class_install_property (gobject_class,
629 g_param_spec_string ("role",
631 P_("Unique identifier for the window to be used when restoring a session"),
633 GTK_PARAM_READWRITE));
636 * GtkWindow:startup-id:
638 * The :startup-id is a write-only property for setting window's
639 * startup notification identifier. See gtk_window_set_startup_id()
644 g_object_class_install_property (gobject_class,
646 g_param_spec_string ("startup-id",
648 P_("Unique startup identifier for the window used by startup-notification"),
650 GTK_PARAM_WRITABLE));
652 g_object_class_install_property (gobject_class,
654 g_param_spec_boolean ("resizable",
656 P_("If TRUE, users can resize the window"),
658 GTK_PARAM_READWRITE));
660 g_object_class_install_property (gobject_class,
662 g_param_spec_boolean ("modal",
664 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
666 GTK_PARAM_READWRITE));
668 g_object_class_install_property (gobject_class,
670 g_param_spec_enum ("window-position",
671 P_("Window Position"),
672 P_("The initial position of the window"),
673 GTK_TYPE_WINDOW_POSITION,
675 GTK_PARAM_READWRITE));
677 g_object_class_install_property (gobject_class,
679 g_param_spec_int ("default-width",
681 P_("The default width of the window, used when initially showing the window"),
685 GTK_PARAM_READWRITE));
687 g_object_class_install_property (gobject_class,
689 g_param_spec_int ("default-height",
690 P_("Default Height"),
691 P_("The default height of the window, used when initially showing the window"),
695 GTK_PARAM_READWRITE));
697 g_object_class_install_property (gobject_class,
698 PROP_DESTROY_WITH_PARENT,
699 g_param_spec_boolean ("destroy-with-parent",
700 P_("Destroy with Parent"),
701 P_("If this window should be destroyed when the parent is destroyed"),
703 GTK_PARAM_READWRITE));
705 g_object_class_install_property (gobject_class,
707 g_param_spec_object ("icon",
709 P_("Icon for this window"),
711 GTK_PARAM_READWRITE));
712 g_object_class_install_property (gobject_class,
713 PROP_MNEMONICS_VISIBLE,
714 g_param_spec_boolean ("mnemonics-visible",
715 P_("Mnemonics Visible"),
716 P_("Whether mnemonics are currently visible in this window"),
718 GTK_PARAM_READWRITE));
721 * GtkWindow:icon-name:
723 * The :icon-name property specifies the name of the themed icon to
724 * use as the window icon. See #GtkIconTheme for more details.
728 g_object_class_install_property (gobject_class,
730 g_param_spec_string ("icon-name",
732 P_("Name of the themed icon for this window"),
734 GTK_PARAM_READWRITE));
736 g_object_class_install_property (gobject_class,
738 g_param_spec_object ("screen",
740 P_("The screen where this window will be displayed"),
742 GTK_PARAM_READWRITE));
744 g_object_class_install_property (gobject_class,
746 g_param_spec_boolean ("is-active",
748 P_("Whether the toplevel is the current active window"),
750 GTK_PARAM_READABLE));
752 g_object_class_install_property (gobject_class,
753 PROP_HAS_TOPLEVEL_FOCUS,
754 g_param_spec_boolean ("has-toplevel-focus",
755 P_("Focus in Toplevel"),
756 P_("Whether the input focus is within this GtkWindow"),
758 GTK_PARAM_READABLE));
760 g_object_class_install_property (gobject_class,
762 g_param_spec_enum ("type-hint",
764 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
765 GDK_TYPE_WINDOW_TYPE_HINT,
766 GDK_WINDOW_TYPE_HINT_NORMAL,
767 GTK_PARAM_READWRITE));
769 g_object_class_install_property (gobject_class,
770 PROP_SKIP_TASKBAR_HINT,
771 g_param_spec_boolean ("skip-taskbar-hint",
773 P_("TRUE if the window should not be in the task bar."),
775 GTK_PARAM_READWRITE));
777 g_object_class_install_property (gobject_class,
778 PROP_SKIP_PAGER_HINT,
779 g_param_spec_boolean ("skip-pager-hint",
781 P_("TRUE if the window should not be in the pager."),
783 GTK_PARAM_READWRITE));
785 g_object_class_install_property (gobject_class,
787 g_param_spec_boolean ("urgency-hint",
789 P_("TRUE if the window should be brought to the user's attention."),
791 GTK_PARAM_READWRITE));
794 * GtkWindow:accept-focus:
796 * Whether the window should receive the input focus.
800 g_object_class_install_property (gobject_class,
802 g_param_spec_boolean ("accept-focus",
804 P_("TRUE if the window should receive the input focus."),
806 GTK_PARAM_READWRITE));
809 * GtkWindow:focus-on-map:
811 * Whether the window should receive the input focus when mapped.
815 g_object_class_install_property (gobject_class,
817 g_param_spec_boolean ("focus-on-map",
819 P_("TRUE if the window should receive the input focus when mapped."),
821 GTK_PARAM_READWRITE));
824 * GtkWindow:decorated:
826 * Whether the window should be decorated by the window manager.
830 g_object_class_install_property (gobject_class,
832 g_param_spec_boolean ("decorated",
834 P_("Whether the window should be decorated by the window manager"),
836 GTK_PARAM_READWRITE));
839 * GtkWindow:deletable:
841 * Whether the window frame should have a close button.
845 g_object_class_install_property (gobject_class,
847 g_param_spec_boolean ("deletable",
849 P_("Whether the window frame should have a close button"),
851 GTK_PARAM_READWRITE));
854 * GtkWindow:has-resize-grip
856 * Whether the window has a corner resize grip.
858 * Note that the resize grip is only shown if the window is
859 * actually resizable and not maximized. Use
860 * #GtkWindow:resize-grip-visible to find out if the resize
861 * grip is currently shown.
865 g_object_class_install_property (gobject_class,
866 PROP_HAS_RESIZE_GRIP,
867 g_param_spec_boolean ("has-resize-grip",
869 P_("Specifies whether the window should have a resize grip"),
871 GTK_PARAM_READWRITE));
874 * GtkWindow: resize-grip-visible:
876 * Whether a corner resize grip is currently shown.
880 g_object_class_install_property (gobject_class,
881 PROP_RESIZE_GRIP_VISIBLE,
882 g_param_spec_boolean ("resize-grip-visible",
883 P_("Resize grip is visible"),
884 P_("Specifies whether the window's resize grip is visible."),
886 GTK_PARAM_READABLE));
892 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
893 * more details about window gravity.
897 g_object_class_install_property (gobject_class,
899 g_param_spec_enum ("gravity",
901 P_("The window gravity of the window"),
903 GDK_GRAVITY_NORTH_WEST,
904 GTK_PARAM_READWRITE));
908 * GtkWindow:transient-for:
910 * The transient parent of the window. See gtk_window_set_transient_for() for
911 * more details about transient windows.
915 g_object_class_install_property (gobject_class,
917 g_param_spec_object ("transient-for",
918 P_("Transient for Window"),
919 P_("The transient parent of the dialog"),
921 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
926 * The requested opacity of the window. See gtk_window_set_opacity() for
927 * more details about window opacity.
931 g_object_class_install_property (gobject_class,
933 g_param_spec_double ("opacity",
934 P_("Opacity for Window"),
935 P_("The opacity of the window, from 0 to 1"),
939 GTK_PARAM_READWRITE));
943 gtk_widget_class_install_style_property (widget_class,
944 g_param_spec_int ("resize-grip-width",
945 P_("Width of resize grip"),
946 P_("Width of resize grip"),
947 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
949 gtk_widget_class_install_style_property (widget_class,
950 g_param_spec_int ("resize-grip-height",
951 P_("Height of resize grip"),
952 P_("Height of resize grip"),
953 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
959 * GtkWindow:application:
961 * The #GtkApplication associated with the window.
963 * The application will be kept alive for at least as long as the
968 g_object_class_install_property (gobject_class,
970 g_param_spec_object ("application",
971 P_("GtkApplication"),
972 P_("The GtkApplication for the window"),
973 GTK_TYPE_APPLICATION,
974 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
976 window_signals[SET_FOCUS] =
977 g_signal_new (I_("set-focus"),
978 G_TYPE_FROM_CLASS (gobject_class),
980 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
982 _gtk_marshal_VOID__OBJECT,
986 window_signals[FRAME_EVENT] =
987 g_signal_new (I_("frame-event"),
988 G_TYPE_FROM_CLASS (gobject_class),
990 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
991 _gtk_boolean_handled_accumulator, NULL,
992 _gtk_marshal_BOOLEAN__BOXED,
997 * GtkWindow::activate-focus:
998 * @window: the window which received the signal
1000 * The ::activate-focus signal is a
1001 * <link linkend="keybinding-signals">keybinding signal</link>
1002 * which gets emitted when the user activates the currently
1003 * focused widget of @window.
1005 window_signals[ACTIVATE_FOCUS] =
1006 g_signal_new (I_("activate-focus"),
1007 G_TYPE_FROM_CLASS (gobject_class),
1008 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1009 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1011 _gtk_marshal_VOID__VOID,
1016 * GtkWindow::activate-default:
1017 * @window: the window which received the signal
1019 * The ::activate-default signal is a
1020 * <link linkend="keybinding-signals">keybinding signal</link>
1021 * which gets emitted when the user activates the default widget
1024 window_signals[ACTIVATE_DEFAULT] =
1025 g_signal_new (I_("activate-default"),
1026 G_TYPE_FROM_CLASS (gobject_class),
1027 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1028 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1030 _gtk_marshal_VOID__VOID,
1035 * GtkWindow::keys-changed:
1036 * @window: the window which received the signal
1038 * The ::keys-changed signal gets emitted when the set of accelerators
1039 * or mnemonics that are associated with @window changes.
1041 window_signals[KEYS_CHANGED] =
1042 g_signal_new (I_("keys-changed"),
1043 G_TYPE_FROM_CLASS (gobject_class),
1045 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1047 _gtk_marshal_VOID__VOID,
1055 binding_set = gtk_binding_set_by_class (klass);
1057 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1058 "activate-focus", 0);
1059 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1060 "activate-focus", 0);
1062 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1063 "activate-default", 0);
1064 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1065 "activate-default", 0);
1066 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1067 "activate-default", 0);
1069 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1070 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1071 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1072 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1074 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1075 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1076 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1077 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1081 gtk_window_init (GtkWindow *window)
1083 GtkWindowPrivate *priv;
1085 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1088 priv = window->priv;
1090 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1091 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1093 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1095 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1098 priv->wmclass_name = g_strdup (g_get_prgname ());
1099 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1100 priv->wm_role = NULL;
1101 priv->geometry_info = NULL;
1102 priv->type = GTK_WINDOW_TOPLEVEL;
1103 priv->focus_widget = NULL;
1104 priv->default_widget = NULL;
1105 priv->configure_request_count = 0;
1106 priv->resizable = TRUE;
1107 priv->configure_notify_received = FALSE;
1108 priv->position = GTK_WIN_POS_NONE;
1109 priv->need_default_size = TRUE;
1110 priv->need_default_position = TRUE;
1111 priv->modal = FALSE;
1113 priv->has_frame = FALSE;
1114 priv->frame_left = 0;
1115 priv->frame_right = 0;
1116 priv->frame_top = 0;
1117 priv->frame_bottom = 0;
1118 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1119 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1120 priv->decorated = TRUE;
1121 priv->mnemonic_modifier = GDK_MOD1_MASK;
1122 priv->screen = gdk_screen_get_default ();
1124 priv->accept_focus = TRUE;
1125 priv->focus_on_map = TRUE;
1126 priv->deletable = TRUE;
1127 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1128 priv->opacity = 1.0;
1129 priv->startup_id = NULL;
1130 priv->has_resize_grip = TRUE;
1131 priv->mnemonics_visible = TRUE;
1133 g_object_ref_sink (window);
1134 priv->has_user_ref_count = TRUE;
1135 toplevel_list = g_slist_prepend (toplevel_list, window);
1137 g_signal_connect (priv->screen, "composited-changed",
1138 G_CALLBACK (gtk_window_on_composited_changed), window);
1142 gtk_window_set_property (GObject *object,
1144 const GValue *value,
1147 GtkWindow *window = GTK_WINDOW (object);
1148 GtkWindowPrivate *priv = window->priv;
1153 priv->type = g_value_get_enum (value);
1156 gtk_window_set_title (window, g_value_get_string (value));
1159 gtk_window_set_role (window, g_value_get_string (value));
1161 case PROP_STARTUP_ID:
1162 gtk_window_set_startup_id (window, g_value_get_string (value));
1164 case PROP_RESIZABLE:
1165 gtk_window_set_resizable (window, g_value_get_boolean (value));
1168 gtk_window_set_modal (window, g_value_get_boolean (value));
1171 gtk_window_set_position (window, g_value_get_enum (value));
1173 case PROP_DEFAULT_WIDTH:
1174 gtk_window_set_default_size_internal (window,
1175 TRUE, g_value_get_int (value),
1178 case PROP_DEFAULT_HEIGHT:
1179 gtk_window_set_default_size_internal (window,
1181 TRUE, g_value_get_int (value), FALSE);
1183 case PROP_DESTROY_WITH_PARENT:
1184 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1187 gtk_window_set_icon (window,
1188 g_value_get_object (value));
1190 case PROP_ICON_NAME:
1191 gtk_window_set_icon_name (window, g_value_get_string (value));
1194 gtk_window_set_screen (window, g_value_get_object (value));
1196 case PROP_TYPE_HINT:
1197 gtk_window_set_type_hint (window,
1198 g_value_get_enum (value));
1200 case PROP_SKIP_TASKBAR_HINT:
1201 gtk_window_set_skip_taskbar_hint (window,
1202 g_value_get_boolean (value));
1204 case PROP_SKIP_PAGER_HINT:
1205 gtk_window_set_skip_pager_hint (window,
1206 g_value_get_boolean (value));
1208 case PROP_URGENCY_HINT:
1209 gtk_window_set_urgency_hint (window,
1210 g_value_get_boolean (value));
1212 case PROP_ACCEPT_FOCUS:
1213 gtk_window_set_accept_focus (window,
1214 g_value_get_boolean (value));
1216 case PROP_FOCUS_ON_MAP:
1217 gtk_window_set_focus_on_map (window,
1218 g_value_get_boolean (value));
1220 case PROP_DECORATED:
1221 gtk_window_set_decorated (window, g_value_get_boolean (value));
1223 case PROP_DELETABLE:
1224 gtk_window_set_deletable (window, g_value_get_boolean (value));
1227 gtk_window_set_gravity (window, g_value_get_enum (value));
1229 case PROP_TRANSIENT_FOR:
1230 gtk_window_set_transient_for (window, g_value_get_object (value));
1233 gtk_window_set_opacity (window, g_value_get_double (value));
1235 case PROP_HAS_RESIZE_GRIP:
1236 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1238 case PROP_APPLICATION:
1239 gtk_window_set_application (window, g_value_get_object (value));
1241 case PROP_MNEMONICS_VISIBLE:
1242 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1245 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1251 gtk_window_get_property (GObject *object,
1256 GtkWindow *window = GTK_WINDOW (object);
1257 GtkWindowPrivate *priv = window->priv;
1261 GtkWindowGeometryInfo *info;
1263 g_value_set_enum (value, priv->type);
1266 g_value_set_string (value, priv->wm_role);
1269 g_value_set_string (value, priv->title);
1271 case PROP_RESIZABLE:
1272 g_value_set_boolean (value, priv->resizable);
1275 g_value_set_boolean (value, priv->modal);
1278 g_value_set_enum (value, priv->position);
1280 case PROP_DEFAULT_WIDTH:
1281 info = gtk_window_get_geometry_info (window, FALSE);
1283 g_value_set_int (value, -1);
1285 g_value_set_int (value, info->default_width);
1287 case PROP_DEFAULT_HEIGHT:
1288 info = gtk_window_get_geometry_info (window, FALSE);
1290 g_value_set_int (value, -1);
1292 g_value_set_int (value, info->default_height);
1294 case PROP_DESTROY_WITH_PARENT:
1295 g_value_set_boolean (value, priv->destroy_with_parent);
1298 g_value_set_object (value, gtk_window_get_icon (window));
1300 case PROP_ICON_NAME:
1301 g_value_set_string (value, gtk_window_get_icon_name (window));
1304 g_value_set_object (value, priv->screen);
1306 case PROP_IS_ACTIVE:
1307 g_value_set_boolean (value, priv->is_active);
1309 case PROP_HAS_TOPLEVEL_FOCUS:
1310 g_value_set_boolean (value, priv->has_toplevel_focus);
1312 case PROP_TYPE_HINT:
1313 g_value_set_enum (value, priv->type_hint);
1315 case PROP_SKIP_TASKBAR_HINT:
1316 g_value_set_boolean (value,
1317 gtk_window_get_skip_taskbar_hint (window));
1319 case PROP_SKIP_PAGER_HINT:
1320 g_value_set_boolean (value,
1321 gtk_window_get_skip_pager_hint (window));
1323 case PROP_URGENCY_HINT:
1324 g_value_set_boolean (value,
1325 gtk_window_get_urgency_hint (window));
1327 case PROP_ACCEPT_FOCUS:
1328 g_value_set_boolean (value,
1329 gtk_window_get_accept_focus (window));
1331 case PROP_FOCUS_ON_MAP:
1332 g_value_set_boolean (value,
1333 gtk_window_get_focus_on_map (window));
1335 case PROP_DECORATED:
1336 g_value_set_boolean (value, gtk_window_get_decorated (window));
1338 case PROP_DELETABLE:
1339 g_value_set_boolean (value, gtk_window_get_deletable (window));
1342 g_value_set_enum (value, gtk_window_get_gravity (window));
1344 case PROP_TRANSIENT_FOR:
1345 g_value_set_object (value, gtk_window_get_transient_for (window));
1348 g_value_set_double (value, gtk_window_get_opacity (window));
1350 case PROP_HAS_RESIZE_GRIP:
1351 g_value_set_boolean (value, priv->has_resize_grip);
1353 case PROP_RESIZE_GRIP_VISIBLE:
1354 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1356 case PROP_APPLICATION:
1357 g_value_set_object (value, gtk_window_get_application (window));
1359 case PROP_MNEMONICS_VISIBLE:
1360 g_value_set_boolean (value, priv->mnemonics_visible);
1363 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1369 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1371 parent_buildable_iface = g_type_interface_peek_parent (iface);
1372 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1373 iface->parser_finished = gtk_window_buildable_parser_finished;
1374 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1375 iface->custom_finished = gtk_window_buildable_custom_finished;
1379 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1380 GtkBuilder *builder,
1382 const GValue *value)
1384 GtkWindow *window = GTK_WINDOW (buildable);
1385 GtkWindowPrivate *priv = window->priv;
1387 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1388 priv->builder_visible = TRUE;
1390 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1394 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1395 GtkBuilder *builder)
1397 GtkWindow *window = GTK_WINDOW (buildable);
1398 GtkWindowPrivate *priv = window->priv;
1402 if (priv->builder_visible)
1403 gtk_widget_show (GTK_WIDGET (buildable));
1405 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1406 for (l = accels; l; l = l->next)
1408 object = gtk_builder_get_object (builder, l->data);
1411 g_warning ("Unknown accel group %s specified in window %s",
1412 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1415 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1416 GTK_ACCEL_GROUP (object));
1420 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1422 parent_buildable_iface->parser_finished (buildable, builder);
1428 } GSListSubParserData;
1431 window_start_element (GMarkupParseContext *context,
1432 const gchar *element_name,
1433 const gchar **names,
1434 const gchar **values,
1439 GSListSubParserData *data = (GSListSubParserData*)user_data;
1441 if (strcmp (element_name, "group") == 0)
1443 for (i = 0; names[i]; i++)
1445 if (strcmp (names[i], "name") == 0)
1446 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1449 else if (strcmp (element_name, "accel-groups") == 0)
1452 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1457 static const GMarkupParser window_parser =
1459 window_start_element
1463 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1464 GtkBuilder *builder,
1466 const gchar *tagname,
1467 GMarkupParser *parser,
1470 GSListSubParserData *parser_data;
1472 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1473 tagname, parser, data))
1476 if (strcmp (tagname, "accel-groups") == 0)
1478 parser_data = g_slice_new0 (GSListSubParserData);
1479 parser_data->items = NULL;
1480 parser_data->object = G_OBJECT (buildable);
1482 *parser = window_parser;
1483 *data = parser_data;
1491 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1492 GtkBuilder *builder,
1494 const gchar *tagname,
1497 GSListSubParserData *data;
1499 parent_buildable_iface->custom_finished (buildable, builder, child,
1500 tagname, user_data);
1502 if (strcmp (tagname, "accel-groups") != 0)
1505 data = (GSListSubParserData*)user_data;
1507 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1508 data->items, (GDestroyNotify) g_slist_free);
1510 g_slice_free (GSListSubParserData, data);
1515 * @type: type of window
1517 * Creates a new #GtkWindow, which is a toplevel window that can
1518 * contain other widgets. Nearly always, the type of the window should
1519 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1520 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1521 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1522 * dialogs, though in some other toolkits dialogs are called "popups".
1523 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1524 * On X11, popup windows are not controlled by the <link
1525 * linkend="gtk-X11-arch">window manager</link>.
1527 * If you simply want an undecorated window (no window borders), use
1528 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1530 * Return value: a new #GtkWindow.
1533 gtk_window_new (GtkWindowType type)
1535 GtkWindowPrivate *priv;
1538 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1540 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1541 priv = window->priv;
1545 return GTK_WIDGET (window);
1549 * gtk_window_set_title:
1550 * @window: a #GtkWindow
1551 * @title: title of the window
1553 * Sets the title of the #GtkWindow. The title of a window will be
1554 * displayed in its title bar; on the X Window System, the title bar
1555 * is rendered by the <link linkend="gtk-X11-arch">window
1556 * manager</link>, so exactly how the title appears to users may vary
1557 * according to a user's exact configuration. The title should help a
1558 * user distinguish this window from other windows they may have
1559 * open. A good title might include the application name and current
1560 * document filename, for example.
1564 gtk_window_set_title (GtkWindow *window,
1567 GtkWindowPrivate *priv;
1571 g_return_if_fail (GTK_IS_WINDOW (window));
1573 priv = window->priv;
1574 widget = GTK_WIDGET (window);
1576 new_title = g_strdup (title);
1577 g_free (priv->title);
1578 priv->title = new_title;
1580 if (gtk_widget_get_realized (widget))
1582 gdk_window_set_title (gtk_widget_get_window (widget),
1586 g_object_notify (G_OBJECT (window), "title");
1590 * gtk_window_get_title:
1591 * @window: a #GtkWindow
1593 * Retrieves the title of the window. See gtk_window_set_title().
1595 * Return value: the title of the window, or %NULL if none has
1596 * been set explicitely. The returned string is owned by the widget
1597 * and must not be modified or freed.
1599 G_CONST_RETURN gchar *
1600 gtk_window_get_title (GtkWindow *window)
1602 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1604 return window->priv->title;
1608 * gtk_window_set_wmclass:
1609 * @window: a #GtkWindow
1610 * @wmclass_name: window name hint
1611 * @wmclass_class: window class hint
1613 * Don't use this function. It sets the X Window System "class" and
1614 * "name" hints for a window. According to the ICCCM, you should
1615 * always set these to the same value for all windows in an
1616 * application, and GTK+ sets them to that value by default, so calling
1617 * this function is sort of pointless. However, you may want to call
1618 * gtk_window_set_role() on each window in your application, for the
1619 * benefit of the session manager. Setting the role allows the window
1620 * manager to restore window positions when loading a saved session.
1624 gtk_window_set_wmclass (GtkWindow *window,
1625 const gchar *wmclass_name,
1626 const gchar *wmclass_class)
1628 GtkWindowPrivate *priv;
1630 g_return_if_fail (GTK_IS_WINDOW (window));
1632 priv = window->priv;
1634 g_free (priv->wmclass_name);
1635 priv->wmclass_name = g_strdup (wmclass_name);
1637 g_free (priv->wmclass_class);
1638 priv->wmclass_class = g_strdup (wmclass_class);
1640 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1641 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1645 * gtk_window_set_role:
1646 * @window: a #GtkWindow
1647 * @role: unique identifier for the window to be used when restoring a session
1649 * This function is only useful on X11, not with other GTK+ targets.
1651 * In combination with the window title, the window role allows a
1652 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1653 * same" window when an application is restarted. So for example you
1654 * might set the "toolbox" role on your app's toolbox window, so that
1655 * when the user restarts their session, the window manager can put
1656 * the toolbox back in the same place.
1658 * If a window already has a unique title, you don't need to set the
1659 * role, since the WM can use the title to identify the window when
1660 * restoring the session.
1664 gtk_window_set_role (GtkWindow *window,
1667 GtkWindowPrivate *priv;
1670 g_return_if_fail (GTK_IS_WINDOW (window));
1672 priv = window->priv;
1674 new_role = g_strdup (role);
1675 g_free (priv->wm_role);
1676 priv->wm_role = new_role;
1678 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1679 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1682 g_object_notify (G_OBJECT (window), "role");
1686 * gtk_window_set_startup_id:
1687 * @window: a #GtkWindow
1688 * @startup_id: a string with startup-notification identifier
1690 * Startup notification identifiers are used by desktop environment to
1691 * track application startup, to provide user feedback and other
1692 * features. This function changes the corresponding property on the
1693 * underlying GdkWindow. Normally, startup identifier is managed
1694 * automatically and you should only use this function in special cases
1695 * like transferring focus from other processes. You should use this
1696 * function before calling gtk_window_present() or any equivalent
1697 * function generating a window map event.
1699 * This function is only useful on X11, not with other GTK+ targets.
1704 gtk_window_set_startup_id (GtkWindow *window,
1705 const gchar *startup_id)
1707 GtkWindowPrivate *priv;
1710 g_return_if_fail (GTK_IS_WINDOW (window));
1712 priv = window->priv;
1713 widget = GTK_WIDGET (window);
1715 g_free (priv->startup_id);
1716 priv->startup_id = g_strdup (startup_id);
1718 if (gtk_widget_get_realized (widget))
1720 GdkWindow *gdk_window;
1721 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1723 gdk_window = gtk_widget_get_window (widget);
1725 #ifdef GDK_WINDOWING_X11
1726 if (timestamp != GDK_CURRENT_TIME)
1727 gdk_x11_window_set_user_time (gdk_window, timestamp);
1730 /* Here we differentiate real and "fake" startup notification IDs,
1731 * constructed on purpose just to pass interaction timestamp
1733 if (startup_id_is_fake (priv->startup_id))
1734 gtk_window_present_with_time (window, timestamp);
1737 gdk_window_set_startup_id (gdk_window,
1740 /* If window is mapped, terminate the startup-notification too */
1741 if (gtk_widget_get_mapped (widget) &&
1742 !disable_startup_notification)
1743 gdk_notify_startup_complete_with_id (priv->startup_id);
1747 g_object_notify (G_OBJECT (window), "startup-id");
1751 * gtk_window_get_role:
1752 * @window: a #GtkWindow
1754 * Returns the role of the window. See gtk_window_set_role() for
1755 * further explanation.
1757 * Return value: the role of the window if set, or %NULL. The
1758 * returned is owned by the widget and must not be modified
1761 G_CONST_RETURN gchar *
1762 gtk_window_get_role (GtkWindow *window)
1764 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1766 return window->priv->wm_role;
1770 * gtk_window_set_focus:
1771 * @window: a #GtkWindow
1772 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1773 * any focus widget for the toplevel window.
1775 * If @focus is not the current focus widget, and is focusable, sets
1776 * it as the focus widget for the window. If @focus is %NULL, unsets
1777 * the focus widget for this window. To set the focus to a particular
1778 * widget in the toplevel, it is usually more convenient to use
1779 * gtk_widget_grab_focus() instead of this function.
1782 gtk_window_set_focus (GtkWindow *window,
1785 GtkWindowPrivate *priv;
1788 g_return_if_fail (GTK_IS_WINDOW (window));
1790 priv = window->priv;
1794 g_return_if_fail (GTK_IS_WIDGET (focus));
1795 g_return_if_fail (gtk_widget_get_can_focus (focus));
1799 gtk_widget_grab_focus (focus);
1802 /* Clear the existing focus chain, so that when we focus into
1803 * the window again, we start at the beginnning.
1805 GtkWidget *widget = priv->focus_widget;
1808 while ((parent = gtk_widget_get_parent (widget)))
1811 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1815 _gtk_window_internal_set_focus (window, NULL);
1820 _gtk_window_internal_set_focus (GtkWindow *window,
1823 GtkWindowPrivate *priv;
1825 g_return_if_fail (GTK_IS_WINDOW (window));
1827 priv = window->priv;
1829 if ((priv->focus_widget != focus) ||
1830 (focus && !gtk_widget_has_focus (focus)))
1831 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1835 * gtk_window_set_default:
1836 * @window: a #GtkWindow
1837 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1838 * default widget for the toplevel.
1840 * The default widget is the widget that's activated when the user
1841 * presses Enter in a dialog (for example). This function sets or
1842 * unsets the default widget for a #GtkWindow about. When setting
1843 * (rather than unsetting) the default widget it's generally easier to
1844 * call gtk_widget_grab_focus() on the widget. Before making a widget
1845 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1846 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1849 gtk_window_set_default (GtkWindow *window,
1850 GtkWidget *default_widget)
1852 GtkWindowPrivate *priv;
1854 g_return_if_fail (GTK_IS_WINDOW (window));
1856 priv = window->priv;
1859 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1861 if (priv->default_widget != default_widget)
1863 GtkWidget *old_default_widget = NULL;
1866 g_object_ref (default_widget);
1868 if (priv->default_widget)
1870 old_default_widget = priv->default_widget;
1872 if (priv->focus_widget != priv->default_widget ||
1873 !gtk_widget_get_receives_default (priv->default_widget))
1874 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1876 gtk_widget_queue_draw (priv->default_widget);
1879 priv->default_widget = default_widget;
1881 if (priv->default_widget)
1883 if (priv->focus_widget == NULL ||
1884 !gtk_widget_get_receives_default (priv->focus_widget))
1885 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1887 gtk_widget_queue_draw (priv->default_widget);
1890 if (old_default_widget)
1891 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1895 g_object_notify (G_OBJECT (default_widget), "has-default");
1896 g_object_unref (default_widget);
1902 * gtk_window_get_default_widget:
1903 * @window: a #GtkWindow
1905 * Returns the default widget for @window. See gtk_window_set_default()
1908 * Returns: (transfer none): the default widget, or %NULL if there is none.
1913 gtk_window_get_default_widget (GtkWindow *window)
1915 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1917 return window->priv->default_widget;
1921 handle_keys_changed (gpointer data)
1923 GtkWindow *window = GTK_WINDOW (data);
1924 GtkWindowPrivate *priv = window->priv;
1926 if (priv->keys_changed_handler)
1928 g_source_remove (priv->keys_changed_handler);
1929 priv->keys_changed_handler = 0;
1932 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1938 gtk_window_notify_keys_changed (GtkWindow *window)
1940 GtkWindowPrivate *priv = window->priv;
1942 if (!priv->keys_changed_handler)
1943 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1947 * gtk_window_add_accel_group:
1948 * @window: window to attach accelerator group to
1949 * @accel_group: a #GtkAccelGroup
1951 * Associate @accel_group with @window, such that calling
1952 * gtk_accel_groups_activate() on @window will activate accelerators
1956 gtk_window_add_accel_group (GtkWindow *window,
1957 GtkAccelGroup *accel_group)
1959 g_return_if_fail (GTK_IS_WINDOW (window));
1960 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1962 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1963 g_signal_connect_object (accel_group, "accel-changed",
1964 G_CALLBACK (gtk_window_notify_keys_changed),
1965 window, G_CONNECT_SWAPPED);
1966 gtk_window_notify_keys_changed (window);
1970 * gtk_window_remove_accel_group:
1971 * @window: a #GtkWindow
1972 * @accel_group: a #GtkAccelGroup
1974 * Reverses the effects of gtk_window_add_accel_group().
1977 gtk_window_remove_accel_group (GtkWindow *window,
1978 GtkAccelGroup *accel_group)
1980 g_return_if_fail (GTK_IS_WINDOW (window));
1981 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1983 g_signal_handlers_disconnect_by_func (accel_group,
1984 gtk_window_notify_keys_changed,
1986 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1987 gtk_window_notify_keys_changed (window);
1990 static GtkMnemonicHash *
1991 gtk_window_get_mnemonic_hash (GtkWindow *window,
1994 GtkWindowPrivate *private = window->priv;
1996 if (!private->mnemonic_hash && create)
1997 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1999 return private->mnemonic_hash;
2003 * gtk_window_add_mnemonic:
2004 * @window: a #GtkWindow
2005 * @keyval: the mnemonic
2006 * @target: the widget that gets activated by the mnemonic
2008 * Adds a mnemonic to this window.
2011 gtk_window_add_mnemonic (GtkWindow *window,
2015 g_return_if_fail (GTK_IS_WINDOW (window));
2016 g_return_if_fail (GTK_IS_WIDGET (target));
2018 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2020 gtk_window_notify_keys_changed (window);
2024 * gtk_window_remove_mnemonic:
2025 * @window: a #GtkWindow
2026 * @keyval: the mnemonic
2027 * @target: the widget that gets activated by the mnemonic
2029 * Removes a mnemonic from this window.
2032 gtk_window_remove_mnemonic (GtkWindow *window,
2036 g_return_if_fail (GTK_IS_WINDOW (window));
2037 g_return_if_fail (GTK_IS_WIDGET (target));
2039 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2041 gtk_window_notify_keys_changed (window);
2045 * gtk_window_mnemonic_activate:
2046 * @window: a #GtkWindow
2047 * @keyval: the mnemonic
2048 * @modifier: the modifiers
2049 * @returns: %TRUE if the activation is done.
2051 * Activates the targets associated with the mnemonic.
2054 gtk_window_mnemonic_activate (GtkWindow *window,
2056 GdkModifierType modifier)
2058 GtkWindowPrivate *priv;
2060 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2062 priv = window->priv;
2064 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2066 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2068 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2075 * gtk_window_set_mnemonic_modifier:
2076 * @window: a #GtkWindow
2077 * @modifier: the modifier mask used to activate
2078 * mnemonics on this window.
2080 * Sets the mnemonic modifier for this window.
2083 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2084 GdkModifierType modifier)
2086 GtkWindowPrivate *priv;
2088 g_return_if_fail (GTK_IS_WINDOW (window));
2089 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2091 priv = window->priv;
2093 priv->mnemonic_modifier = modifier;
2094 gtk_window_notify_keys_changed (window);
2098 * gtk_window_get_mnemonic_modifier:
2099 * @window: a #GtkWindow
2101 * Returns the mnemonic modifier for this window. See
2102 * gtk_window_set_mnemonic_modifier().
2104 * Return value: the modifier mask used to activate
2105 * mnemonics on this window.
2108 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2110 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2112 return window->priv->mnemonic_modifier;
2116 * gtk_window_set_position:
2117 * @window: a #GtkWindow.
2118 * @position: a position constraint.
2120 * Sets a position constraint for this window. If the old or new
2121 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2122 * the window to be repositioned to satisfy the new constraint.
2125 gtk_window_set_position (GtkWindow *window,
2126 GtkWindowPosition position)
2128 GtkWindowPrivate *priv;
2130 g_return_if_fail (GTK_IS_WINDOW (window));
2132 priv = window->priv;
2134 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2135 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2137 GtkWindowGeometryInfo *info;
2139 info = gtk_window_get_geometry_info (window, TRUE);
2141 /* this flag causes us to re-request the CENTER_ALWAYS
2142 * constraint in gtk_window_move_resize(), see
2143 * comment in that function.
2145 info->position_constraints_changed = TRUE;
2147 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2150 priv->position = position;
2152 g_object_notify (G_OBJECT (window), "window-position");
2156 * gtk_window_activate_focus:
2157 * @window: a #GtkWindow
2159 * Activates the current focused widget within the window.
2161 * Return value: %TRUE if a widget got activated.
2164 gtk_window_activate_focus (GtkWindow *window)
2166 GtkWindowPrivate *priv;
2168 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2170 priv = window->priv;
2172 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2173 return gtk_widget_activate (priv->focus_widget);
2179 * gtk_window_get_focus:
2180 * @window: a #GtkWindow
2182 * Retrieves the current focused widget within the window.
2183 * Note that this is the widget that would have the focus
2184 * if the toplevel window focused; if the toplevel window
2185 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2186 * not be %TRUE for the widget.
2188 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2191 gtk_window_get_focus (GtkWindow *window)
2193 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2195 return window->priv->focus_widget;
2199 * gtk_window_activate_default:
2200 * @window: a #GtkWindow
2202 * Activates the default widget for the window, unless the current
2203 * focused widget has been configured to receive the default action
2204 * (see gtk_widget_set_receives_default()), in which case the
2205 * focused widget is activated.
2207 * Return value: %TRUE if a widget got activated.
2210 gtk_window_activate_default (GtkWindow *window)
2212 GtkWindowPrivate *priv;
2214 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2216 priv = window->priv;
2218 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2219 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2220 return gtk_widget_activate (priv->default_widget);
2221 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2222 return gtk_widget_activate (priv->focus_widget);
2228 * gtk_window_set_modal:
2229 * @window: a #GtkWindow
2230 * @modal: whether the window is modal
2232 * Sets a window modal or non-modal. Modal windows prevent interaction
2233 * with other windows in the same application. To keep modal dialogs
2234 * on top of main application windows, use
2235 * gtk_window_set_transient_for() to make the dialog transient for the
2236 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2237 * will then disallow lowering the dialog below the parent.
2242 gtk_window_set_modal (GtkWindow *window,
2245 GtkWindowPrivate *priv;
2248 g_return_if_fail (GTK_IS_WINDOW (window));
2250 priv = window->priv;
2252 modal = modal != FALSE;
2253 if (priv->modal == modal)
2256 priv->modal = modal;
2257 widget = GTK_WIDGET (window);
2259 /* adjust desired modality state */
2260 if (gtk_widget_get_realized (widget))
2263 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2265 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2268 if (gtk_widget_get_visible (widget))
2271 gtk_grab_add (widget);
2273 gtk_grab_remove (widget);
2276 g_object_notify (G_OBJECT (window), "modal");
2280 * gtk_window_get_modal:
2281 * @window: a #GtkWindow
2283 * Returns whether the window is modal. See gtk_window_set_modal().
2285 * Return value: %TRUE if the window is set to be modal and
2286 * establishes a grab when shown
2289 gtk_window_get_modal (GtkWindow *window)
2291 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2293 return window->priv->modal;
2297 * gtk_window_list_toplevels:
2299 * Returns a list of all existing toplevel windows. The widgets
2300 * in the list are not individually referenced. If you want
2301 * to iterate through the list and perform actions involving
2302 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2303 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2304 * then unref all the widgets afterwards.
2306 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2309 gtk_window_list_toplevels (void)
2314 for (slist = toplevel_list; slist; slist = slist->next)
2315 list = g_list_prepend (list, slist->data);
2321 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2323 GList *embedded_windows;
2325 g_return_if_fail (GTK_IS_WINDOW (window));
2327 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2328 if (embedded_windows)
2329 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2330 embedded_windows = g_list_prepend (embedded_windows,
2331 GUINT_TO_POINTER (xid));
2333 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2336 (GDestroyNotify) g_list_free : NULL);
2340 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2342 GList *embedded_windows;
2345 g_return_if_fail (GTK_IS_WINDOW (window));
2347 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2348 if (embedded_windows)
2349 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2351 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2354 embedded_windows = g_list_remove_link (embedded_windows, node);
2355 g_list_free_1 (node);
2358 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2361 (GDestroyNotify) g_list_free : NULL);
2365 gtk_window_dispose (GObject *object)
2367 GtkWindow *window = GTK_WINDOW (object);
2369 gtk_window_set_focus (window, NULL);
2370 gtk_window_set_default (window, NULL);
2372 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2376 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2378 gtk_widget_destroy (GTK_WIDGET (child));
2382 connect_parent_destroyed (GtkWindow *window)
2384 GtkWindowPrivate *priv = window->priv;
2386 if (priv->transient_parent)
2388 g_signal_connect (priv->transient_parent,
2390 G_CALLBACK (parent_destroyed_callback),
2396 disconnect_parent_destroyed (GtkWindow *window)
2398 GtkWindowPrivate *priv = window->priv;
2400 if (priv->transient_parent)
2402 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2403 parent_destroyed_callback,
2409 gtk_window_transient_parent_realized (GtkWidget *parent,
2412 if (gtk_widget_get_realized (window))
2413 gdk_window_set_transient_for (gtk_widget_get_window (window),
2414 gtk_widget_get_window (parent));
2418 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2421 if (gtk_widget_get_realized (window))
2422 gdk_property_delete (gtk_widget_get_window (window),
2423 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2427 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2431 gtk_window_set_screen (window, parent->priv->screen);
2435 gtk_window_unset_transient_for (GtkWindow *window)
2437 GtkWindowPrivate *priv = window->priv;
2439 if (priv->transient_parent)
2441 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2442 gtk_window_transient_parent_realized,
2444 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2445 gtk_window_transient_parent_unrealized,
2447 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2448 gtk_window_transient_parent_screen_changed,
2450 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2451 gtk_widget_destroyed,
2452 &priv->transient_parent);
2454 if (priv->destroy_with_parent)
2455 disconnect_parent_destroyed (window);
2457 priv->transient_parent = NULL;
2459 if (priv->transient_parent_group)
2461 priv->transient_parent_group = FALSE;
2462 gtk_window_group_remove_window (priv->group,
2469 * gtk_window_set_transient_for:
2470 * @window: a #GtkWindow
2471 * @parent: (allow-none): parent window, or %NULL
2473 * Dialog windows should be set transient for the main application
2474 * window they were spawned from. This allows <link
2475 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2476 * dialog on top of the main window, or center the dialog over the
2477 * main window. gtk_dialog_new_with_buttons() and other convenience
2478 * functions in GTK+ will sometimes call
2479 * gtk_window_set_transient_for() on your behalf.
2481 * Passing %NULL for @parent unsets the current transient window.
2483 * On Windows, this function puts the child window on top of the parent,
2484 * much as the window manager would have done on X.
2487 gtk_window_set_transient_for (GtkWindow *window,
2490 GtkWindowPrivate *priv;
2492 g_return_if_fail (GTK_IS_WINDOW (window));
2493 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2494 g_return_if_fail (window != parent);
2496 priv = window->priv;
2498 if (priv->transient_parent)
2500 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2501 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2502 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2503 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2504 GTK_WIDGET (window));
2506 gtk_window_unset_transient_for (window);
2509 priv->transient_parent = parent;
2513 g_signal_connect (parent, "destroy",
2514 G_CALLBACK (gtk_widget_destroyed),
2515 &priv->transient_parent);
2516 g_signal_connect (parent, "realize",
2517 G_CALLBACK (gtk_window_transient_parent_realized),
2519 g_signal_connect (parent, "unrealize",
2520 G_CALLBACK (gtk_window_transient_parent_unrealized),
2522 g_signal_connect (parent, "notify::screen",
2523 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2526 gtk_window_set_screen (window, parent->priv->screen);
2528 if (priv->destroy_with_parent)
2529 connect_parent_destroyed (window);
2531 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2532 gtk_widget_get_realized (GTK_WIDGET (parent)))
2533 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2534 GTK_WIDGET (window));
2536 if (parent->priv->group)
2538 gtk_window_group_add_window (parent->priv->group, window);
2539 priv->transient_parent_group = TRUE;
2545 * gtk_window_get_transient_for:
2546 * @window: a #GtkWindow
2548 * Fetches the transient parent for this window. See
2549 * gtk_window_set_transient_for().
2551 * Return value: (transfer none): the transient parent for this window, or %NULL
2552 * if no transient parent has been set.
2555 gtk_window_get_transient_for (GtkWindow *window)
2557 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2559 return window->priv->transient_parent;
2563 * gtk_window_set_opacity:
2564 * @window: a #GtkWindow
2565 * @opacity: desired opacity, between 0 and 1
2567 * Request the windowing system to make @window partially transparent,
2568 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2569 * of the opacity parameter are clamped to the [0,1] range.) On X11
2570 * this has any effect only on X screens with a compositing manager
2571 * running. See gtk_widget_is_composited(). On Windows it should work
2574 * Note that setting a window's opacity after the window has been
2575 * shown causes it to flicker once on Windows.
2580 gtk_window_set_opacity (GtkWindow *window,
2583 GtkWindowPrivate *priv;
2585 g_return_if_fail (GTK_IS_WINDOW (window));
2587 priv = window->priv;
2591 else if (opacity > 1.0)
2594 priv->opacity_set = TRUE;
2595 priv->opacity = opacity;
2597 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2598 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2603 * gtk_window_get_opacity:
2604 * @window: a #GtkWindow
2606 * Fetches the requested opacity for this window. See
2607 * gtk_window_set_opacity().
2609 * Return value: the requested opacity for this window.
2614 gtk_window_get_opacity (GtkWindow *window)
2616 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2618 return window->priv->opacity;
2622 * gtk_window_get_application:
2623 * @window: a #GtkWindow
2625 * Gets the #GtkApplication associated with the window (if any).
2627 * Return value: a #GtkApplication, or %NULL
2632 gtk_window_get_application (GtkWindow *window)
2634 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2636 return window->priv->application;
2640 gtk_window_release_application (GtkWindow *window)
2642 if (window->priv->application)
2644 GtkApplication *application;
2646 /* steal reference into temp variable */
2647 application = window->priv->application;
2648 window->priv->application = NULL;
2650 gtk_application_remove_window (application, window);
2651 g_object_unref (application);
2656 * gtk_window_set_application:
2657 * @window: a #GtkWindow
2658 * @application: a #GtkApplication, or %NULL
2660 * Sets or unsets the #GtkApplication associated with the window.
2662 * The application will be kept alive for at least as long as the window
2668 gtk_window_set_application (GtkWindow *window,
2669 GtkApplication *application)
2671 GtkWindowPrivate *priv;
2673 g_return_if_fail (GTK_IS_WINDOW (window));
2675 priv = window->priv;
2676 if (priv->application != application)
2678 gtk_window_release_application (window);
2680 priv->application = application;
2682 if (priv->application != NULL)
2684 g_object_ref (priv->application);
2686 gtk_application_add_window (priv->application, window);
2689 g_object_notify (G_OBJECT (window), "application");
2694 * gtk_window_set_type_hint:
2695 * @window: a #GtkWindow
2696 * @hint: the window type
2698 * By setting the type hint for the window, you allow the window
2699 * manager to decorate and handle the window in a way which is
2700 * suitable to the function of the window in your application.
2702 * This function should be called before the window becomes visible.
2704 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2705 * will sometimes call gtk_window_set_type_hint() on your behalf.
2709 gtk_window_set_type_hint (GtkWindow *window,
2710 GdkWindowTypeHint hint)
2712 GtkWindowPrivate *priv;
2714 g_return_if_fail (GTK_IS_WINDOW (window));
2715 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2717 priv = window->priv;
2719 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2720 priv->gdk_type_hint = hint;
2722 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2724 priv->reset_type_hint = TRUE;
2725 priv->type_hint = hint;
2729 * gtk_window_get_type_hint:
2730 * @window: a #GtkWindow
2732 * Gets the type hint for this window. See gtk_window_set_type_hint().
2734 * Return value: the type hint for @window.
2737 gtk_window_get_type_hint (GtkWindow *window)
2739 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2741 return window->priv->type_hint;
2745 * gtk_window_set_skip_taskbar_hint:
2746 * @window: a #GtkWindow
2747 * @setting: %TRUE to keep this window from appearing in the task bar
2749 * Windows may set a hint asking the desktop environment not to display
2750 * the window in the task bar. This function sets this hint.
2755 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2758 GtkWindowPrivate *priv;
2760 g_return_if_fail (GTK_IS_WINDOW (window));
2762 priv = window->priv;
2764 setting = setting != FALSE;
2766 if (priv->skips_taskbar != setting)
2768 priv->skips_taskbar = setting;
2769 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2770 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2771 priv->skips_taskbar);
2772 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2777 * gtk_window_get_skip_taskbar_hint:
2778 * @window: a #GtkWindow
2780 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2782 * Return value: %TRUE if window shouldn't be in taskbar
2787 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2789 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2791 return window->priv->skips_taskbar;
2795 * gtk_window_set_skip_pager_hint:
2796 * @window: a #GtkWindow
2797 * @setting: %TRUE to keep this window from appearing in the pager
2799 * Windows may set a hint asking the desktop environment not to display
2800 * the window in the pager. This function sets this hint.
2801 * (A "pager" is any desktop navigation tool such as a workspace
2802 * switcher that displays a thumbnail representation of the windows
2808 gtk_window_set_skip_pager_hint (GtkWindow *window,
2811 GtkWindowPrivate *priv;
2813 g_return_if_fail (GTK_IS_WINDOW (window));
2815 priv = window->priv;
2817 setting = setting != FALSE;
2819 if (priv->skips_pager != setting)
2821 priv->skips_pager = setting;
2822 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2823 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2825 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2830 * gtk_window_get_skip_pager_hint:
2831 * @window: a #GtkWindow
2833 * Gets the value set by gtk_window_set_skip_pager_hint().
2835 * Return value: %TRUE if window shouldn't be in pager
2840 gtk_window_get_skip_pager_hint (GtkWindow *window)
2842 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2844 return window->priv->skips_pager;
2848 * gtk_window_set_urgency_hint:
2849 * @window: a #GtkWindow
2850 * @setting: %TRUE to mark this window as urgent
2852 * Windows may set a hint asking the desktop environment to draw
2853 * the users attention to the window. This function sets this hint.
2858 gtk_window_set_urgency_hint (GtkWindow *window,
2861 GtkWindowPrivate *priv;
2863 g_return_if_fail (GTK_IS_WINDOW (window));
2865 priv = window->priv;
2867 setting = setting != FALSE;
2869 if (priv->urgent != setting)
2871 priv->urgent = setting;
2872 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2873 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2875 g_object_notify (G_OBJECT (window), "urgency-hint");
2880 * gtk_window_get_urgency_hint:
2881 * @window: a #GtkWindow
2883 * Gets the value set by gtk_window_set_urgency_hint()
2885 * Return value: %TRUE if window is urgent
2890 gtk_window_get_urgency_hint (GtkWindow *window)
2892 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2894 return window->priv->urgent;
2898 * gtk_window_set_accept_focus:
2899 * @window: a #GtkWindow
2900 * @setting: %TRUE to let this window receive input focus
2902 * Windows may set a hint asking the desktop environment not to receive
2903 * the input focus. This function sets this hint.
2908 gtk_window_set_accept_focus (GtkWindow *window,
2911 GtkWindowPrivate *priv;
2913 g_return_if_fail (GTK_IS_WINDOW (window));
2915 priv = window->priv;
2917 setting = setting != FALSE;
2919 if (priv->accept_focus != setting)
2921 priv->accept_focus = setting;
2922 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2923 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2924 priv->accept_focus);
2925 g_object_notify (G_OBJECT (window), "accept-focus");
2930 * gtk_window_get_accept_focus:
2931 * @window: a #GtkWindow
2933 * Gets the value set by gtk_window_set_accept_focus().
2935 * Return value: %TRUE if window should receive the input focus
2940 gtk_window_get_accept_focus (GtkWindow *window)
2942 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2944 return window->priv->accept_focus;
2948 * gtk_window_set_focus_on_map:
2949 * @window: a #GtkWindow
2950 * @setting: %TRUE to let this window receive input focus on map
2952 * Windows may set a hint asking the desktop environment not to receive
2953 * the input focus when the window is mapped. This function sets this
2959 gtk_window_set_focus_on_map (GtkWindow *window,
2962 GtkWindowPrivate *priv;
2964 g_return_if_fail (GTK_IS_WINDOW (window));
2966 priv = window->priv;
2968 setting = setting != FALSE;
2970 if (priv->focus_on_map != setting)
2972 priv->focus_on_map = setting;
2973 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2974 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2975 priv->focus_on_map);
2976 g_object_notify (G_OBJECT (window), "focus-on-map");
2981 * gtk_window_get_focus_on_map:
2982 * @window: a #GtkWindow
2984 * Gets the value set by gtk_window_set_focus_on_map().
2986 * Return value: %TRUE if window should receive the input focus when
2992 gtk_window_get_focus_on_map (GtkWindow *window)
2994 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2996 return window->priv->focus_on_map;
3000 * gtk_window_set_destroy_with_parent:
3001 * @window: a #GtkWindow
3002 * @setting: whether to destroy @window with its transient parent
3004 * If @setting is %TRUE, then destroying the transient parent of @window
3005 * will also destroy @window itself. This is useful for dialogs that
3006 * shouldn't persist beyond the lifetime of the main window they're
3007 * associated with, for example.
3010 gtk_window_set_destroy_with_parent (GtkWindow *window,
3013 GtkWindowPrivate *priv;
3015 g_return_if_fail (GTK_IS_WINDOW (window));
3017 priv = window->priv;
3019 if (priv->destroy_with_parent == (setting != FALSE))
3022 if (priv->destroy_with_parent)
3024 disconnect_parent_destroyed (window);
3028 connect_parent_destroyed (window);
3031 priv->destroy_with_parent = setting;
3033 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3037 * gtk_window_get_destroy_with_parent:
3038 * @window: a #GtkWindow
3040 * Returns whether the window will be destroyed with its transient parent. See
3041 * gtk_window_set_destroy_with_parent ().
3043 * Return value: %TRUE if the window will be destroyed with its transient parent.
3046 gtk_window_get_destroy_with_parent (GtkWindow *window)
3048 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3050 return window->priv->destroy_with_parent;
3053 static GtkWindowGeometryInfo*
3054 gtk_window_get_geometry_info (GtkWindow *window,
3057 GtkWindowPrivate *priv = window->priv;
3058 GtkWindowGeometryInfo *info;
3060 info = priv->geometry_info;
3061 if (!info && create)
3063 info = g_new0 (GtkWindowGeometryInfo, 1);
3065 info->default_width = -1;
3066 info->default_height = -1;
3067 info->resize_width = -1;
3068 info->resize_height = -1;
3069 info->initial_x = 0;
3070 info->initial_y = 0;
3071 info->initial_pos_set = FALSE;
3072 info->default_is_geometry = FALSE;
3073 info->position_constraints_changed = FALSE;
3074 info->last.configure_request.x = 0;
3075 info->last.configure_request.y = 0;
3076 info->last.configure_request.width = -1;
3077 info->last.configure_request.height = -1;
3078 info->widget = NULL;
3080 priv->geometry_info = info;
3087 * gtk_window_set_geometry_hints:
3088 * @window: a #GtkWindow
3089 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3090 * @geometry: (allow-none): struct containing geometry information or %NULL
3091 * @geom_mask: mask indicating which struct fields should be paid attention to
3093 * This function sets up hints about how a window can be resized by
3094 * the user. You can set a minimum and maximum size; allowed resize
3095 * increments (e.g. for xterm, you can only resize by the size of a
3096 * character); aspect ratios; and more. See the #GdkGeometry struct.
3100 gtk_window_set_geometry_hints (GtkWindow *window,
3101 GtkWidget *geometry_widget,
3102 GdkGeometry *geometry,
3103 GdkWindowHints geom_mask)
3105 GtkWindowGeometryInfo *info;
3107 g_return_if_fail (GTK_IS_WINDOW (window));
3108 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3110 info = gtk_window_get_geometry_info (window, TRUE);
3113 g_signal_handlers_disconnect_by_func (info->widget,
3114 gtk_widget_destroyed,
3117 info->widget = geometry_widget;
3119 g_signal_connect (geometry_widget, "destroy",
3120 G_CALLBACK (gtk_widget_destroyed),
3124 info->geometry = *geometry;
3126 /* We store gravity in priv->gravity not in the hints. */
3127 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3129 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3131 gtk_window_set_gravity (window, geometry->win_gravity);
3134 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3138 * gtk_window_set_decorated:
3139 * @window: a #GtkWindow
3140 * @setting: %TRUE to decorate the window
3142 * By default, windows are decorated with a title bar, resize
3143 * controls, etc. Some <link linkend="gtk-X11-arch">window
3144 * managers</link> allow GTK+ to disable these decorations, creating a
3145 * borderless window. If you set the decorated property to %FALSE
3146 * using this function, GTK+ will do its best to convince the window
3147 * manager not to decorate the window. Depending on the system, this
3148 * function may not have any effect when called on a window that is
3149 * already visible, so you should call it before calling gtk_window_show().
3151 * On Windows, this function always works, since there's no window manager
3156 gtk_window_set_decorated (GtkWindow *window,
3159 GtkWindowPrivate *priv;
3160 GdkWindow *gdk_window;
3162 g_return_if_fail (GTK_IS_WINDOW (window));
3164 priv = window->priv;
3166 setting = setting != FALSE;
3168 if (setting == priv->decorated)
3171 priv->decorated = setting;
3173 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3176 if (priv->decorated)
3177 gdk_window_set_decorations (gdk_window,
3180 gdk_window_set_decorations (gdk_window,
3184 g_object_notify (G_OBJECT (window), "decorated");
3188 * gtk_window_get_decorated:
3189 * @window: a #GtkWindow
3191 * Returns whether the window has been set to have decorations
3192 * such as a title bar via gtk_window_set_decorated().
3194 * Return value: %TRUE if the window has been set to have decorations
3197 gtk_window_get_decorated (GtkWindow *window)
3199 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3201 return window->priv->decorated;
3205 * gtk_window_set_deletable:
3206 * @window: a #GtkWindow
3207 * @setting: %TRUE to decorate the window as deletable
3209 * By default, windows have a close button in the window frame. Some
3210 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3211 * disable this button. If you set the deletable property to %FALSE
3212 * using this function, GTK+ will do its best to convince the window
3213 * manager not to show a close button. Depending on the system, this
3214 * function may not have any effect when called on a window that is
3215 * already visible, so you should call it before calling gtk_window_show().
3217 * On Windows, this function always works, since there's no window manager
3223 gtk_window_set_deletable (GtkWindow *window,
3226 GtkWindowPrivate *priv;
3227 GdkWindow *gdk_window;
3229 g_return_if_fail (GTK_IS_WINDOW (window));
3231 priv = window->priv;
3233 setting = setting != FALSE;
3235 if (setting == priv->deletable)
3238 priv->deletable = setting;
3240 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3243 if (priv->deletable)
3244 gdk_window_set_functions (gdk_window,
3247 gdk_window_set_functions (gdk_window,
3248 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3251 g_object_notify (G_OBJECT (window), "deletable");
3255 * gtk_window_get_deletable:
3256 * @window: a #GtkWindow
3258 * Returns whether the window has been set to have a close button
3259 * via gtk_window_set_deletable().
3261 * Return value: %TRUE if the window has been set to have a close button
3266 gtk_window_get_deletable (GtkWindow *window)
3268 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3270 return window->priv->deletable;
3273 static GtkWindowIconInfo*
3274 get_icon_info (GtkWindow *window)
3276 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3280 free_icon_info (GtkWindowIconInfo *info)
3282 g_free (info->icon_name);
3283 g_slice_free (GtkWindowIconInfo, info);
3287 static GtkWindowIconInfo*
3288 ensure_icon_info (GtkWindow *window)
3290 GtkWindowIconInfo *info;
3292 info = get_icon_info (window);
3296 info = g_slice_new0 (GtkWindowIconInfo);
3297 g_object_set_qdata_full (G_OBJECT (window),
3298 quark_gtk_window_icon_info,
3300 (GDestroyNotify)free_icon_info);
3307 icon_list_from_theme (GtkWidget *widget,
3312 GtkIconTheme *icon_theme;
3317 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3319 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3322 for (i = 0; sizes[i]; i++)
3325 * We need an EWMH extension to handle scalable icons
3326 * by passing their name to the WM. For now just use a
3330 icon = gtk_icon_theme_load_icon (icon_theme, name,
3333 icon = gtk_icon_theme_load_icon (icon_theme, name,
3336 list = g_list_append (list, icon);
3346 gtk_window_realize_icon (GtkWindow *window)
3348 GtkWindowPrivate *priv = window->priv;
3350 GtkWindowIconInfo *info;
3351 GdkWindow *gdk_window;
3354 widget = GTK_WIDGET (window);
3355 gdk_window = gtk_widget_get_window (widget);
3357 g_return_if_fail (gdk_window != NULL);
3359 /* no point setting an icon on override-redirect */
3360 if (priv->type == GTK_WINDOW_POPUP)
3365 info = ensure_icon_info (window);
3370 info->using_default_icon = FALSE;
3371 info->using_parent_icon = FALSE;
3372 info->using_themed_icon = FALSE;
3374 icon_list = info->icon_list;
3376 /* Look up themed icon */
3377 if (icon_list == NULL && info->icon_name)
3379 icon_list = icon_list_from_theme (widget, info->icon_name);
3381 info->using_themed_icon = TRUE;
3384 /* Inherit from transient parent */
3385 if (icon_list == NULL && priv->transient_parent)
3387 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3389 info->using_parent_icon = TRUE;
3392 /* Inherit from default */
3393 if (icon_list == NULL)
3395 icon_list = default_icon_list;
3397 info->using_default_icon = TRUE;
3400 /* Look up themed icon */
3401 if (icon_list == NULL && default_icon_name)
3403 icon_list = icon_list_from_theme (widget, default_icon_name);
3404 info->using_default_icon = TRUE;
3405 info->using_themed_icon = TRUE;
3408 info->realized = TRUE;
3410 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3412 if (info->using_themed_icon)
3414 GtkIconTheme *icon_theme;
3416 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3417 g_list_free (icon_list);
3419 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3420 g_signal_connect (icon_theme, "changed",
3421 G_CALLBACK (update_themed_icon), window);
3426 gtk_window_unrealize_icon (GtkWindow *window)
3428 GtkWindowIconInfo *info;
3430 info = get_icon_info (window);
3435 if (info->using_themed_icon)
3437 GtkIconTheme *icon_theme;
3439 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3441 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3444 /* We don't clear the properties on the window, just figure the
3445 * window is going away.
3448 info->realized = FALSE;
3453 * gtk_window_set_icon_list:
3454 * @window: a #GtkWindow
3455 * @list: (element-type GdkPixbuf) (transfer container): list of #GdkPixbuf
3457 * Sets up the icon representing a #GtkWindow. The icon is used when
3458 * the window is minimized (also known as iconified). Some window
3459 * managers or desktop environments may also place it in the window
3460 * frame, or display it in other contexts.
3462 * gtk_window_set_icon_list() allows you to pass in the same icon in
3463 * several hand-drawn sizes. The list should contain the natural sizes
3464 * your icon is available in; that is, don't scale the image before
3465 * passing it to GTK+. Scaling is postponed until the last minute,
3466 * when the desired final size is known, to allow best quality.
3468 * By passing several sizes, you may improve the final image quality
3469 * of the icon, by reducing or eliminating automatic image scaling.
3471 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3472 * larger images (64x64, 128x128) if you have them.
3474 * See also gtk_window_set_default_icon_list() to set the icon
3475 * for all windows in your application in one go.
3477 * Note that transient windows (those who have been set transient for another
3478 * window using gtk_window_set_transient_for()) will inherit their
3479 * icon from their transient parent. So there's no need to explicitly
3480 * set the icon on transient windows.
3483 gtk_window_set_icon_list (GtkWindow *window,
3486 GtkWindowIconInfo *info;
3488 g_return_if_fail (GTK_IS_WINDOW (window));
3490 info = ensure_icon_info (window);
3492 if (info->icon_list == list) /* check for NULL mostly */
3495 g_list_foreach (list,
3496 (GFunc) g_object_ref, NULL);
3498 g_list_foreach (info->icon_list,
3499 (GFunc) g_object_unref, NULL);
3501 g_list_free (info->icon_list);
3503 info->icon_list = g_list_copy (list);
3505 g_object_notify (G_OBJECT (window), "icon");
3507 gtk_window_unrealize_icon (window);
3509 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3510 gtk_window_realize_icon (window);
3512 /* We could try to update our transient children, but I don't think
3513 * it's really worth it. If we did it, the best way would probably
3514 * be to have children connect to notify::icon-list
3519 * gtk_window_get_icon_list:
3520 * @window: a #GtkWindow
3522 * Retrieves the list of icons set by gtk_window_set_icon_list().
3523 * The list is copied, but the reference count on each
3524 * member won't be incremented.
3526 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3529 gtk_window_get_icon_list (GtkWindow *window)
3531 GtkWindowIconInfo *info;
3533 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3535 info = get_icon_info (window);
3538 return g_list_copy (info->icon_list);
3544 * gtk_window_set_icon:
3545 * @window: a #GtkWindow
3546 * @icon: (allow-none): icon image, or %NULL
3548 * Sets up the icon representing a #GtkWindow. This icon is used when
3549 * the window is minimized (also known as iconified). Some window
3550 * managers or desktop environments may also place it in the window
3551 * frame, or display it in other contexts.
3553 * The icon should be provided in whatever size it was naturally
3554 * drawn; that is, don't scale the image before passing it to
3555 * GTK+. Scaling is postponed until the last minute, when the desired
3556 * final size is known, to allow best quality.
3558 * If you have your icon hand-drawn in multiple sizes, use
3559 * gtk_window_set_icon_list(). Then the best size will be used.
3561 * This function is equivalent to calling gtk_window_set_icon_list()
3562 * with a 1-element list.
3564 * See also gtk_window_set_default_icon_list() to set the icon
3565 * for all windows in your application in one go.
3568 gtk_window_set_icon (GtkWindow *window,
3573 g_return_if_fail (GTK_IS_WINDOW (window));
3574 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3579 list = g_list_append (list, icon);
3581 gtk_window_set_icon_list (window, list);
3587 update_themed_icon (GtkIconTheme *icon_theme,
3590 g_object_notify (G_OBJECT (window), "icon");
3592 gtk_window_unrealize_icon (window);
3594 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3595 gtk_window_realize_icon (window);
3599 * gtk_window_set_icon_name:
3600 * @window: a #GtkWindow
3601 * @name: (allow-none): the name of the themed icon
3603 * Sets the icon for the window from a named themed icon. See
3604 * the docs for #GtkIconTheme for more details.
3606 * Note that this has nothing to do with the WM_ICON_NAME
3607 * property which is mentioned in the ICCCM.
3612 gtk_window_set_icon_name (GtkWindow *window,
3615 GtkWindowIconInfo *info;
3618 g_return_if_fail (GTK_IS_WINDOW (window));
3620 info = ensure_icon_info (window);
3622 if (g_strcmp0 (info->icon_name, name) == 0)
3625 tmp = info->icon_name;
3626 info->icon_name = g_strdup (name);
3629 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3630 g_list_free (info->icon_list);
3631 info->icon_list = NULL;
3633 update_themed_icon (NULL, window);
3635 g_object_notify (G_OBJECT (window), "icon-name");
3639 * gtk_window_get_icon_name:
3640 * @window: a #GtkWindow
3642 * Returns the name of the themed icon for the window,
3643 * see gtk_window_set_icon_name().
3645 * Returns: the icon name or %NULL if the window has
3651 gtk_window_get_icon_name (GtkWindow *window)
3653 GtkWindowIconInfo *info;
3655 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3657 info = ensure_icon_info (window);
3659 return info->icon_name;
3663 * gtk_window_get_icon:
3664 * @window: a #GtkWindow
3666 * Gets the value set by gtk_window_set_icon() (or if you've
3667 * called gtk_window_set_icon_list(), gets the first icon in
3670 * Return value: (transfer none): icon for window
3673 gtk_window_get_icon (GtkWindow *window)
3675 GtkWindowIconInfo *info;
3677 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3679 info = get_icon_info (window);
3680 if (info && info->icon_list)
3681 return GDK_PIXBUF (info->icon_list->data);
3686 /* Load pixbuf, printing warning on failure if error == NULL
3689 load_pixbuf_verbosely (const char *filename,
3692 GError *local_err = NULL;
3695 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3703 g_warning ("Error loading icon from file '%s':\n\t%s",
3704 filename, local_err->message);
3705 g_error_free (local_err);
3713 * gtk_window_set_icon_from_file:
3714 * @window: a #GtkWindow
3715 * @filename: location of icon file
3716 * @err: (allow-none): location to store error, or %NULL.
3718 * Sets the icon for @window.
3719 * Warns on failure if @err is %NULL.
3721 * This function is equivalent to calling gtk_window_set_icon()
3722 * with a pixbuf created by loading the image from @filename.
3724 * Returns: %TRUE if setting the icon succeeded.
3729 gtk_window_set_icon_from_file (GtkWindow *window,
3730 const gchar *filename,
3733 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3737 gtk_window_set_icon (window, pixbuf);
3738 g_object_unref (pixbuf);
3747 * gtk_window_set_default_icon_list:
3748 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3750 * Sets an icon list to be used as fallback for windows that haven't
3751 * had gtk_window_set_icon_list() called on them to set up a
3752 * window-specific icon list. This function allows you to set up the
3753 * icon for all windows in your app at once.
3755 * See gtk_window_set_icon_list() for more details.
3759 gtk_window_set_default_icon_list (GList *list)
3763 if (list == default_icon_list)
3766 /* Update serial so we don't used cached pixmaps/masks
3768 default_icon_serial++;
3770 g_list_foreach (list,
3771 (GFunc) g_object_ref, NULL);
3773 g_list_foreach (default_icon_list,
3774 (GFunc) g_object_unref, NULL);
3776 g_list_free (default_icon_list);
3778 default_icon_list = g_list_copy (list);
3780 /* Update all toplevels */
3781 toplevels = gtk_window_list_toplevels ();
3782 tmp_list = toplevels;
3783 while (tmp_list != NULL)
3785 GtkWindowIconInfo *info;
3786 GtkWindow *w = tmp_list->data;
3788 info = get_icon_info (w);
3789 if (info && info->using_default_icon)
3791 gtk_window_unrealize_icon (w);
3792 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3793 gtk_window_realize_icon (w);
3796 tmp_list = tmp_list->next;
3798 g_list_free (toplevels);
3802 * gtk_window_set_default_icon:
3805 * Sets an icon to be used as fallback for windows that haven't
3806 * had gtk_window_set_icon() called on them from a pixbuf.
3811 gtk_window_set_default_icon (GdkPixbuf *icon)
3815 g_return_if_fail (GDK_IS_PIXBUF (icon));
3817 list = g_list_prepend (NULL, icon);
3818 gtk_window_set_default_icon_list (list);
3823 * gtk_window_set_default_icon_name:
3824 * @name: the name of the themed icon
3826 * Sets an icon to be used as fallback for windows that haven't
3827 * had gtk_window_set_icon_list() called on them from a named
3828 * themed icon, see gtk_window_set_icon_name().
3833 gtk_window_set_default_icon_name (const gchar *name)
3838 /* Update serial so we don't used cached pixmaps/masks
3840 default_icon_serial++;
3842 g_free (default_icon_name);
3843 default_icon_name = g_strdup (name);
3845 g_list_foreach (default_icon_list,
3846 (GFunc) g_object_unref, NULL);
3848 g_list_free (default_icon_list);
3849 default_icon_list = NULL;
3851 /* Update all toplevels */
3852 toplevels = gtk_window_list_toplevels ();
3853 tmp_list = toplevels;
3854 while (tmp_list != NULL)
3856 GtkWindowIconInfo *info;
3857 GtkWindow *w = tmp_list->data;
3859 info = get_icon_info (w);
3860 if (info && info->using_default_icon && info->using_themed_icon)
3862 gtk_window_unrealize_icon (w);
3863 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3864 gtk_window_realize_icon (w);
3867 tmp_list = tmp_list->next;
3869 g_list_free (toplevels);
3873 * gtk_window_get_default_icon_name:
3875 * Returns the fallback icon name for windows that has been set
3876 * with gtk_window_set_default_icon_name(). The returned
3877 * string is owned by GTK+ and should not be modified. It
3878 * is only valid until the next call to
3879 * gtk_window_set_default_icon_name().
3881 * Returns: the fallback icon name for windows
3886 gtk_window_get_default_icon_name (void)
3888 return default_icon_name;
3892 * gtk_window_set_default_icon_from_file:
3893 * @filename: location of icon file
3894 * @err: (allow-none): location to store error, or %NULL.
3896 * Sets an icon to be used as fallback for windows that haven't
3897 * had gtk_window_set_icon_list() called on them from a file
3898 * on disk. Warns on failure if @err is %NULL.
3900 * Returns: %TRUE if setting the icon succeeded.
3905 gtk_window_set_default_icon_from_file (const gchar *filename,
3908 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3912 gtk_window_set_default_icon (pixbuf);
3913 g_object_unref (pixbuf);
3922 * gtk_window_get_default_icon_list:
3924 * Gets the value set by gtk_window_set_default_icon_list().
3925 * The list is a copy and should be freed with g_list_free(),
3926 * but the pixbufs in the list have not had their reference count
3929 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3932 gtk_window_get_default_icon_list (void)
3934 return g_list_copy (default_icon_list);
3938 gtk_window_set_default_size_internal (GtkWindow *window,
3939 gboolean change_width,
3941 gboolean change_height,
3943 gboolean is_geometry)
3945 GtkWindowGeometryInfo *info;
3947 g_return_if_fail (change_width == FALSE || width >= -1);
3948 g_return_if_fail (change_height == FALSE || height >= -1);
3950 info = gtk_window_get_geometry_info (window, TRUE);
3952 g_object_freeze_notify (G_OBJECT (window));
3954 info->default_is_geometry = is_geometry != FALSE;
3964 info->default_width = width;
3966 g_object_notify (G_OBJECT (window), "default-width");
3977 info->default_height = height;
3979 g_object_notify (G_OBJECT (window), "default-height");
3982 g_object_thaw_notify (G_OBJECT (window));
3984 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3988 * gtk_window_set_default_size:
3989 * @window: a #GtkWindow
3990 * @width: width in pixels, or -1 to unset the default width
3991 * @height: height in pixels, or -1 to unset the default height
3993 * Sets the default size of a window. If the window's "natural" size
3994 * (its size request) is larger than the default, the default will be
3995 * ignored. More generally, if the default size does not obey the
3996 * geometry hints for the window (gtk_window_set_geometry_hints() can
3997 * be used to set these explicitly), the default size will be clamped
3998 * to the nearest permitted size.
4000 * Unlike gtk_widget_set_size_request(), which sets a size request for
4001 * a widget and thus would keep users from shrinking the window, this
4002 * function only sets the initial size, just as if the user had
4003 * resized the window themselves. Users can still shrink the window
4004 * again as they normally would. Setting a default size of -1 means to
4005 * use the "natural" default size (the size request of the window).
4007 * For more control over a window's initial size and how resizing works,
4008 * investigate gtk_window_set_geometry_hints().
4010 * For some uses, gtk_window_resize() is a more appropriate function.
4011 * gtk_window_resize() changes the current size of the window, rather
4012 * than the size to be used on initial display. gtk_window_resize() always
4013 * affects the window itself, not the geometry widget.
4015 * The default size of a window only affects the first time a window is
4016 * shown; if a window is hidden and re-shown, it will remember the size
4017 * it had prior to hiding, rather than using the default size.
4019 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4020 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4023 gtk_window_set_default_size (GtkWindow *window,
4027 g_return_if_fail (GTK_IS_WINDOW (window));
4028 g_return_if_fail (width >= -1);
4029 g_return_if_fail (height >= -1);
4031 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4035 * gtk_window_set_default_geometry:
4036 * @window: a #GtkWindow
4037 * @width: width in resize increments, or -1 to unset the default width
4038 * @height: height in resize increments, or -1 to unset the default height
4040 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4041 * in terms of the base size and increment set with
4042 * gtk_window_set_geometry_hints.
4047 gtk_window_set_default_geometry (GtkWindow *window,
4051 g_return_if_fail (GTK_IS_WINDOW (window));
4052 g_return_if_fail (width >= -1);
4053 g_return_if_fail (height >= -1);
4055 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4059 * gtk_window_get_default_size:
4060 * @window: a #GtkWindow
4061 * @width: (out) (allow-none): location to store the default width, or %NULL
4062 * @height: (out) (allow-none): location to store the default height, or %NULL
4064 * Gets the default size of the window. A value of -1 for the width or
4065 * height indicates that a default size has not been explicitly set
4066 * for that dimension, so the "natural" size of the window will be
4071 gtk_window_get_default_size (GtkWindow *window,
4075 GtkWindowGeometryInfo *info;
4077 g_return_if_fail (GTK_IS_WINDOW (window));
4079 info = gtk_window_get_geometry_info (window, FALSE);
4082 *width = info ? info->default_width : -1;
4085 *height = info ? info->default_height : -1;
4089 * gtk_window_resize:
4090 * @window: a #GtkWindow
4091 * @width: width in pixels to resize the window to
4092 * @height: height in pixels to resize the window to
4094 * Resizes the window as if the user had done so, obeying geometry
4095 * constraints. The default geometry constraint is that windows may
4096 * not be smaller than their size request; to override this
4097 * constraint, call gtk_widget_set_size_request() to set the window's
4098 * request to a smaller value.
4100 * If gtk_window_resize() is called before showing a window for the
4101 * first time, it overrides any default size set with
4102 * gtk_window_set_default_size().
4104 * Windows may not be resized smaller than 1 by 1 pixels.
4108 gtk_window_resize (GtkWindow *window,
4112 GtkWindowGeometryInfo *info;
4114 g_return_if_fail (GTK_IS_WINDOW (window));
4115 g_return_if_fail (width > 0);
4116 g_return_if_fail (height > 0);
4118 info = gtk_window_get_geometry_info (window, TRUE);
4120 info->resize_width = width;
4121 info->resize_height = height;
4122 info->resize_is_geometry = FALSE;
4124 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4128 * gtk_window_resize_to_geometry:
4129 * @window: a #GtkWindow
4130 * @width: width in resize increments to resize the window to
4131 * @height: height in resize increments to resize the window to
4133 * Like gtk_window_resize(), but @width and @height are interpreted
4134 * in terms of the base size and increment set with
4135 * gtk_window_set_geometry_hints.
4140 gtk_window_resize_to_geometry (GtkWindow *window,
4144 GtkWindowGeometryInfo *info;
4146 g_return_if_fail (GTK_IS_WINDOW (window));
4147 g_return_if_fail (width > 0);
4148 g_return_if_fail (height > 0);
4150 info = gtk_window_get_geometry_info (window, TRUE);
4152 info->resize_width = width;
4153 info->resize_height = height;
4154 info->resize_is_geometry = TRUE;
4156 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4160 * gtk_window_get_size:
4161 * @window: a #GtkWindow
4162 * @width: (out) (allow-none): return location for width, or %NULL
4163 * @height: (out) (allow-none): return location for height, or %NULL
4165 * Obtains the current size of @window. If @window is not onscreen,
4166 * it returns the size GTK+ will suggest to the <link
4167 * linkend="gtk-X11-arch">window manager</link> for the initial window
4168 * size (but this is not reliably the same as the size the window
4169 * manager will actually select). The size obtained by
4170 * gtk_window_get_size() is the last size received in a
4171 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4172 * rather than querying the X server for the size. As a result, if you
4173 * call gtk_window_resize() then immediately call
4174 * gtk_window_get_size(), the size won't have taken effect yet. After
4175 * the window manager processes the resize request, GTK+ receives
4176 * notification that the size has changed via a configure event, and
4177 * the size of the window gets updated.
4179 * Note 1: Nearly any use of this function creates a race condition,
4180 * because the size of the window may change between the time that you
4181 * get the size and the time that you perform some action assuming
4182 * that size is the current size. To avoid race conditions, connect to
4183 * "configure-event" on the window and adjust your size-dependent
4184 * state to match the size delivered in the #GdkEventConfigure.
4186 * Note 2: The returned size does <emphasis>not</emphasis> include the
4187 * size of the window manager decorations (aka the window frame or
4188 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4189 * method of determining their size.
4191 * Note 3: If you are getting a window size in order to position
4192 * the window onscreen, there may be a better way. The preferred
4193 * way is to simply set the window's semantic type with
4194 * gtk_window_set_type_hint(), which allows the window manager to
4195 * e.g. center dialogs. Also, if you set the transient parent of
4196 * dialogs with gtk_window_set_transient_for() window managers
4197 * will often center the dialog over its parent window. It's
4198 * much preferred to let the window manager handle these
4199 * things rather than doing it yourself, because all apps will
4200 * behave consistently and according to user prefs if the window
4201 * manager handles it. Also, the window manager can take the size
4202 * of the window decorations/border into account, while your
4203 * application cannot.
4205 * In any case, if you insist on application-specified window
4206 * positioning, there's <emphasis>still</emphasis> a better way than
4207 * doing it yourself - gtk_window_set_position() will frequently
4208 * handle the details for you.
4212 gtk_window_get_size (GtkWindow *window,
4218 g_return_if_fail (GTK_IS_WINDOW (window));
4220 if (width == NULL && height == NULL)
4223 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4225 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4226 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4230 GdkRectangle configure_request;
4232 gtk_window_compute_configure_request (window,
4236 w = configure_request.width;
4237 h = configure_request.height;
4248 * @window: a #GtkWindow
4249 * @x: X coordinate to move window to
4250 * @y: Y coordinate to move window to
4252 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4253 * @window to the given position. Window managers are free to ignore
4254 * this; most window managers ignore requests for initial window
4255 * positions (instead using a user-defined placement algorithm) and
4256 * honor requests after the window has already been shown.
4258 * Note: the position is the position of the gravity-determined
4259 * reference point for the window. The gravity determines two things:
4260 * first, the location of the reference point in root window
4261 * coordinates; and second, which point on the window is positioned at
4262 * the reference point.
4264 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4265 * point is simply the @x, @y supplied to gtk_window_move(). The
4266 * top-left corner of the window decorations (aka window frame or
4267 * border) will be placed at @x, @y. Therefore, to position a window
4268 * at the top left of the screen, you want to use the default gravity
4269 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4271 * To position a window at the bottom right corner of the screen, you
4272 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4273 * point is at @x + the window width and @y + the window height, and
4274 * the bottom-right corner of the window border will be placed at that
4275 * reference point. So, to place a window in the bottom right corner
4276 * you would first set gravity to south east, then write:
4277 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4278 * gdk_screen_height () - window_height)</literal> (note that this
4279 * example does not take multi-head scenarios into account).
4281 * The Extended Window Manager Hints specification at <ulink
4282 * url="http://www.freedesktop.org/Standards/wm-spec">
4283 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4284 * nice table of gravities in the "implementation notes" section.
4286 * The gtk_window_get_position() documentation may also be relevant.
4289 gtk_window_move (GtkWindow *window,
4293 GtkWindowPrivate *priv;
4294 GtkWindowGeometryInfo *info;
4297 g_return_if_fail (GTK_IS_WINDOW (window));
4299 priv = window->priv;
4300 widget = GTK_WIDGET (window);
4302 info = gtk_window_get_geometry_info (window, TRUE);
4304 if (gtk_widget_get_mapped (widget))
4306 GtkAllocation allocation;
4308 gtk_widget_get_allocation (widget, &allocation);
4310 /* we have now sent a request with this position
4311 * with currently-active constraints, so toggle flag.
4313 info->position_constraints_changed = FALSE;
4315 /* we only constrain if mapped - if not mapped,
4316 * then gtk_window_compute_configure_request()
4317 * will apply the constraints later, and we
4318 * don't want to lose information about
4319 * what position the user set before then.
4320 * i.e. if you do a move() then turn off POS_CENTER
4321 * then show the window, your move() will work.
4323 gtk_window_constrain_position (window,
4324 allocation.width, allocation.height,
4327 /* Note that this request doesn't go through our standard request
4328 * framework, e.g. doesn't increment configure_request_count,
4329 * doesn't set info->last, etc.; that's because
4330 * we don't save the info needed to arrive at this same request
4333 * To gtk_window_move_resize(), this will end up looking exactly
4334 * the same as the position being changed by the window
4338 /* FIXME are we handling gravity properly for framed windows? */
4340 gdk_window_move (priv->frame,
4341 x - priv->frame_left,
4342 y - priv->frame_top);
4344 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)),
4349 /* Save this position to apply on mapping */
4350 info->initial_x = x;
4351 info->initial_y = y;
4352 info->initial_pos_set = TRUE;
4357 * gtk_window_get_position:
4358 * @window: a #GtkWindow
4359 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4360 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4362 * This function returns the position you need to pass to
4363 * gtk_window_move() to keep @window in its current position. This
4364 * means that the meaning of the returned value varies with window
4365 * gravity. See gtk_window_move() for more details.
4367 * If you haven't changed the window gravity, its gravity will be
4368 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4369 * gets the position of the top-left corner of the window manager
4370 * frame for the window. gtk_window_move() sets the position of this
4371 * same top-left corner.
4373 * gtk_window_get_position() is not 100% reliable because the X Window System
4374 * does not specify a way to obtain the geometry of the
4375 * decorations placed on a window by the window manager.
4376 * Thus GTK+ is using a "best guess" that works with most
4379 * Moreover, nearly all window managers are historically broken with
4380 * respect to their handling of window gravity. So moving a window to
4381 * its current position as returned by gtk_window_get_position() tends
4382 * to result in moving the window slightly. Window managers are
4383 * slowly getting better over time.
4385 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4386 * frame is not relevant, and thus gtk_window_get_position() will
4387 * always produce accurate results. However you can't use static
4388 * gravity to do things like place a window in a corner of the screen,
4389 * because static gravity ignores the window manager decorations.
4391 * If you are saving and restoring your application's window
4392 * positions, you should know that it's impossible for applications to
4393 * do this without getting it somewhat wrong because applications do
4394 * not have sufficient knowledge of window manager state. The Correct
4395 * Mechanism is to support the session management protocol (see the
4396 * "GnomeClient" object in the GNOME libraries for example) and allow
4397 * the window manager to save your window sizes and positions.
4402 gtk_window_get_position (GtkWindow *window,
4406 GtkWindowPrivate *priv;
4408 GdkWindow *gdk_window;
4410 g_return_if_fail (GTK_IS_WINDOW (window));
4412 priv = window->priv;
4413 widget = GTK_WIDGET (window);
4414 gdk_window = gtk_widget_get_window (widget);
4416 if (priv->gravity == GDK_GRAVITY_STATIC)
4418 if (gtk_widget_get_mapped (widget))
4420 /* This does a server round-trip, which is sort of wrong;
4421 * but a server round-trip is inevitable for
4422 * gdk_window_get_frame_extents() in the usual
4423 * NorthWestGravity case below, so not sure what else to
4424 * do. We should likely be consistent about whether we get
4425 * the client-side info or the server-side info.
4427 gdk_window_get_origin (gdk_window, root_x, root_y);
4431 GdkRectangle configure_request;
4433 gtk_window_compute_configure_request (window,
4437 *root_x = configure_request.x;
4438 *root_y = configure_request.y;
4443 GdkRectangle frame_extents;
4448 if (gtk_widget_get_mapped (widget))
4451 gdk_window_get_frame_extents (priv->frame, &frame_extents);
4453 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4454 x = frame_extents.x;
4455 y = frame_extents.y;
4456 gtk_window_get_size (window, &w, &h);
4460 /* We just say the frame has 0 size on all sides.
4461 * Not sure what else to do.
4463 gtk_window_compute_configure_request (window,
4466 x = frame_extents.x;
4467 y = frame_extents.y;
4468 w = frame_extents.width;
4469 h = frame_extents.height;
4472 switch (priv->gravity)
4474 case GDK_GRAVITY_NORTH:
4475 case GDK_GRAVITY_CENTER:
4476 case GDK_GRAVITY_SOUTH:
4477 /* Find center of frame. */
4478 x += frame_extents.width / 2;
4479 /* Center client window on that point. */
4483 case GDK_GRAVITY_SOUTH_EAST:
4484 case GDK_GRAVITY_EAST:
4485 case GDK_GRAVITY_NORTH_EAST:
4486 /* Find right edge of frame */
4487 x += frame_extents.width;
4488 /* Align left edge of client at that point. */
4495 switch (priv->gravity)
4497 case GDK_GRAVITY_WEST:
4498 case GDK_GRAVITY_CENTER:
4499 case GDK_GRAVITY_EAST:
4500 /* Find center of frame. */
4501 y += frame_extents.height / 2;
4502 /* Center client window there. */
4505 case GDK_GRAVITY_SOUTH_WEST:
4506 case GDK_GRAVITY_SOUTH:
4507 case GDK_GRAVITY_SOUTH_EAST:
4508 /* Find south edge of frame */
4509 y += frame_extents.height;
4510 /* Place bottom edge of client there */
4525 * gtk_window_reshow_with_initial_size:
4526 * @window: a #GtkWindow
4528 * Hides @window, then reshows it, resetting the
4529 * default size and position of the window. Used
4530 * by GUI builders only.
4533 gtk_window_reshow_with_initial_size (GtkWindow *window)
4537 g_return_if_fail (GTK_IS_WINDOW (window));
4539 widget = GTK_WIDGET (window);
4541 gtk_widget_hide (widget);
4542 gtk_widget_unrealize (widget);
4543 gtk_widget_show (widget);
4547 gtk_window_destroy (GtkWidget *widget)
4549 GtkWindow *window = GTK_WINDOW (widget);
4550 GtkWindowPrivate *priv = window->priv;
4552 toplevel_list = g_slist_remove (toplevel_list, window);
4554 if (priv->transient_parent)
4555 gtk_window_set_transient_for (window, NULL);
4557 /* frees the icons */
4558 gtk_window_set_icon_list (window, NULL);
4560 if (priv->has_user_ref_count)
4562 priv->has_user_ref_count = FALSE;
4563 g_object_unref (window);
4567 gtk_window_group_remove_window (priv->group, window);
4569 gtk_window_free_key_hash (window);
4571 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4575 gtk_window_finalize (GObject *object)
4577 GtkWindow *window = GTK_WINDOW (object);
4578 GtkWindowPrivate *priv = window->priv;
4579 GtkMnemonicHash *mnemonic_hash;
4581 g_free (priv->title);
4582 g_free (priv->wmclass_name);
4583 g_free (priv->wmclass_class);
4584 g_free (priv->wm_role);
4585 gtk_window_release_application (window);
4587 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4589 _gtk_mnemonic_hash_free (mnemonic_hash);
4591 if (priv->geometry_info)
4593 if (priv->geometry_info->widget)
4594 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4595 gtk_widget_destroyed,
4596 &priv->geometry_info->widget);
4597 g_free (priv->geometry_info);
4600 if (priv->keys_changed_handler)
4602 g_source_remove (priv->keys_changed_handler);
4603 priv->keys_changed_handler = 0;
4607 g_signal_handlers_disconnect_by_func (priv->screen,
4608 gtk_window_on_composited_changed, window);
4610 g_free (priv->startup_id);
4612 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4616 gtk_window_show (GtkWidget *widget)
4618 GtkWindow *window = GTK_WINDOW (widget);
4619 GtkWindowPrivate *priv = window->priv;
4620 GtkContainer *container = GTK_CONTAINER (window);
4621 gboolean need_resize;
4623 _gtk_widget_set_visible_flag (widget, TRUE);
4625 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4626 _gtk_container_set_need_resize (container, FALSE);
4630 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4631 GtkAllocation allocation = { 0, 0 };
4632 GdkRectangle configure_request;
4633 GdkGeometry new_geometry;
4635 gboolean was_realized;
4637 /* We are going to go ahead and perform this configure request
4638 * and then emulate a configure notify by going ahead and
4639 * doing a size allocate. Sort of a synchronous
4640 * mini-copy of gtk_window_move_resize() here.
4642 gtk_window_compute_configure_request (window,
4647 /* We update this because we are going to go ahead
4648 * and gdk_window_resize() below, rather than
4651 info->last.configure_request.width = configure_request.width;
4652 info->last.configure_request.height = configure_request.height;
4654 /* and allocate the window - this is normally done
4655 * in move_resize in response to configure notify
4657 allocation.width = configure_request.width;
4658 allocation.height = configure_request.height;
4659 gtk_widget_size_allocate (widget, &allocation);
4661 /* Then we guarantee we have a realize */
4662 was_realized = FALSE;
4663 if (!gtk_widget_get_realized (widget))
4665 gtk_widget_realize (widget);
4666 was_realized = TRUE;
4669 /* We only send configure request if we didn't just finish
4670 * creating the window; if we just created the window
4671 * then we created it with widget->allocation anyhow.
4674 gdk_window_move_resize (gtk_widget_get_window (widget),
4675 configure_request.x,
4676 configure_request.y,
4677 configure_request.width,
4678 configure_request.height);
4681 gtk_container_check_resize (container);
4683 gtk_widget_map (widget);
4685 /* Try to make sure that we have some focused widget
4687 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4688 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4691 gtk_grab_add (widget);
4695 gtk_window_hide (GtkWidget *widget)
4697 GtkWindow *window = GTK_WINDOW (widget);
4698 GtkWindowPrivate *priv = window->priv;
4700 _gtk_widget_set_visible_flag (widget, FALSE);
4701 gtk_widget_unmap (widget);
4704 gtk_grab_remove (widget);
4708 gtk_window_map (GtkWidget *widget)
4711 GtkWindow *window = GTK_WINDOW (widget);
4712 GtkWindowPrivate *priv = window->priv;
4713 GdkWindow *toplevel;
4714 GdkWindow *gdk_window;
4715 gboolean auto_mnemonics;
4717 gdk_window = gtk_widget_get_window (widget);
4719 gtk_widget_set_mapped (widget, TRUE);
4721 child = gtk_bin_get_child (&(window->bin));
4723 gtk_widget_get_visible (child) &&
4724 !gtk_widget_get_mapped (child))
4725 gtk_widget_map (child);
4728 toplevel = priv->frame;
4730 toplevel = gdk_window;
4732 if (priv->maximize_initially)
4733 gdk_window_maximize (toplevel);
4735 gdk_window_unmaximize (toplevel);
4737 if (priv->stick_initially)
4738 gdk_window_stick (toplevel);
4740 gdk_window_unstick (toplevel);
4742 if (priv->iconify_initially)
4743 gdk_window_iconify (toplevel);
4745 gdk_window_deiconify (toplevel);
4747 if (priv->fullscreen_initially)
4748 gdk_window_fullscreen (toplevel);
4750 gdk_window_unfullscreen (toplevel);
4752 gdk_window_set_keep_above (toplevel, priv->above_initially);
4754 gdk_window_set_keep_below (toplevel, priv->below_initially);
4756 /* No longer use the default settings */
4757 priv->need_default_size = FALSE;
4758 priv->need_default_position = FALSE;
4760 if (priv->reset_type_hint)
4762 /* We should only reset the type hint when the application
4763 * used gtk_window_set_type_hint() to change the hint.
4764 * Some applications use X directly to change the properties;
4765 * in that case, we shouldn't overwrite what they did.
4767 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4768 priv->reset_type_hint = FALSE;
4771 gdk_window_show (gdk_window);
4774 gdk_window_show (priv->frame);
4776 if (priv->grip_window)
4777 gdk_window_show (priv->grip_window);
4779 if (!disable_startup_notification)
4781 /* Do we have a custom startup-notification id? */
4782 if (priv->startup_id != NULL)
4784 /* Make sure we have a "real" id */
4785 if (!startup_id_is_fake (priv->startup_id))
4786 gdk_notify_startup_complete_with_id (priv->startup_id);
4788 g_free (priv->startup_id);
4789 priv->startup_id = NULL;
4791 else if (!sent_startup_notification)
4793 sent_startup_notification = TRUE;
4794 gdk_notify_startup_complete ();
4798 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4799 * (as in the case of popup menus), then hide mnemonics initially
4801 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4802 &auto_mnemonics, NULL);
4803 if (auto_mnemonics && !priv->mnemonics_visible_set)
4804 gtk_window_set_mnemonics_visible (window, FALSE);
4808 gtk_window_map_event (GtkWidget *widget,
4811 if (!gtk_widget_get_mapped (widget))
4813 /* we should be be unmapped, but are getting a MapEvent, this may happen
4814 * to toplevel XWindows if mapping was intercepted by a window manager
4815 * and an unmap request occoured while the MapRequestEvent was still
4816 * being handled. we work around this situaiton here by re-requesting
4817 * the window being unmapped. more details can be found in:
4818 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4820 gdk_window_hide (gtk_widget_get_window (widget));
4826 gtk_window_unmap (GtkWidget *widget)
4828 GtkWindow *window = GTK_WINDOW (widget);
4829 GtkWindowPrivate *priv = window->priv;
4830 GtkWindowGeometryInfo *info;
4831 GdkWindow *gdk_window;
4832 GdkWindowState state;
4834 gdk_window = gtk_widget_get_window (widget);
4836 gtk_widget_set_mapped (widget, FALSE);
4838 gdk_window_withdraw (priv->frame);
4840 gdk_window_withdraw (gdk_window);
4842 priv->configure_request_count = 0;
4843 priv->configure_notify_received = FALSE;
4845 /* on unmap, we reset the default positioning of the window,
4846 * so it's placed again, but we don't reset the default
4847 * size of the window, so it's remembered.
4849 priv->need_default_position = TRUE;
4851 info = gtk_window_get_geometry_info (window, FALSE);
4854 info->initial_pos_set = FALSE;
4855 info->position_constraints_changed = FALSE;
4858 state = gdk_window_get_state (gdk_window);
4859 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4860 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4861 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4862 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4863 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4867 gtk_window_realize (GtkWidget *widget)
4869 GtkAllocation allocation;
4871 GdkWindow *parent_window;
4872 GdkWindow *gdk_window;
4873 GdkWindowAttr attributes;
4874 gint attributes_mask;
4875 GtkWindowPrivate *priv;
4876 GtkStyleContext *context;
4878 window = GTK_WINDOW (widget);
4879 priv = window->priv;
4881 gtk_widget_get_allocation (widget, &allocation);
4883 /* ensure widget tree is properly size allocated */
4884 if (allocation.x == -1 &&
4885 allocation.y == -1 &&
4886 allocation.width == 1 &&
4887 allocation.height == 1)
4889 GtkRequisition requisition;
4893 allocation.width = 200;
4894 allocation.height = 200;
4896 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4897 if (requisition.width || requisition.height)
4899 /* non-empty window */
4900 allocation.width = requisition.width;
4901 allocation.height = requisition.height;
4903 gtk_widget_size_allocate (widget, &allocation);
4905 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4907 g_return_if_fail (!gtk_widget_get_realized (widget));
4910 gtk_widget_set_realized (widget, TRUE);
4914 case GTK_WINDOW_TOPLEVEL:
4915 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4917 case GTK_WINDOW_POPUP:
4918 attributes.window_type = GDK_WINDOW_TEMP;
4921 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4925 attributes.title = priv->title;
4926 attributes.wmclass_name = priv->wmclass_name;
4927 attributes.wmclass_class = priv->wmclass_class;
4928 attributes.wclass = GDK_INPUT_OUTPUT;
4929 attributes.visual = gtk_widget_get_visual (widget);
4931 if (priv->has_frame)
4933 gtk_widget_get_allocation (widget, &allocation);
4934 attributes.width = allocation.width + priv->frame_left + priv->frame_right;
4935 attributes.height = allocation.height + priv->frame_top + priv->frame_bottom;
4936 attributes.event_mask = (GDK_EXPOSURE_MASK |
4937 GDK_KEY_PRESS_MASK |
4938 GDK_ENTER_NOTIFY_MASK |
4939 GDK_LEAVE_NOTIFY_MASK |
4940 GDK_FOCUS_CHANGE_MASK |
4941 GDK_STRUCTURE_MASK |
4942 GDK_BUTTON_MOTION_MASK |
4943 GDK_POINTER_MOTION_HINT_MASK |
4944 GDK_BUTTON_PRESS_MASK |
4945 GDK_BUTTON_RELEASE_MASK);
4947 attributes_mask = GDK_WA_VISUAL;
4949 priv->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4950 &attributes, attributes_mask);
4952 if (priv->opacity_set)
4953 gdk_window_set_opacity (priv->frame, priv->opacity);
4955 gdk_window_set_user_data (priv->frame, widget);
4957 attributes.window_type = GDK_WINDOW_CHILD;
4958 attributes.x = priv->frame_left;
4959 attributes.y = priv->frame_top;
4961 attributes_mask = GDK_WA_X | GDK_WA_Y;
4963 parent_window = priv->frame;
4965 g_signal_connect (window,
4967 G_CALLBACK (gtk_window_event),
4972 attributes_mask = 0;
4973 parent_window = gtk_widget_get_root_window (widget);
4976 gtk_widget_get_allocation (widget, &allocation);
4977 attributes.width = allocation.width;
4978 attributes.height = allocation.height;
4979 attributes.event_mask = gtk_widget_get_events (widget);
4980 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4981 GDK_KEY_PRESS_MASK |
4982 GDK_KEY_RELEASE_MASK |
4983 GDK_ENTER_NOTIFY_MASK |
4984 GDK_LEAVE_NOTIFY_MASK |
4985 GDK_FOCUS_CHANGE_MASK |
4986 GDK_STRUCTURE_MASK);
4987 attributes.type_hint = priv->type_hint;
4989 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4990 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4991 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4993 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4994 gtk_widget_set_window (widget, gdk_window);
4996 if (!priv->has_frame && priv->opacity_set)
4997 gdk_window_set_opacity (gdk_window, priv->opacity);
4999 gdk_window_enable_synchronized_configure (gdk_window);
5001 gdk_window_set_user_data (gdk_window, window);
5003 gtk_widget_style_attach (widget);
5004 context = gtk_widget_get_style_context (widget);
5006 gtk_style_context_set_background (context, gdk_window);
5008 gtk_style_context_set_background (context, priv->frame);
5010 if (priv->transient_parent &&
5011 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5012 gdk_window_set_transient_for (gdk_window,
5013 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5016 gdk_window_set_role (gdk_window, priv->wm_role);
5018 if (!priv->decorated)
5019 gdk_window_set_decorations (gdk_window, 0);
5021 if (!priv->deletable)
5022 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5024 if (gtk_window_get_skip_pager_hint (window))
5025 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5027 if (gtk_window_get_skip_taskbar_hint (window))
5028 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5030 if (gtk_window_get_accept_focus (window))
5031 gdk_window_set_accept_focus (gdk_window, TRUE);
5033 gdk_window_set_accept_focus (gdk_window, FALSE);
5035 if (gtk_window_get_focus_on_map (window))
5036 gdk_window_set_focus_on_map (gdk_window, TRUE);
5038 gdk_window_set_focus_on_map (gdk_window, FALSE);
5041 gdk_window_set_modal_hint (gdk_window, TRUE);
5043 gdk_window_set_modal_hint (gdk_window, FALSE);
5045 if (priv->startup_id)
5047 #ifdef GDK_WINDOWING_X11
5048 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5049 if (timestamp != GDK_CURRENT_TIME)
5050 gdk_x11_window_set_user_time (gdk_window, timestamp);
5052 if (!startup_id_is_fake (priv->startup_id))
5053 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5057 gtk_window_realize_icon (window);
5059 if (priv->has_resize_grip)
5060 resize_grip_create_window (window);
5064 gtk_window_unrealize (GtkWidget *widget)
5066 GtkWindow *window = GTK_WINDOW (widget);
5067 GtkWindowPrivate *priv = window->priv;
5068 GtkWindowGeometryInfo *info;
5070 /* On unrealize, we reset the size of the window such
5071 * that we will re-apply the default sizing stuff
5072 * next time we show the window.
5074 * Default positioning is reset on unmap, instead of unrealize.
5076 priv->need_default_size = TRUE;
5077 info = gtk_window_get_geometry_info (window, FALSE);
5080 info->resize_width = -1;
5081 info->resize_height = -1;
5082 info->last.configure_request.x = 0;
5083 info->last.configure_request.y = 0;
5084 info->last.configure_request.width = -1;
5085 info->last.configure_request.height = -1;
5086 /* be sure we reset geom hints on re-realize */
5087 info->last.flags = 0;
5092 gdk_window_set_user_data (priv->frame, NULL);
5093 gdk_window_destroy (priv->frame);
5098 gtk_window_unrealize_icon (window);
5100 if (priv->grip_window != NULL)
5101 resize_grip_destroy_window (window);
5103 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5106 static GtkJunctionSides
5107 get_grip_junction (GtkWidget *widget)
5109 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5110 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5112 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5116 get_drag_edge (GtkWidget *widget,
5117 GdkWindowEdge *edge)
5119 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5120 gboolean hresizable;
5121 gboolean vresizable;
5122 GtkTextDirection dir;
5123 GtkWindowGeometryInfo *info;
5128 info = priv->geometry_info;
5131 GdkWindowHints flags = info->last.flags;
5132 GdkGeometry *geometry = &info->last.geometry;
5134 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5136 hresizable = geometry->min_width < geometry->max_width;
5137 vresizable = geometry->min_height < geometry->max_height;
5141 dir = gtk_widget_get_direction (widget);
5143 if (hresizable && vresizable)
5144 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5145 else if (hresizable)
5146 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5147 else if (vresizable)
5148 *edge = GDK_WINDOW_EDGE_SOUTH;
5156 set_grip_cursor (GtkWindow *window)
5158 GtkWidget *widget = GTK_WIDGET (window);
5159 GtkWindowPrivate *priv = window->priv;
5161 if (priv->grip_window == NULL)
5164 if (gtk_widget_is_sensitive (widget))
5167 GdkDisplay *display;
5168 GdkCursorType cursor_type;
5171 cursor_type = GDK_LEFT_PTR;
5173 if (get_drag_edge (widget, &edge))
5177 case GDK_WINDOW_EDGE_EAST:
5178 cursor_type = GDK_RIGHT_SIDE;
5180 case GDK_WINDOW_EDGE_SOUTH_EAST:
5181 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5183 case GDK_WINDOW_EDGE_SOUTH:
5184 cursor_type = GDK_BOTTOM_SIDE;
5186 case GDK_WINDOW_EDGE_SOUTH_WEST:
5187 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5189 case GDK_WINDOW_EDGE_WEST:
5190 cursor_type = GDK_LEFT_SIDE;
5196 display = gtk_widget_get_display (widget);
5197 cursor = gdk_cursor_new_for_display (display, cursor_type);
5198 gdk_window_set_cursor (priv->grip_window, cursor);
5199 gdk_cursor_unref (cursor);
5202 gdk_window_set_cursor (priv->grip_window, NULL);
5206 set_grip_shape (GtkWindow *window)
5208 GtkWindowPrivate *priv = window->priv;
5209 cairo_region_t *region;
5210 cairo_surface_t *surface;
5212 double width, height;
5214 if (priv->grip_window == NULL)
5217 width = gdk_window_get_width (priv->grip_window);
5218 height = gdk_window_get_height (priv->grip_window);
5219 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5221 cr = cairo_create (surface);
5222 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5224 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5225 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5227 cairo_move_to (cr, width, 0.0);
5228 cairo_line_to (cr, width, height);
5229 cairo_line_to (cr, 0.0, height);
5233 cairo_move_to (cr, 0.0, 0.0);
5234 cairo_line_to (cr, width, height);
5235 cairo_line_to (cr, 0.0, height);
5237 cairo_close_path (cr);
5240 region = gdk_cairo_region_create_from_surface (surface);
5241 cairo_surface_destroy (surface);
5243 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5244 cairo_region_destroy (region);
5248 set_grip_position (GtkWindow *window)
5250 GtkWindowPrivate *priv = window->priv;
5253 if (priv->grip_window == NULL)
5256 gtk_window_get_resize_grip_area (window, &rect);
5257 gdk_window_raise (priv->grip_window);
5258 gdk_window_move_resize (priv->grip_window,
5260 rect.width, rect.height);
5264 gtk_window_size_allocate (GtkWidget *widget,
5265 GtkAllocation *allocation)
5267 GtkWindow *window = GTK_WINDOW (widget);
5268 GtkWindowPrivate *priv = window->priv;
5269 GtkAllocation child_allocation;
5273 gtk_widget_set_allocation (widget, allocation);
5275 child = gtk_bin_get_child (&(window->bin));
5276 if (child && gtk_widget_get_visible (child))
5278 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5279 child_allocation.x = border_width;
5280 child_allocation.y = border_width;
5281 child_allocation.width =
5282 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5283 child_allocation.height =
5284 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5286 gtk_widget_size_allocate (child, &child_allocation);
5289 if (gtk_widget_get_realized (widget))
5292 gdk_window_resize (priv->frame,
5293 allocation->width + priv->frame_left + priv->frame_right,
5294 allocation->height + priv->frame_top + priv->frame_bottom);
5295 update_grip_visibility (window);
5296 set_grip_position (window);
5301 gtk_window_event (GtkWidget *widget, GdkEvent *event)
5303 GtkWindow *window = GTK_WINDOW (widget);
5304 GtkWindowPrivate *priv = window->priv;
5305 gboolean return_val;
5307 if (priv->frame && (event->any.window == priv->frame))
5309 if ((event->type != GDK_KEY_PRESS) &&
5310 (event->type != GDK_KEY_RELEASE) &&
5311 (event->type != GDK_FOCUS_CHANGE))
5313 g_signal_stop_emission_by_name (widget, "event");
5315 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
5320 g_object_unref (event->any.window);
5321 event->any.window = g_object_ref (gtk_widget_get_window (widget));
5329 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
5331 GtkWindowPrivate *priv = window->priv;
5332 GdkEventConfigure *configure_event;
5335 switch (event->type)
5338 configure_event = (GdkEventConfigure *)event;
5340 /* Invalidate the decorations */
5343 rect.width = configure_event->width;
5344 rect.height = configure_event->height;
5346 gdk_window_invalidate_rect (priv->frame, &rect, FALSE);
5348 /* Pass on the (modified) configure event */
5349 configure_event->width -= priv->frame_left + priv->frame_right;
5350 configure_event->height -= priv->frame_top + priv->frame_bottom;
5351 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
5360 gtk_window_configure_event (GtkWidget *widget,
5361 GdkEventConfigure *event)
5363 GtkAllocation allocation;
5364 GtkWindow *window = GTK_WINDOW (widget);
5365 GtkWindowPrivate *priv = window->priv;
5366 gboolean expected_reply = priv->configure_request_count > 0;
5368 /* priv->configure_request_count incremented for each
5369 * configure request, and decremented to a min of 0 for
5370 * each configure notify.
5372 * All it means is that we know we will get at least
5373 * priv->configure_request_count more configure notifies.
5374 * We could get more configure notifies than that; some
5375 * of the configure notifies we get may be unrelated to
5376 * the configure requests. But we will get at least
5377 * priv->configure_request_count notifies.
5380 if (priv->configure_request_count > 0)
5382 priv->configure_request_count -= 1;
5383 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5386 /* As an optimization, we avoid a resize when possible.
5388 * The only times we can avoid a resize are:
5389 * - we know only the position changed, not the size
5390 * - we know we have made more requests and so will get more
5391 * notifies and can wait to resize when we get them
5393 gtk_widget_get_allocation (widget, &allocation);
5394 if (!expected_reply &&
5395 (allocation.width == event->width &&
5396 allocation.height == event->height))
5398 gdk_window_configure_finished (gtk_widget_get_window (widget));
5403 * If we do need to resize, we do that by:
5404 * - filling in widget->allocation with the new size
5405 * - setting configure_notify_received to TRUE
5406 * for use in gtk_window_move_resize()
5407 * - queueing a resize, leading to invocation of
5408 * gtk_window_move_resize() in an idle handler
5412 priv->configure_notify_received = TRUE;
5414 allocation.width = event->width;
5415 allocation.height = event->height;
5416 gtk_widget_set_allocation (widget, &allocation);
5418 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5420 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5426 gtk_window_state_event (GtkWidget *widget,
5427 GdkEventWindowState *event)
5429 update_grip_visibility (GTK_WINDOW (widget));
5435 gtk_window_direction_changed (GtkWidget *widget,
5436 GtkTextDirection prev_dir)
5438 GtkWindow *window = GTK_WINDOW (widget);
5440 set_grip_cursor (window);
5441 set_grip_position (window);
5442 set_grip_shape (window);
5446 gtk_window_state_changed (GtkWidget *widget,
5447 GtkStateType previous_state)
5449 GtkWindow *window = GTK_WINDOW (widget);
5451 update_grip_visibility (window);
5455 gtk_window_style_updated (GtkWidget *widget)
5457 GtkWindow *window = GTK_WINDOW (widget);
5458 GtkWindowPrivate *priv = window->priv;
5461 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5463 gdk_window_move_resize (priv->grip_window,
5465 rect.width, rect.height);
5467 set_grip_shape (window);
5468 gtk_widget_queue_resize (widget);
5473 resize_grip_create_window (GtkWindow *window)
5476 GtkWindowPrivate *priv;
5477 GdkWindowAttr attributes;
5478 gint attributes_mask;
5481 priv = window->priv;
5482 widget = GTK_WIDGET (window);
5484 g_return_if_fail (gtk_widget_get_realized (widget));
5485 g_return_if_fail (priv->grip_window == NULL);
5487 gtk_window_get_resize_grip_area (window, &rect);
5489 attributes.x = rect.x;
5490 attributes.y = rect.y;
5491 attributes.width = rect.width;
5492 attributes.height = rect.height;
5493 attributes.window_type = GDK_WINDOW_CHILD;
5494 attributes.wclass = GDK_INPUT_OUTPUT;
5495 attributes.event_mask = gtk_widget_get_events (widget) |
5497 GDK_BUTTON_PRESS_MASK;
5499 attributes_mask = GDK_WA_X | GDK_WA_Y;
5501 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5505 gdk_window_set_user_data (priv->grip_window, widget);
5507 gdk_window_raise (priv->grip_window);
5509 set_grip_shape (window);
5510 update_grip_visibility (window);
5514 resize_grip_destroy_window (GtkWindow *window)
5516 GtkWindowPrivate *priv = window->priv;
5518 gdk_window_set_user_data (priv->grip_window, NULL);
5519 gdk_window_destroy (priv->grip_window);
5520 priv->grip_window = NULL;
5521 update_grip_visibility (window);
5525 * gtk_window_set_has_resize_grip:
5526 * @window: a #GtkWindow
5527 * @value: %TRUE to allow a resize grip
5529 * Sets whether @window has a corner resize grip.
5531 * Note that the resize grip is only shown if the window
5532 * is actually resizable and not maximized. Use
5533 * gtk_window_resize_grip_is_visible() to find out if the
5534 * resize grip is currently shown.
5539 gtk_window_set_has_resize_grip (GtkWindow *window,
5542 GtkWidget *widget = GTK_WIDGET (window);
5543 GtkWindowPrivate *priv = window->priv;
5545 value = value != FALSE;
5547 if (value != priv->has_resize_grip)
5549 priv->has_resize_grip = value;
5550 gtk_widget_queue_draw (widget);
5552 if (gtk_widget_get_realized (widget))
5554 if (priv->has_resize_grip && priv->grip_window == NULL)
5555 resize_grip_create_window (window);
5556 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5557 resize_grip_destroy_window (window);
5560 g_object_notify (G_OBJECT (window), "has-resize-grip");
5565 update_grip_visibility (GtkWindow *window)
5567 GtkWindowPrivate *priv = window->priv;
5570 val = gtk_window_resize_grip_is_visible (window);
5572 if (priv->grip_window != NULL)
5576 gdk_window_show (priv->grip_window);
5577 set_grip_cursor (window);
5581 gdk_window_hide (priv->grip_window);
5585 if (priv->resize_grip_visible != val)
5587 priv->resize_grip_visible = val;
5589 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5594 * gtk_window_resize_grip_is_visible:
5595 * @window: a #GtkWindow
5597 * Determines whether a resize grip is visible for the specified window.
5599 * Returns %TRUE if a resize grip exists and is visible.
5604 gtk_window_resize_grip_is_visible (GtkWindow *window)
5607 GtkWindowPrivate *priv;
5610 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5612 priv = window->priv;
5613 widget = GTK_WIDGET (window);
5615 if (priv->type == GTK_WINDOW_POPUP)
5618 if (!priv->resizable)
5621 if (gtk_widget_get_realized (widget))
5623 GdkWindowState state;
5625 state = gdk_window_get_state (gtk_widget_get_window (widget));
5627 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5631 if (!get_drag_edge (widget, &edge))
5634 return window->priv->has_resize_grip;
5638 * gtk_window_get_has_resize_grip:
5639 * @window: a #GtkWindow
5641 * Determines whether the window may have a resize grip.
5643 * Returns: %TRUE if the window has a resize grip.
5648 gtk_window_get_has_resize_grip (GtkWindow *window)
5650 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5652 return window->priv->has_resize_grip;
5656 * gtk_window_get_resize_grip_area:
5657 * @window: a #GtkWindow
5658 * @rect: a pointer to a #GdkRectangle which we should store the
5661 * If a window has a resize grip, this will retrieve the grip
5662 * position, width and height into the specified #GdkRectangle.
5664 * Returns: %TRUE if the resize grip's area was retrieved.
5669 gtk_window_get_resize_grip_area (GtkWindow *window,
5672 GtkWidget *widget = GTK_WIDGET (window);
5673 GtkAllocation allocation;
5677 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5679 if (!window->priv->has_resize_grip)
5682 gtk_widget_get_allocation (widget, &allocation);
5684 gtk_widget_style_get (widget,
5685 "resize-grip-width", &grip_width,
5686 "resize-grip-height", &grip_height,
5689 if (grip_width > allocation.width)
5690 grip_width = allocation.width;
5692 if (grip_height > allocation.height)
5693 grip_height = allocation.height;
5695 rect->width = grip_width;
5696 rect->height = grip_height;
5697 rect->y = allocation.y + allocation.height - grip_height;
5699 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5700 rect->x = allocation.x + allocation.width - grip_width;
5702 rect->x = allocation.x;
5707 /* the accel_key and accel_mods fields of the key have to be setup
5708 * upon calling this function. it'll then return whether that key
5709 * is at all used as accelerator, and if so will OR in the
5710 * accel_flags member of the key.
5713 _gtk_window_query_nonaccels (GtkWindow *window,
5715 GdkModifierType accel_mods)
5717 GtkWindowPrivate *priv;
5719 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5721 priv = window->priv;
5723 /* movement keys are considered locked accels */
5726 static const guint bindings[] = {
5727 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,
5728 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,
5732 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5733 if (bindings[i] == accel_key)
5737 /* mnemonics are considered locked accels */
5738 if (accel_mods == priv->mnemonic_modifier)
5740 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5741 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5749 * gtk_window_propagate_key_event:
5750 * @window: a #GtkWindow
5751 * @event: a #GdkEventKey
5753 * Propagate a key press or release event to the focus widget and
5754 * up the focus container chain until a widget handles @event.
5755 * This is normally called by the default ::key_press_event and
5756 * ::key_release_event handlers for toplevel windows,
5757 * however in some cases it may be useful to call this directly when
5758 * overriding the standard key handling for a toplevel window.
5760 * Return value: %TRUE if a widget in the focus chain handled the event.
5765 gtk_window_propagate_key_event (GtkWindow *window,
5768 GtkWindowPrivate *priv;
5769 gboolean handled = FALSE;
5770 GtkWidget *widget, *focus;
5772 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5774 priv = window->priv;
5775 widget = GTK_WIDGET (window);
5777 focus = priv->focus_widget;
5779 g_object_ref (focus);
5782 focus && focus != widget &&
5783 gtk_widget_get_toplevel (focus) == widget)
5787 if (gtk_widget_is_sensitive (focus))
5788 handled = gtk_widget_event (focus, (GdkEvent*) event);
5790 parent = gtk_widget_get_parent (focus);
5792 g_object_ref (parent);
5794 g_object_unref (focus);
5800 g_object_unref (focus);
5806 gtk_window_key_press_event (GtkWidget *widget,
5809 GtkWindow *window = GTK_WINDOW (widget);
5810 gboolean handled = FALSE;
5812 /* handle mnemonics and accelerators */
5814 handled = gtk_window_activate_key (window, event);
5816 /* handle focus widget key events */
5818 handled = gtk_window_propagate_key_event (window, event);
5820 /* Chain up, invokes binding set */
5822 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5828 gtk_window_key_release_event (GtkWidget *widget,
5831 GtkWindow *window = GTK_WINDOW (widget);
5832 gboolean handled = FALSE;
5834 /* handle focus widget key events */
5836 handled = gtk_window_propagate_key_event (window, event);
5838 /* Chain up, invokes binding set */
5840 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5846 gtk_window_button_press_event (GtkWidget *widget,
5847 GdkEventButton *event)
5849 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5852 if (event->window == priv->grip_window)
5854 if (get_drag_edge (widget, &edge))
5855 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5869 gtk_window_real_activate_default (GtkWindow *window)
5871 gtk_window_activate_default (window);
5875 gtk_window_real_activate_focus (GtkWindow *window)
5877 gtk_window_activate_focus (window);
5881 gtk_window_enter_notify_event (GtkWidget *widget,
5882 GdkEventCrossing *event)
5888 gtk_window_leave_notify_event (GtkWidget *widget,
5889 GdkEventCrossing *event)
5895 do_focus_change (GtkWidget *widget,
5899 GdkDeviceManager *device_manager;
5902 g_object_ref (widget);
5904 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5905 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5906 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5907 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5909 for (d = devices; d; d = d->next)
5911 GdkDevice *dev = d->data;
5914 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5917 /* Skip non-master keyboards that haven't
5918 * selected for events from this window
5920 window = gtk_widget_get_window (widget);
5921 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5922 window && !gdk_window_get_device_events (window, dev))
5925 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5927 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5928 fevent->focus_change.window = window;
5930 g_object_ref (window);
5931 fevent->focus_change.in = in;
5932 gdk_event_set_device (fevent, dev);
5934 gtk_widget_send_focus_change (widget, fevent);
5936 gdk_event_free (fevent);
5939 g_list_free (devices);
5940 g_object_unref (widget);
5944 gtk_window_focus_in_event (GtkWidget *widget,
5945 GdkEventFocus *event)
5947 GtkWindow *window = GTK_WINDOW (widget);
5949 /* It appears spurious focus in events can occur when
5950 * the window is hidden. So we'll just check to see if
5951 * the window is visible before actually handling the
5954 if (gtk_widget_get_visible (widget))
5956 _gtk_window_set_has_toplevel_focus (window, TRUE);
5957 _gtk_window_set_is_active (window, TRUE);
5964 gtk_window_focus_out_event (GtkWidget *widget,
5965 GdkEventFocus *event)
5967 GtkWindow *window = GTK_WINDOW (widget);
5968 gboolean auto_mnemonics;
5970 _gtk_window_set_has_toplevel_focus (window, FALSE);
5971 _gtk_window_set_is_active (window, FALSE);
5973 /* set the mnemonic-visible property to false */
5974 g_object_get (gtk_widget_get_settings (widget),
5975 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5977 gtk_window_set_mnemonics_visible (window, FALSE);
5982 static GdkAtom atom_rcfiles = GDK_NONE;
5983 static GdkAtom atom_iconthemes = GDK_NONE;
5986 send_client_message_to_embedded_windows (GtkWidget *widget,
5987 GdkAtom message_type)
5989 GList *embedded_windows;
5991 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5992 if (embedded_windows)
5994 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5997 for (i = 0; i < 5; i++)
5998 send_event->client.data.l[i] = 0;
5999 send_event->client.data_format = 32;
6000 send_event->client.message_type = message_type;
6002 while (embedded_windows)
6004 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
6005 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
6006 embedded_windows = embedded_windows->next;
6009 gdk_event_free (send_event);
6014 gtk_window_client_event (GtkWidget *widget,
6015 GdkEventClient *event)
6019 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
6020 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
6023 if (event->message_type == atom_rcfiles)
6025 send_client_message_to_embedded_windows (widget, atom_rcfiles);
6026 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
6029 if (event->message_type == atom_iconthemes)
6031 send_client_message_to_embedded_windows (widget, atom_iconthemes);
6032 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
6039 gtk_window_check_resize (GtkContainer *container)
6041 if (gtk_widget_get_visible (GTK_WIDGET (container)))
6042 gtk_window_move_resize (GTK_WINDOW (container));
6046 gtk_window_focus (GtkWidget *widget,
6047 GtkDirectionType direction)
6049 GtkWindowPrivate *priv;
6052 GtkContainer *container;
6054 GtkWidget *old_focus_child;
6057 container = GTK_CONTAINER (widget);
6058 window = GTK_WINDOW (widget);
6059 priv = window->priv;
6060 bin = GTK_BIN (widget);
6062 old_focus_child = gtk_container_get_focus_child (container);
6064 /* We need a special implementation here to deal properly with wrapping
6065 * around in the tab chain without the danger of going into an
6068 if (old_focus_child)
6070 if (gtk_widget_child_focus (old_focus_child, direction))
6074 if (priv->focus_widget)
6076 if (direction == GTK_DIR_LEFT ||
6077 direction == GTK_DIR_RIGHT ||
6078 direction == GTK_DIR_UP ||
6079 direction == GTK_DIR_DOWN)
6084 /* Wrapped off the end, clear the focus setting for the toplpevel */
6085 parent = gtk_widget_get_parent (priv->focus_widget);
6088 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6089 parent = gtk_widget_get_parent (parent);
6092 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6095 /* Now try to focus the first widget in the window */
6096 child = gtk_bin_get_child (bin);
6099 if (gtk_widget_child_focus (child, direction))
6107 gtk_window_move_focus (GtkWidget *widget,
6108 GtkDirectionType dir)
6110 gtk_widget_child_focus (widget, dir);
6112 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6113 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6117 gtk_window_real_set_focus (GtkWindow *window,
6120 GtkWindowPrivate *priv = window->priv;
6121 GtkWidget *old_focus = priv->focus_widget;
6122 gboolean had_default = FALSE;
6123 gboolean focus_had_default = FALSE;
6124 gboolean old_focus_had_default = FALSE;
6128 g_object_ref (old_focus);
6129 g_object_freeze_notify (G_OBJECT (old_focus));
6130 old_focus_had_default = gtk_widget_has_default (old_focus);
6134 g_object_ref (focus);
6135 g_object_freeze_notify (G_OBJECT (focus));
6136 focus_had_default = gtk_widget_has_default (focus);
6139 if (priv->default_widget)
6140 had_default = gtk_widget_has_default (priv->default_widget);
6142 if (priv->focus_widget)
6144 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6145 (priv->focus_widget != priv->default_widget))
6147 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6148 gtk_widget_queue_draw (priv->focus_widget);
6150 if (priv->default_widget)
6151 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6154 priv->focus_widget = NULL;
6156 if (priv->has_focus)
6157 do_focus_change (old_focus, FALSE);
6159 g_object_notify (G_OBJECT (old_focus), "is-focus");
6162 /* The above notifications may have set a new focus widget,
6163 * if so, we don't want to override it.
6165 if (focus && !priv->focus_widget)
6167 priv->focus_widget = focus;
6169 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6170 (priv->focus_widget != priv->default_widget))
6172 if (gtk_widget_get_can_default (priv->focus_widget))
6173 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6175 if (priv->default_widget)
6176 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6179 if (priv->has_focus)
6180 do_focus_change (priv->focus_widget, TRUE);
6182 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6185 /* If the default widget changed, a redraw will have been queued
6186 * on the old and new default widgets by gtk_window_set_default(), so
6187 * we only have to worry about the case where it didn't change.
6188 * We'll sometimes queue a draw twice on the new widget but that
6191 if (priv->default_widget &&
6192 (had_default != gtk_widget_has_default (priv->default_widget)))
6193 gtk_widget_queue_draw (priv->default_widget);
6197 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6198 gtk_widget_queue_draw (old_focus);
6200 g_object_thaw_notify (G_OBJECT (old_focus));
6201 g_object_unref (old_focus);
6205 if (focus_had_default != gtk_widget_has_default (focus))
6206 gtk_widget_queue_draw (focus);
6208 g_object_thaw_notify (G_OBJECT (focus));
6209 g_object_unref (focus);
6215 gtk_window_get_preferred_width (GtkWidget *widget,
6223 window = GTK_WINDOW (widget);
6224 child = gtk_bin_get_child (GTK_BIN (window));
6226 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6227 *minimum_size = border_width * 2;
6228 *natural_size = border_width * 2;
6230 if (child && gtk_widget_get_visible (child))
6232 gint child_min, child_nat;
6233 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6235 *minimum_size += child_min;
6236 *natural_size += child_nat;
6241 gtk_window_get_preferred_height (GtkWidget *widget,
6249 window = GTK_WINDOW (widget);
6250 child = gtk_bin_get_child (GTK_BIN (window));
6252 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6253 *minimum_size = border_width * 2;
6254 *natural_size = border_width * 2;
6256 if (child && gtk_widget_get_visible (child))
6258 gint child_min, child_nat;
6259 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6261 *minimum_size += child_min;
6262 *natural_size += child_nat;
6268 * _gtk_window_unset_focus_and_default:
6269 * @window: a #GtkWindow
6270 * @widget: a widget inside of @window
6272 * Checks whether the focus and default widgets of @window are
6273 * @widget or a descendent of @widget, and if so, unset them.
6276 _gtk_window_unset_focus_and_default (GtkWindow *window,
6280 GtkWindowPrivate *priv = window->priv;
6284 g_object_ref (window);
6285 g_object_ref (widget);
6287 parent = gtk_widget_get_parent (widget);
6288 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6290 child = priv->focus_widget;
6292 while (child && child != widget)
6293 child = gtk_widget_get_parent (child);
6295 if (child == widget)
6296 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6299 child = priv->default_widget;
6301 while (child && child != widget)
6302 child = gtk_widget_get_parent (child);
6304 if (child == widget)
6305 gtk_window_set_default (window, NULL);
6307 g_object_unref (widget);
6308 g_object_unref (window);
6311 /*********************************
6312 * Functions related to resizing *
6313 *********************************/
6316 geometry_size_to_pixels (GdkGeometry *geometry,
6321 gint base_width = 0;
6322 gint base_height = 0;
6324 gint min_height = 0;
6326 gint height_inc = 1;
6328 if (flags & GDK_HINT_BASE_SIZE)
6330 base_width = geometry->base_width;
6331 base_height = geometry->base_height;
6333 if (flags & GDK_HINT_MIN_SIZE)
6335 min_width = geometry->min_width;
6336 min_height = geometry->min_height;
6338 if (flags & GDK_HINT_RESIZE_INC)
6340 width_inc = geometry->width_inc;
6341 height_inc = geometry->height_inc;
6345 *width = MAX (*width * width_inc + base_width, min_width);
6347 *height = MAX (*height * height_inc + base_height, min_height);
6350 /* This function doesn't constrain to geometry hints */
6352 gtk_window_compute_configure_request_size (GtkWindow *window,
6353 GdkGeometry *geometry,
6358 GtkWindowPrivate *priv = window->priv;
6359 GtkRequisition requisition;
6360 GtkWindowGeometryInfo *info;
6364 * - we've done a size request
6367 widget = GTK_WIDGET (window);
6369 info = gtk_window_get_geometry_info (window, FALSE);
6371 if (priv->need_default_size)
6373 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6375 /* Default to requisition */
6376 *width = requisition.width;
6377 *height = requisition.height;
6379 /* If window is empty so requests 0, default to random nonzero size */
6380 if (*width == 0 && *height == 0)
6386 /* Override requisition with default size */
6390 if (info->default_width > 0)
6391 *width = info->default_width;
6392 if (info->default_height > 0)
6393 *height = info->default_height;
6395 if (info->default_is_geometry)
6396 geometry_size_to_pixels (geometry, flags,
6397 info->default_width > 0 ? width : NULL,
6398 info->default_height > 0 ? height : NULL);
6403 GtkAllocation allocation;
6405 gtk_widget_get_allocation (widget, &allocation);
6407 /* Default to keeping current size */
6408 *width = allocation.width;
6409 *height = allocation.height;
6412 /* Override any size with gtk_window_resize() values */
6415 if (info->resize_width > 0)
6416 *width = info->resize_width;
6417 if (info->resize_height > 0)
6418 *height = info->resize_height;
6420 if (info->resize_is_geometry)
6421 geometry_size_to_pixels (geometry, flags,
6422 info->resize_width > 0 ? width : NULL,
6423 info->resize_height > 0 ? height : NULL);
6426 /* Don't ever request zero width or height, its not supported by
6427 gdk. The size allocation code will round it to 1 anyway but if
6428 we do it then the value returned from this function will is
6429 not comparable to the size allocation read from the GtkWindow. */
6430 *width = MAX (*width, 1);
6431 *height = MAX (*height, 1);
6434 static GtkWindowPosition
6435 get_effective_position (GtkWindow *window)
6437 GtkWindowPrivate *priv = window->priv;
6438 GtkWindowPosition pos = priv->position;
6440 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6441 (priv->transient_parent == NULL ||
6442 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6443 pos = GTK_WIN_POS_NONE;
6449 get_center_monitor_of_window (GtkWindow *window)
6451 /* We could try to sort out the relative positions of the monitors and
6452 * stuff, or we could just be losers and assume you have a row
6453 * or column of monitors.
6455 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6459 get_monitor_containing_pointer (GtkWindow *window)
6463 GdkScreen *window_screen;
6464 GdkScreen *pointer_screen;
6465 GdkDisplay *display;
6466 GdkDeviceManager *device_manager;
6469 window_screen = gtk_window_check_screen (window);
6470 display = gdk_screen_get_display (window_screen);
6471 device_manager = gdk_display_get_device_manager (display);
6472 pointer = gdk_device_manager_get_client_pointer (device_manager);
6474 gdk_display_get_device_state (display, pointer,
6478 if (pointer_screen == window_screen)
6479 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6487 center_window_on_monitor (GtkWindow *window,
6493 GdkRectangle monitor;
6496 monitor_num = get_monitor_containing_pointer (window);
6498 if (monitor_num == -1)
6499 monitor_num = get_center_monitor_of_window (window);
6501 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6502 monitor_num, &monitor);
6504 *x = (monitor.width - w) / 2 + monitor.x;
6505 *y = (monitor.height - h) / 2 + monitor.y;
6507 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6508 * and WM decorations.
6522 if (extent > clamp_extent)
6524 *base = clamp_base + clamp_extent/2 - extent/2;
6525 else if (*base < clamp_base)
6527 else if (*base + extent > clamp_base + clamp_extent)
6528 *base = clamp_base + clamp_extent - extent;
6532 clamp_window_to_rectangle (gint *x,
6536 const GdkRectangle *rect)
6538 #ifdef DEBUGGING_OUTPUT
6539 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);
6542 /* If it is too large, center it. If it fits on the monitor but is
6543 * partially outside, move it to the closest edge. Do this
6544 * separately in x and y directions.
6546 clamp (x, w, rect->x, rect->width);
6547 clamp (y, h, rect->y, rect->height);
6548 #ifdef DEBUGGING_OUTPUT
6549 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6555 gtk_window_compute_configure_request (GtkWindow *window,
6556 GdkRectangle *request,
6557 GdkGeometry *geometry,
6560 GtkWindowPrivate *priv = window->priv;
6561 GdkGeometry new_geometry;
6565 GtkWindowPosition pos;
6566 GtkWidget *parent_widget;
6567 GtkWindowGeometryInfo *info;
6571 widget = GTK_WIDGET (window);
6573 screen = gtk_window_check_screen (window);
6575 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6576 gtk_window_compute_configure_request_size (window,
6577 &new_geometry, new_flags,
6578 (guint *)&w, (guint *)&h);
6580 gtk_window_constrain_size (window,
6581 &new_geometry, new_flags,
6585 parent_widget = (GtkWidget*) priv->transient_parent;
6587 pos = get_effective_position (window);
6588 info = gtk_window_get_geometry_info (window, FALSE);
6590 /* by default, don't change position requested */
6593 x = info->last.configure_request.x;
6594 y = info->last.configure_request.y;
6603 if (priv->need_default_position)
6606 /* FIXME this all interrelates with window gravity.
6607 * For most of them I think we want to set GRAVITY_CENTER.
6609 * Not sure how to go about that.
6614 /* here we are only handling CENTER_ALWAYS
6615 * as it relates to default positioning,
6616 * where it's equivalent to simply CENTER
6618 case GTK_WIN_POS_CENTER_ALWAYS:
6619 case GTK_WIN_POS_CENTER:
6620 center_window_on_monitor (window, w, h, &x, &y);
6623 case GTK_WIN_POS_CENTER_ON_PARENT:
6625 GtkAllocation allocation;
6626 GdkWindow *gdk_window;
6628 GdkRectangle monitor;
6631 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6633 gdk_window = gtk_widget_get_window (parent_widget);
6635 if (gdk_window != NULL)
6636 monitor_num = gdk_screen_get_monitor_at_window (screen,
6641 gdk_window_get_origin (gdk_window,
6644 gtk_widget_get_allocation (parent_widget, &allocation);
6645 x = ox + (allocation.width - w) / 2;
6646 y = oy + (allocation.height - h) / 2;
6648 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6649 * WM decorations. If parent wasn't on a monitor, just
6652 if (monitor_num >= 0)
6654 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6655 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6660 case GTK_WIN_POS_MOUSE:
6662 gint screen_width = gdk_screen_get_width (screen);
6663 gint screen_height = gdk_screen_get_height (screen);
6665 GdkRectangle monitor;
6666 GdkDisplay *display;
6667 GdkDeviceManager *device_manager;
6669 GdkScreen *pointer_screen;
6672 display = gdk_screen_get_display (screen);
6673 device_manager = gdk_display_get_device_manager (display);
6674 pointer = gdk_device_manager_get_client_pointer (device_manager);
6676 gdk_display_get_device_state (display, pointer,
6680 if (pointer_screen == screen)
6681 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6687 x = CLAMP (x, 0, screen_width - w);
6688 y = CLAMP (y, 0, screen_height - h);
6690 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6691 * WM decorations. Don't try to figure out what's going
6692 * on if the mouse wasn't inside a monitor.
6694 if (monitor_num >= 0)
6696 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6697 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6705 } /* if (priv->need_default_position) */
6707 if (priv->need_default_position && info &&
6708 info->initial_pos_set)
6710 x = info->initial_x;
6711 y = info->initial_y;
6712 gtk_window_constrain_position (window, w, h, &x, &y);
6718 request->height = h;
6721 *geometry = new_geometry;
6727 gtk_window_constrain_position (GtkWindow *window,
6733 GtkWindowPrivate *priv = window->priv;
6735 /* See long comments in gtk_window_move_resize()
6736 * on when it's safe to call this function.
6738 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6740 gint center_x, center_y;
6742 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6750 gtk_window_move_resize (GtkWindow *window)
6754 * First we determine whether any information has changed that would
6755 * cause us to revise our last configure request. If we would send
6756 * a different configure request from last time, then
6757 * configure_request_size_changed = TRUE or
6758 * configure_request_pos_changed = TRUE. configure_request_size_changed
6759 * may be true due to new hints, a gtk_window_resize(), or whatever.
6760 * configure_request_pos_changed may be true due to gtk_window_set_position()
6761 * or gtk_window_move().
6763 * If the configure request has changed, we send off a new one. To
6764 * ensure GTK+ invariants are maintained (resize queue does what it
6765 * should), we go ahead and size_allocate the requested size in this
6768 * If the configure request has not changed, we don't ever resend
6769 * it, because it could mean fighting the user or window manager.
6772 * To prepare the configure request, we come up with a base size/pos:
6773 * - the one from gtk_window_move()/gtk_window_resize()
6774 * - else default_width, default_height if we haven't ever
6776 * - else the size request if we haven't ever been mapped,
6777 * as a substitute default size
6778 * - else the current size of the window, as received from
6779 * configure notifies (i.e. the current allocation)
6781 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6782 * the position request to be centered.
6784 GtkWindowPrivate *priv = window->priv;
6785 GtkAllocation allocation;
6787 GtkContainer *container;
6788 GtkWindowGeometryInfo *info;
6789 GdkGeometry new_geometry;
6790 GdkWindow *gdk_window;
6792 GdkRectangle new_request;
6793 gboolean configure_request_size_changed;
6794 gboolean configure_request_pos_changed;
6795 gboolean hints_changed; /* do we need to send these again */
6796 GtkWindowLastGeometryInfo saved_last_info;
6798 widget = GTK_WIDGET (window);
6799 gdk_window = gtk_widget_get_window (widget);
6800 container = GTK_CONTAINER (widget);
6801 info = gtk_window_get_geometry_info (window, TRUE);
6803 configure_request_size_changed = FALSE;
6804 configure_request_pos_changed = FALSE;
6806 gtk_window_compute_configure_request (window, &new_request,
6807 &new_geometry, &new_flags);
6809 /* This check implies the invariant that we never set info->last
6810 * without setting the hints and sending off a configure request.
6812 * If we change info->last without sending the request, we may
6815 if (info->last.configure_request.x != new_request.x ||
6816 info->last.configure_request.y != new_request.y)
6817 configure_request_pos_changed = TRUE;
6819 if ((info->last.configure_request.width != new_request.width ||
6820 info->last.configure_request.height != new_request.height))
6821 configure_request_size_changed = TRUE;
6823 hints_changed = FALSE;
6825 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6826 &new_geometry, new_flags))
6828 hints_changed = TRUE;
6831 /* Position Constraints
6832 * ====================
6834 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6835 * a default. The other POS_ values are used only when the
6836 * window is shown, not after that.
6838 * However, we can't implement a position constraint as
6839 * "anytime the window size changes, center the window"
6840 * because this may well end up fighting the WM or user. In
6841 * fact it gets in an infinite loop with at least one WM.
6843 * Basically, applications are in no way in a position to
6844 * constrain the position of a window, with one exception:
6845 * override redirect windows. (Really the intended purpose
6846 * of CENTER_ALWAYS anyhow, I would think.)
6848 * So the way we implement this "constraint" is to say that when WE
6849 * cause a move or resize, i.e. we make a configure request changing
6850 * window size, we recompute the CENTER_ALWAYS position to reflect
6851 * the new window size, and include it in our request. Also, if we
6852 * just turned on CENTER_ALWAYS we snap to center with a new
6853 * request. Otherwise, if we are just NOTIFIED of a move or resize
6854 * done by someone else e.g. the window manager, we do NOT send a
6855 * new configure request.
6857 * For override redirect windows, this works fine; all window
6858 * sizes are from our configure requests. For managed windows,
6859 * it is at least semi-sane, though who knows what the
6860 * app author is thinking.
6863 /* This condition should be kept in sync with the condition later on
6864 * that determines whether we send a configure request. i.e. we
6865 * should do this position constraining anytime we were going to
6866 * send a configure request anyhow, plus when constraints have
6869 if (configure_request_pos_changed ||
6870 configure_request_size_changed ||
6872 info->position_constraints_changed)
6874 /* We request the constrained position if:
6875 * - we were changing position, and need to clamp
6876 * the change to the constraint
6877 * - we're changing the size anyway
6878 * - set_position() was called to toggle CENTER_ALWAYS on
6881 gtk_window_constrain_position (window,
6887 /* Update whether we need to request a move */
6888 if (info->last.configure_request.x != new_request.x ||
6889 info->last.configure_request.y != new_request.y)
6890 configure_request_pos_changed = TRUE;
6892 configure_request_pos_changed = FALSE;
6896 if (priv->type == GTK_WINDOW_TOPLEVEL)
6898 int notify_x, notify_y;
6900 /* this is the position from the last configure notify */
6901 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6903 g_message ("--- %s ---\n"
6904 "last : %d,%d\t%d x %d\n"
6905 "this : %d,%d\t%d x %d\n"
6906 "alloc : %d,%d\t%d x %d\n"
6908 "resize: \t%d x %d\n"
6909 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6910 "configure_notify_received: %d\n"
6911 "configure_request_count: %d\n"
6912 "position_constraints_changed: %d\n",
6913 priv->title ? priv->title : "(no title)",
6914 info->last.configure_request.x,
6915 info->last.configure_request.y,
6916 info->last.configure_request.width,
6917 info->last.configure_request.height,
6923 widget->allocation.width,
6924 widget->allocation.height,
6925 widget->requisition.width,
6926 widget->requisition.height,
6928 info->resize_height,
6929 configure_request_pos_changed,
6930 configure_request_size_changed,
6932 priv->configure_notify_received,
6933 priv->configure_request_count,
6934 info->position_constraints_changed);
6938 saved_last_info = info->last;
6939 info->last.geometry = new_geometry;
6940 info->last.flags = new_flags;
6941 info->last.configure_request = new_request;
6943 /* need to set PPosition so the WM will look at our position,
6944 * but we don't want to count PPosition coming and going as a hints
6945 * change for future iterations. So we saved info->last prior to
6949 /* Also, if the initial position was explicitly set, then we always
6950 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6954 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6955 * this is an initial map
6958 if ((configure_request_pos_changed ||
6959 info->initial_pos_set ||
6960 (priv->need_default_position &&
6961 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6962 (new_flags & GDK_HINT_POS) == 0)
6964 new_flags |= GDK_HINT_POS;
6965 hints_changed = TRUE;
6968 /* Set hints if necessary
6971 gdk_window_set_geometry_hints (gdk_window,
6975 gtk_widget_get_allocation (widget, &allocation);
6977 /* handle resizing/moving and widget tree allocation
6979 if (priv->configure_notify_received)
6981 /* If we have received a configure event since
6982 * the last time in this function, we need to
6983 * accept our new size and size_allocate child widgets.
6984 * (see gtk_window_configure_event() for more details).
6986 * 1 or more configure notifies may have been received.
6987 * Also, configure_notify_received will only be TRUE
6988 * if all expected configure notifies have been received
6989 * (one per configure request), as an optimization.
6992 priv->configure_notify_received = FALSE;
6994 /* gtk_window_configure_event() filled in widget->allocation */
6995 gtk_widget_size_allocate (widget, &allocation);
6997 set_grip_position (window);
6998 update_grip_visibility (window);
7000 gdk_window_process_updates (gdk_window, TRUE);
7002 gdk_window_configure_finished (gdk_window);
7004 /* If the configure request changed, it means that
7006 * 1) coincidentally changed hints or widget properties
7007 * impacting the configure request before getting
7008 * a configure notify, or
7009 * 2) some broken widget is changing its size request
7010 * during size allocation, resulting in
7011 * a false appearance of changed configure request.
7013 * For 1), we could just go ahead and ask for the
7014 * new size right now, but doing that for 2)
7015 * might well be fighting the user (and can even
7016 * trigger a loop). Since we really don't want to
7017 * do that, we requeue a resize in hopes that
7018 * by the time it gets handled, the child has seen
7019 * the light and is willing to go along with the
7020 * new size. (this happens for the zvt widget, since
7021 * the size_allocate() above will have stored the
7022 * requisition corresponding to the new size in the
7025 * This doesn't buy us anything for 1), but it shouldn't
7026 * hurt us too badly, since it is what would have
7027 * happened if we had gotten the configure event before
7028 * the new size had been set.
7031 if (configure_request_size_changed ||
7032 configure_request_pos_changed)
7034 /* Don't change the recorded last info after all, because we
7035 * haven't actually updated to the new info yet - we decided
7036 * to postpone our configure request until later.
7038 info->last = saved_last_info;
7040 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7043 return; /* Bail out, we didn't really process the move/resize */
7045 else if ((configure_request_size_changed || hints_changed) &&
7046 (allocation.width != new_request.width || allocation.height != new_request.height))
7049 /* We are in one of the following situations:
7050 * A. configure_request_size_changed
7051 * our requisition has changed and we need a different window size,
7052 * so we request it from the window manager.
7053 * B. !configure_request_size_changed && hints_changed
7054 * the window manager rejects our size, but we have just changed the
7055 * window manager hints, so there's a chance our request will
7056 * be honoured this time, so we try again.
7058 * However, if the new requisition is the same as the current allocation,
7059 * we don't request it again, since we won't get a ConfigureNotify back from
7060 * the window manager unless it decides to change our requisition. If
7061 * we don't get the ConfigureNotify back, the resize queue will never be run.
7064 /* Now send the configure request */
7065 if (configure_request_pos_changed)
7069 gdk_window_move_resize (priv->frame,
7070 new_request.x - priv->frame_left,
7071 new_request.y - priv->frame_top,
7072 new_request.width + priv->frame_left + priv->frame_right,
7073 new_request.height + priv->frame_top + priv->frame_bottom);
7074 gdk_window_resize (gdk_window,
7075 new_request.width, new_request.height);
7078 gdk_window_move_resize (gdk_window,
7079 new_request.x, new_request.y,
7080 new_request.width, new_request.height);
7082 else /* only size changed */
7085 gdk_window_resize (priv->frame,
7086 new_request.width + priv->frame_left + priv->frame_right,
7087 new_request.height + priv->frame_top + priv->frame_bottom);
7088 gdk_window_resize (gdk_window,
7089 new_request.width, new_request.height);
7092 if (priv->type == GTK_WINDOW_POPUP)
7094 GtkAllocation allocation;
7096 /* Directly size allocate for override redirect (popup) windows. */
7099 allocation.width = new_request.width;
7100 allocation.height = new_request.height;
7102 gtk_widget_size_allocate (widget, &allocation);
7104 gdk_window_process_updates (gdk_window, TRUE);
7106 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7107 gtk_widget_queue_draw (widget);
7111 /* Increment the number of have-not-yet-received-notify requests */
7112 priv->configure_request_count += 1;
7113 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7115 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7116 * configure event in response to our resizing request.
7117 * the configure event will cause a new resize with
7118 * ->configure_notify_received=TRUE.
7119 * until then, we want to
7120 * - discard expose events
7121 * - coalesce resizes for our children
7122 * - defer any window resizes until the configure event arrived
7123 * to achieve this, we queue a resize for the window, but remove its
7124 * resizing handler, so resizing will not be handled from the next
7125 * idle handler but when the configure event arrives.
7127 * FIXME: we should also dequeue the pending redraws here, since
7128 * we handle those ourselves upon ->configure_notify_received==TRUE.
7130 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7132 gtk_widget_queue_resize_no_redraw (widget);
7133 _gtk_container_dequeue_resize_handler (container);
7139 /* Handle any position changes.
7141 if (configure_request_pos_changed)
7145 gdk_window_move (priv->frame,
7146 new_request.x - priv->frame_left,
7147 new_request.y - priv->frame_top);
7150 gdk_window_move (gdk_window,
7151 new_request.x, new_request.y);
7154 /* And run the resize queue.
7156 gtk_container_resize_children (container);
7159 /* We have now processed a move/resize since the last position
7160 * constraint change, setting of the initial position, or resize.
7161 * (Not resetting these flags here can lead to infinite loops for
7162 * GTK_RESIZE_IMMEDIATE containers)
7164 info->position_constraints_changed = FALSE;
7165 info->initial_pos_set = FALSE;
7166 info->resize_width = -1;
7167 info->resize_height = -1;
7170 /* Compare two sets of Geometry hints for equality.
7173 gtk_window_compare_hints (GdkGeometry *geometry_a,
7175 GdkGeometry *geometry_b,
7178 if (flags_a != flags_b)
7181 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7182 (geometry_a->min_width != geometry_b->min_width ||
7183 geometry_a->min_height != geometry_b->min_height))
7186 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7187 (geometry_a->max_width != geometry_b->max_width ||
7188 geometry_a->max_height != geometry_b->max_height))
7191 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7192 (geometry_a->base_width != geometry_b->base_width ||
7193 geometry_a->base_height != geometry_b->base_height))
7196 if ((flags_a & GDK_HINT_ASPECT) &&
7197 (geometry_a->min_aspect != geometry_b->min_aspect ||
7198 geometry_a->max_aspect != geometry_b->max_aspect))
7201 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7202 (geometry_a->width_inc != geometry_b->width_inc ||
7203 geometry_a->height_inc != geometry_b->height_inc))
7206 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7207 geometry_a->win_gravity != geometry_b->win_gravity)
7214 _gtk_window_constrain_size (GtkWindow *window,
7220 GtkWindowPrivate *priv;
7221 GtkWindowGeometryInfo *info;
7223 g_return_if_fail (GTK_IS_WINDOW (window));
7225 priv = window->priv;
7227 info = priv->geometry_info;
7230 GdkWindowHints flags = info->last.flags;
7231 GdkGeometry *geometry = &info->last.geometry;
7233 gtk_window_constrain_size (window,
7244 gtk_window_constrain_size (GtkWindow *window,
7245 GdkGeometry *geometry,
7252 gdk_window_constrain_size (geometry, flags, width, height,
7253 new_width, new_height);
7256 /* Compute the set of geometry hints and flags for a window
7257 * based on the application set geometry, and requisition
7258 * of the window. gtk_widget_get_preferred_size() must have been
7262 gtk_window_compute_hints (GtkWindow *window,
7263 GdkGeometry *new_geometry,
7266 GtkWindowPrivate *priv = window->priv;
7268 gint extra_width = 0;
7269 gint extra_height = 0;
7270 GtkWindowGeometryInfo *geometry_info;
7271 GtkRequisition requisition;
7273 widget = GTK_WIDGET (window);
7275 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7276 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7280 *new_flags = geometry_info->mask;
7281 *new_geometry = geometry_info->geometry;
7288 if (geometry_info && geometry_info->widget)
7290 /* If the geometry widget is set, then the hints really apply to that
7291 * widget. This is pretty much meaningless unless the window layout
7292 * is such that the rest of the window adds fixed size borders to
7293 * the geometry widget. Our job is to figure the size of the borders;
7294 * We do that by asking how big the toplevel would be if the
7295 * geometry widget was *really big*.
7298 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7299 * |GGGGG B| in the border can confuse things
7305 * |AAAAAAAAA | When the geometry widget is large, things are
7306 * |GGGGGGGGGGB| clearer.
7311 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7312 GtkRequisition requisition;
7313 int current_width, current_height;
7315 _gtk_widget_override_size_request (geometry_info->widget,
7316 TEMPORARY_SIZE, TEMPORARY_SIZE,
7317 ¤t_width, ¤t_height);
7318 gtk_widget_get_preferred_size (widget,
7319 &requisition, NULL);
7320 _gtk_widget_restore_size_request (geometry_info->widget,
7321 current_width, current_height);
7323 extra_width = requisition.width - TEMPORARY_SIZE;
7324 extra_height = requisition.height - TEMPORARY_SIZE;
7326 if (extra_width < 0 || extra_width < 0)
7328 g_warning("Toplevel size doesn't seem to directly depend on the "
7329 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7330 "The geometry widget might not be in the window, or it might not "
7331 "be packed into the window appropriately");
7332 extra_width = MAX(extra_width, 0);
7333 extra_height = MAX(extra_height, 0);
7335 #undef TEMPORARY_SIZE
7338 /* We don't want to set GDK_HINT_POS in here, we just set it
7339 * in gtk_window_move_resize() when we want the position
7343 if (*new_flags & GDK_HINT_BASE_SIZE)
7345 new_geometry->base_width += extra_width;
7346 new_geometry->base_height += extra_height;
7350 /* For simplicity, we always set the base hint, even when we
7351 * don't expect it to have any visible effect.
7352 * (Note: geometry_size_to_pixels() depends on this.)
7354 *new_flags |= GDK_HINT_BASE_SIZE;
7356 new_geometry->base_width = extra_width;
7357 new_geometry->base_height = extra_height;
7359 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7360 * base size is the minimum size */
7361 if (*new_flags & GDK_HINT_MIN_SIZE)
7363 if (new_geometry->min_width > 0)
7364 new_geometry->base_width += new_geometry->min_width;
7365 if (new_geometry->min_height > 0)
7366 new_geometry->base_height += new_geometry->min_height;
7370 if (*new_flags & GDK_HINT_MIN_SIZE)
7372 if (new_geometry->min_width < 0)
7373 new_geometry->min_width = requisition.width;
7375 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7377 if (new_geometry->min_height < 0)
7378 new_geometry->min_height = requisition.height;
7380 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7384 *new_flags |= GDK_HINT_MIN_SIZE;
7386 new_geometry->min_width = requisition.width;
7387 new_geometry->min_height = requisition.height;
7390 if (*new_flags & GDK_HINT_MAX_SIZE)
7392 if (new_geometry->max_width < 0)
7393 new_geometry->max_width = requisition.width;
7395 new_geometry->max_width += extra_width;
7397 if (new_geometry->max_height < 0)
7398 new_geometry->max_height = requisition.height;
7400 new_geometry->max_height += extra_height;
7402 else if (!priv->resizable)
7404 *new_flags |= GDK_HINT_MAX_SIZE;
7406 new_geometry->max_width = requisition.width;
7407 new_geometry->max_height = requisition.height;
7410 *new_flags |= GDK_HINT_WIN_GRAVITY;
7411 new_geometry->win_gravity = priv->gravity;
7414 /***********************
7415 * Redrawing functions *
7416 ***********************/
7419 gtk_window_draw (GtkWidget *widget,
7422 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7423 GtkStyleContext *context;
7424 gboolean ret = FALSE;
7426 context = gtk_widget_get_style_context (widget);
7428 gtk_style_context_save (context);
7430 if (!gtk_widget_get_app_paintable (widget))
7432 GtkStateFlags state;
7434 state = gtk_widget_get_state_flags (widget);
7436 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7437 state |= GTK_STATE_FLAG_FOCUSED;
7439 gtk_style_context_set_state (context, state);
7440 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7441 gtk_render_background (context, cr, 0, 0,
7442 gtk_widget_get_allocated_width (widget),
7443 gtk_widget_get_allocated_height (widget));
7446 gtk_style_context_restore (context);
7448 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7449 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7451 if (priv->grip_window != NULL &&
7452 gtk_cairo_should_draw_window (cr, priv->grip_window))
7456 gtk_style_context_save (context);
7459 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7460 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7462 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7463 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7464 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7467 gtk_style_context_restore (context);
7474 * gtk_window_set_has_frame:
7475 * @window: a #GtkWindow
7476 * @setting: a boolean
7478 * (Note: this is a special-purpose function for the framebuffer port,
7479 * that causes GTK+ to draw its own window border. For most applications,
7480 * you want gtk_window_set_decorated() instead, which tells the window
7481 * manager whether to draw the window border.)
7483 * If this function is called on a window with setting of %TRUE, before
7484 * it is realized or showed, it will have a "frame" window around
7485 * @window->window, accessible in @window->frame. Using the signal
7486 * frame_event you can receive all events targeted at the frame.
7488 * This function is used by the linux-fb port to implement managed
7489 * windows, but it could conceivably be used by X-programs that
7490 * want to do their own window decorations.
7494 gtk_window_set_has_frame (GtkWindow *window,
7497 GtkWindowPrivate *priv;
7499 g_return_if_fail (GTK_IS_WINDOW (window));
7500 g_return_if_fail (!gtk_widget_get_realized (GTK_WIDGET (window)));
7502 priv = window->priv;
7504 priv->has_frame = setting != FALSE;
7508 * gtk_window_get_has_frame:
7509 * @window: a #GtkWindow
7511 * Accessor for whether the window has a frame window exterior to
7512 * @window->window. Gets the value set by gtk_window_set_has_frame ().
7514 * Return value: %TRUE if a frame has been added to the window
7515 * via gtk_window_set_has_frame().
7518 gtk_window_get_has_frame (GtkWindow *window)
7520 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7522 return window->priv->has_frame;
7526 * gtk_window_set_frame_dimensions:
7527 * @window: a #GtkWindow that has a frame
7528 * @left: The width of the left border
7529 * @top: The height of the top border
7530 * @right: The width of the right border
7531 * @bottom: The height of the bottom border
7533 * (Note: this is a special-purpose function intended for the framebuffer
7534 * port; see gtk_window_set_has_frame(). It will have no effect on the
7535 * window border drawn by the window manager, which is the normal
7536 * case when using the X Window system.)
7538 * For windows with frames (see gtk_window_set_has_frame()) this function
7539 * can be used to change the size of the frame border.
7542 gtk_window_set_frame_dimensions (GtkWindow *window,
7548 GtkWindowPrivate *priv;
7549 GtkAllocation allocation;
7552 g_return_if_fail (GTK_IS_WINDOW (window));
7554 priv = window->priv;
7555 widget = GTK_WIDGET (window);
7557 if (priv->frame_left == left &&
7558 priv->frame_top == top &&
7559 priv->frame_right == right &&
7560 priv->frame_bottom == bottom)
7563 priv->frame_left = left;
7564 priv->frame_top = top;
7565 priv->frame_right = right;
7566 priv->frame_bottom = bottom;
7568 if (gtk_widget_get_realized (widget) && priv->frame)
7571 gtk_widget_get_allocation (widget, &allocation);
7573 width = allocation.width + left + right;
7574 height = allocation.height + top + bottom;
7575 gdk_window_resize (priv->frame, width, height);
7576 gdk_window_move_resize (gtk_widget_get_window (GTK_WIDGET (window)),
7584 * gtk_window_present:
7585 * @window: a #GtkWindow
7587 * Presents a window to the user. This may mean raising the window
7588 * in the stacking order, deiconifying it, moving it to the current
7589 * desktop, and/or giving it the keyboard focus, possibly dependent
7590 * on the user's platform, window manager, and preferences.
7592 * If @window is hidden, this function calls gtk_widget_show()
7595 * This function should be used when the user tries to open a window
7596 * that's already open. Say for example the preferences dialog is
7597 * currently open, and the user chooses Preferences from the menu
7598 * a second time; use gtk_window_present() to move the already-open dialog
7599 * where the user can see it.
7601 * If you are calling this function in response to a user interaction,
7602 * it is preferable to use gtk_window_present_with_time().
7606 gtk_window_present (GtkWindow *window)
7608 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7612 * gtk_window_present_with_time:
7613 * @window: a #GtkWindow
7614 * @timestamp: the timestamp of the user interaction (typically a
7615 * button or key press event) which triggered this call
7617 * Presents a window to the user in response to a user interaction.
7618 * If you need to present a window without a timestamp, use
7619 * gtk_window_present(). See gtk_window_present() for details.
7624 gtk_window_present_with_time (GtkWindow *window,
7628 GdkWindow *gdk_window;
7630 g_return_if_fail (GTK_IS_WINDOW (window));
7632 widget = GTK_WIDGET (window);
7634 if (gtk_widget_get_visible (widget))
7636 gdk_window = gtk_widget_get_window (widget);
7638 g_assert (gdk_window != NULL);
7640 gdk_window_show (gdk_window);
7642 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7643 if (timestamp == GDK_CURRENT_TIME)
7645 #ifdef GDK_WINDOWING_X11
7646 GdkDisplay *display;
7648 display = gtk_widget_get_display (GTK_WIDGET (window));
7649 timestamp = gdk_x11_display_get_user_time (display);
7651 timestamp = gtk_get_current_event_time ();
7655 gdk_window_focus (gdk_window, timestamp);
7659 gtk_widget_show (widget);
7664 * gtk_window_iconify:
7665 * @window: a #GtkWindow
7667 * Asks to iconify (i.e. minimize) the specified @window. Note that
7668 * you shouldn't assume the window is definitely iconified afterward,
7669 * because other entities (e.g. the user or <link
7670 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7671 * again, or there may not be a window manager in which case
7672 * iconification isn't possible, etc. But normally the window will end
7673 * up iconified. Just don't write code that crashes if not.
7675 * It's permitted to call this function before showing a window,
7676 * in which case the window will be iconified before it ever appears
7679 * You can track iconification via the "window-state-event" signal
7684 gtk_window_iconify (GtkWindow *window)
7686 GtkWindowPrivate *priv;
7688 GdkWindow *toplevel;
7690 g_return_if_fail (GTK_IS_WINDOW (window));
7692 priv = window->priv;
7693 widget = GTK_WIDGET (window);
7695 priv->iconify_initially = TRUE;
7698 toplevel = priv->frame;
7700 toplevel = gtk_widget_get_window (widget);
7702 if (toplevel != NULL)
7703 gdk_window_iconify (toplevel);
7707 * gtk_window_deiconify:
7708 * @window: a #GtkWindow
7710 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7711 * that you shouldn't assume the window is definitely deiconified
7712 * afterward, because other entities (e.g. the user or <link
7713 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7714 * again before your code which assumes deiconification gets to run.
7716 * You can track iconification via the "window-state-event" signal
7720 gtk_window_deiconify (GtkWindow *window)
7722 GtkWindowPrivate *priv;
7724 GdkWindow *toplevel;
7726 g_return_if_fail (GTK_IS_WINDOW (window));
7728 priv = window->priv;
7729 widget = GTK_WIDGET (window);
7731 priv->iconify_initially = FALSE;
7734 toplevel = priv->frame;
7736 toplevel = gtk_widget_get_window (widget);
7738 if (toplevel != NULL)
7739 gdk_window_deiconify (toplevel);
7744 * @window: a #GtkWindow
7746 * Asks to stick @window, which means that it will appear on all user
7747 * desktops. Note that you shouldn't assume the window is definitely
7748 * stuck afterward, because other entities (e.g. the user or <link
7749 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7750 * again, and some window managers do not support sticking
7751 * windows. But normally the window will end up stuck. Just don't
7752 * write code that crashes if not.
7754 * It's permitted to call this function before showing a window.
7756 * You can track stickiness via the "window-state-event" signal
7761 gtk_window_stick (GtkWindow *window)
7763 GtkWindowPrivate *priv;
7765 GdkWindow *toplevel;
7767 g_return_if_fail (GTK_IS_WINDOW (window));
7769 priv = window->priv;
7770 widget = GTK_WIDGET (window);
7772 priv->stick_initially = TRUE;
7775 toplevel = priv->frame;
7777 toplevel = gtk_widget_get_window (widget);
7779 if (toplevel != NULL)
7780 gdk_window_stick (toplevel);
7784 * gtk_window_unstick:
7785 * @window: a #GtkWindow
7787 * Asks to unstick @window, which means that it will appear on only
7788 * one of the user's desktops. Note that you shouldn't assume the
7789 * window is definitely unstuck afterward, because other entities
7790 * (e.g. the user or <link linkend="gtk-X11-arch">window
7791 * manager</link>) could stick it again. But normally the window will
7792 * end up stuck. Just don't write code that crashes if not.
7794 * You can track stickiness via the "window-state-event" signal
7799 gtk_window_unstick (GtkWindow *window)
7801 GtkWindowPrivate *priv;
7803 GdkWindow *toplevel;
7805 g_return_if_fail (GTK_IS_WINDOW (window));
7807 priv = window->priv;
7808 widget = GTK_WIDGET (window);
7810 priv->stick_initially = FALSE;
7813 toplevel = priv->frame;
7815 toplevel = gtk_widget_get_window (widget);
7817 if (toplevel != NULL)
7818 gdk_window_unstick (toplevel);
7822 * gtk_window_maximize:
7823 * @window: a #GtkWindow
7825 * Asks to maximize @window, so that it becomes full-screen. Note that
7826 * you shouldn't assume the window is definitely maximized afterward,
7827 * because other entities (e.g. the user or <link
7828 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7829 * again, and not all window managers support maximization. But
7830 * normally the window will end up maximized. Just don't write code
7831 * that crashes if not.
7833 * It's permitted to call this function before showing a window,
7834 * in which case the window will be maximized when it appears onscreen
7837 * You can track maximization via the "window-state-event" signal
7842 gtk_window_maximize (GtkWindow *window)
7844 GtkWindowPrivate *priv;
7846 GdkWindow *toplevel;
7848 g_return_if_fail (GTK_IS_WINDOW (window));
7850 priv = window->priv;
7851 widget = GTK_WIDGET (window);
7853 priv->maximize_initially = TRUE;
7856 toplevel = priv->frame;
7858 toplevel = gtk_widget_get_window (widget);
7860 if (toplevel != NULL)
7861 gdk_window_maximize (toplevel);
7865 * gtk_window_unmaximize:
7866 * @window: a #GtkWindow
7868 * Asks to unmaximize @window. Note that you shouldn't assume the
7869 * window is definitely unmaximized afterward, because other entities
7870 * (e.g. the user or <link linkend="gtk-X11-arch">window
7871 * manager</link>) could maximize it again, and not all window
7872 * managers honor requests to unmaximize. But normally the window will
7873 * end up unmaximized. Just don't write code that crashes if not.
7875 * You can track maximization via the "window-state-event" signal
7880 gtk_window_unmaximize (GtkWindow *window)
7882 GtkWindowPrivate *priv;
7884 GdkWindow *toplevel;
7886 g_return_if_fail (GTK_IS_WINDOW (window));
7888 priv = window->priv;
7889 widget = GTK_WIDGET (window);
7891 priv->maximize_initially = FALSE;
7894 toplevel = priv->frame;
7896 toplevel = gtk_widget_get_window (widget);
7898 if (toplevel != NULL)
7899 gdk_window_unmaximize (toplevel);
7903 * gtk_window_fullscreen:
7904 * @window: a #GtkWindow
7906 * Asks to place @window in the fullscreen state. Note that you
7907 * shouldn't assume the window is definitely full screen afterward,
7908 * because other entities (e.g. the user or <link
7909 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7910 * again, and not all window managers honor requests to fullscreen
7911 * windows. But normally the window will end up fullscreen. Just
7912 * don't write code that crashes if not.
7914 * You can track the fullscreen state via the "window-state-event" signal
7920 gtk_window_fullscreen (GtkWindow *window)
7922 GtkWindowPrivate *priv;
7924 GdkWindow *toplevel;
7926 g_return_if_fail (GTK_IS_WINDOW (window));
7928 priv = window->priv;
7929 widget = GTK_WIDGET (window);
7931 priv->fullscreen_initially = TRUE;
7934 toplevel = priv->frame;
7936 toplevel = gtk_widget_get_window (widget);
7938 if (toplevel != NULL)
7939 gdk_window_fullscreen (toplevel);
7943 * gtk_window_unfullscreen:
7944 * @window: a #GtkWindow
7946 * Asks to toggle off the fullscreen state for @window. Note that you
7947 * shouldn't assume the window is definitely not full screen
7948 * afterward, because other entities (e.g. the user or <link
7949 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7950 * again, and not all window managers honor requests to unfullscreen
7951 * windows. But normally the window will end up restored to its normal
7952 * state. Just don't write code that crashes if not.
7954 * You can track the fullscreen state via the "window-state-event" signal
7960 gtk_window_unfullscreen (GtkWindow *window)
7963 GdkWindow *toplevel;
7964 GtkWindowPrivate *priv;
7966 g_return_if_fail (GTK_IS_WINDOW (window));
7968 priv = window->priv;
7969 widget = GTK_WIDGET (window);
7971 priv->fullscreen_initially = FALSE;
7974 toplevel = priv->frame;
7976 toplevel = gtk_widget_get_window (widget);
7978 if (toplevel != NULL)
7979 gdk_window_unfullscreen (toplevel);
7983 * gtk_window_set_keep_above:
7984 * @window: a #GtkWindow
7985 * @setting: whether to keep @window above other windows
7987 * Asks to keep @window above, so that it stays on top. Note that
7988 * you shouldn't assume the window is definitely above afterward,
7989 * because other entities (e.g. the user or <link
7990 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7991 * and not all window managers support keeping windows above. But
7992 * normally the window will end kept above. Just don't write code
7993 * that crashes if not.
7995 * It's permitted to call this function before showing a window,
7996 * in which case the window will be kept above when it appears onscreen
7999 * You can track the above state via the "window-state-event" signal
8002 * Note that, according to the <ulink
8003 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8004 * Manager Hints</ulink> specification, the above state is mainly meant
8005 * for user preferences and should not be used by applications e.g. for
8006 * drawing attention to their dialogs.
8011 gtk_window_set_keep_above (GtkWindow *window,
8015 GtkWindowPrivate *priv;
8016 GdkWindow *toplevel;
8018 g_return_if_fail (GTK_IS_WINDOW (window));
8020 priv = window->priv;
8021 widget = GTK_WIDGET (window);
8023 priv->above_initially = setting != FALSE;
8025 priv->below_initially = FALSE;
8028 toplevel = priv->frame;
8030 toplevel = gtk_widget_get_window (widget);
8032 if (toplevel != NULL)
8033 gdk_window_set_keep_above (toplevel, setting);
8037 * gtk_window_set_keep_below:
8038 * @window: a #GtkWindow
8039 * @setting: whether to keep @window below other windows
8041 * Asks to keep @window below, so that it stays in bottom. Note that
8042 * you shouldn't assume the window is definitely below afterward,
8043 * because other entities (e.g. the user or <link
8044 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8045 * and not all window managers support putting windows below. But
8046 * normally the window will be kept below. Just don't write code
8047 * that crashes if not.
8049 * It's permitted to call this function before showing a window,
8050 * in which case the window will be kept below when it appears onscreen
8053 * You can track the below state via the "window-state-event" signal
8056 * Note that, according to the <ulink
8057 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8058 * Manager Hints</ulink> specification, the above state is mainly meant
8059 * for user preferences and should not be used by applications e.g. for
8060 * drawing attention to their dialogs.
8065 gtk_window_set_keep_below (GtkWindow *window,
8069 GtkWindowPrivate *priv;
8070 GdkWindow *toplevel;
8072 g_return_if_fail (GTK_IS_WINDOW (window));
8074 priv = window->priv;
8075 widget = GTK_WIDGET (window);
8077 priv->below_initially = setting != FALSE;
8079 priv->above_initially = FALSE;
8082 toplevel = priv->frame;
8084 toplevel = gtk_widget_get_window (widget);
8086 if (toplevel != NULL)
8087 gdk_window_set_keep_below (toplevel, setting);
8091 * gtk_window_set_resizable:
8092 * @window: a #GtkWindow
8093 * @resizable: %TRUE if the user can resize this window
8095 * Sets whether the user can resize a window. Windows are user resizable
8099 gtk_window_set_resizable (GtkWindow *window,
8102 GtkWindowPrivate *priv;
8104 g_return_if_fail (GTK_IS_WINDOW (window));
8106 priv = window->priv;
8108 resizable = (resizable != FALSE);
8110 if (priv->resizable != resizable)
8112 priv->resizable = (resizable != FALSE);
8114 update_grip_visibility (window);
8116 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8118 g_object_notify (G_OBJECT (window), "resizable");
8123 * gtk_window_get_resizable:
8124 * @window: a #GtkWindow
8126 * Gets the value set by gtk_window_set_resizable().
8128 * Return value: %TRUE if the user can resize the window
8131 gtk_window_get_resizable (GtkWindow *window)
8133 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8135 return window->priv->resizable;
8139 * gtk_window_set_gravity:
8140 * @window: a #GtkWindow
8141 * @gravity: window gravity
8143 * Window gravity defines the meaning of coordinates passed to
8144 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8147 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8148 * typically "do what you mean."
8152 gtk_window_set_gravity (GtkWindow *window,
8155 GtkWindowPrivate *priv;
8157 g_return_if_fail (GTK_IS_WINDOW (window));
8159 priv = window->priv;
8161 if (gravity != priv->gravity)
8163 priv->gravity = gravity;
8165 /* gtk_window_move_resize() will adapt gravity
8167 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8169 g_object_notify (G_OBJECT (window), "gravity");
8174 * gtk_window_get_gravity:
8175 * @window: a #GtkWindow
8177 * Gets the value set by gtk_window_set_gravity().
8179 * Return value: (transfer none): window gravity
8182 gtk_window_get_gravity (GtkWindow *window)
8184 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8186 return window->priv->gravity;
8190 * gtk_window_begin_resize_drag:
8191 * @window: a #GtkWindow
8192 * @button: mouse button that initiated the drag
8193 * @edge: position of the resize control
8194 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8195 * @root_y: Y position where the user clicked to initiate the drag
8196 * @timestamp: timestamp from the click event that initiated the drag
8198 * Starts resizing a window. This function is used if an application
8199 * has window resizing controls. When GDK can support it, the resize
8200 * will be done using the standard mechanism for the <link
8201 * linkend="gtk-X11-arch">window manager</link> or windowing
8202 * system. Otherwise, GDK will try to emulate window resizing,
8203 * potentially not all that well, depending on the windowing system.
8207 gtk_window_begin_resize_drag (GtkWindow *window,
8214 GtkWindowPrivate *priv;
8216 GdkWindow *toplevel;
8218 g_return_if_fail (GTK_IS_WINDOW (window));
8219 widget = GTK_WIDGET (window);
8220 g_return_if_fail (gtk_widget_get_visible (widget));
8222 priv = window->priv;
8225 toplevel = priv->frame;
8227 toplevel = gtk_widget_get_window (widget);
8229 gdk_window_begin_resize_drag (toplevel,
8236 * gtk_window_get_frame_dimensions:
8237 * @window: a #GtkWindow
8238 * @left: (out) (allow-none): location to store the width of the frame at the left, or %NULL
8239 * @top: (out) (allow-none): location to store the height of the frame at the top, or %NULL
8240 * @right: (out) (allow-none): location to store the width of the frame at the returns, or %NULL
8241 * @bottom: (out) (allow-none): location to store the height of the frame at the bottom, or %NULL
8243 * (Note: this is a special-purpose function intended for the
8244 * framebuffer port; see gtk_window_set_has_frame(). It will not
8245 * return the size of the window border drawn by the <link
8246 * linkend="gtk-X11-arch">window manager</link>, which is the normal
8247 * case when using a windowing system. See
8248 * gdk_window_get_frame_extents() to get the standard window border
8251 * Retrieves the dimensions of the frame window for this toplevel.
8252 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
8255 gtk_window_get_frame_dimensions (GtkWindow *window,
8261 GtkWindowPrivate *priv;
8263 g_return_if_fail (GTK_IS_WINDOW (window));
8265 priv = window->priv;
8268 *left = priv->frame_left;
8270 *top = priv->frame_top;
8272 *right = priv->frame_right;
8274 *bottom = priv->frame_bottom;
8278 * gtk_window_begin_move_drag:
8279 * @window: a #GtkWindow
8280 * @button: mouse button that initiated the drag
8281 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8282 * @root_y: Y position where the user clicked to initiate the drag
8283 * @timestamp: timestamp from the click event that initiated the drag
8285 * Starts moving a window. This function is used if an application has
8286 * window movement grips. When GDK can support it, the window movement
8287 * will be done using the standard mechanism for the <link
8288 * linkend="gtk-X11-arch">window manager</link> or windowing
8289 * system. Otherwise, GDK will try to emulate window movement,
8290 * potentially not all that well, depending on the windowing system.
8294 gtk_window_begin_move_drag (GtkWindow *window,
8300 GtkWindowPrivate *priv;
8302 GdkWindow *toplevel;
8304 g_return_if_fail (GTK_IS_WINDOW (window));
8305 widget = GTK_WIDGET (window);
8306 g_return_if_fail (gtk_widget_get_visible (widget));
8308 priv = window->priv;
8311 toplevel = priv->frame;
8313 toplevel = gtk_widget_get_window (widget);
8315 gdk_window_begin_move_drag (toplevel,
8322 * gtk_window_set_screen:
8323 * @window: a #GtkWindow.
8324 * @screen: a #GdkScreen.
8326 * Sets the #GdkScreen where the @window is displayed; if
8327 * the window is already mapped, it will be unmapped, and
8328 * then remapped on the new screen.
8333 gtk_window_set_screen (GtkWindow *window,
8336 GtkWindowPrivate *priv;
8338 GdkScreen *previous_screen;
8339 gboolean was_mapped;
8341 g_return_if_fail (GTK_IS_WINDOW (window));
8342 g_return_if_fail (GDK_IS_SCREEN (screen));
8344 priv = window->priv;
8346 if (screen == priv->screen)
8349 widget = GTK_WIDGET (window);
8351 previous_screen = priv->screen;
8352 was_mapped = gtk_widget_get_mapped (widget);
8355 gtk_widget_unmap (widget);
8356 if (gtk_widget_get_realized (widget))
8357 gtk_widget_unrealize (widget);
8359 gtk_window_free_key_hash (window);
8360 priv->screen = screen;
8361 gtk_widget_reset_rc_styles (widget);
8362 if (screen != previous_screen)
8364 g_signal_handlers_disconnect_by_func (previous_screen,
8365 gtk_window_on_composited_changed, window);
8366 g_signal_connect (screen, "composited-changed",
8367 G_CALLBACK (gtk_window_on_composited_changed), window);
8369 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8370 _gtk_widget_propagate_composited_changed (widget);
8372 g_object_notify (G_OBJECT (window), "screen");
8375 gtk_widget_map (widget);
8379 gtk_window_on_composited_changed (GdkScreen *screen,
8382 gtk_widget_queue_draw (GTK_WIDGET (window));
8384 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8388 gtk_window_check_screen (GtkWindow *window)
8390 GtkWindowPrivate *priv = window->priv;
8393 return priv->screen;
8396 g_warning ("Screen for GtkWindow not set; you must always set\n"
8397 "a screen for a GtkWindow before using the window");
8403 * gtk_window_get_screen:
8404 * @window: a #GtkWindow.
8406 * Returns the #GdkScreen associated with @window.
8408 * Return value: (transfer none): a #GdkScreen.
8413 gtk_window_get_screen (GtkWindow *window)
8415 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8417 return window->priv->screen;
8421 * gtk_window_is_active:
8422 * @window: a #GtkWindow
8424 * Returns whether the window is part of the current active toplevel.
8425 * (That is, the toplevel window receiving keystrokes.)
8426 * The return value is %TRUE if the window is active toplevel
8427 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8428 * You might use this function if you wanted to draw a widget
8429 * differently in an active window from a widget in an inactive window.
8430 * See gtk_window_has_toplevel_focus()
8432 * Return value: %TRUE if the window part of the current active window.
8437 gtk_window_is_active (GtkWindow *window)
8439 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8441 return window->priv->is_active;
8445 * gtk_window_has_toplevel_focus:
8446 * @window: a #GtkWindow
8448 * Returns whether the input focus is within this GtkWindow.
8449 * For real toplevel windows, this is identical to gtk_window_is_active(),
8450 * but for embedded windows, like #GtkPlug, the results will differ.
8452 * Return value: %TRUE if the input focus is within this GtkWindow
8457 gtk_window_has_toplevel_focus (GtkWindow *window)
8459 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8461 return window->priv->has_toplevel_focus;
8465 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8467 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8471 gtk_window_group_get_type (void)
8473 static GType window_group_type = 0;
8475 if (!window_group_type)
8477 const GTypeInfo window_group_info =
8479 sizeof (GtkWindowGroupClass),
8480 NULL, /* base_init */
8481 NULL, /* base_finalize */
8482 (GClassInitFunc) gtk_window_group_class_init,
8483 NULL, /* class_finalize */
8484 NULL, /* class_data */
8485 sizeof (GtkWindowGroup),
8486 0, /* n_preallocs */
8487 (GInstanceInitFunc) NULL,
8490 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
8491 &window_group_info, 0);
8494 return window_group_type;
8498 * gtk_window_group_new:
8500 * Creates a new #GtkWindowGroup object. Grabs added with
8501 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8503 * Return value: a new #GtkWindowGroup.
8506 gtk_window_group_new (void)
8508 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8512 window_group_cleanup_grabs (GtkWindowGroup *group,
8515 GtkWindowGroupPrivate *priv;
8516 GtkDeviceGrabInfo *info;
8518 GSList *to_remove = NULL;
8520 tmp_list = group->grabs;
8523 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8524 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8525 tmp_list = tmp_list->next;
8530 gtk_grab_remove (to_remove->data);
8531 g_object_unref (to_remove->data);
8532 to_remove = g_slist_delete_link (to_remove, to_remove);
8535 priv = GTK_WINDOW_GROUP_GET_PRIVATE (group);
8536 tmp_list = priv->device_grabs;
8540 info = tmp_list->data;
8542 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8543 to_remove = g_slist_prepend (to_remove, info);
8545 tmp_list = tmp_list->next;
8550 info = to_remove->data;
8552 gtk_device_grab_remove (info->widget, info->device);
8553 to_remove = g_slist_delete_link (to_remove, to_remove);
8558 * gtk_window_group_add_window:
8559 * @window_group: a #GtkWindowGroup
8560 * @window: the #GtkWindow to add
8562 * Adds a window to a #GtkWindowGroup.
8565 gtk_window_group_add_window (GtkWindowGroup *window_group,
8568 GtkWindowPrivate *priv;
8570 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8571 g_return_if_fail (GTK_IS_WINDOW (window));
8573 priv = window->priv;
8575 if (priv->group != window_group)
8577 g_object_ref (window);
8578 g_object_ref (window_group);
8581 gtk_window_group_remove_window (priv->group, window);
8583 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8585 priv->group = window_group;
8587 g_object_unref (window);
8592 * gtk_window_group_remove_window:
8593 * @window_group: a #GtkWindowGroup
8594 * @window: the #GtkWindow to remove
8596 * Removes a window from a #GtkWindowGroup.
8599 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8602 GtkWindowPrivate *priv;
8604 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8605 g_return_if_fail (GTK_IS_WINDOW (window));
8606 priv = window->priv;
8607 g_return_if_fail (priv->group == window_group);
8609 g_object_ref (window);
8611 window_group_cleanup_grabs (window_group, window);
8614 g_object_unref (window_group);
8615 g_object_unref (window);
8619 * gtk_window_group_list_windows:
8620 * @window_group: a #GtkWindowGroup
8622 * Returns a list of the #GtkWindows that belong to @window_group.
8624 * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
8625 * windows inside the group.
8630 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8632 GList *toplevels, *toplevel, *group_windows;
8634 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8636 group_windows = NULL;
8637 toplevels = gtk_window_list_toplevels ();
8639 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8641 GtkWindow *window = toplevel->data;
8643 if (window_group == window->priv->group)
8644 group_windows = g_list_prepend (group_windows, window);
8647 return g_list_reverse (group_windows);
8651 * gtk_window_get_group:
8652 * @window: (allow-none): a #GtkWindow, or %NULL
8654 * Returns the group for @window or the default group, if
8655 * @window is %NULL or if @window does not have an explicit
8658 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8663 gtk_window_get_group (GtkWindow *window)
8665 if (window && window->priv->group)
8666 return window->priv->group;
8669 static GtkWindowGroup *default_group = NULL;
8672 default_group = gtk_window_group_new ();
8674 return default_group;
8679 * gtk_window_has_group:
8680 * @window: a #GtkWindow
8682 * Returns whether @window has an explicit window group.
8684 * Return value: %TRUE if @window has an explicit window group.
8689 gtk_window_has_group (GtkWindow *window)
8691 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8693 return window->priv->group != NULL;
8697 * gtk_window_group_get_current_grab:
8698 * @window_group: a #GtkWindowGroup
8700 * Gets the current grab widget of the given group,
8701 * see gtk_grab_add().
8703 * Returns: the current grab widget of the group
8708 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8710 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8712 if (window_group->grabs)
8713 return GTK_WIDGET (window_group->grabs->data);
8718 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8721 gboolean block_others)
8723 GtkWindowGroupPrivate *priv;
8724 GtkDeviceGrabInfo *info;
8726 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8728 info = g_slice_new0 (GtkDeviceGrabInfo);
8729 info->widget = widget;
8730 info->device = device;
8731 info->block_others = block_others;
8733 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8737 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8741 GtkWindowGroupPrivate *priv;
8742 GtkDeviceGrabInfo *info;
8743 GSList *list, *node = NULL;
8744 GdkDevice *other_device;
8746 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8747 other_device = gdk_device_get_associated_device (device);
8748 list = priv->device_grabs;
8754 if (info->widget == widget &&
8755 (info->device == device ||
8756 info->device == other_device))
8769 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8770 g_slice_free (GtkDeviceGrabInfo, info);
8775 * gtk_window_group_get_current_device_grab:
8776 * @window_group: a #GtkWindowGroup
8777 * @device: a #GdkDevice
8779 * Returns the current grab widget for @device, or %NULL if none.
8781 * Returns: The grab widget, or %NULL
8786 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8789 GtkWindowGroupPrivate *priv;
8790 GtkDeviceGrabInfo *info;
8791 GdkDevice *other_device;
8794 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8795 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8797 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8798 list = priv->device_grabs;
8799 other_device = gdk_device_get_associated_device (device);
8806 if (info->device == device ||
8807 info->device == other_device)
8808 return info->widget;
8815 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8819 GtkWindowGroupPrivate *priv;
8820 GtkDeviceGrabInfo *info;
8821 GdkDevice *other_device;
8824 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8825 other_device = gdk_device_get_associated_device (device);
8826 list = priv->device_grabs;
8833 /* Look for blocking grabs on other device pairs
8834 * that have the passed widget within the GTK+ grab.
8836 if (info->block_others &&
8837 info->device != device &&
8838 info->device != other_device &&
8839 (info->widget == widget ||
8840 gtk_widget_is_ancestor (widget, info->widget)))
8848 Derived from XParseGeometry() in XFree86
8850 Copyright 1985, 1986, 1987,1998 The Open Group
8852 All Rights Reserved.
8854 The above copyright notice and this permission notice shall be included
8855 in all copies or substantial portions of the Software.
8857 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8858 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8859 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8860 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8861 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8862 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8863 OTHER DEALINGS IN THE SOFTWARE.
8865 Except as contained in this notice, the name of The Open Group shall
8866 not be used in advertising or otherwise to promote the sale, use or
8867 other dealings in this Software without prior written authorization
8868 from The Open Group.
8873 * XParseGeometry parses strings of the form
8874 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8875 * width, height, xoffset, and yoffset are unsigned integers.
8876 * Example: "=80x24+300-49"
8877 * The equal sign is optional.
8878 * It returns a bitmask that indicates which of the four values
8879 * were actually found in the string. For each value found,
8880 * the corresponding argument is updated; for each value
8881 * not found, the corresponding argument is left unchanged.
8884 /* The following code is from Xlib, and is minimally modified, so we
8885 * can track any upstream changes if required. Don't change this
8886 * code. Or if you do, put in a huge comment marking which thing
8891 read_int (gchar *string,
8899 else if (*string == '-')
8905 for (; (*string >= '0') && (*string <= '9'); string++)
8907 result = (result * 10) + (*string - '0');
8919 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8920 * value (x, y, width, height) was found in the parsed string.
8922 #define NoValue 0x0000
8923 #define XValue 0x0001
8924 #define YValue 0x0002
8925 #define WidthValue 0x0004
8926 #define HeightValue 0x0008
8927 #define AllValues 0x000F
8928 #define XNegative 0x0010
8929 #define YNegative 0x0020
8931 /* Try not to reformat/modify, so we can compare/sync with X sources */
8933 gtk_XParseGeometry (const char *string,
8936 unsigned int *width,
8937 unsigned int *height)
8941 unsigned int tempWidth, tempHeight;
8943 char *nextCharacter;
8945 /* These initializations are just to silence gcc */
8951 if ( (string == NULL) || (*string == '\0')) return(mask);
8953 string++; /* ignore possible '=' at beg of geometry spec */
8955 strind = (char *)string;
8956 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8957 tempWidth = read_int(strind, &nextCharacter);
8958 if (strind == nextCharacter)
8960 strind = nextCharacter;
8964 if (*strind == 'x' || *strind == 'X') {
8966 tempHeight = read_int(strind, &nextCharacter);
8967 if (strind == nextCharacter)
8969 strind = nextCharacter;
8970 mask |= HeightValue;
8973 if ((*strind == '+') || (*strind == '-')) {
8974 if (*strind == '-') {
8976 tempX = -read_int(strind, &nextCharacter);
8977 if (strind == nextCharacter)
8979 strind = nextCharacter;
8985 tempX = read_int(strind, &nextCharacter);
8986 if (strind == nextCharacter)
8988 strind = nextCharacter;
8991 if ((*strind == '+') || (*strind == '-')) {
8992 if (*strind == '-') {
8994 tempY = -read_int(strind, &nextCharacter);
8995 if (strind == nextCharacter)
8997 strind = nextCharacter;
9004 tempY = read_int(strind, &nextCharacter);
9005 if (strind == nextCharacter)
9007 strind = nextCharacter;
9013 /* If strind isn't at the end of the string the it's an invalid
9014 geometry specification. */
9016 if (*strind != '\0') return (0);
9022 if (mask & WidthValue)
9024 if (mask & HeightValue)
9025 *height = tempHeight;
9030 * gtk_window_parse_geometry:
9031 * @window: a #GtkWindow
9032 * @geometry: geometry string
9034 * Parses a standard X Window System geometry string - see the
9035 * manual page for X (type 'man X') for details on this.
9036 * gtk_window_parse_geometry() does work on all GTK+ ports
9037 * including Win32 but is primarily intended for an X environment.
9039 * If either a size or a position can be extracted from the
9040 * geometry string, gtk_window_parse_geometry() returns %TRUE
9041 * and calls gtk_window_set_default_size() and/or gtk_window_move()
9042 * to resize/move the window.
9044 * If gtk_window_parse_geometry() returns %TRUE, it will also
9045 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9046 * indicating to the window manager that the size/position of
9047 * the window was user-specified. This causes most window
9048 * managers to honor the geometry.
9050 * Note that for gtk_window_parse_geometry() to work as expected, it has
9051 * to be called when the window has its "final" size, i.e. after calling
9052 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9055 * #include <gtk/gtk.h>
9058 * fill_with_content (GtkWidget *vbox)
9060 * /* fill with content... */
9064 * main (int argc, char *argv[])
9066 * GtkWidget *window, *vbox;
9067 * GdkGeometry size_hints = {
9068 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
9071 * gtk_init (&argc, &argv);
9073 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9074 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9076 * gtk_container_add (GTK_CONTAINER (window), vbox);
9077 * fill_with_content (vbox);
9078 * gtk_widget_show_all (vbox);
9080 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
9083 * GDK_HINT_MIN_SIZE |
9084 * GDK_HINT_BASE_SIZE |
9085 * GDK_HINT_RESIZE_INC);
9089 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9090 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9093 * gtk_widget_show_all (window);
9100 * Return value: %TRUE if string was parsed successfully
9103 gtk_window_parse_geometry (GtkWindow *window,
9104 const gchar *geometry)
9106 gint result, x = 0, y = 0;
9110 gboolean size_set, pos_set;
9113 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9114 g_return_val_if_fail (geometry != NULL, FALSE);
9116 child = gtk_bin_get_child (GTK_BIN (window));
9117 if (!child || !gtk_widget_get_visible (child))
9118 g_warning ("gtk_window_parse_geometry() called on a window with no "
9119 "visible children; the window should be set up before "
9120 "gtk_window_parse_geometry() is called.");
9122 screen = gtk_window_check_screen (window);
9124 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9127 if ((result & WidthValue) || (result & HeightValue))
9129 gtk_window_set_default_size_internal (window,
9130 TRUE, result & WidthValue ? w : -1,
9131 TRUE, result & HeightValue ? h : -1,
9136 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9138 grav = GDK_GRAVITY_NORTH_WEST;
9140 if ((result & XNegative) && (result & YNegative))
9141 grav = GDK_GRAVITY_SOUTH_EAST;
9142 else if (result & XNegative)
9143 grav = GDK_GRAVITY_NORTH_EAST;
9144 else if (result & YNegative)
9145 grav = GDK_GRAVITY_SOUTH_WEST;
9147 if ((result & XValue) == 0)
9150 if ((result & YValue) == 0)
9153 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9154 grav == GDK_GRAVITY_SOUTH_EAST)
9155 y = gdk_screen_get_height (screen) - h + y;
9157 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9158 grav == GDK_GRAVITY_NORTH_EAST)
9159 x = gdk_screen_get_width (screen) - w + x;
9161 /* we don't let you put a window offscreen; maybe some people would
9162 * prefer to be able to, but it's kind of a bogus thing to do.
9171 if ((result & XValue) || (result & YValue))
9173 gtk_window_set_gravity (window, grav);
9174 gtk_window_move (window, x, y);
9178 if (size_set || pos_set)
9180 /* Set USSize, USPosition hints */
9181 GtkWindowGeometryInfo *info;
9183 info = gtk_window_get_geometry_info (window, TRUE);
9186 info->mask |= GDK_HINT_USER_POS;
9188 info->mask |= GDK_HINT_USER_SIZE;
9195 gtk_window_mnemonic_hash_foreach (guint keyval,
9201 GtkWindowKeysForeachFunc func;
9205 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9209 _gtk_window_keys_foreach (GtkWindow *window,
9210 GtkWindowKeysForeachFunc func,
9214 GtkMnemonicHash *mnemonic_hash;
9218 GtkWindowKeysForeachFunc func;
9222 info.window = window;
9224 info.func_data = func_data;
9226 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9228 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9229 gtk_window_mnemonic_hash_foreach, &info);
9231 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9234 GtkAccelGroup *group = groups->data;
9237 for (i = 0; i < group->priv->n_accels; i++)
9239 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9242 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9245 groups = groups->next;
9250 gtk_window_keys_changed (GtkWindow *window)
9252 gtk_window_free_key_hash (window);
9253 gtk_window_get_key_hash (window);
9256 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9258 struct _GtkWindowKeyEntry
9262 guint is_mnemonic : 1;
9266 window_key_entry_destroy (gpointer data)
9268 g_slice_free (GtkWindowKeyEntry, data);
9272 add_to_key_hash (GtkWindow *window,
9274 GdkModifierType modifiers,
9275 gboolean is_mnemonic,
9278 GtkKeyHash *key_hash = data;
9280 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9282 entry->keyval = keyval;
9283 entry->modifiers = modifiers;
9284 entry->is_mnemonic = is_mnemonic;
9286 /* GtkAccelGroup stores lowercased accelerators. To deal
9287 * with this, if <Shift> was specified, uppercase.
9289 if (modifiers & GDK_SHIFT_MASK)
9291 if (keyval == GDK_KEY_Tab)
9292 keyval = GDK_KEY_ISO_Left_Tab;
9294 keyval = gdk_keyval_to_upper (keyval);
9297 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9301 gtk_window_get_key_hash (GtkWindow *window)
9303 GdkScreen *screen = gtk_window_check_screen (window);
9304 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9309 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9310 (GDestroyNotify)window_key_entry_destroy);
9311 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9312 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9318 gtk_window_free_key_hash (GtkWindow *window)
9320 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9323 _gtk_key_hash_free (key_hash);
9324 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9329 * gtk_window_activate_key:
9330 * @window: a #GtkWindow
9331 * @event: a #GdkEventKey
9333 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9334 * called by the default ::key_press_event handler for toplevel windows,
9335 * however in some cases it may be useful to call this directly when
9336 * overriding the standard key handling for a toplevel window.
9338 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9343 gtk_window_activate_key (GtkWindow *window,
9346 GtkKeyHash *key_hash;
9347 GtkWindowKeyEntry *found_entry = NULL;
9348 gboolean enable_mnemonics;
9349 gboolean enable_accels;
9351 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9352 g_return_val_if_fail (event != NULL, FALSE);
9354 key_hash = gtk_window_get_key_hash (window);
9359 GSList *entries = _gtk_key_hash_lookup (key_hash,
9360 event->hardware_keycode,
9362 gtk_accelerator_get_default_mod_mask (),
9365 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9366 "gtk-enable-mnemonics", &enable_mnemonics,
9367 "gtk-enable-accels", &enable_accels,
9370 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9372 GtkWindowKeyEntry *entry = tmp_list->data;
9373 if (entry->is_mnemonic)
9375 if (enable_mnemonics)
9377 found_entry = entry;
9383 if (enable_accels && !found_entry)
9385 found_entry = entry;
9390 g_slist_free (entries);
9395 if (found_entry->is_mnemonic)
9397 if (enable_mnemonics)
9398 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9399 found_entry->modifiers);
9404 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9405 found_entry->modifiers);
9413 window_update_has_focus (GtkWindow *window)
9415 GtkWindowPrivate *priv = window->priv;
9416 GtkWidget *widget = GTK_WIDGET (window);
9417 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9419 if (has_focus != priv->has_focus)
9421 priv->has_focus = has_focus;
9425 if (priv->focus_widget &&
9426 priv->focus_widget != widget &&
9427 !gtk_widget_has_focus (priv->focus_widget))
9428 do_focus_change (priv->focus_widget, TRUE);
9432 if (priv->focus_widget &&
9433 priv->focus_widget != widget &&
9434 gtk_widget_has_focus (priv->focus_widget))
9435 do_focus_change (priv->focus_widget, FALSE);
9441 * _gtk_window_set_is_active:
9442 * @window: a #GtkWindow
9443 * @is_active: %TRUE if the window is in the currently active toplevel
9445 * Internal function that sets whether the #GtkWindow is part
9446 * of the currently active toplevel window (taking into account inter-process
9450 _gtk_window_set_is_active (GtkWindow *window,
9453 GtkWindowPrivate *priv;
9455 g_return_if_fail (GTK_IS_WINDOW (window));
9457 priv = window->priv;
9459 is_active = is_active != FALSE;
9461 if (is_active != priv->is_active)
9463 priv->is_active = is_active;
9464 window_update_has_focus (window);
9466 g_object_notify (G_OBJECT (window), "is-active");
9471 * _gtk_window_set_is_toplevel:
9472 * @window: a #GtkWindow
9473 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9474 * parent of the root window); %FALSE if it is not (for example, for an
9475 * in-process, parented GtkPlug)
9477 * Internal function used by #GtkPlug when it gets parented/unparented by a
9478 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9479 * global list of toplevel windows.
9482 _gtk_window_set_is_toplevel (GtkWindow *window,
9483 gboolean is_toplevel)
9487 widget = GTK_WIDGET (window);
9489 if (gtk_widget_is_toplevel (widget))
9490 g_assert (g_slist_find (toplevel_list, window) != NULL);
9492 g_assert (g_slist_find (toplevel_list, window) == NULL);
9494 if (is_toplevel == gtk_widget_is_toplevel (widget))
9499 _gtk_widget_set_is_toplevel (widget, TRUE);
9500 toplevel_list = g_slist_prepend (toplevel_list, window);
9504 _gtk_widget_set_is_toplevel (widget, FALSE);
9505 toplevel_list = g_slist_remove (toplevel_list, window);
9510 * _gtk_window_set_has_toplevel_focus:
9511 * @window: a #GtkWindow
9512 * @has_toplevel_focus: %TRUE if the in
9514 * Internal function that sets whether the keyboard focus for the
9515 * toplevel window (taking into account inter-process embedding.)
9518 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9519 gboolean has_toplevel_focus)
9521 GtkWindowPrivate *priv;
9523 g_return_if_fail (GTK_IS_WINDOW (window));
9525 priv = window->priv;
9527 has_toplevel_focus = has_toplevel_focus != FALSE;
9529 if (has_toplevel_focus != priv->has_toplevel_focus)
9531 priv->has_toplevel_focus = has_toplevel_focus;
9532 window_update_has_focus (window);
9534 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9539 * gtk_window_set_auto_startup_notification:
9540 * @setting: %TRUE to automatically do startup notification
9542 * By default, after showing the first #GtkWindow, GTK+ calls
9543 * gdk_notify_startup_complete(). Call this function to disable
9544 * the automatic startup notification. You might do this if your
9545 * first window is a splash screen, and you want to delay notification
9546 * until after your real main window has been shown, for example.
9548 * In that example, you would disable startup notification
9549 * temporarily, show your splash screen, then re-enable it so that
9550 * showing the main window would automatically result in notification.
9555 gtk_window_set_auto_startup_notification (gboolean setting)
9557 disable_startup_notification = !setting;
9561 * gtk_window_get_window_type:
9562 * @window: a #GtkWindow
9564 * Gets the type of the window. See #GtkWindowType.
9566 * Return value: the type of the window
9571 gtk_window_get_window_type (GtkWindow *window)
9573 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9575 return window->priv->type;
9579 * gtk_window_get_mnemonics_visible:
9580 * @window: a #GtkWindow
9582 * Gets the value of the #GtkWindow:mnemonics-visible property.
9584 * Returns: %TRUE if mnemonics are supposed to be visible
9590 gtk_window_get_mnemonics_visible (GtkWindow *window)
9592 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9594 return window->priv->mnemonics_visible;
9598 * gtk_window_set_mnemonics_visible:
9599 * @window: a #GtkWindow
9600 * @setting: the new value
9602 * Sets the #GtkWindow:mnemonics-visible property.
9607 gtk_window_set_mnemonics_visible (GtkWindow *window,
9610 GtkWindowPrivate *priv;
9612 g_return_if_fail (GTK_IS_WINDOW (window));
9614 priv = window->priv;
9616 setting = setting != FALSE;
9618 if (priv->mnemonics_visible != setting)
9620 priv->mnemonics_visible = setting;
9621 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9624 priv->mnemonics_visible_set = TRUE;
9628 _gtk_window_get_wmclass (GtkWindow *window,
9629 gchar **wmclass_name,
9630 gchar **wmclass_class)
9632 GtkWindowPrivate *priv = window->priv;
9634 *wmclass_name = priv->wmclass_name;
9635 *wmclass_class = priv->wmclass_class;