1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
33 #include "gdk/gdkkeysyms.h"
37 #include "gtkprivate.h"
39 #include "gtkwindow.h"
40 #include "gtkwindow-decorate.h"
41 #include "gtkbindings.h"
42 #include "gtkkeyhash.h"
44 #include "gtkmnemonichash.h"
45 #include "gtkiconfactory.h"
46 #include "gtkicontheme.h"
47 #include "gtkmarshalers.h"
49 #include "gtkbuildable.h"
52 #ifdef GDK_WINDOWING_X11
81 PROP_DESTROY_WITH_PARENT,
86 PROP_SKIP_TASKBAR_HINT,
97 /* Readonly properties */
99 PROP_HAS_TOPLEVEL_FOCUS,
101 /* Writeonly properties */
110 GdkPixmap *icon_pixmap;
111 GdkPixmap *icon_mask;
114 guint using_default_icon : 1;
115 guint using_parent_icon : 1;
116 guint using_themed_icon : 1;
120 GdkGeometry geometry; /* Last set of geometry hints we set */
121 GdkWindowHints flags;
122 GdkRectangle configure_request;
123 } GtkWindowLastGeometryInfo;
125 struct _GtkWindowGeometryInfo
127 /* Properties that the app has set on the window
129 GdkGeometry geometry; /* Geometry hints */
131 GtkWidget *widget; /* subwidget to which hints apply */
132 /* from last gtk_window_resize () - if > 0, indicates that
133 * we should resize to this size.
138 /* From last gtk_window_move () prior to mapping -
139 * only used if initial_pos_set
144 /* Default size - used only the FIRST time we map a window,
149 /* whether to use initial_x, initial_y */
150 guint initial_pos_set : 1;
151 /* CENTER_ALWAYS or other position constraint changed since
152 * we sent the last configure request.
154 guint position_constraints_changed : 1;
156 /* if true, default_width, height come from gtk_window_parse_geometry,
157 * and thus should be multiplied by the increments and affect the
158 * geometry widget only
160 guint default_is_geometry : 1;
162 GtkWindowLastGeometryInfo last;
165 #define GTK_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW, GtkWindowPrivate))
167 typedef struct _GtkWindowPrivate GtkWindowPrivate;
169 struct _GtkWindowPrivate
171 GtkMnemonicHash *mnemonic_hash;
173 guint above_initially : 1;
174 guint below_initially : 1;
175 guint fullscreen_initially : 1;
176 guint skips_taskbar : 1;
177 guint skips_pager : 1;
179 guint accept_focus : 1;
180 guint focus_on_map : 1;
182 guint transient_parent_group : 1;
184 guint reset_type_hint : 1;
185 guint opacity_set : 1;
186 guint builder_visible : 1;
188 GdkWindowTypeHint type_hint;
195 static void gtk_window_dispose (GObject *object);
196 static void gtk_window_destroy (GtkObject *object);
197 static void gtk_window_finalize (GObject *object);
198 static void gtk_window_show (GtkWidget *widget);
199 static void gtk_window_hide (GtkWidget *widget);
200 static void gtk_window_map (GtkWidget *widget);
201 static void gtk_window_unmap (GtkWidget *widget);
202 static void gtk_window_realize (GtkWidget *widget);
203 static void gtk_window_unrealize (GtkWidget *widget);
204 static void gtk_window_size_request (GtkWidget *widget,
205 GtkRequisition *requisition);
206 static void gtk_window_size_allocate (GtkWidget *widget,
207 GtkAllocation *allocation);
208 static gint gtk_window_event (GtkWidget *widget,
210 static gboolean gtk_window_map_event (GtkWidget *widget,
212 static gboolean gtk_window_frame_event (GtkWindow *window,
214 static gint gtk_window_configure_event (GtkWidget *widget,
215 GdkEventConfigure *event);
216 static gint gtk_window_key_press_event (GtkWidget *widget,
218 static gint gtk_window_key_release_event (GtkWidget *widget,
220 static gint gtk_window_enter_notify_event (GtkWidget *widget,
221 GdkEventCrossing *event);
222 static gint gtk_window_leave_notify_event (GtkWidget *widget,
223 GdkEventCrossing *event);
224 static gint gtk_window_focus_in_event (GtkWidget *widget,
225 GdkEventFocus *event);
226 static gint gtk_window_focus_out_event (GtkWidget *widget,
227 GdkEventFocus *event);
228 static gint gtk_window_client_event (GtkWidget *widget,
229 GdkEventClient *event);
230 static void gtk_window_check_resize (GtkContainer *container);
231 static gint gtk_window_focus (GtkWidget *widget,
232 GtkDirectionType direction);
233 static void gtk_window_real_set_focus (GtkWindow *window,
236 static void gtk_window_real_activate_default (GtkWindow *window);
237 static void gtk_window_real_activate_focus (GtkWindow *window);
238 static void gtk_window_move_focus (GtkWindow *window,
239 GtkDirectionType dir);
240 static void gtk_window_keys_changed (GtkWindow *window);
241 static void gtk_window_paint (GtkWidget *widget,
243 static gint gtk_window_expose (GtkWidget *widget,
244 GdkEventExpose *event);
245 static void gtk_window_unset_transient_for (GtkWindow *window);
246 static void gtk_window_transient_parent_realized (GtkWidget *parent,
248 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
251 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
253 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
256 static void gtk_window_move_resize (GtkWindow *window);
257 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
259 GdkGeometry *geometry_b,
261 static void gtk_window_constrain_size (GtkWindow *window,
262 GdkGeometry *geometry,
268 static void gtk_window_constrain_position (GtkWindow *window,
273 static void gtk_window_compute_hints (GtkWindow *window,
274 GdkGeometry *new_geometry,
276 static void gtk_window_compute_configure_request (GtkWindow *window,
277 GdkRectangle *request,
278 GdkGeometry *geometry,
281 static void gtk_window_set_default_size_internal (GtkWindow *window,
282 gboolean change_width,
284 gboolean change_height,
286 gboolean is_geometry);
288 static void update_themed_icon (GtkIconTheme *theme,
290 static GList *icon_list_from_theme (GtkWidget *widget,
292 static void gtk_window_realize_icon (GtkWindow *window);
293 static void gtk_window_unrealize_icon (GtkWindow *window);
295 static void gtk_window_notify_keys_changed (GtkWindow *window);
296 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
297 static void gtk_window_free_key_hash (GtkWindow *window);
298 static void gtk_window_on_composited_changed (GdkScreen *screen,
301 static GSList *toplevel_list = NULL;
302 static guint window_signals[LAST_SIGNAL] = { 0 };
303 static GList *default_icon_list = NULL;
304 static gchar *default_icon_name = NULL;
305 static guint default_icon_serial = 0;
306 static gboolean disable_startup_notification = FALSE;
307 static gboolean sent_startup_notification = FALSE;
309 static GQuark quark_gtk_embedded = 0;
310 static GQuark quark_gtk_window_key_hash = 0;
311 static GQuark quark_gtk_window_default_icon_pixmap = 0;
312 static GQuark quark_gtk_window_icon_info = 0;
313 static GQuark quark_gtk_buildable_accels = 0;
315 static GtkBuildableIface *parent_buildable_iface;
317 static void gtk_window_set_property (GObject *object,
321 static void gtk_window_get_property (GObject *object,
327 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
328 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
331 const GValue *value);
332 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
333 GtkBuilder *builder);
334 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
337 const gchar *tagname,
338 GMarkupParser *parser,
340 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
343 const gchar *tagname,
347 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
348 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
349 gtk_window_buildable_interface_init))
352 add_tab_bindings (GtkBindingSet *binding_set,
353 GdkModifierType modifiers,
354 GtkDirectionType direction)
356 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
358 GTK_TYPE_DIRECTION_TYPE, direction);
359 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
361 GTK_TYPE_DIRECTION_TYPE, direction);
365 add_arrow_bindings (GtkBindingSet *binding_set,
367 GtkDirectionType direction)
369 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
371 gtk_binding_entry_add_signal (binding_set, keysym, 0,
373 GTK_TYPE_DIRECTION_TYPE, direction);
374 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
376 GTK_TYPE_DIRECTION_TYPE, direction);
377 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
379 GTK_TYPE_DIRECTION_TYPE, direction);
380 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
382 GTK_TYPE_DIRECTION_TYPE, direction);
386 extract_time_from_startup_id (const gchar* startup_id)
388 gchar *timestr = g_strrstr (startup_id, "_TIME");
389 guint32 retval = GDK_CURRENT_TIME;
396 /* Skip past the "_TIME" part */
400 timestamp = strtoul (timestr, &end, 0);
401 if (end != timestr && errno == 0)
409 startup_id_is_fake (const gchar* startup_id)
411 return strncmp (startup_id, "_TIME", 5) == 0;
415 gtk_window_class_init (GtkWindowClass *klass)
417 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
418 GtkObjectClass *object_class;
419 GtkWidgetClass *widget_class;
420 GtkContainerClass *container_class;
421 GtkBindingSet *binding_set;
423 object_class = (GtkObjectClass*) klass;
424 widget_class = (GtkWidgetClass*) klass;
425 container_class = (GtkContainerClass*) klass;
427 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
428 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
429 quark_gtk_window_default_icon_pixmap = g_quark_from_static_string ("gtk-window-default-icon-pixmap");
430 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
431 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
433 gobject_class->dispose = gtk_window_dispose;
434 gobject_class->finalize = gtk_window_finalize;
436 gobject_class->set_property = gtk_window_set_property;
437 gobject_class->get_property = gtk_window_get_property;
439 object_class->destroy = gtk_window_destroy;
441 widget_class->show = gtk_window_show;
442 widget_class->hide = gtk_window_hide;
443 widget_class->map = gtk_window_map;
444 widget_class->map_event = gtk_window_map_event;
445 widget_class->unmap = gtk_window_unmap;
446 widget_class->realize = gtk_window_realize;
447 widget_class->unrealize = gtk_window_unrealize;
448 widget_class->size_request = gtk_window_size_request;
449 widget_class->size_allocate = gtk_window_size_allocate;
450 widget_class->configure_event = gtk_window_configure_event;
451 widget_class->key_press_event = gtk_window_key_press_event;
452 widget_class->key_release_event = gtk_window_key_release_event;
453 widget_class->enter_notify_event = gtk_window_enter_notify_event;
454 widget_class->leave_notify_event = gtk_window_leave_notify_event;
455 widget_class->focus_in_event = gtk_window_focus_in_event;
456 widget_class->focus_out_event = gtk_window_focus_out_event;
457 widget_class->client_event = gtk_window_client_event;
458 widget_class->focus = gtk_window_focus;
460 widget_class->expose_event = gtk_window_expose;
462 container_class->check_resize = gtk_window_check_resize;
464 klass->set_focus = gtk_window_real_set_focus;
465 klass->frame_event = gtk_window_frame_event;
467 klass->activate_default = gtk_window_real_activate_default;
468 klass->activate_focus = gtk_window_real_activate_focus;
469 klass->move_focus = gtk_window_move_focus;
470 klass->keys_changed = gtk_window_keys_changed;
472 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
475 g_object_class_install_property (gobject_class,
477 g_param_spec_enum ("type",
479 P_("The type of the window"),
480 GTK_TYPE_WINDOW_TYPE,
482 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
484 g_object_class_install_property (gobject_class,
486 g_param_spec_string ("title",
488 P_("The title of the window"),
490 GTK_PARAM_READWRITE));
492 g_object_class_install_property (gobject_class,
494 g_param_spec_string ("role",
496 P_("Unique identifier for the window to be used when restoring a session"),
498 GTK_PARAM_READWRITE));
501 * GtkWindow:startup-id:
503 * The :startup-id is a write-only property for setting window's
504 * startup notification identifier. See gtk_window_set_startup_id()
509 g_object_class_install_property (gobject_class,
511 g_param_spec_string ("startup-id",
513 P_("Unique startup identifier for the window used by startup-notification"),
515 GTK_PARAM_WRITABLE));
517 g_object_class_install_property (gobject_class,
519 g_param_spec_boolean ("allow-shrink",
521 /* xgettext:no-c-format */
522 P_("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
524 GTK_PARAM_READWRITE));
526 g_object_class_install_property (gobject_class,
528 g_param_spec_boolean ("allow-grow",
530 P_("If TRUE, users can expand the window beyond its minimum size"),
532 GTK_PARAM_READWRITE));
534 g_object_class_install_property (gobject_class,
536 g_param_spec_boolean ("resizable",
538 P_("If TRUE, users can resize the window"),
540 GTK_PARAM_READWRITE));
542 g_object_class_install_property (gobject_class,
544 g_param_spec_boolean ("modal",
546 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
548 GTK_PARAM_READWRITE));
550 g_object_class_install_property (gobject_class,
552 g_param_spec_enum ("window-position",
553 P_("Window Position"),
554 P_("The initial position of the window"),
555 GTK_TYPE_WINDOW_POSITION,
557 GTK_PARAM_READWRITE));
559 g_object_class_install_property (gobject_class,
561 g_param_spec_int ("default-width",
563 P_("The default width of the window, used when initially showing the window"),
567 GTK_PARAM_READWRITE));
569 g_object_class_install_property (gobject_class,
571 g_param_spec_int ("default-height",
572 P_("Default Height"),
573 P_("The default height of the window, used when initially showing the window"),
577 GTK_PARAM_READWRITE));
579 g_object_class_install_property (gobject_class,
580 PROP_DESTROY_WITH_PARENT,
581 g_param_spec_boolean ("destroy-with-parent",
582 P_("Destroy with Parent"),
583 P_("If this window should be destroyed when the parent is destroyed"),
585 GTK_PARAM_READWRITE));
587 g_object_class_install_property (gobject_class,
589 g_param_spec_object ("icon",
591 P_("Icon for this window"),
593 GTK_PARAM_READWRITE));
596 * GtkWindow:icon-name:
598 * The :icon-name property specifies the name of the themed icon to
599 * use as the window icon. See #GtkIconTheme for more details.
603 g_object_class_install_property (gobject_class,
605 g_param_spec_string ("icon-name",
607 P_("Name of the themed icon for this window"),
609 GTK_PARAM_READWRITE));
611 g_object_class_install_property (gobject_class,
613 g_param_spec_object ("screen",
615 P_("The screen where this window will be displayed"),
617 GTK_PARAM_READWRITE));
619 g_object_class_install_property (gobject_class,
621 g_param_spec_boolean ("is-active",
623 P_("Whether the toplevel is the current active window"),
625 GTK_PARAM_READABLE));
627 g_object_class_install_property (gobject_class,
628 PROP_HAS_TOPLEVEL_FOCUS,
629 g_param_spec_boolean ("has-toplevel-focus",
630 P_("Focus in Toplevel"),
631 P_("Whether the input focus is within this GtkWindow"),
633 GTK_PARAM_READABLE));
635 g_object_class_install_property (gobject_class,
637 g_param_spec_enum ("type-hint",
639 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
640 GDK_TYPE_WINDOW_TYPE_HINT,
641 GDK_WINDOW_TYPE_HINT_NORMAL,
642 GTK_PARAM_READWRITE));
644 g_object_class_install_property (gobject_class,
645 PROP_SKIP_TASKBAR_HINT,
646 g_param_spec_boolean ("skip-taskbar-hint",
648 P_("TRUE if the window should not be in the task bar."),
650 GTK_PARAM_READWRITE));
652 g_object_class_install_property (gobject_class,
653 PROP_SKIP_PAGER_HINT,
654 g_param_spec_boolean ("skip-pager-hint",
656 P_("TRUE if the window should not be in the pager."),
658 GTK_PARAM_READWRITE));
660 g_object_class_install_property (gobject_class,
662 g_param_spec_boolean ("urgency-hint",
664 P_("TRUE if the window should be brought to the user's attention."),
666 GTK_PARAM_READWRITE));
669 * GtkWindow:accept-focus-hint:
671 * Whether the window should receive the input focus.
675 g_object_class_install_property (gobject_class,
677 g_param_spec_boolean ("accept-focus",
679 P_("TRUE if the window should receive the input focus."),
681 GTK_PARAM_READWRITE));
684 * GtkWindow:focus-on-map-hint:
686 * Whether the window should receive the input focus when mapped.
690 g_object_class_install_property (gobject_class,
692 g_param_spec_boolean ("focus-on-map",
694 P_("TRUE if the window should receive the input focus when mapped."),
696 GTK_PARAM_READWRITE));
699 * GtkWindow:decorated:
701 * Whether the window should be decorated by the window manager.
705 g_object_class_install_property (gobject_class,
707 g_param_spec_boolean ("decorated",
709 P_("Whether the window should be decorated by the window manager"),
711 GTK_PARAM_READWRITE));
714 * GtkWindow:deletable:
716 * Whether the window frame should have a close button.
720 g_object_class_install_property (gobject_class,
722 g_param_spec_boolean ("deletable",
724 P_("Whether the window frame should have a close button"),
726 GTK_PARAM_READWRITE));
732 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
733 * more details about window gravity.
737 g_object_class_install_property (gobject_class,
739 g_param_spec_enum ("gravity",
741 P_("The window gravity of the window"),
743 GDK_GRAVITY_NORTH_WEST,
744 GTK_PARAM_READWRITE));
748 * GtkWindow:transient-for:
750 * The transient parent of the window. See gtk_window_set_transient_for() for
751 * more details about transient windows.
755 g_object_class_install_property (gobject_class,
757 g_param_spec_object ("transient-for",
758 P_("Transient for Window"),
759 P_("The transient parent of the dialog"),
761 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
766 * The requested opacity of the window. See gtk_window_set_opacity() for
767 * more details about window opacity.
771 g_object_class_install_property (gobject_class,
773 g_param_spec_double ("opacity",
774 P_("Opacity for Window"),
775 P_("The opacity of the window, from 0 to 1"),
779 GTK_PARAM_READWRITE));
781 window_signals[SET_FOCUS] =
782 g_signal_new (I_("set-focus"),
783 G_TYPE_FROM_CLASS (gobject_class),
785 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
787 _gtk_marshal_VOID__OBJECT,
791 window_signals[FRAME_EVENT] =
792 g_signal_new (I_("frame-event"),
793 G_TYPE_FROM_CLASS (gobject_class),
795 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
796 _gtk_boolean_handled_accumulator, NULL,
797 _gtk_marshal_BOOLEAN__BOXED,
802 * GtkWindow::activate-focus:
803 * @window: the window which received the signal
805 * The ::activate-default signal is a
806 * <link linkend="keybinding-signals">keybinding signal</link>
807 * which gets emitted when the user activates the currently
808 * focused widget of @window.
810 window_signals[ACTIVATE_FOCUS] =
811 g_signal_new (I_("activate-focus"),
812 G_TYPE_FROM_CLASS (gobject_class),
813 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
814 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
816 _gtk_marshal_VOID__VOID,
821 * GtkWindow::activate-default:
822 * @window: the window which received the signal
824 * The ::activate-default signal is a
825 * <link linkend="keybinding-signals">keybinding signal</link>
826 * which gets emitted when the user activates the default widget
829 window_signals[ACTIVATE_DEFAULT] =
830 g_signal_new (I_("activate-default"),
831 G_TYPE_FROM_CLASS (gobject_class),
832 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
833 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
835 _gtk_marshal_VOID__VOID,
840 * GtkWindow::keys-changed:
841 * @window: the window which received the signal
843 * The ::keys-changed signal gets emitted when the set of accelerators
844 * or mnemonics that are associated with @window changes.
846 window_signals[KEYS_CHANGED] =
847 g_signal_new (I_("keys-changed"),
848 G_TYPE_FROM_CLASS (gobject_class),
850 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
852 _gtk_marshal_VOID__VOID,
860 binding_set = gtk_binding_set_by_class (klass);
862 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
863 "activate-focus", 0);
864 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
865 "activate-focus", 0);
867 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
868 "activate-default", 0);
869 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0,
870 "activate-default", 0);
871 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
872 "activate-default", 0);
874 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
875 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
876 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
877 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
879 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
880 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
881 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
882 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
886 gtk_window_init (GtkWindow *window)
888 GdkColormap *colormap;
889 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
891 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
892 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
894 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
896 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
898 window->title = NULL;
899 window->wmclass_name = g_strdup (g_get_prgname ());
900 window->wmclass_class = g_strdup (gdk_get_program_class ());
901 window->wm_role = NULL;
902 window->geometry_info = NULL;
903 window->type = GTK_WINDOW_TOPLEVEL;
904 window->focus_widget = NULL;
905 window->default_widget = NULL;
906 window->configure_request_count = 0;
907 window->allow_shrink = FALSE;
908 window->allow_grow = TRUE;
909 window->configure_notify_received = FALSE;
910 window->position = GTK_WIN_POS_NONE;
911 window->need_default_size = TRUE;
912 window->need_default_position = TRUE;
913 window->modal = FALSE;
914 window->frame = NULL;
915 window->has_frame = FALSE;
916 window->frame_left = 0;
917 window->frame_right = 0;
918 window->frame_top = 0;
919 window->frame_bottom = 0;
920 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
921 window->gravity = GDK_GRAVITY_NORTH_WEST;
922 window->decorated = TRUE;
923 window->mnemonic_modifier = GDK_MOD1_MASK;
924 window->screen = gdk_screen_get_default ();
926 priv->accept_focus = TRUE;
927 priv->focus_on_map = TRUE;
928 priv->deletable = TRUE;
929 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
931 priv->startup_id = NULL;
933 colormap = _gtk_widget_peek_colormap ();
935 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
937 g_object_ref_sink (window);
938 window->has_user_ref_count = TRUE;
939 toplevel_list = g_slist_prepend (toplevel_list, window);
941 gtk_decorated_window_init (window);
943 g_signal_connect (window->screen, "composited-changed",
944 G_CALLBACK (gtk_window_on_composited_changed), window);
948 gtk_window_set_property (GObject *object,
955 window = GTK_WINDOW (object);
960 window->type = g_value_get_enum (value);
963 gtk_window_set_title (window, g_value_get_string (value));
966 gtk_window_set_role (window, g_value_get_string (value));
968 case PROP_STARTUP_ID:
969 gtk_window_set_startup_id (window, g_value_get_string (value));
971 case PROP_ALLOW_SHRINK:
972 window->allow_shrink = g_value_get_boolean (value);
973 gtk_widget_queue_resize (GTK_WIDGET (window));
975 case PROP_ALLOW_GROW:
976 window->allow_grow = g_value_get_boolean (value);
977 gtk_widget_queue_resize (GTK_WIDGET (window));
978 g_object_notify (G_OBJECT (window), "resizable");
981 window->allow_grow = g_value_get_boolean (value);
982 gtk_widget_queue_resize (GTK_WIDGET (window));
983 g_object_notify (G_OBJECT (window), "allow-grow");
986 gtk_window_set_modal (window, g_value_get_boolean (value));
989 gtk_window_set_position (window, g_value_get_enum (value));
991 case PROP_DEFAULT_WIDTH:
992 gtk_window_set_default_size_internal (window,
993 TRUE, g_value_get_int (value),
996 case PROP_DEFAULT_HEIGHT:
997 gtk_window_set_default_size_internal (window,
999 TRUE, g_value_get_int (value), FALSE);
1001 case PROP_DESTROY_WITH_PARENT:
1002 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1005 gtk_window_set_icon (window,
1006 g_value_get_object (value));
1008 case PROP_ICON_NAME:
1009 gtk_window_set_icon_name (window, g_value_get_string (value));
1012 gtk_window_set_screen (window, g_value_get_object (value));
1014 case PROP_TYPE_HINT:
1015 gtk_window_set_type_hint (window,
1016 g_value_get_enum (value));
1018 case PROP_SKIP_TASKBAR_HINT:
1019 gtk_window_set_skip_taskbar_hint (window,
1020 g_value_get_boolean (value));
1022 case PROP_SKIP_PAGER_HINT:
1023 gtk_window_set_skip_pager_hint (window,
1024 g_value_get_boolean (value));
1026 case PROP_URGENCY_HINT:
1027 gtk_window_set_urgency_hint (window,
1028 g_value_get_boolean (value));
1030 case PROP_ACCEPT_FOCUS:
1031 gtk_window_set_accept_focus (window,
1032 g_value_get_boolean (value));
1034 case PROP_FOCUS_ON_MAP:
1035 gtk_window_set_focus_on_map (window,
1036 g_value_get_boolean (value));
1038 case PROP_DECORATED:
1039 gtk_window_set_decorated (window, g_value_get_boolean (value));
1041 case PROP_DELETABLE:
1042 gtk_window_set_deletable (window, g_value_get_boolean (value));
1045 gtk_window_set_gravity (window, g_value_get_enum (value));
1047 case PROP_TRANSIENT_FOR:
1048 gtk_window_set_transient_for (window, g_value_get_object (value));
1051 gtk_window_set_opacity (window, g_value_get_double (value));
1054 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1060 gtk_window_get_property (GObject *object,
1066 GtkWindowPrivate *priv;
1068 window = GTK_WINDOW (object);
1069 priv = GTK_WINDOW_GET_PRIVATE (window);
1073 GtkWindowGeometryInfo *info;
1075 g_value_set_enum (value, window->type);
1078 g_value_set_string (value, window->wm_role);
1081 g_value_set_string (value, window->title);
1083 case PROP_ALLOW_SHRINK:
1084 g_value_set_boolean (value, window->allow_shrink);
1086 case PROP_ALLOW_GROW:
1087 g_value_set_boolean (value, window->allow_grow);
1089 case PROP_RESIZABLE:
1090 g_value_set_boolean (value, window->allow_grow);
1093 g_value_set_boolean (value, window->modal);
1096 g_value_set_enum (value, window->position);
1098 case PROP_DEFAULT_WIDTH:
1099 info = gtk_window_get_geometry_info (window, FALSE);
1101 g_value_set_int (value, -1);
1103 g_value_set_int (value, info->default_width);
1105 case PROP_DEFAULT_HEIGHT:
1106 info = gtk_window_get_geometry_info (window, FALSE);
1108 g_value_set_int (value, -1);
1110 g_value_set_int (value, info->default_height);
1112 case PROP_DESTROY_WITH_PARENT:
1113 g_value_set_boolean (value, window->destroy_with_parent);
1116 g_value_set_object (value, gtk_window_get_icon (window));
1118 case PROP_ICON_NAME:
1119 g_value_set_string (value, gtk_window_get_icon_name (window));
1122 g_value_set_object (value, window->screen);
1124 case PROP_IS_ACTIVE:
1125 g_value_set_boolean (value, window->is_active);
1127 case PROP_HAS_TOPLEVEL_FOCUS:
1128 g_value_set_boolean (value, window->has_toplevel_focus);
1130 case PROP_TYPE_HINT:
1131 g_value_set_enum (value, priv->type_hint);
1133 case PROP_SKIP_TASKBAR_HINT:
1134 g_value_set_boolean (value,
1135 gtk_window_get_skip_taskbar_hint (window));
1137 case PROP_SKIP_PAGER_HINT:
1138 g_value_set_boolean (value,
1139 gtk_window_get_skip_pager_hint (window));
1141 case PROP_URGENCY_HINT:
1142 g_value_set_boolean (value,
1143 gtk_window_get_urgency_hint (window));
1145 case PROP_ACCEPT_FOCUS:
1146 g_value_set_boolean (value,
1147 gtk_window_get_accept_focus (window));
1149 case PROP_FOCUS_ON_MAP:
1150 g_value_set_boolean (value,
1151 gtk_window_get_focus_on_map (window));
1153 case PROP_DECORATED:
1154 g_value_set_boolean (value, gtk_window_get_decorated (window));
1156 case PROP_DELETABLE:
1157 g_value_set_boolean (value, gtk_window_get_deletable (window));
1160 g_value_set_enum (value, gtk_window_get_gravity (window));
1162 case PROP_TRANSIENT_FOR:
1163 g_value_set_object (value, gtk_window_get_transient_for (window));
1166 g_value_set_double (value, gtk_window_get_opacity (window));
1169 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1175 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1177 parent_buildable_iface = g_type_interface_peek_parent (iface);
1178 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1179 iface->parser_finished = gtk_window_buildable_parser_finished;
1180 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1181 iface->custom_finished = gtk_window_buildable_custom_finished;
1185 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1186 GtkBuilder *builder,
1188 const GValue *value)
1190 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (buildable);
1192 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1193 priv->builder_visible = TRUE;
1195 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1199 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1200 GtkBuilder *builder)
1202 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (buildable);
1206 if (priv->builder_visible)
1207 gtk_widget_show (GTK_WIDGET (buildable));
1209 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1210 for (l = accels; l; l = l->next)
1212 object = gtk_builder_get_object (builder, l->data);
1215 g_warning ("Unknown accel group %s specified in window %s",
1216 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1219 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1220 GTK_ACCEL_GROUP (object));
1224 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1226 parent_buildable_iface->parser_finished (buildable, builder);
1232 } GSListSubParserData;
1235 window_start_element (GMarkupParseContext *context,
1236 const gchar *element_name,
1237 const gchar **names,
1238 const gchar **values,
1243 GSListSubParserData *data = (GSListSubParserData*)user_data;
1245 if (strcmp (element_name, "group") == 0)
1247 for (i = 0; names[i]; i++)
1249 if (strcmp (names[i], "name") == 0)
1250 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1253 else if (strcmp (element_name, "accel-groups") == 0)
1256 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1261 static const GMarkupParser window_parser =
1263 window_start_element
1267 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1268 GtkBuilder *builder,
1270 const gchar *tagname,
1271 GMarkupParser *parser,
1274 GSListSubParserData *parser_data;
1276 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1277 tagname, parser, data))
1280 if (strcmp (tagname, "accel-groups") == 0)
1282 parser_data = g_slice_new0 (GSListSubParserData);
1283 parser_data->items = NULL;
1284 parser_data->object = G_OBJECT (buildable);
1286 *parser = window_parser;
1287 *data = parser_data;
1295 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1296 GtkBuilder *builder,
1298 const gchar *tagname,
1301 GSListSubParserData *data;
1303 parent_buildable_iface->custom_finished (buildable, builder, child,
1304 tagname, user_data);
1306 if (strcmp (tagname, "accel-groups") != 0)
1309 data = (GSListSubParserData*)user_data;
1311 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1312 data->items, (GDestroyNotify) g_slist_free);
1314 g_slice_free (GSListSubParserData, data);
1319 * @type: type of window
1321 * Creates a new #GtkWindow, which is a toplevel window that can
1322 * contain other widgets. Nearly always, the type of the window should
1323 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1324 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1325 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1326 * dialogs, though in some other toolkits dialogs are called "popups".
1327 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1328 * On X11, popup windows are not controlled by the <link
1329 * linkend="gtk-X11-arch">window manager</link>.
1331 * If you simply want an undecorated window (no window borders), use
1332 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1334 * Return value: a new #GtkWindow.
1337 gtk_window_new (GtkWindowType type)
1341 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1343 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1345 window->type = type;
1347 return GTK_WIDGET (window);
1351 * gtk_window_set_title:
1352 * @window: a #GtkWindow
1353 * @title: title of the window
1355 * Sets the title of the #GtkWindow. The title of a window will be
1356 * displayed in its title bar; on the X Window System, the title bar
1357 * is rendered by the <link linkend="gtk-X11-arch">window
1358 * manager</link>, so exactly how the title appears to users may vary
1359 * according to a user's exact configuration. The title should help a
1360 * user distinguish this window from other windows they may have
1361 * open. A good title might include the application name and current
1362 * document filename, for example.
1366 gtk_window_set_title (GtkWindow *window,
1371 g_return_if_fail (GTK_IS_WINDOW (window));
1373 new_title = g_strdup (title);
1374 g_free (window->title);
1375 window->title = new_title;
1377 if (GTK_WIDGET_REALIZED (window))
1379 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
1381 gtk_decorated_window_set_title (window, title);
1384 g_object_notify (G_OBJECT (window), "title");
1388 * gtk_window_get_title:
1389 * @window: a #GtkWindow
1391 * Retrieves the title of the window. See gtk_window_set_title().
1393 * Return value: the title of the window, or %NULL if none has
1394 * been set explicitely. The returned string is owned by the widget
1395 * and must not be modified or freed.
1397 G_CONST_RETURN gchar *
1398 gtk_window_get_title (GtkWindow *window)
1400 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1402 return window->title;
1406 * gtk_window_set_wmclass:
1407 * @window: a #GtkWindow
1408 * @wmclass_name: window name hint
1409 * @wmclass_class: window class hint
1411 * Don't use this function. It sets the X Window System "class" and
1412 * "name" hints for a window. According to the ICCCM, you should
1413 * always set these to the same value for all windows in an
1414 * application, and GTK+ sets them to that value by default, so calling
1415 * this function is sort of pointless. However, you may want to call
1416 * gtk_window_set_role() on each window in your application, for the
1417 * benefit of the session manager. Setting the role allows the window
1418 * manager to restore window positions when loading a saved session.
1422 gtk_window_set_wmclass (GtkWindow *window,
1423 const gchar *wmclass_name,
1424 const gchar *wmclass_class)
1426 g_return_if_fail (GTK_IS_WINDOW (window));
1428 g_free (window->wmclass_name);
1429 window->wmclass_name = g_strdup (wmclass_name);
1431 g_free (window->wmclass_class);
1432 window->wmclass_class = g_strdup (wmclass_class);
1434 if (GTK_WIDGET_REALIZED (window))
1435 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1439 * gtk_window_set_role:
1440 * @window: a #GtkWindow
1441 * @role: unique identifier for the window to be used when restoring a session
1443 * This function is only useful on X11, not with other GTK+ targets.
1445 * In combination with the window title, the window role allows a
1446 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1447 * same" window when an application is restarted. So for example you
1448 * might set the "toolbox" role on your app's toolbox window, so that
1449 * when the user restarts their session, the window manager can put
1450 * the toolbox back in the same place.
1452 * If a window already has a unique title, you don't need to set the
1453 * role, since the WM can use the title to identify the window when
1454 * restoring the session.
1458 gtk_window_set_role (GtkWindow *window,
1463 g_return_if_fail (GTK_IS_WINDOW (window));
1465 new_role = g_strdup (role);
1466 g_free (window->wm_role);
1467 window->wm_role = new_role;
1469 if (GTK_WIDGET_REALIZED (window))
1470 gdk_window_set_role (GTK_WIDGET (window)->window, window->wm_role);
1472 g_object_notify (G_OBJECT (window), "role");
1476 * gtk_window_set_startup_id:
1477 * @window: a #GtkWindow
1478 * @startup_id: a string with startup-notification identifier
1480 * Startup notification identifiers are used by desktop environment to
1481 * track application startup, to provide user feedback and other
1482 * features. This function changes the corresponding property on the
1483 * underlying GdkWindow. Normally, startup identifier is managed
1484 * automatically and you should only use this function in special cases
1485 * like transferring focus from other processes. You should use this
1486 * function before calling gtk_window_present() or any equivalent
1487 * function generating a window map event.
1489 * This function is only useful on X11, not with other GTK+ targets.
1494 gtk_window_set_startup_id (GtkWindow *window,
1495 const gchar *startup_id)
1497 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
1499 g_return_if_fail (GTK_IS_WINDOW (window));
1501 g_free (priv->startup_id);
1502 priv->startup_id = g_strdup (startup_id);
1504 if (GTK_WIDGET_REALIZED (window))
1506 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1508 #ifdef GDK_WINDOWING_X11
1509 if (timestamp != GDK_CURRENT_TIME)
1510 gdk_x11_window_set_user_time (GTK_WIDGET (window)->window, timestamp);
1513 /* Here we differentiate real and "fake" startup notification IDs,
1514 * constructed on purpose just to pass interaction timestamp
1516 if (startup_id_is_fake (priv->startup_id))
1517 gtk_window_present_with_time (window, timestamp);
1520 gdk_window_set_startup_id (GTK_WIDGET (window)->window,
1523 /* If window is mapped, terminate the startup-notification too */
1524 if (GTK_WIDGET_MAPPED (window) && !disable_startup_notification)
1525 gdk_notify_startup_complete_with_id (priv->startup_id);
1529 g_object_notify (G_OBJECT (window), "startup-id");
1533 * gtk_window_get_role:
1534 * @window: a #GtkWindow
1536 * Returns the role of the window. See gtk_window_set_role() for
1537 * further explanation.
1539 * Return value: the role of the window if set, or %NULL. The
1540 * returned is owned by the widget and must not be modified
1543 G_CONST_RETURN gchar *
1544 gtk_window_get_role (GtkWindow *window)
1546 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1548 return window->wm_role;
1552 * gtk_window_set_focus:
1553 * @window: a #GtkWindow
1554 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1555 * any focus widget for the toplevel window.
1557 * If @focus is not the current focus widget, and is focusable, sets
1558 * it as the focus widget for the window. If @focus is %NULL, unsets
1559 * the focus widget for this window. To set the focus to a particular
1560 * widget in the toplevel, it is usually more convenient to use
1561 * gtk_widget_grab_focus() instead of this function.
1564 gtk_window_set_focus (GtkWindow *window,
1567 g_return_if_fail (GTK_IS_WINDOW (window));
1570 g_return_if_fail (GTK_IS_WIDGET (focus));
1571 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1575 gtk_widget_grab_focus (focus);
1578 /* Clear the existing focus chain, so that when we focus into
1579 * the window again, we start at the beginnning.
1581 GtkWidget *widget = window->focus_widget;
1584 while (widget->parent)
1586 widget = widget->parent;
1587 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1591 _gtk_window_internal_set_focus (window, NULL);
1596 _gtk_window_internal_set_focus (GtkWindow *window,
1599 g_return_if_fail (GTK_IS_WINDOW (window));
1601 if ((window->focus_widget != focus) ||
1602 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1603 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1607 * gtk_window_set_default:
1608 * @window: a #GtkWindow
1609 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1610 * default widget for the toplevel.
1612 * The default widget is the widget that's activated when the user
1613 * presses Enter in a dialog (for example). This function sets or
1614 * unsets the default widget for a #GtkWindow about. When setting
1615 * (rather than unsetting) the default widget it's generally easier to
1616 * call gtk_widget_grab_focus() on the widget. Before making a widget
1617 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1618 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1621 gtk_window_set_default (GtkWindow *window,
1622 GtkWidget *default_widget)
1624 g_return_if_fail (GTK_IS_WINDOW (window));
1627 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1629 if (window->default_widget != default_widget)
1631 GtkWidget *old_default_widget = NULL;
1634 g_object_ref (default_widget);
1636 if (window->default_widget)
1638 old_default_widget = window->default_widget;
1640 if (window->focus_widget != window->default_widget ||
1641 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1642 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1643 gtk_widget_queue_draw (window->default_widget);
1646 window->default_widget = default_widget;
1648 if (window->default_widget)
1650 if (window->focus_widget == NULL ||
1651 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1652 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1653 gtk_widget_queue_draw (window->default_widget);
1656 if (old_default_widget)
1657 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1661 g_object_notify (G_OBJECT (default_widget), "has-default");
1662 g_object_unref (default_widget);
1668 * gtk_window_get_default_widget:
1669 * @window: a #GtkWindow
1671 * Returns the default widget for @window. See gtk_window_set_default()
1674 * Returns: the default widget, or %NULL if there is none.
1679 gtk_window_get_default_widget (GtkWindow *window)
1681 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1683 return window->default_widget;
1687 gtk_window_set_policy_internal (GtkWindow *window,
1688 gboolean allow_shrink,
1689 gboolean allow_grow,
1690 gboolean auto_shrink)
1692 window->allow_shrink = (allow_shrink != FALSE);
1693 window->allow_grow = (allow_grow != FALSE);
1695 g_object_freeze_notify (G_OBJECT (window));
1696 g_object_notify (G_OBJECT (window), "allow-shrink");
1697 g_object_notify (G_OBJECT (window), "allow-grow");
1698 g_object_notify (G_OBJECT (window), "resizable");
1699 g_object_thaw_notify (G_OBJECT (window));
1701 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
1705 gtk_window_set_policy (GtkWindow *window,
1706 gboolean allow_shrink,
1707 gboolean allow_grow,
1708 gboolean auto_shrink)
1710 g_return_if_fail (GTK_IS_WINDOW (window));
1712 gtk_window_set_policy_internal (window, allow_shrink, allow_grow, auto_shrink);
1716 handle_keys_changed (gpointer data)
1720 window = GTK_WINDOW (data);
1722 if (window->keys_changed_handler)
1724 g_source_remove (window->keys_changed_handler);
1725 window->keys_changed_handler = 0;
1728 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1734 gtk_window_notify_keys_changed (GtkWindow *window)
1736 if (!window->keys_changed_handler)
1737 window->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1741 * gtk_window_add_accel_group:
1742 * @window: window to attach accelerator group to
1743 * @accel_group: a #GtkAccelGroup
1745 * Associate @accel_group with @window, such that calling
1746 * gtk_accel_groups_activate() on @window will activate accelerators
1750 gtk_window_add_accel_group (GtkWindow *window,
1751 GtkAccelGroup *accel_group)
1753 g_return_if_fail (GTK_IS_WINDOW (window));
1754 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1756 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1757 g_signal_connect_object (accel_group, "accel-changed",
1758 G_CALLBACK (gtk_window_notify_keys_changed),
1759 window, G_CONNECT_SWAPPED);
1760 gtk_window_notify_keys_changed (window);
1764 * gtk_window_remove_accel_group:
1765 * @window: a #GtkWindow
1766 * @accel_group: a #GtkAccelGroup
1768 * Reverses the effects of gtk_window_add_accel_group().
1771 gtk_window_remove_accel_group (GtkWindow *window,
1772 GtkAccelGroup *accel_group)
1774 g_return_if_fail (GTK_IS_WINDOW (window));
1775 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1777 g_signal_handlers_disconnect_by_func (accel_group,
1778 gtk_window_notify_keys_changed,
1780 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1781 gtk_window_notify_keys_changed (window);
1784 static GtkMnemonicHash *
1785 gtk_window_get_mnemonic_hash (GtkWindow *window,
1788 GtkWindowPrivate *private = GTK_WINDOW_GET_PRIVATE (window);
1789 if (!private->mnemonic_hash && create)
1790 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1792 return private->mnemonic_hash;
1796 * gtk_window_add_mnemonic:
1797 * @window: a #GtkWindow
1798 * @keyval: the mnemonic
1799 * @target: the widget that gets activated by the mnemonic
1801 * Adds a mnemonic to this window.
1804 gtk_window_add_mnemonic (GtkWindow *window,
1808 g_return_if_fail (GTK_IS_WINDOW (window));
1809 g_return_if_fail (GTK_IS_WIDGET (target));
1811 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1813 gtk_window_notify_keys_changed (window);
1817 * gtk_window_remove_mnemonic:
1818 * @window: a #GtkWindow
1819 * @keyval: the mnemonic
1820 * @target: the widget that gets activated by the mnemonic
1822 * Removes a mnemonic from this window.
1825 gtk_window_remove_mnemonic (GtkWindow *window,
1829 g_return_if_fail (GTK_IS_WINDOW (window));
1830 g_return_if_fail (GTK_IS_WIDGET (target));
1832 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
1834 gtk_window_notify_keys_changed (window);
1838 * gtk_window_mnemonic_activate:
1839 * @window: a #GtkWindow
1840 * @keyval: the mnemonic
1841 * @modifier: the modifiers
1842 * @returns: %TRUE if the activation is done.
1844 * Activates the targets associated with the mnemonic.
1847 gtk_window_mnemonic_activate (GtkWindow *window,
1849 GdkModifierType modifier)
1851 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1853 if (window->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
1855 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
1857 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
1864 * gtk_window_set_mnemonic_modifier:
1865 * @window: a #GtkWindow
1866 * @modifier: the modifier mask used to activate
1867 * mnemonics on this window.
1869 * Sets the mnemonic modifier for this window.
1872 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1873 GdkModifierType modifier)
1875 g_return_if_fail (GTK_IS_WINDOW (window));
1876 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1878 window->mnemonic_modifier = modifier;
1879 gtk_window_notify_keys_changed (window);
1883 * gtk_window_get_mnemonic_modifier:
1884 * @window: a #GtkWindow
1886 * Returns the mnemonic modifier for this window. See
1887 * gtk_window_set_mnemonic_modifier().
1889 * Return value: the modifier mask used to activate
1890 * mnemonics on this window.
1893 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1895 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1897 return window->mnemonic_modifier;
1901 * gtk_window_set_position:
1902 * @window: a #GtkWindow.
1903 * @position: a position constraint.
1905 * Sets a position constraint for this window. If the old or new
1906 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1907 * the window to be repositioned to satisfy the new constraint.
1910 gtk_window_set_position (GtkWindow *window,
1911 GtkWindowPosition position)
1913 g_return_if_fail (GTK_IS_WINDOW (window));
1915 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1916 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1918 GtkWindowGeometryInfo *info;
1920 info = gtk_window_get_geometry_info (window, TRUE);
1922 /* this flag causes us to re-request the CENTER_ALWAYS
1923 * constraint in gtk_window_move_resize(), see
1924 * comment in that function.
1926 info->position_constraints_changed = TRUE;
1928 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
1931 window->position = position;
1933 g_object_notify (G_OBJECT (window), "window-position");
1937 * gtk_window_activate_focus:
1938 * @window: a #GtkWindow
1940 * Activates the current focused widget within the window.
1942 * Return value: %TRUE if a widget got activated.
1945 gtk_window_activate_focus (GtkWindow *window)
1947 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1949 if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1950 return gtk_widget_activate (window->focus_widget);
1956 * gtk_window_get_focus:
1957 * @window: a #GtkWindow
1959 * Retrieves the current focused widget within the window.
1960 * Note that this is the widget that would have the focus
1961 * if the toplevel window focused; if the toplevel window
1962 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1963 * not be %TRUE for the widget.
1965 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
1968 gtk_window_get_focus (GtkWindow *window)
1970 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1972 return window->focus_widget;
1976 * gtk_window_activate_default:
1977 * @window: a #GtkWindow
1979 * Activates the default widget for the window, unless the current
1980 * focused widget has been configured to receive the default action
1981 * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
1982 * focused widget is activated.
1984 * Return value: %TRUE if a widget got activated.
1987 gtk_window_activate_default (GtkWindow *window)
1989 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1991 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1992 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1993 return gtk_widget_activate (window->default_widget);
1994 else if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1995 return gtk_widget_activate (window->focus_widget);
2001 * gtk_window_set_modal:
2002 * @window: a #GtkWindow
2003 * @modal: whether the window is modal
2005 * Sets a window modal or non-modal. Modal windows prevent interaction
2006 * with other windows in the same application. To keep modal dialogs
2007 * on top of main application windows, use
2008 * gtk_window_set_transient_for() to make the dialog transient for the
2009 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2010 * will then disallow lowering the dialog below the parent.
2015 gtk_window_set_modal (GtkWindow *window,
2018 g_return_if_fail (GTK_IS_WINDOW (window));
2020 modal = modal != FALSE;
2021 if (window->modal == modal)
2024 window->modal = modal;
2026 /* adjust desired modality state */
2027 if (GTK_WIDGET_REALIZED (window))
2029 GtkWidget *widget = GTK_WIDGET (window);
2032 gdk_window_set_modal_hint (widget->window, TRUE);
2034 gdk_window_set_modal_hint (widget->window, FALSE);
2037 if (GTK_WIDGET_VISIBLE (window))
2040 gtk_grab_add (GTK_WIDGET (window));
2042 gtk_grab_remove (GTK_WIDGET (window));
2045 g_object_notify (G_OBJECT (window), "modal");
2049 * gtk_window_get_modal:
2050 * @window: a #GtkWindow
2052 * Returns whether the window is modal. See gtk_window_set_modal().
2054 * Return value: %TRUE if the window is set to be modal and
2055 * establishes a grab when shown
2058 gtk_window_get_modal (GtkWindow *window)
2060 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2062 return window->modal;
2066 * gtk_window_list_toplevels:
2068 * Returns a list of all existing toplevel windows. The widgets
2069 * in the list are not individually referenced. If you want
2070 * to iterate through the list and perform actions involving
2071 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2072 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2073 * then unref all the widgets afterwards.
2075 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2078 gtk_window_list_toplevels (void)
2083 for (slist = toplevel_list; slist; slist = slist->next)
2084 list = g_list_prepend (list, slist->data);
2090 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2092 GList *embedded_windows;
2094 g_return_if_fail (GTK_IS_WINDOW (window));
2096 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2097 if (embedded_windows)
2098 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2099 embedded_windows = g_list_prepend (embedded_windows,
2100 GUINT_TO_POINTER (xid));
2102 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2105 (GDestroyNotify) g_list_free : NULL);
2109 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2111 GList *embedded_windows;
2114 g_return_if_fail (GTK_IS_WINDOW (window));
2116 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2117 if (embedded_windows)
2118 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2120 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2123 embedded_windows = g_list_remove_link (embedded_windows, node);
2124 g_list_free_1 (node);
2127 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2130 (GDestroyNotify) g_list_free : NULL);
2134 _gtk_window_reposition (GtkWindow *window,
2138 g_return_if_fail (GTK_IS_WINDOW (window));
2140 gtk_window_move (window, x, y);
2144 gtk_window_dispose (GObject *object)
2146 GtkWindow *window = GTK_WINDOW (object);
2148 gtk_window_set_focus (window, NULL);
2149 gtk_window_set_default (window, NULL);
2151 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2155 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2157 gtk_widget_destroy (GTK_WIDGET (child));
2161 connect_parent_destroyed (GtkWindow *window)
2163 if (window->transient_parent)
2165 g_signal_connect (window->transient_parent,
2167 G_CALLBACK (parent_destroyed_callback),
2173 disconnect_parent_destroyed (GtkWindow *window)
2175 if (window->transient_parent)
2177 g_signal_handlers_disconnect_by_func (window->transient_parent,
2178 parent_destroyed_callback,
2184 gtk_window_transient_parent_realized (GtkWidget *parent,
2187 if (GTK_WIDGET_REALIZED (window))
2188 gdk_window_set_transient_for (window->window, parent->window);
2192 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2195 if (GTK_WIDGET_REALIZED (window))
2196 gdk_property_delete (window->window,
2197 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2201 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2205 gtk_window_set_screen (window, parent->screen);
2209 gtk_window_unset_transient_for (GtkWindow *window)
2211 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
2213 if (window->transient_parent)
2215 g_signal_handlers_disconnect_by_func (window->transient_parent,
2216 gtk_window_transient_parent_realized,
2218 g_signal_handlers_disconnect_by_func (window->transient_parent,
2219 gtk_window_transient_parent_unrealized,
2221 g_signal_handlers_disconnect_by_func (window->transient_parent,
2222 gtk_window_transient_parent_screen_changed,
2224 g_signal_handlers_disconnect_by_func (window->transient_parent,
2225 gtk_widget_destroyed,
2226 &window->transient_parent);
2228 if (window->destroy_with_parent)
2229 disconnect_parent_destroyed (window);
2231 window->transient_parent = NULL;
2233 if (priv->transient_parent_group)
2235 priv->transient_parent_group = FALSE;
2236 gtk_window_group_remove_window (window->group,
2243 * gtk_window_set_transient_for:
2244 * @window: a #GtkWindow
2245 * @parent: (allow-none): parent window
2247 * Dialog windows should be set transient for the main application
2248 * window they were spawned from. This allows <link
2249 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2250 * dialog on top of the main window, or center the dialog over the
2251 * main window. gtk_dialog_new_with_buttons() and other convenience
2252 * functions in GTK+ will sometimes call
2253 * gtk_window_set_transient_for() on your behalf.
2255 * On Windows, this function puts the child window on top of the parent,
2256 * much as the window manager would have done on X.
2260 gtk_window_set_transient_for (GtkWindow *window,
2263 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
2265 g_return_if_fail (GTK_IS_WINDOW (window));
2266 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2267 g_return_if_fail (window != parent);
2269 if (window->transient_parent)
2271 if (GTK_WIDGET_REALIZED (window) &&
2272 GTK_WIDGET_REALIZED (window->transient_parent) &&
2273 (!parent || !GTK_WIDGET_REALIZED (parent)))
2274 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
2275 GTK_WIDGET (window));
2277 gtk_window_unset_transient_for (window);
2280 window->transient_parent = parent;
2284 g_signal_connect (parent, "destroy",
2285 G_CALLBACK (gtk_widget_destroyed),
2286 &window->transient_parent);
2287 g_signal_connect (parent, "realize",
2288 G_CALLBACK (gtk_window_transient_parent_realized),
2290 g_signal_connect (parent, "unrealize",
2291 G_CALLBACK (gtk_window_transient_parent_unrealized),
2293 g_signal_connect (parent, "notify::screen",
2294 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2297 gtk_window_set_screen (window, parent->screen);
2299 if (window->destroy_with_parent)
2300 connect_parent_destroyed (window);
2302 if (GTK_WIDGET_REALIZED (window) &&
2303 GTK_WIDGET_REALIZED (parent))
2304 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2305 GTK_WIDGET (window));
2309 gtk_window_group_add_window (parent->group, window);
2310 priv->transient_parent_group = TRUE;
2316 * gtk_window_get_transient_for:
2317 * @window: a #GtkWindow
2319 * Fetches the transient parent for this window. See
2320 * gtk_window_set_transient_for().
2322 * Return value: (transfer none): the transient parent for this window, or %NULL
2323 * if no transient parent has been set.
2326 gtk_window_get_transient_for (GtkWindow *window)
2328 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2330 return window->transient_parent;
2334 * gtk_window_set_opacity:
2335 * @window: a #GtkWindow
2336 * @opacity: desired opacity, between 0 and 1
2338 * Request the windowing system to make @window partially transparent,
2339 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2340 * of the opacity parameter are clamped to the [0,1] range.) On X11
2341 * this has any effect only on X screens with a compositing manager
2342 * running. See gtk_widget_is_composited(). On Windows it should work
2345 * Note that setting a window's opacity after the window has been
2346 * shown causes it to flicker once on Windows.
2351 gtk_window_set_opacity (GtkWindow *window,
2354 GtkWindowPrivate *priv;
2356 g_return_if_fail (GTK_IS_WINDOW (window));
2358 priv = GTK_WINDOW_GET_PRIVATE (window);
2362 else if (opacity > 1.0)
2365 priv->opacity_set = TRUE;
2366 priv->opacity = opacity;
2368 if (GTK_WIDGET_REALIZED (window))
2369 gdk_window_set_opacity (GTK_WIDGET (window)->window, priv->opacity);
2373 * gtk_window_get_opacity:
2374 * @window: a #GtkWindow
2376 * Fetches the requested opacity for this window. See
2377 * gtk_window_set_opacity().
2379 * Return value: the requested opacity for this window.
2384 gtk_window_get_opacity (GtkWindow *window)
2386 GtkWindowPrivate *priv;
2388 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2390 priv = GTK_WINDOW_GET_PRIVATE (window);
2392 return priv->opacity;
2396 * gtk_window_set_type_hint:
2397 * @window: a #GtkWindow
2398 * @hint: the window type
2400 * By setting the type hint for the window, you allow the window
2401 * manager to decorate and handle the window in a way which is
2402 * suitable to the function of the window in your application.
2404 * This function should be called before the window becomes visible.
2406 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2407 * will sometimes call gtk_window_set_type_hint() on your behalf.
2411 gtk_window_set_type_hint (GtkWindow *window,
2412 GdkWindowTypeHint hint)
2414 GtkWindowPrivate *priv;
2416 g_return_if_fail (GTK_IS_WINDOW (window));
2417 g_return_if_fail (!GTK_WIDGET_MAPPED (window));
2419 priv = GTK_WINDOW_GET_PRIVATE (window);
2421 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2422 window->type_hint = hint;
2424 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2426 priv->reset_type_hint = TRUE;
2427 priv->type_hint = hint;
2431 * gtk_window_get_type_hint:
2432 * @window: a #GtkWindow
2434 * Gets the type hint for this window. See gtk_window_set_type_hint().
2436 * Return value: the type hint for @window.
2439 gtk_window_get_type_hint (GtkWindow *window)
2441 GtkWindowPrivate *priv;
2443 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2445 priv = GTK_WINDOW_GET_PRIVATE (window);
2447 return priv->type_hint;
2451 * gtk_window_set_skip_taskbar_hint:
2452 * @window: a #GtkWindow
2453 * @setting: %TRUE to keep this window from appearing in the task bar
2455 * Windows may set a hint asking the desktop environment not to display
2456 * the window in the task bar. This function sets this hint.
2461 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2464 GtkWindowPrivate *priv;
2466 g_return_if_fail (GTK_IS_WINDOW (window));
2468 priv = GTK_WINDOW_GET_PRIVATE (window);
2470 setting = setting != FALSE;
2472 if (priv->skips_taskbar != setting)
2474 priv->skips_taskbar = setting;
2475 if (GTK_WIDGET_REALIZED (window))
2476 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
2477 priv->skips_taskbar);
2478 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2483 * gtk_window_get_skip_taskbar_hint:
2484 * @window: a #GtkWindow
2486 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2488 * Return value: %TRUE if window shouldn't be in taskbar
2493 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2495 GtkWindowPrivate *priv;
2497 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2499 priv = GTK_WINDOW_GET_PRIVATE (window);
2501 return priv->skips_taskbar;
2505 * gtk_window_set_skip_pager_hint:
2506 * @window: a #GtkWindow
2507 * @setting: %TRUE to keep this window from appearing in the pager
2509 * Windows may set a hint asking the desktop environment not to display
2510 * the window in the pager. This function sets this hint.
2511 * (A "pager" is any desktop navigation tool such as a workspace
2512 * switcher that displays a thumbnail representation of the windows
2518 gtk_window_set_skip_pager_hint (GtkWindow *window,
2521 GtkWindowPrivate *priv;
2523 g_return_if_fail (GTK_IS_WINDOW (window));
2525 priv = GTK_WINDOW_GET_PRIVATE (window);
2527 setting = setting != FALSE;
2529 if (priv->skips_pager != setting)
2531 priv->skips_pager = setting;
2532 if (GTK_WIDGET_REALIZED (window))
2533 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2535 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2540 * gtk_window_get_skip_pager_hint:
2541 * @window: a #GtkWindow
2543 * Gets the value set by gtk_window_set_skip_pager_hint().
2545 * Return value: %TRUE if window shouldn't be in pager
2550 gtk_window_get_skip_pager_hint (GtkWindow *window)
2552 GtkWindowPrivate *priv;
2554 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2556 priv = GTK_WINDOW_GET_PRIVATE (window);
2558 return priv->skips_pager;
2562 * gtk_window_set_urgency_hint:
2563 * @window: a #GtkWindow
2564 * @setting: %TRUE to mark this window as urgent
2566 * Windows may set a hint asking the desktop environment to draw
2567 * the users attention to the window. This function sets this hint.
2572 gtk_window_set_urgency_hint (GtkWindow *window,
2575 GtkWindowPrivate *priv;
2577 g_return_if_fail (GTK_IS_WINDOW (window));
2579 priv = GTK_WINDOW_GET_PRIVATE (window);
2581 setting = setting != FALSE;
2583 if (priv->urgent != setting)
2585 priv->urgent = setting;
2586 if (GTK_WIDGET_REALIZED (window))
2587 gdk_window_set_urgency_hint (GTK_WIDGET (window)->window,
2589 g_object_notify (G_OBJECT (window), "urgency-hint");
2594 * gtk_window_get_urgency_hint:
2595 * @window: a #GtkWindow
2597 * Gets the value set by gtk_window_set_urgency_hint()
2599 * Return value: %TRUE if window is urgent
2604 gtk_window_get_urgency_hint (GtkWindow *window)
2606 GtkWindowPrivate *priv;
2608 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2610 priv = GTK_WINDOW_GET_PRIVATE (window);
2612 return priv->urgent;
2616 * gtk_window_set_accept_focus:
2617 * @window: a #GtkWindow
2618 * @setting: %TRUE to let this window receive input focus
2620 * Windows may set a hint asking the desktop environment not to receive
2621 * the input focus. This function sets this hint.
2626 gtk_window_set_accept_focus (GtkWindow *window,
2629 GtkWindowPrivate *priv;
2631 g_return_if_fail (GTK_IS_WINDOW (window));
2633 priv = GTK_WINDOW_GET_PRIVATE (window);
2635 setting = setting != FALSE;
2637 if (priv->accept_focus != setting)
2639 priv->accept_focus = setting;
2640 if (GTK_WIDGET_REALIZED (window))
2641 gdk_window_set_accept_focus (GTK_WIDGET (window)->window,
2642 priv->accept_focus);
2643 g_object_notify (G_OBJECT (window), "accept-focus");
2648 * gtk_window_get_accept_focus:
2649 * @window: a #GtkWindow
2651 * Gets the value set by gtk_window_set_accept_focus().
2653 * Return value: %TRUE if window should receive the input focus
2658 gtk_window_get_accept_focus (GtkWindow *window)
2660 GtkWindowPrivate *priv;
2662 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2664 priv = GTK_WINDOW_GET_PRIVATE (window);
2666 return priv->accept_focus;
2670 * gtk_window_set_focus_on_map:
2671 * @window: a #GtkWindow
2672 * @setting: %TRUE to let this window receive input focus on map
2674 * Windows may set a hint asking the desktop environment not to receive
2675 * the input focus when the window is mapped. This function sets this
2681 gtk_window_set_focus_on_map (GtkWindow *window,
2684 GtkWindowPrivate *priv;
2686 g_return_if_fail (GTK_IS_WINDOW (window));
2688 priv = GTK_WINDOW_GET_PRIVATE (window);
2690 setting = setting != FALSE;
2692 if (priv->focus_on_map != setting)
2694 priv->focus_on_map = setting;
2695 if (GTK_WIDGET_REALIZED (window))
2696 gdk_window_set_focus_on_map (GTK_WIDGET (window)->window,
2697 priv->focus_on_map);
2698 g_object_notify (G_OBJECT (window), "focus-on-map");
2703 * gtk_window_get_focus_on_map:
2704 * @window: a #GtkWindow
2706 * Gets the value set by gtk_window_set_focus_on_map().
2708 * Return value: %TRUE if window should receive the input focus when
2714 gtk_window_get_focus_on_map (GtkWindow *window)
2716 GtkWindowPrivate *priv;
2718 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2720 priv = GTK_WINDOW_GET_PRIVATE (window);
2722 return priv->focus_on_map;
2726 * gtk_window_set_destroy_with_parent:
2727 * @window: a #GtkWindow
2728 * @setting: whether to destroy @window with its transient parent
2730 * If @setting is %TRUE, then destroying the transient parent of @window
2731 * will also destroy @window itself. This is useful for dialogs that
2732 * shouldn't persist beyond the lifetime of the main window they're
2733 * associated with, for example.
2736 gtk_window_set_destroy_with_parent (GtkWindow *window,
2739 g_return_if_fail (GTK_IS_WINDOW (window));
2741 if (window->destroy_with_parent == (setting != FALSE))
2744 if (window->destroy_with_parent)
2746 disconnect_parent_destroyed (window);
2750 connect_parent_destroyed (window);
2753 window->destroy_with_parent = setting;
2755 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2759 * gtk_window_get_destroy_with_parent:
2760 * @window: a #GtkWindow
2762 * Returns whether the window will be destroyed with its transient parent. See
2763 * gtk_window_set_destroy_with_parent ().
2765 * Return value: %TRUE if the window will be destroyed with its transient parent.
2768 gtk_window_get_destroy_with_parent (GtkWindow *window)
2770 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2772 return window->destroy_with_parent;
2775 static GtkWindowGeometryInfo*
2776 gtk_window_get_geometry_info (GtkWindow *window,
2779 GtkWindowGeometryInfo *info;
2781 info = window->geometry_info;
2782 if (!info && create)
2784 info = g_new0 (GtkWindowGeometryInfo, 1);
2786 info->default_width = -1;
2787 info->default_height = -1;
2788 info->resize_width = -1;
2789 info->resize_height = -1;
2790 info->initial_x = 0;
2791 info->initial_y = 0;
2792 info->initial_pos_set = FALSE;
2793 info->default_is_geometry = FALSE;
2794 info->position_constraints_changed = FALSE;
2795 info->last.configure_request.x = 0;
2796 info->last.configure_request.y = 0;
2797 info->last.configure_request.width = -1;
2798 info->last.configure_request.height = -1;
2799 info->widget = NULL;
2801 window->geometry_info = info;
2808 * gtk_window_set_geometry_hints:
2809 * @window: a #GtkWindow
2810 * @geometry_widget: widget the geometry hints will be applied to
2811 * @geometry: struct containing geometry information
2812 * @geom_mask: mask indicating which struct fields should be paid attention to
2814 * This function sets up hints about how a window can be resized by
2815 * the user. You can set a minimum and maximum size; allowed resize
2816 * increments (e.g. for xterm, you can only resize by the size of a
2817 * character); aspect ratios; and more. See the #GdkGeometry struct.
2821 gtk_window_set_geometry_hints (GtkWindow *window,
2822 GtkWidget *geometry_widget,
2823 GdkGeometry *geometry,
2824 GdkWindowHints geom_mask)
2826 GtkWindowGeometryInfo *info;
2828 g_return_if_fail (GTK_IS_WINDOW (window));
2829 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2831 info = gtk_window_get_geometry_info (window, TRUE);
2834 g_signal_handlers_disconnect_by_func (info->widget,
2835 gtk_widget_destroyed,
2838 info->widget = geometry_widget;
2840 g_signal_connect (geometry_widget, "destroy",
2841 G_CALLBACK (gtk_widget_destroyed),
2845 info->geometry = *geometry;
2847 /* We store gravity in window->gravity not in the hints. */
2848 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2850 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2852 gtk_window_set_gravity (window, geometry->win_gravity);
2855 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2859 * gtk_window_set_decorated:
2860 * @window: a #GtkWindow
2861 * @setting: %TRUE to decorate the window
2863 * By default, windows are decorated with a title bar, resize
2864 * controls, etc. Some <link linkend="gtk-X11-arch">window
2865 * managers</link> allow GTK+ to disable these decorations, creating a
2866 * borderless window. If you set the decorated property to %FALSE
2867 * using this function, GTK+ will do its best to convince the window
2868 * manager not to decorate the window. Depending on the system, this
2869 * function may not have any effect when called on a window that is
2870 * already visible, so you should call it before calling gtk_window_show().
2872 * On Windows, this function always works, since there's no window manager
2877 gtk_window_set_decorated (GtkWindow *window,
2880 g_return_if_fail (GTK_IS_WINDOW (window));
2882 setting = setting != FALSE;
2884 if (setting == window->decorated)
2887 window->decorated = setting;
2889 if (GTK_WIDGET (window)->window)
2891 if (window->decorated)
2892 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2895 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2899 g_object_notify (G_OBJECT (window), "decorated");
2903 * gtk_window_get_decorated:
2904 * @window: a #GtkWindow
2906 * Returns whether the window has been set to have decorations
2907 * such as a title bar via gtk_window_set_decorated().
2909 * Return value: %TRUE if the window has been set to have decorations
2912 gtk_window_get_decorated (GtkWindow *window)
2914 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2916 return window->decorated;
2920 * gtk_window_set_deletable:
2921 * @window: a #GtkWindow
2922 * @setting: %TRUE to decorate the window as deletable
2924 * By default, windows have a close button in the window frame. Some
2925 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
2926 * disable this button. If you set the deletable property to %FALSE
2927 * using this function, GTK+ will do its best to convince the window
2928 * manager not to show a close button. Depending on the system, this
2929 * function may not have any effect when called on a window that is
2930 * already visible, so you should call it before calling gtk_window_show().
2932 * On Windows, this function always works, since there's no window manager
2938 gtk_window_set_deletable (GtkWindow *window,
2941 GtkWindowPrivate *priv;
2943 g_return_if_fail (GTK_IS_WINDOW (window));
2945 priv = GTK_WINDOW_GET_PRIVATE (window);
2947 setting = setting != FALSE;
2949 if (setting == priv->deletable)
2952 priv->deletable = setting;
2954 if (GTK_WIDGET (window)->window)
2956 if (priv->deletable)
2957 gdk_window_set_functions (GTK_WIDGET (window)->window,
2960 gdk_window_set_functions (GTK_WIDGET (window)->window,
2961 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
2964 g_object_notify (G_OBJECT (window), "deletable");
2968 * gtk_window_get_deletable:
2969 * @window: a #GtkWindow
2971 * Returns whether the window has been set to have a close button
2972 * via gtk_window_set_deletable().
2974 * Return value: %TRUE if the window has been set to have a close button
2979 gtk_window_get_deletable (GtkWindow *window)
2981 GtkWindowPrivate *priv;
2983 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2985 priv = GTK_WINDOW_GET_PRIVATE (window);
2987 return priv->deletable;
2990 static GtkWindowIconInfo*
2991 get_icon_info (GtkWindow *window)
2993 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
2997 free_icon_info (GtkWindowIconInfo *info)
2999 g_free (info->icon_name);
3000 g_slice_free (GtkWindowIconInfo, info);
3004 static GtkWindowIconInfo*
3005 ensure_icon_info (GtkWindow *window)
3007 GtkWindowIconInfo *info;
3009 info = get_icon_info (window);
3013 info = g_slice_new0 (GtkWindowIconInfo);
3014 g_object_set_qdata_full (G_OBJECT (window),
3015 quark_gtk_window_icon_info,
3017 (GDestroyNotify)free_icon_info);
3029 static ScreenIconInfo *
3030 get_screen_icon_info (GdkScreen *screen)
3032 ScreenIconInfo *info = g_object_get_qdata (G_OBJECT (screen),
3033 quark_gtk_window_default_icon_pixmap);
3036 info = g_slice_new0 (ScreenIconInfo);
3037 g_object_set_qdata (G_OBJECT (screen),
3038 quark_gtk_window_default_icon_pixmap, info);
3041 if (info->serial != default_icon_serial)
3045 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
3046 info->pixmap = NULL;
3051 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
3055 info->serial = default_icon_serial;
3062 get_pixmap_and_mask (GdkWindow *window,
3063 GtkWindowIconInfo *parent_info,
3064 gboolean is_default_list,
3066 GdkPixmap **pmap_return,
3067 GdkBitmap **mask_return)
3069 GdkScreen *screen = gdk_drawable_get_screen (window);
3070 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
3071 GdkPixbuf *best_icon;
3075 *pmap_return = NULL;
3076 *mask_return = NULL;
3078 if (is_default_list &&
3079 default_icon_info->pixmap != NULL)
3081 /* Use shared icon pixmap for all windows on this screen.
3083 if (default_icon_info->pixmap)
3084 g_object_ref (default_icon_info->pixmap);
3085 if (default_icon_info->mask)
3086 g_object_ref (default_icon_info->mask);
3088 *pmap_return = default_icon_info->pixmap;
3089 *mask_return = default_icon_info->mask;
3091 else if (parent_info && parent_info->icon_pixmap)
3093 if (parent_info->icon_pixmap)
3094 g_object_ref (parent_info->icon_pixmap);
3095 if (parent_info->icon_mask)
3096 g_object_ref (parent_info->icon_mask);
3098 *pmap_return = parent_info->icon_pixmap;
3099 *mask_return = parent_info->icon_mask;
3103 #define IDEAL_SIZE 48
3105 best_size = G_MAXINT;
3107 tmp_list = icon_list;
3108 while (tmp_list != NULL)
3110 GdkPixbuf *pixbuf = tmp_list->data;
3113 /* average width and height - if someone passes in a rectangular
3114 * icon they deserve what they get.
3116 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
3119 if (best_icon == NULL)
3126 /* icon is better if it's 32 pixels or larger, and closer to
3127 * the ideal size than the current best.
3130 (ABS (best_size - IDEAL_SIZE) <
3131 ABS (this - IDEAL_SIZE)))
3138 tmp_list = tmp_list->next;
3142 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
3143 gdk_screen_get_system_colormap (screen),
3148 /* Save pmap/mask for others to use if appropriate */
3151 parent_info->icon_pixmap = *pmap_return;
3152 parent_info->icon_mask = *mask_return;
3154 if (parent_info->icon_pixmap)
3155 g_object_ref (parent_info->icon_pixmap);
3156 if (parent_info->icon_mask)
3157 g_object_ref (parent_info->icon_mask);
3159 else if (is_default_list)
3161 default_icon_info->pixmap = *pmap_return;
3162 default_icon_info->mask = *mask_return;
3164 if (default_icon_info->pixmap)
3165 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
3166 (gpointer*)&default_icon_info->pixmap);
3167 if (default_icon_info->mask)
3168 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
3169 (gpointer*)&default_icon_info->mask);
3175 icon_list_from_theme (GtkWidget *widget,
3180 GtkIconTheme *icon_theme;
3185 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3187 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3190 for (i = 0; sizes[i]; i++)
3193 * We need an EWMH extension to handle scalable icons
3194 * by passing their name to the WM. For now just use a
3198 icon = gtk_icon_theme_load_icon (icon_theme, name,
3201 icon = gtk_icon_theme_load_icon (icon_theme, name,
3204 list = g_list_append (list, icon);
3214 gtk_window_realize_icon (GtkWindow *window)
3217 GtkWindowIconInfo *info;
3220 widget = GTK_WIDGET (window);
3222 g_return_if_fail (widget->window != NULL);
3224 /* no point setting an icon on override-redirect */
3225 if (window->type == GTK_WINDOW_POPUP)
3230 info = ensure_icon_info (window);
3235 g_return_if_fail (info->icon_pixmap == NULL);
3236 g_return_if_fail (info->icon_mask == NULL);
3238 info->using_default_icon = FALSE;
3239 info->using_parent_icon = FALSE;
3240 info->using_themed_icon = FALSE;
3242 icon_list = info->icon_list;
3244 /* Look up themed icon */
3245 if (icon_list == NULL && info->icon_name)
3247 icon_list = icon_list_from_theme (widget, info->icon_name);
3249 info->using_themed_icon = TRUE;
3252 /* Inherit from transient parent */
3253 if (icon_list == NULL && window->transient_parent)
3255 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
3257 info->using_parent_icon = TRUE;
3260 /* Inherit from default */
3261 if (icon_list == NULL)
3263 icon_list = default_icon_list;
3265 info->using_default_icon = TRUE;
3268 /* Look up themed icon */
3269 if (icon_list == NULL && default_icon_name)
3271 icon_list = icon_list_from_theme (widget, default_icon_name);
3272 info->using_default_icon = TRUE;
3273 info->using_themed_icon = TRUE;
3276 gdk_window_set_icon_list (widget->window, icon_list);
3278 get_pixmap_and_mask (widget->window,
3279 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
3280 info->using_default_icon,
3285 /* This is a slight ICCCM violation since it's a color pixmap not
3286 * a bitmap, but everyone does it.
3288 gdk_window_set_icon (widget->window,
3293 info->realized = TRUE;
3295 if (info->using_themed_icon)
3297 GtkIconTheme *icon_theme;
3299 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3300 g_list_free (icon_list);
3302 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3303 g_signal_connect (icon_theme, "changed",
3304 G_CALLBACK (update_themed_icon), window);
3309 gtk_window_unrealize_icon (GtkWindow *window)
3311 GtkWindowIconInfo *info;
3313 info = get_icon_info (window);
3318 if (info->icon_pixmap)
3319 g_object_unref (info->icon_pixmap);
3321 if (info->icon_mask)
3322 g_object_unref (info->icon_mask);
3324 info->icon_pixmap = NULL;
3325 info->icon_mask = NULL;
3327 if (info->using_themed_icon)
3329 GtkIconTheme *icon_theme;
3331 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3333 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3336 /* We don't clear the properties on the window, just figure the
3337 * window is going away.
3340 info->realized = FALSE;
3345 * gtk_window_set_icon_list:
3346 * @window: a #GtkWindow
3347 * @list: list of #GdkPixbuf
3349 * Sets up the icon representing a #GtkWindow. The icon is used when
3350 * the window is minimized (also known as iconified). Some window
3351 * managers or desktop environments may also place it in the window
3352 * frame, or display it in other contexts.
3354 * gtk_window_set_icon_list() allows you to pass in the same icon in
3355 * several hand-drawn sizes. The list should contain the natural sizes
3356 * your icon is available in; that is, don't scale the image before
3357 * passing it to GTK+. Scaling is postponed until the last minute,
3358 * when the desired final size is known, to allow best quality.
3360 * By passing several sizes, you may improve the final image quality
3361 * of the icon, by reducing or eliminating automatic image scaling.
3363 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3364 * larger images (64x64, 128x128) if you have them.
3366 * See also gtk_window_set_default_icon_list() to set the icon
3367 * for all windows in your application in one go.
3369 * Note that transient windows (those who have been set transient for another
3370 * window using gtk_window_set_transient_for()) will inherit their
3371 * icon from their transient parent. So there's no need to explicitly
3372 * set the icon on transient windows.
3375 gtk_window_set_icon_list (GtkWindow *window,
3378 GtkWindowIconInfo *info;
3380 g_return_if_fail (GTK_IS_WINDOW (window));
3382 info = ensure_icon_info (window);
3384 if (info->icon_list == list) /* check for NULL mostly */
3387 g_list_foreach (list,
3388 (GFunc) g_object_ref, NULL);
3390 g_list_foreach (info->icon_list,
3391 (GFunc) g_object_unref, NULL);
3393 g_list_free (info->icon_list);
3395 info->icon_list = g_list_copy (list);
3397 g_object_notify (G_OBJECT (window), "icon");
3399 gtk_window_unrealize_icon (window);
3401 if (GTK_WIDGET_REALIZED (window))
3402 gtk_window_realize_icon (window);
3404 /* We could try to update our transient children, but I don't think
3405 * it's really worth it. If we did it, the best way would probably
3406 * be to have children connect to notify::icon-list
3411 * gtk_window_get_icon_list:
3412 * @window: a #GtkWindow
3414 * Retrieves the list of icons set by gtk_window_set_icon_list().
3415 * The list is copied, but the reference count on each
3416 * member won't be incremented.
3418 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3421 gtk_window_get_icon_list (GtkWindow *window)
3423 GtkWindowIconInfo *info;
3425 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3427 info = get_icon_info (window);
3430 return g_list_copy (info->icon_list);
3436 * gtk_window_set_icon:
3437 * @window: a #GtkWindow
3438 * @icon: (allow-none): icon image, or %NULL
3440 * Sets up the icon representing a #GtkWindow. This icon is used when
3441 * the window is minimized (also known as iconified). Some window
3442 * managers or desktop environments may also place it in the window
3443 * frame, or display it in other contexts.
3445 * The icon should be provided in whatever size it was naturally
3446 * drawn; that is, don't scale the image before passing it to
3447 * GTK+. Scaling is postponed until the last minute, when the desired
3448 * final size is known, to allow best quality.
3450 * If you have your icon hand-drawn in multiple sizes, use
3451 * gtk_window_set_icon_list(). Then the best size will be used.
3453 * This function is equivalent to calling gtk_window_set_icon_list()
3454 * with a 1-element list.
3456 * See also gtk_window_set_default_icon_list() to set the icon
3457 * for all windows in your application in one go.
3460 gtk_window_set_icon (GtkWindow *window,
3465 g_return_if_fail (GTK_IS_WINDOW (window));
3466 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3471 list = g_list_append (list, icon);
3473 gtk_window_set_icon_list (window, list);
3479 update_themed_icon (GtkIconTheme *icon_theme,
3482 g_object_notify (G_OBJECT (window), "icon");
3484 gtk_window_unrealize_icon (window);
3486 if (GTK_WIDGET_REALIZED (window))
3487 gtk_window_realize_icon (window);
3491 * gtk_window_set_icon_name:
3492 * @window: a #GtkWindow
3493 * @name: (allow-none): the name of the themed icon
3495 * Sets the icon for the window from a named themed icon. See
3496 * the docs for #GtkIconTheme for more details.
3498 * Note that this has nothing to do with the WM_ICON_NAME
3499 * property which is mentioned in the ICCCM.
3504 gtk_window_set_icon_name (GtkWindow *window,
3507 GtkWindowIconInfo *info;
3510 g_return_if_fail (GTK_IS_WINDOW (window));
3512 info = ensure_icon_info (window);
3514 if (g_strcmp0 (info->icon_name, name) == 0)
3517 tmp = info->icon_name;
3518 info->icon_name = g_strdup (name);
3521 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3522 g_list_free (info->icon_list);
3523 info->icon_list = NULL;
3525 update_themed_icon (NULL, window);
3527 g_object_notify (G_OBJECT (window), "icon-name");
3531 * gtk_window_get_icon_name:
3532 * @window: a #GtkWindow
3534 * Returns the name of the themed icon for the window,
3535 * see gtk_window_set_icon_name().
3537 * Returns: the icon name or %NULL if the window has
3542 G_CONST_RETURN gchar *
3543 gtk_window_get_icon_name (GtkWindow *window)
3545 GtkWindowIconInfo *info;
3547 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3549 info = ensure_icon_info (window);
3551 return info->icon_name;
3555 * gtk_window_get_icon:
3556 * @window: a #GtkWindow
3558 * Gets the value set by gtk_window_set_icon() (or if you've
3559 * called gtk_window_set_icon_list(), gets the first icon in
3562 * Return value: (transfer none): icon for window
3565 gtk_window_get_icon (GtkWindow *window)
3567 GtkWindowIconInfo *info;
3569 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3571 info = get_icon_info (window);
3572 if (info && info->icon_list)
3573 return GDK_PIXBUF (info->icon_list->data);
3578 /* Load pixbuf, printing warning on failure if error == NULL
3581 load_pixbuf_verbosely (const char *filename,
3584 GError *local_err = NULL;
3587 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3595 g_warning ("Error loading icon from file '%s':\n\t%s",
3596 filename, local_err->message);
3597 g_error_free (local_err);
3605 * gtk_window_set_icon_from_file:
3606 * @window: a #GtkWindow
3607 * @filename: location of icon file
3608 * @err: location to store error, or %NULL.
3610 * Sets the icon for @window.
3611 * Warns on failure if @err is %NULL.
3613 * This function is equivalent to calling gtk_window_set_icon()
3614 * with a pixbuf created by loading the image from @filename.
3616 * Returns: %TRUE if setting the icon succeeded.
3621 gtk_window_set_icon_from_file (GtkWindow *window,
3622 const gchar *filename,
3625 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3629 gtk_window_set_icon (window, pixbuf);
3630 g_object_unref (pixbuf);
3639 * gtk_window_set_default_icon_list:
3640 * @list: a list of #GdkPixbuf
3642 * Sets an icon list to be used as fallback for windows that haven't
3643 * had gtk_window_set_icon_list() called on them to set up a
3644 * window-specific icon list. This function allows you to set up the
3645 * icon for all windows in your app at once.
3647 * See gtk_window_set_icon_list() for more details.
3651 gtk_window_set_default_icon_list (GList *list)
3655 if (list == default_icon_list)
3658 /* Update serial so we don't used cached pixmaps/masks
3660 default_icon_serial++;
3662 g_list_foreach (list,
3663 (GFunc) g_object_ref, NULL);
3665 g_list_foreach (default_icon_list,
3666 (GFunc) g_object_unref, NULL);
3668 g_list_free (default_icon_list);
3670 default_icon_list = g_list_copy (list);
3672 /* Update all toplevels */
3673 toplevels = gtk_window_list_toplevels ();
3674 tmp_list = toplevels;
3675 while (tmp_list != NULL)
3677 GtkWindowIconInfo *info;
3678 GtkWindow *w = tmp_list->data;
3680 info = get_icon_info (w);
3681 if (info && info->using_default_icon)
3683 gtk_window_unrealize_icon (w);
3684 if (GTK_WIDGET_REALIZED (w))
3685 gtk_window_realize_icon (w);
3688 tmp_list = tmp_list->next;
3690 g_list_free (toplevels);
3694 * gtk_window_set_default_icon:
3697 * Sets an icon to be used as fallback for windows that haven't
3698 * had gtk_window_set_icon() called on them from a pixbuf.
3703 gtk_window_set_default_icon (GdkPixbuf *icon)
3707 g_return_if_fail (GDK_IS_PIXBUF (icon));
3709 list = g_list_prepend (NULL, icon);
3710 gtk_window_set_default_icon_list (list);
3715 * gtk_window_set_default_icon_name:
3716 * @name: the name of the themed icon
3718 * Sets an icon to be used as fallback for windows that haven't
3719 * had gtk_window_set_icon_list() called on them from a named
3720 * themed icon, see gtk_window_set_icon_name().
3725 gtk_window_set_default_icon_name (const gchar *name)
3730 /* Update serial so we don't used cached pixmaps/masks
3732 default_icon_serial++;
3734 g_free (default_icon_name);
3735 default_icon_name = g_strdup (name);
3737 g_list_foreach (default_icon_list,
3738 (GFunc) g_object_unref, NULL);
3740 g_list_free (default_icon_list);
3741 default_icon_list = NULL;
3743 /* Update all toplevels */
3744 toplevels = gtk_window_list_toplevels ();
3745 tmp_list = toplevels;
3746 while (tmp_list != NULL)
3748 GtkWindowIconInfo *info;
3749 GtkWindow *w = tmp_list->data;
3751 info = get_icon_info (w);
3752 if (info && info->using_default_icon && info->using_themed_icon)
3754 gtk_window_unrealize_icon (w);
3755 if (GTK_WIDGET_REALIZED (w))
3756 gtk_window_realize_icon (w);
3759 tmp_list = tmp_list->next;
3761 g_list_free (toplevels);
3765 * gtk_window_get_default_icon_name:
3767 * Returns the fallback icon name for windows that has been set
3768 * with gtk_window_set_default_icon_name(). The returned
3769 * string is owned by GTK+ and should not be modified. It
3770 * is only valid until the next call to
3771 * gtk_window_set_default_icon_name().
3773 * Returns: the fallback icon name for windows
3778 gtk_window_get_default_icon_name (void)
3780 return default_icon_name;
3784 * gtk_window_set_default_icon_from_file:
3785 * @filename: location of icon file
3786 * @err: location to store error, or %NULL.
3788 * Sets an icon to be used as fallback for windows that haven't
3789 * had gtk_window_set_icon_list() called on them from a file
3790 * on disk. Warns on failure if @err is %NULL.
3792 * Returns: %TRUE if setting the icon succeeded.
3797 gtk_window_set_default_icon_from_file (const gchar *filename,
3800 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3804 gtk_window_set_default_icon (pixbuf);
3805 g_object_unref (pixbuf);
3814 * gtk_window_get_default_icon_list:
3816 * Gets the value set by gtk_window_set_default_icon_list().
3817 * The list is a copy and should be freed with g_list_free(),
3818 * but the pixbufs in the list have not had their reference count
3821 * Return value: copy of default icon list
3824 gtk_window_get_default_icon_list (void)
3826 return g_list_copy (default_icon_list);
3830 gtk_window_set_default_size_internal (GtkWindow *window,
3831 gboolean change_width,
3833 gboolean change_height,
3835 gboolean is_geometry)
3837 GtkWindowGeometryInfo *info;
3839 g_return_if_fail (change_width == FALSE || width >= -1);
3840 g_return_if_fail (change_height == FALSE || height >= -1);
3842 info = gtk_window_get_geometry_info (window, TRUE);
3844 g_object_freeze_notify (G_OBJECT (window));
3846 info->default_is_geometry = is_geometry != FALSE;
3856 info->default_width = width;
3858 g_object_notify (G_OBJECT (window), "default-width");
3869 info->default_height = height;
3871 g_object_notify (G_OBJECT (window), "default-height");
3874 g_object_thaw_notify (G_OBJECT (window));
3876 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3880 * gtk_window_set_default_size:
3881 * @window: a #GtkWindow
3882 * @width: width in pixels, or -1 to unset the default width
3883 * @height: height in pixels, or -1 to unset the default height
3885 * Sets the default size of a window. If the window's "natural" size
3886 * (its size request) is larger than the default, the default will be
3887 * ignored. More generally, if the default size does not obey the
3888 * geometry hints for the window (gtk_window_set_geometry_hints() can
3889 * be used to set these explicitly), the default size will be clamped
3890 * to the nearest permitted size.
3892 * Unlike gtk_widget_set_size_request(), which sets a size request for
3893 * a widget and thus would keep users from shrinking the window, this
3894 * function only sets the initial size, just as if the user had
3895 * resized the window themselves. Users can still shrink the window
3896 * again as they normally would. Setting a default size of -1 means to
3897 * use the "natural" default size (the size request of the window).
3899 * For more control over a window's initial size and how resizing works,
3900 * investigate gtk_window_set_geometry_hints().
3902 * For some uses, gtk_window_resize() is a more appropriate function.
3903 * gtk_window_resize() changes the current size of the window, rather
3904 * than the size to be used on initial display. gtk_window_resize() always
3905 * affects the window itself, not the geometry widget.
3907 * The default size of a window only affects the first time a window is
3908 * shown; if a window is hidden and re-shown, it will remember the size
3909 * it had prior to hiding, rather than using the default size.
3911 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3912 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3915 gtk_window_set_default_size (GtkWindow *window,
3919 g_return_if_fail (GTK_IS_WINDOW (window));
3920 g_return_if_fail (width >= -1);
3921 g_return_if_fail (height >= -1);
3923 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3927 * gtk_window_get_default_size:
3928 * @window: a #GtkWindow
3929 * @width: location to store the default width, or %NULL
3930 * @height: location to store the default height, or %NULL
3932 * Gets the default size of the window. A value of -1 for the width or
3933 * height indicates that a default size has not been explicitly set
3934 * for that dimension, so the "natural" size of the window will be
3939 gtk_window_get_default_size (GtkWindow *window,
3943 GtkWindowGeometryInfo *info;
3945 g_return_if_fail (GTK_IS_WINDOW (window));
3947 info = gtk_window_get_geometry_info (window, FALSE);
3950 *width = info ? info->default_width : -1;
3953 *height = info ? info->default_height : -1;
3957 * gtk_window_resize:
3958 * @window: a #GtkWindow
3959 * @width: width in pixels to resize the window to
3960 * @height: height in pixels to resize the window to
3962 * Resizes the window as if the user had done so, obeying geometry
3963 * constraints. The default geometry constraint is that windows may
3964 * not be smaller than their size request; to override this
3965 * constraint, call gtk_widget_set_size_request() to set the window's
3966 * request to a smaller value.
3968 * If gtk_window_resize() is called before showing a window for the
3969 * first time, it overrides any default size set with
3970 * gtk_window_set_default_size().
3972 * Windows may not be resized smaller than 1 by 1 pixels.
3976 gtk_window_resize (GtkWindow *window,
3980 GtkWindowGeometryInfo *info;
3982 g_return_if_fail (GTK_IS_WINDOW (window));
3983 g_return_if_fail (width > 0);
3984 g_return_if_fail (height > 0);
3986 info = gtk_window_get_geometry_info (window, TRUE);
3988 info->resize_width = width;
3989 info->resize_height = height;
3991 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3995 * gtk_window_get_size:
3996 * @window: a #GtkWindow
3997 * @width: (out): return location for width, or %NULL
3998 * @height: (out): return location for height, or %NULL
4000 * Obtains the current size of @window. If @window is not onscreen,
4001 * it returns the size GTK+ will suggest to the <link
4002 * linkend="gtk-X11-arch">window manager</link> for the initial window
4003 * size (but this is not reliably the same as the size the window
4004 * manager will actually select). The size obtained by
4005 * gtk_window_get_size() is the last size received in a
4006 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4007 * rather than querying the X server for the size. As a result, if you
4008 * call gtk_window_resize() then immediately call
4009 * gtk_window_get_size(), the size won't have taken effect yet. After
4010 * the window manager processes the resize request, GTK+ receives
4011 * notification that the size has changed via a configure event, and
4012 * the size of the window gets updated.
4014 * Note 1: Nearly any use of this function creates a race condition,
4015 * because the size of the window may change between the time that you
4016 * get the size and the time that you perform some action assuming
4017 * that size is the current size. To avoid race conditions, connect to
4018 * "configure-event" on the window and adjust your size-dependent
4019 * state to match the size delivered in the #GdkEventConfigure.
4021 * Note 2: The returned size does <emphasis>not</emphasis> include the
4022 * size of the window manager decorations (aka the window frame or
4023 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4024 * method of determining their size.
4026 * Note 3: If you are getting a window size in order to position
4027 * the window onscreen, there may be a better way. The preferred
4028 * way is to simply set the window's semantic type with
4029 * gtk_window_set_type_hint(), which allows the window manager to
4030 * e.g. center dialogs. Also, if you set the transient parent of
4031 * dialogs with gtk_window_set_transient_for() window managers
4032 * will often center the dialog over its parent window. It's
4033 * much preferred to let the window manager handle these
4034 * things rather than doing it yourself, because all apps will
4035 * behave consistently and according to user prefs if the window
4036 * manager handles it. Also, the window manager can take the size
4037 * of the window decorations/border into account, while your
4038 * application cannot.
4040 * In any case, if you insist on application-specified window
4041 * positioning, there's <emphasis>still</emphasis> a better way than
4042 * doing it yourself - gtk_window_set_position() will frequently
4043 * handle the details for you.
4047 gtk_window_get_size (GtkWindow *window,
4053 g_return_if_fail (GTK_IS_WINDOW (window));
4055 if (width == NULL && height == NULL)
4058 if (GTK_WIDGET_MAPPED (window))
4060 gdk_drawable_get_size (GTK_WIDGET (window)->window,
4065 GdkRectangle configure_request;
4067 gtk_window_compute_configure_request (window,
4071 w = configure_request.width;
4072 h = configure_request.height;
4083 * @window: a #GtkWindow
4084 * @x: X coordinate to move window to
4085 * @y: Y coordinate to move window to
4087 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4088 * @window to the given position. Window managers are free to ignore
4089 * this; most window managers ignore requests for initial window
4090 * positions (instead using a user-defined placement algorithm) and
4091 * honor requests after the window has already been shown.
4093 * Note: the position is the position of the gravity-determined
4094 * reference point for the window. The gravity determines two things:
4095 * first, the location of the reference point in root window
4096 * coordinates; and second, which point on the window is positioned at
4097 * the reference point.
4099 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4100 * point is simply the @x, @y supplied to gtk_window_move(). The
4101 * top-left corner of the window decorations (aka window frame or
4102 * border) will be placed at @x, @y. Therefore, to position a window
4103 * at the top left of the screen, you want to use the default gravity
4104 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4106 * To position a window at the bottom right corner of the screen, you
4107 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4108 * point is at @x + the window width and @y + the window height, and
4109 * the bottom-right corner of the window border will be placed at that
4110 * reference point. So, to place a window in the bottom right corner
4111 * you would first set gravity to south east, then write:
4112 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4113 * gdk_screen_height () - window_height)</literal> (note that this
4114 * example does not take multi-head scenarios into account).
4116 * The Extended Window Manager Hints specification at <ulink
4117 * url="http://www.freedesktop.org/Standards/wm-spec">
4118 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4119 * nice table of gravities in the "implementation notes" section.
4121 * The gtk_window_get_position() documentation may also be relevant.
4124 gtk_window_move (GtkWindow *window,
4128 GtkWindowGeometryInfo *info;
4131 g_return_if_fail (GTK_IS_WINDOW (window));
4133 widget = GTK_WIDGET (window);
4135 info = gtk_window_get_geometry_info (window, TRUE);
4137 if (GTK_WIDGET_MAPPED (window))
4139 /* we have now sent a request with this position
4140 * with currently-active constraints, so toggle flag.
4142 info->position_constraints_changed = FALSE;
4144 /* we only constrain if mapped - if not mapped,
4145 * then gtk_window_compute_configure_request()
4146 * will apply the constraints later, and we
4147 * don't want to lose information about
4148 * what position the user set before then.
4149 * i.e. if you do a move() then turn off POS_CENTER
4150 * then show the window, your move() will work.
4152 gtk_window_constrain_position (window,
4153 widget->allocation.width,
4154 widget->allocation.height,
4157 /* Note that this request doesn't go through our standard request
4158 * framework, e.g. doesn't increment configure_request_count,
4159 * doesn't set info->last, etc.; that's because
4160 * we don't save the info needed to arrive at this same request
4163 * To gtk_window_move_resize(), this will end up looking exactly
4164 * the same as the position being changed by the window
4168 /* FIXME are we handling gravity properly for framed windows? */
4170 gdk_window_move (window->frame,
4171 x - window->frame_left,
4172 y - window->frame_top);
4174 gdk_window_move (GTK_WIDGET (window)->window,
4179 /* Save this position to apply on mapping */
4180 info->initial_x = x;
4181 info->initial_y = y;
4182 info->initial_pos_set = TRUE;
4187 * gtk_window_get_position:
4188 * @window: a #GtkWindow
4189 * @root_x: return location for X coordinate of gravity-determined reference point
4190 * @root_y: return location for Y coordinate of gravity-determined reference point
4192 * This function returns the position you need to pass to
4193 * gtk_window_move() to keep @window in its current position. This
4194 * means that the meaning of the returned value varies with window
4195 * gravity. See gtk_window_move() for more details.
4197 * If you haven't changed the window gravity, its gravity will be
4198 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4199 * gets the position of the top-left corner of the window manager
4200 * frame for the window. gtk_window_move() sets the position of this
4201 * same top-left corner.
4203 * gtk_window_get_position() is not 100% reliable because the X Window System
4204 * does not specify a way to obtain the geometry of the
4205 * decorations placed on a window by the window manager.
4206 * Thus GTK+ is using a "best guess" that works with most
4209 * Moreover, nearly all window managers are historically broken with
4210 * respect to their handling of window gravity. So moving a window to
4211 * its current position as returned by gtk_window_get_position() tends
4212 * to result in moving the window slightly. Window managers are
4213 * slowly getting better over time.
4215 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4216 * frame is not relevant, and thus gtk_window_get_position() will
4217 * always produce accurate results. However you can't use static
4218 * gravity to do things like place a window in a corner of the screen,
4219 * because static gravity ignores the window manager decorations.
4221 * If you are saving and restoring your application's window
4222 * positions, you should know that it's impossible for applications to
4223 * do this without getting it somewhat wrong because applications do
4224 * not have sufficient knowledge of window manager state. The Correct
4225 * Mechanism is to support the session management protocol (see the
4226 * "GnomeClient" object in the GNOME libraries for example) and allow
4227 * the window manager to save your window sizes and positions.
4232 gtk_window_get_position (GtkWindow *window,
4238 g_return_if_fail (GTK_IS_WINDOW (window));
4240 widget = GTK_WIDGET (window);
4242 if (window->gravity == GDK_GRAVITY_STATIC)
4244 if (GTK_WIDGET_MAPPED (widget))
4246 /* This does a server round-trip, which is sort of wrong;
4247 * but a server round-trip is inevitable for
4248 * gdk_window_get_frame_extents() in the usual
4249 * NorthWestGravity case below, so not sure what else to
4250 * do. We should likely be consistent about whether we get
4251 * the client-side info or the server-side info.
4253 gdk_window_get_origin (widget->window, root_x, root_y);
4257 GdkRectangle configure_request;
4259 gtk_window_compute_configure_request (window,
4263 *root_x = configure_request.x;
4264 *root_y = configure_request.y;
4269 GdkRectangle frame_extents;
4274 if (GTK_WIDGET_MAPPED (widget))
4277 gdk_window_get_frame_extents (window->frame, &frame_extents);
4279 gdk_window_get_frame_extents (widget->window, &frame_extents);
4280 x = frame_extents.x;
4281 y = frame_extents.y;
4282 gtk_window_get_size (window, &w, &h);
4286 /* We just say the frame has 0 size on all sides.
4287 * Not sure what else to do.
4289 gtk_window_compute_configure_request (window,
4292 x = frame_extents.x;
4293 y = frame_extents.y;
4294 w = frame_extents.width;
4295 h = frame_extents.height;
4298 switch (window->gravity)
4300 case GDK_GRAVITY_NORTH:
4301 case GDK_GRAVITY_CENTER:
4302 case GDK_GRAVITY_SOUTH:
4303 /* Find center of frame. */
4304 x += frame_extents.width / 2;
4305 /* Center client window on that point. */
4309 case GDK_GRAVITY_SOUTH_EAST:
4310 case GDK_GRAVITY_EAST:
4311 case GDK_GRAVITY_NORTH_EAST:
4312 /* Find right edge of frame */
4313 x += frame_extents.width;
4314 /* Align left edge of client at that point. */
4321 switch (window->gravity)
4323 case GDK_GRAVITY_WEST:
4324 case GDK_GRAVITY_CENTER:
4325 case GDK_GRAVITY_EAST:
4326 /* Find center of frame. */
4327 y += frame_extents.height / 2;
4328 /* Center client window there. */
4331 case GDK_GRAVITY_SOUTH_WEST:
4332 case GDK_GRAVITY_SOUTH:
4333 case GDK_GRAVITY_SOUTH_EAST:
4334 /* Find south edge of frame */
4335 y += frame_extents.height;
4336 /* Place bottom edge of client there */
4351 * gtk_window_reshow_with_initial_size:
4352 * @window: a #GtkWindow
4354 * Hides @window, then reshows it, resetting the
4355 * default size and position of the window. Used
4356 * by GUI builders only.
4359 gtk_window_reshow_with_initial_size (GtkWindow *window)
4363 g_return_if_fail (GTK_IS_WINDOW (window));
4365 widget = GTK_WIDGET (window);
4367 gtk_widget_hide (widget);
4368 gtk_widget_unrealize (widget);
4369 gtk_widget_show (widget);
4373 gtk_window_destroy (GtkObject *object)
4375 GtkWindow *window = GTK_WINDOW (object);
4377 toplevel_list = g_slist_remove (toplevel_list, window);
4379 if (window->transient_parent)
4380 gtk_window_set_transient_for (window, NULL);
4382 /* frees the icons */
4383 gtk_window_set_icon_list (window, NULL);
4385 if (window->has_user_ref_count)
4387 window->has_user_ref_count = FALSE;
4388 g_object_unref (window);
4392 gtk_window_group_remove_window (window->group, window);
4394 gtk_window_free_key_hash (window);
4396 GTK_OBJECT_CLASS (gtk_window_parent_class)->destroy (object);
4400 gtk_window_finalize (GObject *object)
4402 GtkWindow *window = GTK_WINDOW (object);
4403 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4404 GtkMnemonicHash *mnemonic_hash;
4406 g_free (window->title);
4407 g_free (window->wmclass_name);
4408 g_free (window->wmclass_class);
4409 g_free (window->wm_role);
4411 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4413 _gtk_mnemonic_hash_free (mnemonic_hash);
4415 if (window->geometry_info)
4417 if (window->geometry_info->widget)
4418 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
4419 gtk_widget_destroyed,
4420 &window->geometry_info->widget);
4421 g_free (window->geometry_info);
4424 if (window->keys_changed_handler)
4426 g_source_remove (window->keys_changed_handler);
4427 window->keys_changed_handler = 0;
4431 g_signal_handlers_disconnect_by_func (window->screen,
4432 gtk_window_on_composited_changed, window);
4434 g_free (priv->startup_id);
4436 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4440 gtk_window_show (GtkWidget *widget)
4442 GtkWindow *window = GTK_WINDOW (widget);
4443 GtkContainer *container = GTK_CONTAINER (window);
4444 gboolean need_resize;
4446 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
4448 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
4449 container->need_resize = FALSE;
4453 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4454 GtkAllocation allocation = { 0, 0 };
4455 GdkRectangle configure_request;
4456 GdkGeometry new_geometry;
4458 gboolean was_realized;
4460 /* We are going to go ahead and perform this configure request
4461 * and then emulate a configure notify by going ahead and
4462 * doing a size allocate. Sort of a synchronous
4463 * mini-copy of gtk_window_move_resize() here.
4465 gtk_window_compute_configure_request (window,
4470 /* We update this because we are going to go ahead
4471 * and gdk_window_resize() below, rather than
4474 info->last.configure_request.width = configure_request.width;
4475 info->last.configure_request.height = configure_request.height;
4477 /* and allocate the window - this is normally done
4478 * in move_resize in response to configure notify
4480 allocation.width = configure_request.width;
4481 allocation.height = configure_request.height;
4482 gtk_widget_size_allocate (widget, &allocation);
4484 /* Then we guarantee we have a realize */
4485 was_realized = FALSE;
4486 if (!GTK_WIDGET_REALIZED (widget))
4488 gtk_widget_realize (widget);
4489 was_realized = TRUE;
4492 /* Must be done after the windows are realized,
4493 * so that the decorations can be read
4495 gtk_decorated_window_calculate_frame_size (window);
4497 /* We only send configure request if we didn't just finish
4498 * creating the window; if we just created the window
4499 * then we created it with widget->allocation anyhow.
4502 gdk_window_move_resize (widget->window,
4503 configure_request.x,
4504 configure_request.y,
4505 configure_request.width,
4506 configure_request.height);
4509 gtk_container_check_resize (container);
4511 gtk_widget_map (widget);
4513 /* Try to make sure that we have some focused widget
4515 if (!window->focus_widget && !GTK_IS_PLUG (window))
4516 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4519 gtk_grab_add (widget);
4523 gtk_window_hide (GtkWidget *widget)
4525 GtkWindow *window = GTK_WINDOW (widget);
4527 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4528 gtk_widget_unmap (widget);
4531 gtk_grab_remove (widget);
4535 gtk_window_map (GtkWidget *widget)
4537 GtkWindow *window = GTK_WINDOW (widget);
4538 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4539 GdkWindow *toplevel;
4541 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4543 if (window->bin.child &&
4544 GTK_WIDGET_VISIBLE (window->bin.child) &&
4545 !GTK_WIDGET_MAPPED (window->bin.child))
4546 gtk_widget_map (window->bin.child);
4549 toplevel = window->frame;
4551 toplevel = widget->window;
4553 if (window->maximize_initially)
4554 gdk_window_maximize (toplevel);
4556 gdk_window_unmaximize (toplevel);
4558 if (window->stick_initially)
4559 gdk_window_stick (toplevel);
4561 gdk_window_unstick (toplevel);
4563 if (window->iconify_initially)
4564 gdk_window_iconify (toplevel);
4566 gdk_window_deiconify (toplevel);
4568 if (priv->fullscreen_initially)
4569 gdk_window_fullscreen (toplevel);
4571 gdk_window_unfullscreen (toplevel);
4573 gdk_window_set_keep_above (toplevel, priv->above_initially);
4575 gdk_window_set_keep_below (toplevel, priv->below_initially);
4577 /* No longer use the default settings */
4578 window->need_default_size = FALSE;
4579 window->need_default_position = FALSE;
4581 if (priv->reset_type_hint)
4583 /* We should only reset the type hint when the application
4584 * used gtk_window_set_type_hint() to change the hint.
4585 * Some applications use X directly to change the properties;
4586 * in that case, we shouldn't overwrite what they did.
4588 gdk_window_set_type_hint (widget->window, priv->type_hint);
4589 priv->reset_type_hint = FALSE;
4592 gdk_window_show (widget->window);
4595 gdk_window_show (window->frame);
4597 if (!disable_startup_notification)
4599 /* Do we have a custom startup-notification id? */
4600 if (priv->startup_id != NULL)
4602 /* Make sure we have a "real" id */
4603 if (!startup_id_is_fake (priv->startup_id))
4604 gdk_notify_startup_complete_with_id (priv->startup_id);
4606 g_free (priv->startup_id);
4607 priv->startup_id = NULL;
4609 else if (!sent_startup_notification)
4611 sent_startup_notification = TRUE;
4612 gdk_notify_startup_complete ();
4618 gtk_window_map_event (GtkWidget *widget,
4621 if (!GTK_WIDGET_MAPPED (widget))
4623 /* we should be be unmapped, but are getting a MapEvent, this may happen
4624 * to toplevel XWindows if mapping was intercepted by a window manager
4625 * and an unmap request occoured while the MapRequestEvent was still
4626 * being handled. we work around this situaiton here by re-requesting
4627 * the window being unmapped. more details can be found in:
4628 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4630 gdk_window_hide (widget->window);
4636 gtk_window_unmap (GtkWidget *widget)
4638 GtkWindow *window = GTK_WINDOW (widget);
4639 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
4640 GtkWindowGeometryInfo *info;
4641 GdkWindowState state;
4643 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4645 gdk_window_withdraw (window->frame);
4647 gdk_window_withdraw (widget->window);
4649 window->configure_request_count = 0;
4650 window->configure_notify_received = FALSE;
4652 /* on unmap, we reset the default positioning of the window,
4653 * so it's placed again, but we don't reset the default
4654 * size of the window, so it's remembered.
4656 window->need_default_position = TRUE;
4658 info = gtk_window_get_geometry_info (window, FALSE);
4661 info->initial_pos_set = FALSE;
4662 info->position_constraints_changed = FALSE;
4665 state = gdk_window_get_state (widget->window);
4666 window->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4667 window->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4668 window->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4669 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4670 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4674 gtk_window_realize (GtkWidget *widget)
4677 GdkWindow *parent_window;
4678 GdkWindowAttr attributes;
4679 gint attributes_mask;
4680 GtkWindowPrivate *priv;
4682 window = GTK_WINDOW (widget);
4683 priv = GTK_WINDOW_GET_PRIVATE (window);
4685 /* ensure widget tree is properly size allocated */
4686 if (widget->allocation.x == -1 &&
4687 widget->allocation.y == -1 &&
4688 widget->allocation.width == 1 &&
4689 widget->allocation.height == 1)
4691 GtkRequisition requisition;
4692 GtkAllocation allocation = { 0, 0, 200, 200 };
4694 gtk_widget_size_request (widget, &requisition);
4695 if (requisition.width || requisition.height)
4697 /* non-empty window */
4698 allocation.width = requisition.width;
4699 allocation.height = requisition.height;
4701 gtk_widget_size_allocate (widget, &allocation);
4703 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4705 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
4708 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4710 switch (window->type)
4712 case GTK_WINDOW_TOPLEVEL:
4713 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4715 case GTK_WINDOW_POPUP:
4716 attributes.window_type = GDK_WINDOW_TEMP;
4719 g_warning (G_STRLOC": Unknown window type %d!", window->type);
4723 attributes.title = window->title;
4724 attributes.wmclass_name = window->wmclass_name;
4725 attributes.wmclass_class = window->wmclass_class;
4726 attributes.wclass = GDK_INPUT_OUTPUT;
4727 attributes.visual = gtk_widget_get_visual (widget);
4728 attributes.colormap = gtk_widget_get_colormap (widget);
4730 if (window->has_frame)
4732 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
4733 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
4734 attributes.event_mask = (GDK_EXPOSURE_MASK |
4735 GDK_KEY_PRESS_MASK |
4736 GDK_ENTER_NOTIFY_MASK |
4737 GDK_LEAVE_NOTIFY_MASK |
4738 GDK_FOCUS_CHANGE_MASK |
4739 GDK_STRUCTURE_MASK |
4740 GDK_BUTTON_MOTION_MASK |
4741 GDK_POINTER_MOTION_HINT_MASK |
4742 GDK_BUTTON_PRESS_MASK |
4743 GDK_BUTTON_RELEASE_MASK);
4745 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4747 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4748 &attributes, attributes_mask);
4750 if (priv->opacity_set)
4751 gdk_window_set_opacity (window->frame, priv->opacity);
4753 gdk_window_set_user_data (window->frame, widget);
4755 attributes.window_type = GDK_WINDOW_CHILD;
4756 attributes.x = window->frame_left;
4757 attributes.y = window->frame_top;
4759 attributes_mask = GDK_WA_X | GDK_WA_Y;
4761 parent_window = window->frame;
4763 g_signal_connect (window,
4765 G_CALLBACK (gtk_window_event),
4770 attributes_mask = 0;
4771 parent_window = gtk_widget_get_root_window (widget);
4774 attributes.width = widget->allocation.width;
4775 attributes.height = widget->allocation.height;
4776 attributes.event_mask = gtk_widget_get_events (widget);
4777 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4778 GDK_KEY_PRESS_MASK |
4779 GDK_KEY_RELEASE_MASK |
4780 GDK_ENTER_NOTIFY_MASK |
4781 GDK_LEAVE_NOTIFY_MASK |
4782 GDK_FOCUS_CHANGE_MASK |
4783 GDK_STRUCTURE_MASK);
4784 attributes.type_hint = priv->type_hint;
4786 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_TYPE_HINT;
4787 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
4788 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
4790 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
4792 if (!window->has_frame && priv->opacity_set)
4793 gdk_window_set_opacity (widget->window, priv->opacity);
4795 gdk_window_enable_synchronized_configure (widget->window);
4797 gdk_window_set_user_data (widget->window, window);
4799 widget->style = gtk_style_attach (widget->style, widget->window);
4800 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4802 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
4804 /* This is a bad hack to set the window background. */
4805 gtk_window_paint (widget, NULL);
4807 if (window->transient_parent &&
4808 GTK_WIDGET_REALIZED (window->transient_parent))
4809 gdk_window_set_transient_for (widget->window,
4810 GTK_WIDGET (window->transient_parent)->window);
4812 if (window->wm_role)
4813 gdk_window_set_role (widget->window, window->wm_role);
4815 if (!window->decorated)
4816 gdk_window_set_decorations (widget->window, 0);
4818 if (!priv->deletable)
4819 gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4821 if (gtk_window_get_skip_pager_hint (window))
4822 gdk_window_set_skip_pager_hint (widget->window, TRUE);
4824 if (gtk_window_get_skip_taskbar_hint (window))
4825 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
4827 if (gtk_window_get_accept_focus (window))
4828 gdk_window_set_accept_focus (widget->window, TRUE);
4830 gdk_window_set_accept_focus (widget->window, FALSE);
4832 if (gtk_window_get_focus_on_map (window))
4833 gdk_window_set_focus_on_map (widget->window, TRUE);
4835 gdk_window_set_focus_on_map (widget->window, FALSE);
4838 gdk_window_set_modal_hint (widget->window, TRUE);
4840 gdk_window_set_modal_hint (widget->window, FALSE);
4842 if (priv->startup_id)
4844 #ifdef GDK_WINDOWING_X11
4845 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4846 if (timestamp != GDK_CURRENT_TIME)
4847 gdk_x11_window_set_user_time (widget->window, timestamp);
4849 if (!startup_id_is_fake (priv->startup_id))
4850 gdk_window_set_startup_id (widget->window, priv->startup_id);
4854 gtk_window_realize_icon (window);
4858 gtk_window_unrealize (GtkWidget *widget)
4861 GtkWindowGeometryInfo *info;
4863 window = GTK_WINDOW (widget);
4865 /* On unrealize, we reset the size of the window such
4866 * that we will re-apply the default sizing stuff
4867 * next time we show the window.
4869 * Default positioning is reset on unmap, instead of unrealize.
4871 window->need_default_size = TRUE;
4872 info = gtk_window_get_geometry_info (window, FALSE);
4875 info->resize_width = -1;
4876 info->resize_height = -1;
4877 info->last.configure_request.x = 0;
4878 info->last.configure_request.y = 0;
4879 info->last.configure_request.width = -1;
4880 info->last.configure_request.height = -1;
4881 /* be sure we reset geom hints on re-realize */
4882 info->last.flags = 0;
4887 gdk_window_set_user_data (window->frame, NULL);
4888 gdk_window_destroy (window->frame);
4889 window->frame = NULL;
4893 gtk_window_unrealize_icon (window);
4895 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
4899 gtk_window_size_request (GtkWidget *widget,
4900 GtkRequisition *requisition)
4905 window = GTK_WINDOW (widget);
4906 bin = GTK_BIN (window);
4908 requisition->width = GTK_CONTAINER (window)->border_width * 2;
4909 requisition->height = GTK_CONTAINER (window)->border_width * 2;
4911 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
4913 GtkRequisition child_requisition;
4915 gtk_widget_size_request (bin->child, &child_requisition);
4917 requisition->width += child_requisition.width;
4918 requisition->height += child_requisition.height;
4923 gtk_window_size_allocate (GtkWidget *widget,
4924 GtkAllocation *allocation)
4927 GtkAllocation child_allocation;
4929 window = GTK_WINDOW (widget);
4930 widget->allocation = *allocation;
4932 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
4934 child_allocation.x = GTK_CONTAINER (window)->border_width;
4935 child_allocation.y = GTK_CONTAINER (window)->border_width;
4936 child_allocation.width =
4937 MAX (1, (gint)allocation->width - child_allocation.x * 2);
4938 child_allocation.height =
4939 MAX (1, (gint)allocation->height - child_allocation.y * 2);
4941 gtk_widget_size_allocate (window->bin.child, &child_allocation);
4944 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4946 gdk_window_resize (window->frame,
4947 allocation->width + window->frame_left + window->frame_right,
4948 allocation->height + window->frame_top + window->frame_bottom);
4953 gtk_window_event (GtkWidget *widget, GdkEvent *event)
4956 gboolean return_val;
4958 window = GTK_WINDOW (widget);
4960 if (window->frame && (event->any.window == window->frame))
4962 if ((event->type != GDK_KEY_PRESS) &&
4963 (event->type != GDK_KEY_RELEASE) &&
4964 (event->type != GDK_FOCUS_CHANGE))
4966 g_signal_stop_emission_by_name (widget, "event");
4968 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
4973 g_object_unref (event->any.window);
4974 event->any.window = g_object_ref (widget->window);
4982 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
4984 GdkEventConfigure *configure_event;
4987 switch (event->type)
4990 configure_event = (GdkEventConfigure *)event;
4992 /* Invalidate the decorations */
4995 rect.width = configure_event->width;
4996 rect.height = configure_event->height;
4998 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
5000 /* Pass on the (modified) configure event */
5001 configure_event->width -= window->frame_left + window->frame_right;
5002 configure_event->height -= window->frame_top + window->frame_bottom;
5003 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
5012 gtk_window_configure_event (GtkWidget *widget,
5013 GdkEventConfigure *event)
5015 GtkWindow *window = GTK_WINDOW (widget);
5016 gboolean expected_reply = window->configure_request_count > 0;
5018 /* window->configure_request_count incremented for each
5019 * configure request, and decremented to a min of 0 for
5020 * each configure notify.
5022 * All it means is that we know we will get at least
5023 * window->configure_request_count more configure notifies.
5024 * We could get more configure notifies than that; some
5025 * of the configure notifies we get may be unrelated to
5026 * the configure requests. But we will get at least
5027 * window->configure_request_count notifies.
5030 if (window->configure_request_count > 0)
5032 window->configure_request_count -= 1;
5033 gdk_window_thaw_toplevel_updates_libgtk_only (widget->window);
5036 /* As an optimization, we avoid a resize when possible.
5038 * The only times we can avoid a resize are:
5039 * - we know only the position changed, not the size
5040 * - we know we have made more requests and so will get more
5041 * notifies and can wait to resize when we get them
5044 if (!expected_reply &&
5045 (widget->allocation.width == event->width &&
5046 widget->allocation.height == event->height))
5048 gdk_window_configure_finished (widget->window);
5053 * If we do need to resize, we do that by:
5054 * - filling in widget->allocation with the new size
5055 * - setting configure_notify_received to TRUE
5056 * for use in gtk_window_move_resize()
5057 * - queueing a resize, leading to invocation of
5058 * gtk_window_move_resize() in an idle handler
5062 window->configure_notify_received = TRUE;
5064 widget->allocation.width = event->width;
5065 widget->allocation.height = event->height;
5067 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5072 /* the accel_key and accel_mods fields of the key have to be setup
5073 * upon calling this function. it'll then return whether that key
5074 * is at all used as accelerator, and if so will OR in the
5075 * accel_flags member of the key.
5078 _gtk_window_query_nonaccels (GtkWindow *window,
5080 GdkModifierType accel_mods)
5082 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5084 /* movement keys are considered locked accels */
5087 static const guint bindings[] = {
5088 GDK_space, GDK_KP_Space, GDK_Return, GDK_ISO_Enter, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
5089 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
5093 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5094 if (bindings[i] == accel_key)
5098 /* mnemonics are considered locked accels */
5099 if (accel_mods == window->mnemonic_modifier)
5101 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5102 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5110 * gtk_window_propagate_key_event:
5111 * @window: a #GtkWindow
5112 * @event: a #GdkEventKey
5114 * Propagate a key press or release event to the focus widget and
5115 * up the focus container chain until a widget handles @event.
5116 * This is normally called by the default ::key_press_event and
5117 * ::key_release_event handlers for toplevel windows,
5118 * however in some cases it may be useful to call this directly when
5119 * overriding the standard key handling for a toplevel window.
5121 * Return value: %TRUE if a widget in the focus chain handled the event.
5126 gtk_window_propagate_key_event (GtkWindow *window,
5129 gboolean handled = FALSE;
5130 GtkWidget *widget, *focus;
5132 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5134 widget = GTK_WIDGET (window);
5135 focus = window->focus_widget;
5137 g_object_ref (focus);
5140 focus && focus != widget &&
5141 gtk_widget_get_toplevel (focus) == widget)
5145 if (GTK_WIDGET_IS_SENSITIVE (focus))
5146 handled = gtk_widget_event (focus, (GdkEvent*) event);
5148 parent = focus->parent;
5150 g_object_ref (parent);
5152 g_object_unref (focus);
5158 g_object_unref (focus);
5164 gtk_window_key_press_event (GtkWidget *widget,
5167 GtkWindow *window = GTK_WINDOW (widget);
5168 gboolean handled = FALSE;
5170 /* handle mnemonics and accelerators */
5172 handled = gtk_window_activate_key (window, event);
5174 /* handle focus widget key events */
5176 handled = gtk_window_propagate_key_event (window, event);
5178 /* Chain up, invokes binding set */
5180 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5186 gtk_window_key_release_event (GtkWidget *widget,
5189 GtkWindow *window = GTK_WINDOW (widget);
5190 gboolean handled = FALSE;
5192 /* handle focus widget key events */
5194 handled = gtk_window_propagate_key_event (window, event);
5196 /* Chain up, invokes binding set */
5198 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5204 gtk_window_real_activate_default (GtkWindow *window)
5206 gtk_window_activate_default (window);
5210 gtk_window_real_activate_focus (GtkWindow *window)
5212 gtk_window_activate_focus (window);
5216 gtk_window_move_focus (GtkWindow *window,
5217 GtkDirectionType dir)
5219 gtk_widget_child_focus (GTK_WIDGET (window), dir);
5221 if (!GTK_CONTAINER (window)->focus_child)
5222 gtk_window_set_focus (window, NULL);
5226 gtk_window_enter_notify_event (GtkWidget *widget,
5227 GdkEventCrossing *event)
5233 gtk_window_leave_notify_event (GtkWidget *widget,
5234 GdkEventCrossing *event)
5240 do_focus_change (GtkWidget *widget,
5243 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5245 g_object_ref (widget);
5248 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
5250 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
5252 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5253 fevent->focus_change.window = widget->window;
5255 g_object_ref (widget->window);
5256 fevent->focus_change.in = in;
5258 gtk_widget_event (widget, fevent);
5260 g_object_notify (G_OBJECT (widget), "has-focus");
5262 g_object_unref (widget);
5263 gdk_event_free (fevent);
5267 gtk_window_focus_in_event (GtkWidget *widget,
5268 GdkEventFocus *event)
5270 GtkWindow *window = GTK_WINDOW (widget);
5272 /* It appears spurious focus in events can occur when
5273 * the window is hidden. So we'll just check to see if
5274 * the window is visible before actually handling the
5277 if (GTK_WIDGET_VISIBLE (widget))
5279 _gtk_window_set_has_toplevel_focus (window, TRUE);
5280 _gtk_window_set_is_active (window, TRUE);
5287 gtk_window_focus_out_event (GtkWidget *widget,
5288 GdkEventFocus *event)
5290 GtkWindow *window = GTK_WINDOW (widget);
5292 _gtk_window_set_has_toplevel_focus (window, FALSE);
5293 _gtk_window_set_is_active (window, FALSE);
5298 static GdkAtom atom_rcfiles = GDK_NONE;
5299 static GdkAtom atom_iconthemes = GDK_NONE;
5302 send_client_message_to_embedded_windows (GtkWidget *widget,
5303 GdkAtom message_type)
5305 GList *embedded_windows;
5307 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5308 if (embedded_windows)
5310 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5313 for (i = 0; i < 5; i++)
5314 send_event->client.data.l[i] = 0;
5315 send_event->client.data_format = 32;
5316 send_event->client.message_type = message_type;
5318 while (embedded_windows)
5320 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
5321 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5322 embedded_windows = embedded_windows->next;
5325 gdk_event_free (send_event);
5330 gtk_window_client_event (GtkWidget *widget,
5331 GdkEventClient *event)
5335 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5336 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5339 if (event->message_type == atom_rcfiles)
5341 send_client_message_to_embedded_windows (widget, atom_rcfiles);
5342 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
5345 if (event->message_type == atom_iconthemes)
5347 send_client_message_to_embedded_windows (widget, atom_iconthemes);
5348 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
5355 gtk_window_check_resize (GtkContainer *container)
5357 GtkWindow *window = GTK_WINDOW (container);
5359 if (GTK_WIDGET_VISIBLE (container))
5360 gtk_window_move_resize (window);
5364 gtk_window_focus (GtkWidget *widget,
5365 GtkDirectionType direction)
5369 GtkContainer *container;
5370 GtkWidget *old_focus_child;
5373 container = GTK_CONTAINER (widget);
5374 window = GTK_WINDOW (widget);
5375 bin = GTK_BIN (widget);
5377 old_focus_child = container->focus_child;
5379 /* We need a special implementation here to deal properly with wrapping
5380 * around in the tab chain without the danger of going into an
5383 if (old_focus_child)
5385 if (gtk_widget_child_focus (old_focus_child, direction))
5389 if (window->focus_widget)
5391 if (direction == GTK_DIR_LEFT ||
5392 direction == GTK_DIR_RIGHT ||
5393 direction == GTK_DIR_UP ||
5394 direction == GTK_DIR_DOWN)
5399 /* Wrapped off the end, clear the focus setting for the toplpevel */
5400 parent = window->focus_widget->parent;
5403 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5404 parent = GTK_WIDGET (parent)->parent;
5407 gtk_window_set_focus (GTK_WINDOW (container), NULL);
5410 /* Now try to focus the first widget in the window */
5413 if (gtk_widget_child_focus (bin->child, direction))
5421 gtk_window_real_set_focus (GtkWindow *window,
5424 GtkWidget *old_focus = window->focus_widget;
5425 gboolean had_default = FALSE;
5426 gboolean focus_had_default = FALSE;
5427 gboolean old_focus_had_default = FALSE;
5431 g_object_ref (old_focus);
5432 g_object_freeze_notify (G_OBJECT (old_focus));
5433 old_focus_had_default = GTK_WIDGET_HAS_DEFAULT (old_focus);
5437 g_object_ref (focus);
5438 g_object_freeze_notify (G_OBJECT (focus));
5439 focus_had_default = GTK_WIDGET_HAS_DEFAULT (focus);
5442 if (window->default_widget)
5443 had_default = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
5445 if (window->focus_widget)
5447 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
5448 (window->focus_widget != window->default_widget))
5450 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
5451 gtk_widget_queue_draw (window->focus_widget);
5453 if (window->default_widget)
5454 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
5457 window->focus_widget = NULL;
5459 if (window->has_focus)
5460 do_focus_change (old_focus, FALSE);
5462 g_object_notify (G_OBJECT (old_focus), "is-focus");
5465 /* The above notifications may have set a new focus widget,
5466 * if so, we don't want to override it.
5468 if (focus && !window->focus_widget)
5470 window->focus_widget = focus;
5472 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
5473 (window->focus_widget != window->default_widget))
5475 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
5476 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
5478 if (window->default_widget)
5479 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
5482 if (window->has_focus)
5483 do_focus_change (window->focus_widget, TRUE);
5485 g_object_notify (G_OBJECT (window->focus_widget), "is-focus");
5488 /* If the default widget changed, a redraw will have been queued
5489 * on the old and new default widgets by gtk_window_set_default(), so
5490 * we only have to worry about the case where it didn't change.
5491 * We'll sometimes queue a draw twice on the new widget but that
5494 if (window->default_widget &&
5495 (had_default != GTK_WIDGET_HAS_DEFAULT (window->default_widget)))
5496 gtk_widget_queue_draw (window->default_widget);
5500 if (old_focus_had_default != GTK_WIDGET_HAS_DEFAULT (old_focus))
5501 gtk_widget_queue_draw (old_focus);
5503 g_object_thaw_notify (G_OBJECT (old_focus));
5504 g_object_unref (old_focus);
5508 if (focus_had_default != GTK_WIDGET_HAS_DEFAULT (focus))
5509 gtk_widget_queue_draw (focus);
5511 g_object_thaw_notify (G_OBJECT (focus));
5512 g_object_unref (focus);
5517 * _gtk_window_unset_focus_and_default:
5518 * @window: a #GtkWindow
5519 * @widget: a widget inside of @window
5521 * Checks whether the focus and default widgets of @window are
5522 * @widget or a descendent of @widget, and if so, unset them.
5525 _gtk_window_unset_focus_and_default (GtkWindow *window,
5531 g_object_ref (window);
5532 g_object_ref (widget);
5534 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
5536 child = window->focus_widget;
5538 while (child && child != widget)
5539 child = child->parent;
5541 if (child == widget)
5542 gtk_window_set_focus (GTK_WINDOW (window), NULL);
5545 child = window->default_widget;
5547 while (child && child != widget)
5548 child = child->parent;
5550 if (child == widget)
5551 gtk_window_set_default (window, NULL);
5553 g_object_unref (widget);
5554 g_object_unref (window);
5557 /*********************************
5558 * Functions related to resizing *
5559 *********************************/
5561 /* This function doesn't constrain to geometry hints */
5563 gtk_window_compute_configure_request_size (GtkWindow *window,
5567 GtkRequisition requisition;
5568 GtkWindowGeometryInfo *info;
5572 * - we've done a size request
5575 widget = GTK_WIDGET (window);
5577 info = gtk_window_get_geometry_info (window, FALSE);
5579 if (window->need_default_size)
5581 gtk_widget_get_child_requisition (widget, &requisition);
5583 /* Default to requisition */
5584 *width = requisition.width;
5585 *height = requisition.height;
5587 /* If window is empty so requests 0, default to random nonzero size */
5588 if (*width == 0 && *height == 0)
5594 /* Override requisition with default size */
5598 gint base_width = 0;
5599 gint base_height = 0;
5601 gint min_height = 0;
5603 gint height_inc = 1;
5605 if (info->default_is_geometry &&
5606 (info->default_width > 0 || info->default_height > 0))
5608 GdkGeometry geometry;
5611 gtk_window_compute_hints (window, &geometry, &flags);
5613 if (flags & GDK_HINT_BASE_SIZE)
5615 base_width = geometry.base_width;
5616 base_height = geometry.base_height;
5618 if (flags & GDK_HINT_MIN_SIZE)
5620 min_width = geometry.min_width;
5621 min_height = geometry.min_height;
5623 if (flags & GDK_HINT_RESIZE_INC)
5625 width_inc = geometry.width_inc;
5626 height_inc = geometry.height_inc;
5630 if (info->default_width > 0)
5631 *width = MAX (info->default_width * width_inc + base_width, min_width);
5633 if (info->default_height > 0)
5634 *height = MAX (info->default_height * height_inc + base_height, min_height);
5639 /* Default to keeping current size */
5640 *width = widget->allocation.width;
5641 *height = widget->allocation.height;
5644 /* Override any size with gtk_window_resize() values */
5647 if (info->resize_width > 0)
5648 *width = info->resize_width;
5650 if (info->resize_height > 0)
5651 *height = info->resize_height;
5654 /* Don't ever request zero width or height, its not supported by
5655 gdk. The size allocation code will round it to 1 anyway but if
5656 we do it then the value returned from this function will is
5657 not comparable to the size allocation read from the GtkWindow. */
5658 *width = MAX (*width, 1);
5659 *height = MAX (*height, 1);
5662 static GtkWindowPosition
5663 get_effective_position (GtkWindow *window)
5665 GtkWindowPosition pos = window->position;
5666 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5667 (window->transient_parent == NULL ||
5668 !GTK_WIDGET_MAPPED (window->transient_parent)))
5669 pos = GTK_WIN_POS_NONE;
5675 get_center_monitor_of_window (GtkWindow *window)
5677 /* We could try to sort out the relative positions of the monitors and
5678 * stuff, or we could just be losers and assume you have a row
5679 * or column of monitors.
5681 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5685 get_monitor_containing_pointer (GtkWindow *window)
5689 GdkScreen *window_screen;
5690 GdkScreen *pointer_screen;
5692 window_screen = gtk_window_check_screen (window);
5693 gdk_display_get_pointer (gdk_screen_get_display (window_screen),
5697 if (pointer_screen == window_screen)
5698 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5706 center_window_on_monitor (GtkWindow *window,
5712 GdkRectangle monitor;
5715 monitor_num = get_monitor_containing_pointer (window);
5717 if (monitor_num == -1)
5718 monitor_num = get_center_monitor_of_window (window);
5720 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5721 monitor_num, &monitor);
5723 *x = (monitor.width - w) / 2 + monitor.x;
5724 *y = (monitor.height - h) / 2 + monitor.y;
5726 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5727 * and WM decorations.
5741 if (extent > clamp_extent)
5743 *base = clamp_base + clamp_extent/2 - extent/2;
5744 else if (*base < clamp_base)
5746 else if (*base + extent > clamp_base + clamp_extent)
5747 *base = clamp_base + clamp_extent - extent;
5751 clamp_window_to_rectangle (gint *x,
5755 const GdkRectangle *rect)
5757 #ifdef DEBUGGING_OUTPUT
5758 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);
5761 /* If it is too large, center it. If it fits on the monitor but is
5762 * partially outside, move it to the closest edge. Do this
5763 * separately in x and y directions.
5765 clamp (x, w, rect->x, rect->width);
5766 clamp (y, h, rect->y, rect->height);
5767 #ifdef DEBUGGING_OUTPUT
5768 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
5774 gtk_window_compute_configure_request (GtkWindow *window,
5775 GdkRectangle *request,
5776 GdkGeometry *geometry,
5779 GdkGeometry new_geometry;
5783 GtkWindowPosition pos;
5784 GtkWidget *parent_widget;
5785 GtkWindowGeometryInfo *info;
5789 widget = GTK_WIDGET (window);
5791 screen = gtk_window_check_screen (window);
5793 gtk_widget_size_request (widget, NULL);
5794 gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
5796 gtk_window_compute_hints (window, &new_geometry, &new_flags);
5797 gtk_window_constrain_size (window,
5798 &new_geometry, new_flags,
5802 parent_widget = (GtkWidget*) window->transient_parent;
5804 pos = get_effective_position (window);
5805 info = gtk_window_get_geometry_info (window, FALSE);
5807 /* by default, don't change position requested */
5810 x = info->last.configure_request.x;
5811 y = info->last.configure_request.y;
5820 if (window->need_default_position)
5823 /* FIXME this all interrelates with window gravity.
5824 * For most of them I think we want to set GRAVITY_CENTER.
5826 * Not sure how to go about that.
5831 /* here we are only handling CENTER_ALWAYS
5832 * as it relates to default positioning,
5833 * where it's equivalent to simply CENTER
5835 case GTK_WIN_POS_CENTER_ALWAYS:
5836 case GTK_WIN_POS_CENTER:
5837 center_window_on_monitor (window, w, h, &x, &y);
5840 case GTK_WIN_POS_CENTER_ON_PARENT:
5843 GdkRectangle monitor;
5846 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
5848 if (parent_widget->window != NULL)
5849 monitor_num = gdk_screen_get_monitor_at_window (screen,
5850 parent_widget->window);
5854 gdk_window_get_origin (parent_widget->window,
5857 x = ox + (parent_widget->allocation.width - w) / 2;
5858 y = oy + (parent_widget->allocation.height - h) / 2;
5860 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5861 * WM decorations. If parent wasn't on a monitor, just
5864 if (monitor_num >= 0)
5866 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5867 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5872 case GTK_WIN_POS_MOUSE:
5874 gint screen_width = gdk_screen_get_width (screen);
5875 gint screen_height = gdk_screen_get_height (screen);
5877 GdkRectangle monitor;
5878 GdkScreen *pointer_screen;
5881 gdk_display_get_pointer (gdk_screen_get_display (screen),
5885 if (pointer_screen == screen)
5886 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
5892 x = CLAMP (x, 0, screen_width - w);
5893 y = CLAMP (y, 0, screen_height - h);
5895 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5896 * WM decorations. Don't try to figure out what's going
5897 * on if the mouse wasn't inside a monitor.
5899 if (monitor_num >= 0)
5901 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5902 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5910 } /* if (window->need_default_position) */
5912 if (window->need_default_position && info &&
5913 info->initial_pos_set)
5915 x = info->initial_x;
5916 y = info->initial_y;
5917 gtk_window_constrain_position (window, w, h, &x, &y);
5923 request->height = h;
5926 *geometry = new_geometry;
5932 gtk_window_constrain_position (GtkWindow *window,
5938 /* See long comments in gtk_window_move_resize()
5939 * on when it's safe to call this function.
5941 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
5943 gint center_x, center_y;
5945 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
5953 gtk_window_move_resize (GtkWindow *window)
5957 * First we determine whether any information has changed that would
5958 * cause us to revise our last configure request. If we would send
5959 * a different configure request from last time, then
5960 * configure_request_size_changed = TRUE or
5961 * configure_request_pos_changed = TRUE. configure_request_size_changed
5962 * may be true due to new hints, a gtk_window_resize(), or whatever.
5963 * configure_request_pos_changed may be true due to gtk_window_set_position()
5964 * or gtk_window_move().
5966 * If the configure request has changed, we send off a new one. To
5967 * ensure GTK+ invariants are maintained (resize queue does what it
5968 * should), we go ahead and size_allocate the requested size in this
5971 * If the configure request has not changed, we don't ever resend
5972 * it, because it could mean fighting the user or window manager.
5975 * To prepare the configure request, we come up with a base size/pos:
5976 * - the one from gtk_window_move()/gtk_window_resize()
5977 * - else default_width, default_height if we haven't ever
5979 * - else the size request if we haven't ever been mapped,
5980 * as a substitute default size
5981 * - else the current size of the window, as received from
5982 * configure notifies (i.e. the current allocation)
5984 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
5985 * the position request to be centered.
5988 GtkContainer *container;
5989 GtkWindowGeometryInfo *info;
5990 GdkGeometry new_geometry;
5992 GdkRectangle new_request;
5993 gboolean configure_request_size_changed;
5994 gboolean configure_request_pos_changed;
5995 gboolean hints_changed; /* do we need to send these again */
5996 GtkWindowLastGeometryInfo saved_last_info;
5998 widget = GTK_WIDGET (window);
5999 container = GTK_CONTAINER (widget);
6000 info = gtk_window_get_geometry_info (window, TRUE);
6002 configure_request_size_changed = FALSE;
6003 configure_request_pos_changed = FALSE;
6005 gtk_window_compute_configure_request (window, &new_request,
6006 &new_geometry, &new_flags);
6008 /* This check implies the invariant that we never set info->last
6009 * without setting the hints and sending off a configure request.
6011 * If we change info->last without sending the request, we may
6014 if (info->last.configure_request.x != new_request.x ||
6015 info->last.configure_request.y != new_request.y)
6016 configure_request_pos_changed = TRUE;
6018 if ((info->last.configure_request.width != new_request.width ||
6019 info->last.configure_request.height != new_request.height))
6020 configure_request_size_changed = TRUE;
6022 hints_changed = FALSE;
6024 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6025 &new_geometry, new_flags))
6027 hints_changed = TRUE;
6030 /* Position Constraints
6031 * ====================
6033 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6034 * a default. The other POS_ values are used only when the
6035 * window is shown, not after that.
6037 * However, we can't implement a position constraint as
6038 * "anytime the window size changes, center the window"
6039 * because this may well end up fighting the WM or user. In
6040 * fact it gets in an infinite loop with at least one WM.
6042 * Basically, applications are in no way in a position to
6043 * constrain the position of a window, with one exception:
6044 * override redirect windows. (Really the intended purpose
6045 * of CENTER_ALWAYS anyhow, I would think.)
6047 * So the way we implement this "constraint" is to say that when WE
6048 * cause a move or resize, i.e. we make a configure request changing
6049 * window size, we recompute the CENTER_ALWAYS position to reflect
6050 * the new window size, and include it in our request. Also, if we
6051 * just turned on CENTER_ALWAYS we snap to center with a new
6052 * request. Otherwise, if we are just NOTIFIED of a move or resize
6053 * done by someone else e.g. the window manager, we do NOT send a
6054 * new configure request.
6056 * For override redirect windows, this works fine; all window
6057 * sizes are from our configure requests. For managed windows,
6058 * it is at least semi-sane, though who knows what the
6059 * app author is thinking.
6062 /* This condition should be kept in sync with the condition later on
6063 * that determines whether we send a configure request. i.e. we
6064 * should do this position constraining anytime we were going to
6065 * send a configure request anyhow, plus when constraints have
6068 if (configure_request_pos_changed ||
6069 configure_request_size_changed ||
6071 info->position_constraints_changed)
6073 /* We request the constrained position if:
6074 * - we were changing position, and need to clamp
6075 * the change to the constraint
6076 * - we're changing the size anyway
6077 * - set_position() was called to toggle CENTER_ALWAYS on
6080 gtk_window_constrain_position (window,
6086 /* Update whether we need to request a move */
6087 if (info->last.configure_request.x != new_request.x ||
6088 info->last.configure_request.y != new_request.y)
6089 configure_request_pos_changed = TRUE;
6091 configure_request_pos_changed = FALSE;
6095 if (window->type == GTK_WINDOW_TOPLEVEL)
6097 int notify_x, notify_y;
6099 /* this is the position from the last configure notify */
6100 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6102 g_message ("--- %s ---\n"
6103 "last : %d,%d\t%d x %d\n"
6104 "this : %d,%d\t%d x %d\n"
6105 "alloc : %d,%d\t%d x %d\n"
6107 "resize: \t%d x %d\n"
6108 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6109 "configure_notify_received: %d\n"
6110 "configure_request_count: %d\n"
6111 "position_constraints_changed: %d\n",
6112 window->title ? window->title : "(no title)",
6113 info->last.configure_request.x,
6114 info->last.configure_request.y,
6115 info->last.configure_request.width,
6116 info->last.configure_request.height,
6122 widget->allocation.width,
6123 widget->allocation.height,
6124 widget->requisition.width,
6125 widget->requisition.height,
6127 info->resize_height,
6128 configure_request_pos_changed,
6129 configure_request_size_changed,
6131 window->configure_notify_received,
6132 window->configure_request_count,
6133 info->position_constraints_changed);
6137 saved_last_info = info->last;
6138 info->last.geometry = new_geometry;
6139 info->last.flags = new_flags;
6140 info->last.configure_request = new_request;
6142 /* need to set PPosition so the WM will look at our position,
6143 * but we don't want to count PPosition coming and going as a hints
6144 * change for future iterations. So we saved info->last prior to
6148 /* Also, if the initial position was explicitly set, then we always
6149 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6153 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6154 * this is an initial map
6157 if ((configure_request_pos_changed ||
6158 info->initial_pos_set ||
6159 (window->need_default_position &&
6160 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6161 (new_flags & GDK_HINT_POS) == 0)
6163 new_flags |= GDK_HINT_POS;
6164 hints_changed = TRUE;
6167 /* Set hints if necessary
6170 gdk_window_set_geometry_hints (widget->window,
6174 /* handle resizing/moving and widget tree allocation
6176 if (window->configure_notify_received)
6178 GtkAllocation allocation;
6180 /* If we have received a configure event since
6181 * the last time in this function, we need to
6182 * accept our new size and size_allocate child widgets.
6183 * (see gtk_window_configure_event() for more details).
6185 * 1 or more configure notifies may have been received.
6186 * Also, configure_notify_received will only be TRUE
6187 * if all expected configure notifies have been received
6188 * (one per configure request), as an optimization.
6191 window->configure_notify_received = FALSE;
6193 /* gtk_window_configure_event() filled in widget->allocation */
6194 allocation = widget->allocation;
6195 gtk_widget_size_allocate (widget, &allocation);
6197 gdk_window_process_updates (widget->window, TRUE);
6199 gdk_window_configure_finished (widget->window);
6201 /* If the configure request changed, it means that
6203 * 1) coincidentally changed hints or widget properties
6204 * impacting the configure request before getting
6205 * a configure notify, or
6206 * 2) some broken widget is changing its size request
6207 * during size allocation, resulting in
6208 * a false appearance of changed configure request.
6210 * For 1), we could just go ahead and ask for the
6211 * new size right now, but doing that for 2)
6212 * might well be fighting the user (and can even
6213 * trigger a loop). Since we really don't want to
6214 * do that, we requeue a resize in hopes that
6215 * by the time it gets handled, the child has seen
6216 * the light and is willing to go along with the
6217 * new size. (this happens for the zvt widget, since
6218 * the size_allocate() above will have stored the
6219 * requisition corresponding to the new size in the
6222 * This doesn't buy us anything for 1), but it shouldn't
6223 * hurt us too badly, since it is what would have
6224 * happened if we had gotten the configure event before
6225 * the new size had been set.
6228 if (configure_request_size_changed ||
6229 configure_request_pos_changed)
6231 /* Don't change the recorded last info after all, because we
6232 * haven't actually updated to the new info yet - we decided
6233 * to postpone our configure request until later.
6235 info->last = saved_last_info;
6237 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6240 return; /* Bail out, we didn't really process the move/resize */
6242 else if ((configure_request_size_changed || hints_changed) &&
6243 (widget->allocation.width != new_request.width ||
6244 widget->allocation.height != new_request.height))
6247 /* We are in one of the following situations:
6248 * A. configure_request_size_changed
6249 * our requisition has changed and we need a different window size,
6250 * so we request it from the window manager.
6251 * B. !configure_request_size_changed && hints_changed
6252 * the window manager rejects our size, but we have just changed the
6253 * window manager hints, so there's a chance our request will
6254 * be honoured this time, so we try again.
6256 * However, if the new requisition is the same as the current allocation,
6257 * we don't request it again, since we won't get a ConfigureNotify back from
6258 * the window manager unless it decides to change our requisition. If
6259 * we don't get the ConfigureNotify back, the resize queue will never be run.
6262 /* Now send the configure request */
6263 if (configure_request_pos_changed)
6267 gdk_window_move_resize (window->frame,
6268 new_request.x - window->frame_left,
6269 new_request.y - window->frame_top,
6270 new_request.width + window->frame_left + window->frame_right,
6271 new_request.height + window->frame_top + window->frame_bottom);
6272 gdk_window_resize (widget->window,
6273 new_request.width, new_request.height);
6276 gdk_window_move_resize (widget->window,
6277 new_request.x, new_request.y,
6278 new_request.width, new_request.height);
6280 else /* only size changed */
6283 gdk_window_resize (window->frame,
6284 new_request.width + window->frame_left + window->frame_right,
6285 new_request.height + window->frame_top + window->frame_bottom);
6286 gdk_window_resize (widget->window,
6287 new_request.width, new_request.height);
6290 if (window->type == GTK_WINDOW_POPUP)
6292 GtkAllocation allocation;
6294 /* Directly size allocate for override redirect (popup) windows. */
6297 allocation.width = new_request.width;
6298 allocation.height = new_request.height;
6300 gtk_widget_size_allocate (widget, &allocation);
6302 gdk_window_process_updates (widget->window, TRUE);
6304 if (container->resize_mode == GTK_RESIZE_QUEUE)
6305 gtk_widget_queue_draw (widget);
6309 /* Increment the number of have-not-yet-received-notify requests */
6310 window->configure_request_count += 1;
6311 gdk_window_freeze_toplevel_updates_libgtk_only (widget->window);
6313 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6314 * configure event in response to our resizing request.
6315 * the configure event will cause a new resize with
6316 * ->configure_notify_received=TRUE.
6317 * until then, we want to
6318 * - discard expose events
6319 * - coalesce resizes for our children
6320 * - defer any window resizes until the configure event arrived
6321 * to achieve this, we queue a resize for the window, but remove its
6322 * resizing handler, so resizing will not be handled from the next
6323 * idle handler but when the configure event arrives.
6325 * FIXME: we should also dequeue the pending redraws here, since
6326 * we handle those ourselves upon ->configure_notify_received==TRUE.
6328 if (container->resize_mode == GTK_RESIZE_QUEUE)
6330 gtk_widget_queue_resize_no_redraw (widget);
6331 _gtk_container_dequeue_resize_handler (container);
6337 /* Handle any position changes.
6339 if (configure_request_pos_changed)
6343 gdk_window_move (window->frame,
6344 new_request.x - window->frame_left,
6345 new_request.y - window->frame_top);
6348 gdk_window_move (widget->window,
6349 new_request.x, new_request.y);
6352 /* And run the resize queue.
6354 gtk_container_resize_children (container);
6357 /* We have now processed a move/resize since the last position
6358 * constraint change, setting of the initial position, or resize.
6359 * (Not resetting these flags here can lead to infinite loops for
6360 * GTK_RESIZE_IMMEDIATE containers)
6362 info->position_constraints_changed = FALSE;
6363 info->initial_pos_set = FALSE;
6364 info->resize_width = -1;
6365 info->resize_height = -1;
6368 /* Compare two sets of Geometry hints for equality.
6371 gtk_window_compare_hints (GdkGeometry *geometry_a,
6373 GdkGeometry *geometry_b,
6376 if (flags_a != flags_b)
6379 if ((flags_a & GDK_HINT_MIN_SIZE) &&
6380 (geometry_a->min_width != geometry_b->min_width ||
6381 geometry_a->min_height != geometry_b->min_height))
6384 if ((flags_a & GDK_HINT_MAX_SIZE) &&
6385 (geometry_a->max_width != geometry_b->max_width ||
6386 geometry_a->max_height != geometry_b->max_height))
6389 if ((flags_a & GDK_HINT_BASE_SIZE) &&
6390 (geometry_a->base_width != geometry_b->base_width ||
6391 geometry_a->base_height != geometry_b->base_height))
6394 if ((flags_a & GDK_HINT_ASPECT) &&
6395 (geometry_a->min_aspect != geometry_b->min_aspect ||
6396 geometry_a->max_aspect != geometry_b->max_aspect))
6399 if ((flags_a & GDK_HINT_RESIZE_INC) &&
6400 (geometry_a->width_inc != geometry_b->width_inc ||
6401 geometry_a->height_inc != geometry_b->height_inc))
6404 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
6405 geometry_a->win_gravity != geometry_b->win_gravity)
6412 _gtk_window_constrain_size (GtkWindow *window,
6418 GtkWindowGeometryInfo *info;
6420 g_return_if_fail (GTK_IS_WINDOW (window));
6422 info = window->geometry_info;
6425 GdkWindowHints flags = info->last.flags;
6426 GdkGeometry *geometry = &info->last.geometry;
6428 gtk_window_constrain_size (window,
6439 gtk_window_constrain_size (GtkWindow *window,
6440 GdkGeometry *geometry,
6447 gdk_window_constrain_size (geometry, flags, width, height,
6448 new_width, new_height);
6451 /* Compute the set of geometry hints and flags for a window
6452 * based on the application set geometry, and requisiition
6453 * of the window. gtk_widget_size_request() must have been
6457 gtk_window_compute_hints (GtkWindow *window,
6458 GdkGeometry *new_geometry,
6462 gint extra_width = 0;
6463 gint extra_height = 0;
6464 GtkWindowGeometryInfo *geometry_info;
6465 GtkRequisition requisition;
6467 widget = GTK_WIDGET (window);
6469 gtk_widget_get_child_requisition (widget, &requisition);
6470 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
6474 *new_flags = geometry_info->mask;
6475 *new_geometry = geometry_info->geometry;
6482 if (geometry_info && geometry_info->widget)
6484 GtkRequisition child_requisition;
6486 /* FIXME: This really isn't right. It gets the min size wrong and forces
6487 * callers to do horrible hacks like set a huge usize on the child requisition
6488 * to get the base size right. We really want to find the answers to:
6490 * - If the geometry widget was infinitely big, how much extra space
6491 * would be needed for the stuff around it.
6493 * - If the geometry widget was infinitely small, how big would the
6494 * window still have to be.
6496 * Finding these answers would be a bit of a mess here. (Bug #68668)
6498 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
6500 extra_width = widget->requisition.width - child_requisition.width;
6501 extra_height = widget->requisition.height - child_requisition.height;
6504 /* We don't want to set GDK_HINT_POS in here, we just set it
6505 * in gtk_window_move_resize() when we want the position
6509 if (*new_flags & GDK_HINT_BASE_SIZE)
6511 new_geometry->base_width += extra_width;
6512 new_geometry->base_height += extra_height;
6514 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
6515 (*new_flags & GDK_HINT_RESIZE_INC) &&
6516 ((extra_width != 0) || (extra_height != 0)))
6518 *new_flags |= GDK_HINT_BASE_SIZE;
6520 new_geometry->base_width = extra_width;
6521 new_geometry->base_height = extra_height;
6524 if (*new_flags & GDK_HINT_MIN_SIZE)
6526 if (new_geometry->min_width < 0)
6527 new_geometry->min_width = requisition.width;
6529 new_geometry->min_width += extra_width;
6531 if (new_geometry->min_height < 0)
6532 new_geometry->min_height = requisition.height;
6534 new_geometry->min_height += extra_height;
6536 else if (!window->allow_shrink)
6538 *new_flags |= GDK_HINT_MIN_SIZE;
6540 new_geometry->min_width = requisition.width;
6541 new_geometry->min_height = requisition.height;
6544 if (*new_flags & GDK_HINT_MAX_SIZE)
6546 if (new_geometry->max_width < 0)
6547 new_geometry->max_width = requisition.width;
6549 new_geometry->max_width += extra_width;
6551 if (new_geometry->max_height < 0)
6552 new_geometry->max_height = requisition.height;
6554 new_geometry->max_height += extra_height;
6556 else if (!window->allow_grow)
6558 *new_flags |= GDK_HINT_MAX_SIZE;
6560 new_geometry->max_width = requisition.width;
6561 new_geometry->max_height = requisition.height;
6564 *new_flags |= GDK_HINT_WIN_GRAVITY;
6565 new_geometry->win_gravity = window->gravity;
6568 /***********************
6569 * Redrawing functions *
6570 ***********************/
6573 gtk_window_paint (GtkWidget *widget,
6576 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
6577 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
6581 gtk_window_expose (GtkWidget *widget,
6582 GdkEventExpose *event)
6584 if (!GTK_WIDGET_APP_PAINTABLE (widget))
6585 gtk_window_paint (widget, &event->area);
6587 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event)
6588 return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event);
6594 * gtk_window_set_has_frame:
6595 * @window: a #GtkWindow
6596 * @setting: a boolean
6598 * (Note: this is a special-purpose function for the framebuffer port,
6599 * that causes GTK+ to draw its own window border. For most applications,
6600 * you want gtk_window_set_decorated() instead, which tells the window
6601 * manager whether to draw the window border.)
6603 * If this function is called on a window with setting of %TRUE, before
6604 * it is realized or showed, it will have a "frame" window around
6605 * @window->window, accessible in @window->frame. Using the signal
6606 * frame_event you can receive all events targeted at the frame.
6608 * This function is used by the linux-fb port to implement managed
6609 * windows, but it could conceivably be used by X-programs that
6610 * want to do their own window decorations.
6614 gtk_window_set_has_frame (GtkWindow *window,
6617 g_return_if_fail (GTK_IS_WINDOW (window));
6618 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
6620 window->has_frame = setting != FALSE;
6624 * gtk_window_get_has_frame:
6625 * @window: a #GtkWindow
6627 * Accessor for whether the window has a frame window exterior to
6628 * @window->window. Gets the value set by gtk_window_set_has_frame ().
6630 * Return value: %TRUE if a frame has been added to the window
6631 * via gtk_window_set_has_frame().
6634 gtk_window_get_has_frame (GtkWindow *window)
6636 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6638 return window->has_frame;
6642 * gtk_window_set_frame_dimensions:
6643 * @window: a #GtkWindow that has a frame
6644 * @left: The width of the left border
6645 * @top: The height of the top border
6646 * @right: The width of the right border
6647 * @bottom: The height of the bottom border
6649 * (Note: this is a special-purpose function intended for the framebuffer
6650 * port; see gtk_window_set_has_frame(). It will have no effect on the
6651 * window border drawn by the window manager, which is the normal
6652 * case when using the X Window system.)
6654 * For windows with frames (see gtk_window_set_has_frame()) this function
6655 * can be used to change the size of the frame border.
6658 gtk_window_set_frame_dimensions (GtkWindow *window,
6666 g_return_if_fail (GTK_IS_WINDOW (window));
6668 widget = GTK_WIDGET (window);
6670 if (window->frame_left == left &&
6671 window->frame_top == top &&
6672 window->frame_right == right &&
6673 window->frame_bottom == bottom)
6676 window->frame_left = left;
6677 window->frame_top = top;
6678 window->frame_right = right;
6679 window->frame_bottom = bottom;
6681 if (GTK_WIDGET_REALIZED (widget) && window->frame)
6683 gint width = widget->allocation.width + left + right;
6684 gint height = widget->allocation.height + top + bottom;
6685 gdk_window_resize (window->frame, width, height);
6686 gtk_decorated_window_move_resize_window (window,
6688 widget->allocation.width,
6689 widget->allocation.height);
6694 * gtk_window_present:
6695 * @window: a #GtkWindow
6697 * Presents a window to the user. This may mean raising the window
6698 * in the stacking order, deiconifying it, moving it to the current
6699 * desktop, and/or giving it the keyboard focus, possibly dependent
6700 * on the user's platform, window manager, and preferences.
6702 * If @window is hidden, this function calls gtk_widget_show()
6705 * This function should be used when the user tries to open a window
6706 * that's already open. Say for example the preferences dialog is
6707 * currently open, and the user chooses Preferences from the menu
6708 * a second time; use gtk_window_present() to move the already-open dialog
6709 * where the user can see it.
6711 * If you are calling this function in response to a user interaction,
6712 * it is preferable to use gtk_window_present_with_time().
6716 gtk_window_present (GtkWindow *window)
6718 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6722 * gtk_window_present_with_time:
6723 * @window: a #GtkWindow
6724 * @timestamp: the timestamp of the user interaction (typically a
6725 * button or key press event) which triggered this call
6727 * Presents a window to the user in response to a user interaction.
6728 * If you need to present a window without a timestamp, use
6729 * gtk_window_present(). See gtk_window_present() for details.
6734 gtk_window_present_with_time (GtkWindow *window,
6739 g_return_if_fail (GTK_IS_WINDOW (window));
6741 widget = GTK_WIDGET (window);
6743 if (GTK_WIDGET_VISIBLE (window))
6745 g_assert (widget->window != NULL);
6747 gdk_window_show (widget->window);
6749 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
6750 if (timestamp == GDK_CURRENT_TIME)
6752 #ifdef GDK_WINDOWING_X11
6753 GdkDisplay *display;
6755 display = gtk_widget_get_display (GTK_WIDGET (window));
6756 timestamp = gdk_x11_display_get_user_time (display);
6758 timestamp = gtk_get_current_event_time ();
6762 gdk_window_focus (widget->window, timestamp);
6766 gtk_widget_show (widget);
6771 * gtk_window_iconify:
6772 * @window: a #GtkWindow
6774 * Asks to iconify (i.e. minimize) the specified @window. Note that
6775 * you shouldn't assume the window is definitely iconified afterward,
6776 * because other entities (e.g. the user or <link
6777 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
6778 * again, or there may not be a window manager in which case
6779 * iconification isn't possible, etc. But normally the window will end
6780 * up iconified. Just don't write code that crashes if not.
6782 * It's permitted to call this function before showing a window,
6783 * in which case the window will be iconified before it ever appears
6786 * You can track iconification via the "window-state-event" signal
6791 gtk_window_iconify (GtkWindow *window)
6794 GdkWindow *toplevel;
6796 g_return_if_fail (GTK_IS_WINDOW (window));
6798 widget = GTK_WIDGET (window);
6800 window->iconify_initially = TRUE;
6803 toplevel = window->frame;
6805 toplevel = widget->window;
6807 if (toplevel != NULL)
6808 gdk_window_iconify (toplevel);
6812 * gtk_window_deiconify:
6813 * @window: a #GtkWindow
6815 * Asks to deiconify (i.e. unminimize) the specified @window. Note
6816 * that you shouldn't assume the window is definitely deiconified
6817 * afterward, because other entities (e.g. the user or <link
6818 * linkend="gtk-X11-arch">window manager</link>) could iconify it
6819 * again before your code which assumes deiconification gets to run.
6821 * You can track iconification via the "window-state-event" signal
6825 gtk_window_deiconify (GtkWindow *window)
6828 GdkWindow *toplevel;
6830 g_return_if_fail (GTK_IS_WINDOW (window));
6832 widget = GTK_WIDGET (window);
6834 window->iconify_initially = FALSE;
6837 toplevel = window->frame;
6839 toplevel = widget->window;
6841 if (toplevel != NULL)
6842 gdk_window_deiconify (toplevel);
6847 * @window: a #GtkWindow
6849 * Asks to stick @window, which means that it will appear on all user
6850 * desktops. Note that you shouldn't assume the window is definitely
6851 * stuck afterward, because other entities (e.g. the user or <link
6852 * linkend="gtk-X11-arch">window manager</link>) could unstick it
6853 * again, and some window managers do not support sticking
6854 * windows. But normally the window will end up stuck. Just don't
6855 * write code that crashes if not.
6857 * It's permitted to call this function before showing a window.
6859 * You can track stickiness via the "window-state-event" signal
6864 gtk_window_stick (GtkWindow *window)
6867 GdkWindow *toplevel;
6869 g_return_if_fail (GTK_IS_WINDOW (window));
6871 widget = GTK_WIDGET (window);
6873 window->stick_initially = TRUE;
6876 toplevel = window->frame;
6878 toplevel = widget->window;
6880 if (toplevel != NULL)
6881 gdk_window_stick (toplevel);
6885 * gtk_window_unstick:
6886 * @window: a #GtkWindow
6888 * Asks to unstick @window, which means that it will appear on only
6889 * one of the user's desktops. Note that you shouldn't assume the
6890 * window is definitely unstuck afterward, because other entities
6891 * (e.g. the user or <link linkend="gtk-X11-arch">window
6892 * manager</link>) could stick it again. But normally the window will
6893 * end up stuck. Just don't write code that crashes if not.
6895 * You can track stickiness via the "window-state-event" signal
6900 gtk_window_unstick (GtkWindow *window)
6903 GdkWindow *toplevel;
6905 g_return_if_fail (GTK_IS_WINDOW (window));
6907 widget = GTK_WIDGET (window);
6909 window->stick_initially = FALSE;
6912 toplevel = window->frame;
6914 toplevel = widget->window;
6916 if (toplevel != NULL)
6917 gdk_window_unstick (toplevel);
6921 * gtk_window_maximize:
6922 * @window: a #GtkWindow
6924 * Asks to maximize @window, so that it becomes full-screen. Note that
6925 * you shouldn't assume the window is definitely maximized afterward,
6926 * because other entities (e.g. the user or <link
6927 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
6928 * again, and not all window managers support maximization. But
6929 * normally the window will end up maximized. Just don't write code
6930 * that crashes if not.
6932 * It's permitted to call this function before showing a window,
6933 * in which case the window will be maximized when it appears onscreen
6936 * You can track maximization via the "window-state-event" signal
6941 gtk_window_maximize (GtkWindow *window)
6944 GdkWindow *toplevel;
6946 g_return_if_fail (GTK_IS_WINDOW (window));
6948 widget = GTK_WIDGET (window);
6950 window->maximize_initially = TRUE;
6953 toplevel = window->frame;
6955 toplevel = widget->window;
6957 if (toplevel != NULL)
6958 gdk_window_maximize (toplevel);
6962 * gtk_window_unmaximize:
6963 * @window: a #GtkWindow
6965 * Asks to unmaximize @window. Note that you shouldn't assume the
6966 * window is definitely unmaximized afterward, because other entities
6967 * (e.g. the user or <link linkend="gtk-X11-arch">window
6968 * manager</link>) could maximize it again, and not all window
6969 * managers honor requests to unmaximize. But normally the window will
6970 * end up unmaximized. Just don't write code that crashes if not.
6972 * You can track maximization via the "window-state-event" signal
6977 gtk_window_unmaximize (GtkWindow *window)
6980 GdkWindow *toplevel;
6982 g_return_if_fail (GTK_IS_WINDOW (window));
6984 widget = GTK_WIDGET (window);
6986 window->maximize_initially = FALSE;
6989 toplevel = window->frame;
6991 toplevel = widget->window;
6993 if (toplevel != NULL)
6994 gdk_window_unmaximize (toplevel);
6998 * gtk_window_fullscreen:
6999 * @window: a #GtkWindow
7001 * Asks to place @window in the fullscreen state. Note that you
7002 * shouldn't assume the window is definitely full screen afterward,
7003 * because other entities (e.g. the user or <link
7004 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7005 * again, and not all window managers honor requests to fullscreen
7006 * windows. But normally the window will end up fullscreen. Just
7007 * don't write code that crashes if not.
7009 * You can track the fullscreen state via the "window-state-event" signal
7015 gtk_window_fullscreen (GtkWindow *window)
7018 GdkWindow *toplevel;
7019 GtkWindowPrivate *priv;
7021 g_return_if_fail (GTK_IS_WINDOW (window));
7023 widget = GTK_WIDGET (window);
7024 priv = GTK_WINDOW_GET_PRIVATE (window);
7026 priv->fullscreen_initially = TRUE;
7029 toplevel = window->frame;
7031 toplevel = widget->window;
7033 if (toplevel != NULL)
7034 gdk_window_fullscreen (toplevel);
7038 * gtk_window_unfullscreen:
7039 * @window: a #GtkWindow
7041 * Asks to toggle off the fullscreen state for @window. Note that you
7042 * shouldn't assume the window is definitely not full screen
7043 * afterward, because other entities (e.g. the user or <link
7044 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7045 * again, and not all window managers honor requests to unfullscreen
7046 * windows. But normally the window will end up restored to its normal
7047 * state. Just don't write code that crashes if not.
7049 * You can track the fullscreen state via the "window-state-event" signal
7055 gtk_window_unfullscreen (GtkWindow *window)
7058 GdkWindow *toplevel;
7059 GtkWindowPrivate *priv;
7061 g_return_if_fail (GTK_IS_WINDOW (window));
7063 widget = GTK_WIDGET (window);
7064 priv = GTK_WINDOW_GET_PRIVATE (window);
7066 priv->fullscreen_initially = FALSE;
7069 toplevel = window->frame;
7071 toplevel = widget->window;
7073 if (toplevel != NULL)
7074 gdk_window_unfullscreen (toplevel);
7078 * gtk_window_set_keep_above:
7079 * @window: a #GtkWindow
7080 * @setting: whether to keep @window above other windows
7082 * Asks to keep @window above, so that it stays on top. Note that
7083 * you shouldn't assume the window is definitely above afterward,
7084 * because other entities (e.g. the user or <link
7085 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7086 * and not all window managers support keeping windows above. But
7087 * normally the window will end kept above. Just don't write code
7088 * that crashes if not.
7090 * It's permitted to call this function before showing a window,
7091 * in which case the window will be kept above when it appears onscreen
7094 * You can track the above state via the "window-state-event" signal
7097 * Note that, according to the <ulink
7098 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7099 * Manager Hints</ulink> specification, the above state is mainly meant
7100 * for user preferences and should not be used by applications e.g. for
7101 * drawing attention to their dialogs.
7106 gtk_window_set_keep_above (GtkWindow *window,
7110 GtkWindowPrivate *priv;
7111 GdkWindow *toplevel;
7113 g_return_if_fail (GTK_IS_WINDOW (window));
7115 widget = GTK_WIDGET (window);
7116 priv = GTK_WINDOW_GET_PRIVATE (window);
7118 priv->above_initially = setting != FALSE;
7120 priv->below_initially = FALSE;
7123 toplevel = window->frame;
7125 toplevel = widget->window;
7127 if (toplevel != NULL)
7128 gdk_window_set_keep_above (toplevel, setting);
7132 * gtk_window_set_keep_below:
7133 * @window: a #GtkWindow
7134 * @setting: whether to keep @window below other windows
7136 * Asks to keep @window below, so that it stays in bottom. Note that
7137 * you shouldn't assume the window is definitely below afterward,
7138 * because other entities (e.g. the user or <link
7139 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7140 * and not all window managers support putting windows below. But
7141 * normally the window will be kept below. Just don't write code
7142 * that crashes if not.
7144 * It's permitted to call this function before showing a window,
7145 * in which case the window will be kept below when it appears onscreen
7148 * You can track the below state via the "window-state-event" signal
7151 * Note that, according to the <ulink
7152 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7153 * Manager Hints</ulink> specification, the above state is mainly meant
7154 * for user preferences and should not be used by applications e.g. for
7155 * drawing attention to their dialogs.
7160 gtk_window_set_keep_below (GtkWindow *window,
7164 GtkWindowPrivate *priv;
7165 GdkWindow *toplevel;
7167 g_return_if_fail (GTK_IS_WINDOW (window));
7169 widget = GTK_WIDGET (window);
7170 priv = GTK_WINDOW_GET_PRIVATE (window);
7172 priv->below_initially = setting != FALSE;
7174 priv->above_initially = FALSE;
7177 toplevel = window->frame;
7179 toplevel = widget->window;
7181 if (toplevel != NULL)
7182 gdk_window_set_keep_below (toplevel, setting);
7186 * gtk_window_set_resizable:
7187 * @window: a #GtkWindow
7188 * @resizable: %TRUE if the user can resize this window
7190 * Sets whether the user can resize a window. Windows are user resizable
7194 gtk_window_set_resizable (GtkWindow *window,
7197 g_return_if_fail (GTK_IS_WINDOW (window));
7199 gtk_window_set_policy_internal (window, FALSE, resizable, FALSE);
7203 * gtk_window_get_resizable:
7204 * @window: a #GtkWindow
7206 * Gets the value set by gtk_window_set_resizable().
7208 * Return value: %TRUE if the user can resize the window
7211 gtk_window_get_resizable (GtkWindow *window)
7213 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7215 /* allow_grow is most likely to indicate the semantic concept we
7216 * mean by "resizable" (and will be a reliable indicator if
7217 * set_policy() hasn't been called)
7219 return window->allow_grow;
7223 * gtk_window_set_gravity:
7224 * @window: a #GtkWindow
7225 * @gravity: window gravity
7227 * Window gravity defines the meaning of coordinates passed to
7228 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7231 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7232 * typically "do what you mean."
7236 gtk_window_set_gravity (GtkWindow *window,
7239 g_return_if_fail (GTK_IS_WINDOW (window));
7241 if (gravity != window->gravity)
7243 window->gravity = gravity;
7245 /* gtk_window_move_resize() will adapt gravity
7247 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7249 g_object_notify (G_OBJECT (window), "gravity");
7254 * gtk_window_get_gravity:
7255 * @window: a #GtkWindow
7257 * Gets the value set by gtk_window_set_gravity().
7259 * Return value: (transfer none): window gravity
7262 gtk_window_get_gravity (GtkWindow *window)
7264 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7266 return window->gravity;
7270 * gtk_window_begin_resize_drag:
7271 * @window: a #GtkWindow
7272 * @button: mouse button that initiated the drag
7273 * @edge: position of the resize control
7274 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7275 * @root_y: Y position where the user clicked to initiate the drag
7276 * @timestamp: timestamp from the click event that initiated the drag
7278 * Starts resizing a window. This function is used if an application
7279 * has window resizing controls. When GDK can support it, the resize
7280 * will be done using the standard mechanism for the <link
7281 * linkend="gtk-X11-arch">window manager</link> or windowing
7282 * system. Otherwise, GDK will try to emulate window resizing,
7283 * potentially not all that well, depending on the windowing system.
7287 gtk_window_begin_resize_drag (GtkWindow *window,
7295 GdkWindow *toplevel;
7297 g_return_if_fail (GTK_IS_WINDOW (window));
7298 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
7300 widget = GTK_WIDGET (window);
7303 toplevel = window->frame;
7305 toplevel = widget->window;
7307 gdk_window_begin_resize_drag (toplevel,
7314 * gtk_window_get_frame_dimensions:
7315 * @window: a #GtkWindow
7316 * @left: location to store the width of the frame at the left, or %NULL
7317 * @top: location to store the height of the frame at the top, or %NULL
7318 * @right: location to store the width of the frame at the returns, or %NULL
7319 * @bottom: location to store the height of the frame at the bottom, or %NULL
7321 * (Note: this is a special-purpose function intended for the
7322 * framebuffer port; see gtk_window_set_has_frame(). It will not
7323 * return the size of the window border drawn by the <link
7324 * linkend="gtk-X11-arch">window manager</link>, which is the normal
7325 * case when using a windowing system. See
7326 * gdk_window_get_frame_extents() to get the standard window border
7329 * Retrieves the dimensions of the frame window for this toplevel.
7330 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
7333 gtk_window_get_frame_dimensions (GtkWindow *window,
7339 g_return_if_fail (GTK_IS_WINDOW (window));
7342 *left = window->frame_left;
7344 *top = window->frame_top;
7346 *right = window->frame_right;
7348 *bottom = window->frame_bottom;
7352 * gtk_window_begin_move_drag:
7353 * @window: a #GtkWindow
7354 * @button: mouse button that initiated the drag
7355 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7356 * @root_y: Y position where the user clicked to initiate the drag
7357 * @timestamp: timestamp from the click event that initiated the drag
7359 * Starts moving a window. This function is used if an application has
7360 * window movement grips. When GDK can support it, the window movement
7361 * will be done using the standard mechanism for the <link
7362 * linkend="gtk-X11-arch">window manager</link> or windowing
7363 * system. Otherwise, GDK will try to emulate window movement,
7364 * potentially not all that well, depending on the windowing system.
7368 gtk_window_begin_move_drag (GtkWindow *window,
7375 GdkWindow *toplevel;
7377 g_return_if_fail (GTK_IS_WINDOW (window));
7378 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
7380 widget = GTK_WIDGET (window);
7383 toplevel = window->frame;
7385 toplevel = widget->window;
7387 gdk_window_begin_move_drag (toplevel,
7394 * gtk_window_set_screen:
7395 * @window: a #GtkWindow.
7396 * @screen: a #GdkScreen.
7398 * Sets the #GdkScreen where the @window is displayed; if
7399 * the window is already mapped, it will be unmapped, and
7400 * then remapped on the new screen.
7405 gtk_window_set_screen (GtkWindow *window,
7409 GdkScreen *previous_screen;
7410 gboolean was_mapped;
7412 g_return_if_fail (GTK_IS_WINDOW (window));
7413 g_return_if_fail (GDK_IS_SCREEN (screen));
7415 if (screen == window->screen)
7418 widget = GTK_WIDGET (window);
7420 previous_screen = window->screen;
7421 was_mapped = GTK_WIDGET_MAPPED (widget);
7424 gtk_widget_unmap (widget);
7425 if (GTK_WIDGET_REALIZED (widget))
7426 gtk_widget_unrealize (widget);
7428 gtk_window_free_key_hash (window);
7429 window->screen = screen;
7430 gtk_widget_reset_rc_styles (widget);
7431 if (screen != previous_screen)
7433 g_signal_handlers_disconnect_by_func (previous_screen,
7434 gtk_window_on_composited_changed, window);
7435 g_signal_connect (screen, "composited-changed",
7436 G_CALLBACK (gtk_window_on_composited_changed), window);
7438 _gtk_widget_propagate_screen_changed (widget, previous_screen);
7439 _gtk_widget_propagate_composited_changed (widget);
7441 g_object_notify (G_OBJECT (window), "screen");
7444 gtk_widget_map (widget);
7448 gtk_window_on_composited_changed (GdkScreen *screen,
7451 gtk_widget_queue_draw (GTK_WIDGET (window));
7453 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
7457 gtk_window_check_screen (GtkWindow *window)
7460 return window->screen;
7463 g_warning ("Screen for GtkWindow not set; you must always set\n"
7464 "a screen for a GtkWindow before using the window");
7470 * gtk_window_get_screen:
7471 * @window: a #GtkWindow.
7473 * Returns the #GdkScreen associated with @window.
7475 * Return value: (transfer none): a #GdkScreen.
7480 gtk_window_get_screen (GtkWindow *window)
7482 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
7484 return window->screen;
7488 * gtk_window_is_active:
7489 * @window: a #GtkWindow
7491 * Returns whether the window is part of the current active toplevel.
7492 * (That is, the toplevel window receiving keystrokes.)
7493 * The return value is %TRUE if the window is active toplevel
7494 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
7495 * You might use this function if you wanted to draw a widget
7496 * differently in an active window from a widget in an inactive window.
7497 * See gtk_window_has_toplevel_focus()
7499 * Return value: %TRUE if the window part of the current active window.
7504 gtk_window_is_active (GtkWindow *window)
7506 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7508 return window->is_active;
7512 * gtk_window_has_toplevel_focus:
7513 * @window: a #GtkWindow
7515 * Returns whether the input focus is within this GtkWindow.
7516 * For real toplevel windows, this is identical to gtk_window_is_active(),
7517 * but for embedded windows, like #GtkPlug, the results will differ.
7519 * Return value: %TRUE if the input focus is within this GtkWindow
7524 gtk_window_has_toplevel_focus (GtkWindow *window)
7526 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7528 return window->has_toplevel_focus;
7532 gtk_window_group_class_init (GtkWindowGroupClass *klass)
7537 gtk_window_group_get_type (void)
7539 static GType window_group_type = 0;
7541 if (!window_group_type)
7543 const GTypeInfo window_group_info =
7545 sizeof (GtkWindowGroupClass),
7546 NULL, /* base_init */
7547 NULL, /* base_finalize */
7548 (GClassInitFunc) gtk_window_group_class_init,
7549 NULL, /* class_finalize */
7550 NULL, /* class_data */
7551 sizeof (GtkWindowGroup),
7552 0, /* n_preallocs */
7553 (GInstanceInitFunc) NULL,
7556 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
7557 &window_group_info, 0);
7560 return window_group_type;
7564 * gtk_window_group_new:
7566 * Creates a new #GtkWindowGroup object. Grabs added with
7567 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
7569 * Return value: a new #GtkWindowGroup.
7572 gtk_window_group_new (void)
7574 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
7578 window_group_cleanup_grabs (GtkWindowGroup *group,
7582 GSList *to_remove = NULL;
7584 tmp_list = group->grabs;
7587 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
7588 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
7589 tmp_list = tmp_list->next;
7594 gtk_grab_remove (to_remove->data);
7595 g_object_unref (to_remove->data);
7596 to_remove = g_slist_delete_link (to_remove, to_remove);
7601 * gtk_window_group_add_window:
7602 * @window_group: a #GtkWindowGroup
7603 * @window: the #GtkWindow to add
7605 * Adds a window to a #GtkWindowGroup.
7608 gtk_window_group_add_window (GtkWindowGroup *window_group,
7611 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7612 g_return_if_fail (GTK_IS_WINDOW (window));
7614 if (window->group != window_group)
7616 g_object_ref (window);
7617 g_object_ref (window_group);
7620 gtk_window_group_remove_window (window->group, window);
7622 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
7624 window->group = window_group;
7626 g_object_unref (window);
7631 * gtk_window_group_remove_window:
7632 * @window_group: a #GtkWindowGroup
7633 * @window: the #GtkWindow to remove
7635 * Removes a window from a #GtkWindowGroup.
7638 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7641 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7642 g_return_if_fail (GTK_IS_WINDOW (window));
7643 g_return_if_fail (window->group == window_group);
7645 g_object_ref (window);
7647 window_group_cleanup_grabs (window_group, window);
7648 window->group = NULL;
7650 g_object_unref (window_group);
7651 g_object_unref (window);
7655 * gtk_window_group_list_windows:
7656 * @window_group: a #GtkWindowGroup
7658 * Returns a list of the #GtkWindows that belong to @window_group.
7660 * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
7661 * windows inside the group.
7666 gtk_window_group_list_windows (GtkWindowGroup *window_group)
7668 GList *toplevels, *toplevel, *group_windows;
7670 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
7672 group_windows = NULL;
7673 toplevels = gtk_window_list_toplevels ();
7675 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
7677 GtkWindow *window = toplevel->data;
7679 if (window_group == window->group)
7680 group_windows = g_list_prepend (group_windows, window);
7683 return g_list_reverse (group_windows);
7687 * gtk_window_get_group:
7688 * @window: a #GtkWindow, or %NULL
7690 * Returns the group for @window or the default group, if
7691 * @window is %NULL or if @window does not have an explicit
7694 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
7699 gtk_window_get_group (GtkWindow *window)
7701 if (window && window->group)
7702 return window->group;
7705 static GtkWindowGroup *default_group = NULL;
7708 default_group = gtk_window_group_new ();
7710 return default_group;
7714 /* Return the current grab widget of the given group
7717 _gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
7719 if (window_group->grabs)
7720 return GTK_WIDGET (window_group->grabs->data);
7725 Derived from XParseGeometry() in XFree86
7727 Copyright 1985, 1986, 1987,1998 The Open Group
7729 All Rights Reserved.
7731 The above copyright notice and this permission notice shall be included
7732 in all copies or substantial portions of the Software.
7734 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
7735 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7736 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7737 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
7738 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7739 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
7740 OTHER DEALINGS IN THE SOFTWARE.
7742 Except as contained in this notice, the name of The Open Group shall
7743 not be used in advertising or otherwise to promote the sale, use or
7744 other dealings in this Software without prior written authorization
7745 from The Open Group.
7750 * XParseGeometry parses strings of the form
7751 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
7752 * width, height, xoffset, and yoffset are unsigned integers.
7753 * Example: "=80x24+300-49"
7754 * The equal sign is optional.
7755 * It returns a bitmask that indicates which of the four values
7756 * were actually found in the string. For each value found,
7757 * the corresponding argument is updated; for each value
7758 * not found, the corresponding argument is left unchanged.
7761 /* The following code is from Xlib, and is minimally modified, so we
7762 * can track any upstream changes if required. Don't change this
7763 * code. Or if you do, put in a huge comment marking which thing
7768 read_int (gchar *string,
7776 else if (*string == '-')
7782 for (; (*string >= '0') && (*string <= '9'); string++)
7784 result = (result * 10) + (*string - '0');
7796 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
7797 * value (x, y, width, height) was found in the parsed string.
7799 #define NoValue 0x0000
7800 #define XValue 0x0001
7801 #define YValue 0x0002
7802 #define WidthValue 0x0004
7803 #define HeightValue 0x0008
7804 #define AllValues 0x000F
7805 #define XNegative 0x0010
7806 #define YNegative 0x0020
7808 /* Try not to reformat/modify, so we can compare/sync with X sources */
7810 gtk_XParseGeometry (const char *string,
7813 unsigned int *width,
7814 unsigned int *height)
7818 unsigned int tempWidth, tempHeight;
7820 char *nextCharacter;
7822 /* These initializations are just to silence gcc */
7828 if ( (string == NULL) || (*string == '\0')) return(mask);
7830 string++; /* ignore possible '=' at beg of geometry spec */
7832 strind = (char *)string;
7833 if (*strind != '+' && *strind != '-' && *strind != 'x') {
7834 tempWidth = read_int(strind, &nextCharacter);
7835 if (strind == nextCharacter)
7837 strind = nextCharacter;
7841 if (*strind == 'x' || *strind == 'X') {
7843 tempHeight = read_int(strind, &nextCharacter);
7844 if (strind == nextCharacter)
7846 strind = nextCharacter;
7847 mask |= HeightValue;
7850 if ((*strind == '+') || (*strind == '-')) {
7851 if (*strind == '-') {
7853 tempX = -read_int(strind, &nextCharacter);
7854 if (strind == nextCharacter)
7856 strind = nextCharacter;
7862 tempX = read_int(strind, &nextCharacter);
7863 if (strind == nextCharacter)
7865 strind = nextCharacter;
7868 if ((*strind == '+') || (*strind == '-')) {
7869 if (*strind == '-') {
7871 tempY = -read_int(strind, &nextCharacter);
7872 if (strind == nextCharacter)
7874 strind = nextCharacter;
7881 tempY = read_int(strind, &nextCharacter);
7882 if (strind == nextCharacter)
7884 strind = nextCharacter;
7890 /* If strind isn't at the end of the string the it's an invalid
7891 geometry specification. */
7893 if (*strind != '\0') return (0);
7899 if (mask & WidthValue)
7901 if (mask & HeightValue)
7902 *height = tempHeight;
7907 * gtk_window_parse_geometry:
7908 * @window: a #GtkWindow
7909 * @geometry: geometry string
7911 * Parses a standard X Window System geometry string - see the
7912 * manual page for X (type 'man X') for details on this.
7913 * gtk_window_parse_geometry() does work on all GTK+ ports
7914 * including Win32 but is primarily intended for an X environment.
7916 * If either a size or a position can be extracted from the
7917 * geometry string, gtk_window_parse_geometry() returns %TRUE
7918 * and calls gtk_window_set_default_size() and/or gtk_window_move()
7919 * to resize/move the window.
7921 * If gtk_window_parse_geometry() returns %TRUE, it will also
7922 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
7923 * indicating to the window manager that the size/position of
7924 * the window was user-specified. This causes most window
7925 * managers to honor the geometry.
7927 * Note that for gtk_window_parse_geometry() to work as expected, it has
7928 * to be called when the window has its "final" size, i.e. after calling
7929 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
7932 * #include <gtk/gtk.h>
7935 * fill_with_content (GtkWidget *vbox)
7937 * /* fill with content... */
7941 * main (int argc, char *argv[])
7943 * GtkWidget *window, *vbox;
7944 * GdkGeometry size_hints = {
7945 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
7948 * gtk_init (&argc, &argv);
7950 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7951 * vbox = gtk_vbox_new (FALSE, 0);
7953 * gtk_container_add (GTK_CONTAINER (window), vbox);
7954 * fill_with_content (vbox);
7955 * gtk_widget_show_all (vbox);
7957 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
7960 * GDK_HINT_MIN_SIZE |
7961 * GDK_HINT_BASE_SIZE |
7962 * GDK_HINT_RESIZE_INC);
7966 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
7967 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
7970 * gtk_widget_show_all (window);
7977 * Return value: %TRUE if string was parsed successfully
7980 gtk_window_parse_geometry (GtkWindow *window,
7981 const gchar *geometry)
7983 gint result, x = 0, y = 0;
7986 gboolean size_set, pos_set;
7989 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7990 g_return_val_if_fail (geometry != NULL, FALSE);
7992 screen = gtk_window_check_screen (window);
7994 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
7997 if ((result & WidthValue) || (result & HeightValue))
7999 gtk_window_set_default_size_internal (window,
8000 TRUE, result & WidthValue ? w : -1,
8001 TRUE, result & HeightValue ? h : -1,
8006 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8008 grav = GDK_GRAVITY_NORTH_WEST;
8010 if ((result & XNegative) && (result & YNegative))
8011 grav = GDK_GRAVITY_SOUTH_EAST;
8012 else if (result & XNegative)
8013 grav = GDK_GRAVITY_NORTH_EAST;
8014 else if (result & YNegative)
8015 grav = GDK_GRAVITY_SOUTH_WEST;
8017 if ((result & XValue) == 0)
8020 if ((result & YValue) == 0)
8023 if (grav == GDK_GRAVITY_SOUTH_WEST ||
8024 grav == GDK_GRAVITY_SOUTH_EAST)
8025 y = gdk_screen_get_height (screen) - h + y;
8027 if (grav == GDK_GRAVITY_SOUTH_EAST ||
8028 grav == GDK_GRAVITY_NORTH_EAST)
8029 x = gdk_screen_get_width (screen) - w + x;
8031 /* we don't let you put a window offscreen; maybe some people would
8032 * prefer to be able to, but it's kind of a bogus thing to do.
8041 if ((result & XValue) || (result & YValue))
8043 gtk_window_set_gravity (window, grav);
8044 gtk_window_move (window, x, y);
8048 if (size_set || pos_set)
8050 /* Set USSize, USPosition hints */
8051 GtkWindowGeometryInfo *info;
8053 info = gtk_window_get_geometry_info (window, TRUE);
8056 info->mask |= GDK_HINT_USER_POS;
8058 info->mask |= GDK_HINT_USER_SIZE;
8065 gtk_window_mnemonic_hash_foreach (guint keyval,
8071 GtkWindowKeysForeachFunc func;
8075 (*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
8079 _gtk_window_keys_foreach (GtkWindow *window,
8080 GtkWindowKeysForeachFunc func,
8084 GtkMnemonicHash *mnemonic_hash;
8088 GtkWindowKeysForeachFunc func;
8092 info.window = window;
8094 info.func_data = func_data;
8096 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8098 _gtk_mnemonic_hash_foreach (mnemonic_hash,
8099 gtk_window_mnemonic_hash_foreach, &info);
8101 groups = gtk_accel_groups_from_object (G_OBJECT (window));
8104 GtkAccelGroup *group = groups->data;
8107 for (i = 0; i < group->n_accels; i++)
8109 GtkAccelKey *key = &group->priv_accels[i].key;
8112 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8115 groups = groups->next;
8120 gtk_window_keys_changed (GtkWindow *window)
8122 gtk_window_free_key_hash (window);
8123 gtk_window_get_key_hash (window);
8126 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8128 struct _GtkWindowKeyEntry
8132 guint is_mnemonic : 1;
8136 window_key_entry_destroy (gpointer data)
8138 g_slice_free (GtkWindowKeyEntry, data);
8142 add_to_key_hash (GtkWindow *window,
8144 GdkModifierType modifiers,
8145 gboolean is_mnemonic,
8148 GtkKeyHash *key_hash = data;
8150 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8152 entry->keyval = keyval;
8153 entry->modifiers = modifiers;
8154 entry->is_mnemonic = is_mnemonic;
8156 /* GtkAccelGroup stores lowercased accelerators. To deal
8157 * with this, if <Shift> was specified, uppercase.
8159 if (modifiers & GDK_SHIFT_MASK)
8161 if (keyval == GDK_Tab)
8162 keyval = GDK_ISO_Left_Tab;
8164 keyval = gdk_keyval_to_upper (keyval);
8167 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
8171 gtk_window_get_key_hash (GtkWindow *window)
8173 GdkScreen *screen = gtk_window_check_screen (window);
8174 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8179 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
8180 (GDestroyNotify)window_key_entry_destroy);
8181 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
8182 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
8188 gtk_window_free_key_hash (GtkWindow *window)
8190 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8193 _gtk_key_hash_free (key_hash);
8194 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
8199 * gtk_window_activate_key:
8200 * @window: a #GtkWindow
8201 * @event: a #GdkEventKey
8203 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
8204 * called by the default ::key_press_event handler for toplevel windows,
8205 * however in some cases it may be useful to call this directly when
8206 * overriding the standard key handling for a toplevel window.
8208 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
8213 gtk_window_activate_key (GtkWindow *window,
8216 GtkKeyHash *key_hash;
8217 GtkWindowKeyEntry *found_entry = NULL;
8218 gboolean enable_mnemonics;
8219 gboolean enable_accels;
8221 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8222 g_return_val_if_fail (event != NULL, FALSE);
8224 key_hash = gtk_window_get_key_hash (window);
8229 GSList *entries = _gtk_key_hash_lookup (key_hash,
8230 event->hardware_keycode,
8232 gtk_accelerator_get_default_mod_mask (),
8235 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
8236 "gtk-enable-mnemonics", &enable_mnemonics,
8237 "gtk-enable-accels", &enable_accels,
8240 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
8242 GtkWindowKeyEntry *entry = tmp_list->data;
8243 if (entry->is_mnemonic)
8245 if (enable_mnemonics)
8247 found_entry = entry;
8253 if (enable_accels && !found_entry)
8255 found_entry = entry;
8260 g_slist_free (entries);
8265 if (found_entry->is_mnemonic)
8267 if (enable_mnemonics)
8268 return gtk_window_mnemonic_activate (window, found_entry->keyval,
8269 found_entry->modifiers);
8274 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
8275 found_entry->modifiers);
8283 window_update_has_focus (GtkWindow *window)
8285 GtkWidget *widget = GTK_WIDGET (window);
8286 gboolean has_focus = window->has_toplevel_focus && window->is_active;
8288 if (has_focus != window->has_focus)
8290 window->has_focus = has_focus;
8294 if (window->focus_widget &&
8295 window->focus_widget != widget &&
8296 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
8297 do_focus_change (window->focus_widget, TRUE);
8301 if (window->focus_widget &&
8302 window->focus_widget != widget &&
8303 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
8304 do_focus_change (window->focus_widget, FALSE);
8310 * _gtk_window_set_is_active:
8311 * @window: a #GtkWindow
8312 * @is_active: %TRUE if the window is in the currently active toplevel
8314 * Internal function that sets whether the #GtkWindow is part
8315 * of the currently active toplevel window (taking into account inter-process
8319 _gtk_window_set_is_active (GtkWindow *window,
8322 g_return_if_fail (GTK_IS_WINDOW (window));
8324 is_active = is_active != FALSE;
8326 if (is_active != window->is_active)
8328 window->is_active = is_active;
8329 window_update_has_focus (window);
8331 g_object_notify (G_OBJECT (window), "is-active");
8336 * _gtk_window_set_is_toplevel:
8337 * @window: a #GtkWindow
8338 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
8339 * parent of the root window); %FALSE if it is not (for example, for an
8340 * in-process, parented GtkPlug)
8342 * Internal function used by #GtkPlug when it gets parented/unparented by a
8343 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
8344 * global list of toplevel windows.
8347 _gtk_window_set_is_toplevel (GtkWindow *window,
8348 gboolean is_toplevel)
8350 if (GTK_WIDGET_TOPLEVEL (window))
8351 g_assert (g_slist_find (toplevel_list, window) != NULL);
8353 g_assert (g_slist_find (toplevel_list, window) == NULL);
8355 if (is_toplevel == GTK_WIDGET_TOPLEVEL (window))
8360 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
8361 toplevel_list = g_slist_prepend (toplevel_list, window);
8365 GTK_WIDGET_UNSET_FLAGS (window, GTK_TOPLEVEL);
8366 toplevel_list = g_slist_remove (toplevel_list, window);
8371 * _gtk_window_set_has_toplevel_focus:
8372 * @window: a #GtkWindow
8373 * @has_toplevel_focus: %TRUE if the in
8375 * Internal function that sets whether the keyboard focus for the
8376 * toplevel window (taking into account inter-process embedding.)
8379 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
8380 gboolean has_toplevel_focus)
8382 g_return_if_fail (GTK_IS_WINDOW (window));
8384 has_toplevel_focus = has_toplevel_focus != FALSE;
8386 if (has_toplevel_focus != window->has_toplevel_focus)
8388 window->has_toplevel_focus = has_toplevel_focus;
8389 window_update_has_focus (window);
8391 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
8396 * gtk_window_set_auto_startup_notification:
8397 * @setting: %TRUE to automatically do startup notification
8399 * By default, after showing the first #GtkWindow, GTK+ calls
8400 * gdk_notify_startup_complete(). Call this function to disable
8401 * the automatic startup notification. You might do this if your
8402 * first window is a splash screen, and you want to delay notification
8403 * until after your real main window has been shown, for example.
8405 * In that example, you would disable startup notification
8406 * temporarily, show your splash screen, then re-enable it so that
8407 * showing the main window would automatically result in notification.
8412 gtk_window_set_auto_startup_notification (gboolean setting)
8414 disable_startup_notification = !setting;
8418 * gtk_window_get_window_type:
8419 * @window: a #GtkWindow
8421 * Gets the type of the window. See #GtkWindowType.
8423 * Return value: the type of the window
8428 gtk_window_get_window_type (GtkWindow *window)
8430 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
8432 return window->type;
8435 #if defined (G_OS_WIN32) && !defined (_WIN64)
8437 #undef gtk_window_set_icon_from_file
8440 gtk_window_set_icon_from_file (GtkWindow *window,
8441 const gchar *filename,
8444 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
8447 if (utf8_filename == NULL)
8450 retval = gtk_window_set_icon_from_file_utf8 (window, utf8_filename, err);
8452 g_free (utf8_filename);
8457 #undef gtk_window_set_default_icon_from_file
8460 gtk_window_set_default_icon_from_file (const gchar *filename,
8463 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
8466 if (utf8_filename == NULL)
8469 retval = gtk_window_set_default_icon_from_file_utf8 (utf8_filename, err);
8471 g_free (utf8_filename);
8478 #define __GTK_WINDOW_C__
8479 #include "gtkaliasdef.c"