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 */
399 timestamp = strtoul (timestr, &end, 0);
400 if (end != timestr && errno == 0)
408 startup_id_is_fake (const gchar* startup_id)
410 return strncmp (startup_id, "_TIME", 5) == 0;
414 gtk_window_class_init (GtkWindowClass *klass)
416 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
417 GtkObjectClass *object_class;
418 GtkWidgetClass *widget_class;
419 GtkContainerClass *container_class;
420 GtkBindingSet *binding_set;
422 object_class = (GtkObjectClass*) klass;
423 widget_class = (GtkWidgetClass*) klass;
424 container_class = (GtkContainerClass*) klass;
426 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
427 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
428 quark_gtk_window_default_icon_pixmap = g_quark_from_static_string ("gtk-window-default-icon-pixmap");
429 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
430 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
432 gobject_class->dispose = gtk_window_dispose;
433 gobject_class->finalize = gtk_window_finalize;
435 gobject_class->set_property = gtk_window_set_property;
436 gobject_class->get_property = gtk_window_get_property;
438 object_class->destroy = gtk_window_destroy;
440 widget_class->show = gtk_window_show;
441 widget_class->hide = gtk_window_hide;
442 widget_class->map = gtk_window_map;
443 widget_class->map_event = gtk_window_map_event;
444 widget_class->unmap = gtk_window_unmap;
445 widget_class->realize = gtk_window_realize;
446 widget_class->unrealize = gtk_window_unrealize;
447 widget_class->size_request = gtk_window_size_request;
448 widget_class->size_allocate = gtk_window_size_allocate;
449 widget_class->configure_event = gtk_window_configure_event;
450 widget_class->key_press_event = gtk_window_key_press_event;
451 widget_class->key_release_event = gtk_window_key_release_event;
452 widget_class->enter_notify_event = gtk_window_enter_notify_event;
453 widget_class->leave_notify_event = gtk_window_leave_notify_event;
454 widget_class->focus_in_event = gtk_window_focus_in_event;
455 widget_class->focus_out_event = gtk_window_focus_out_event;
456 widget_class->client_event = gtk_window_client_event;
457 widget_class->focus = gtk_window_focus;
459 widget_class->expose_event = gtk_window_expose;
461 container_class->check_resize = gtk_window_check_resize;
463 klass->set_focus = gtk_window_real_set_focus;
464 klass->frame_event = gtk_window_frame_event;
466 klass->activate_default = gtk_window_real_activate_default;
467 klass->activate_focus = gtk_window_real_activate_focus;
468 klass->move_focus = gtk_window_move_focus;
469 klass->keys_changed = gtk_window_keys_changed;
471 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
474 g_object_class_install_property (gobject_class,
476 g_param_spec_enum ("type",
478 P_("The type of the window"),
479 GTK_TYPE_WINDOW_TYPE,
481 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
483 g_object_class_install_property (gobject_class,
485 g_param_spec_string ("title",
487 P_("The title of the window"),
489 GTK_PARAM_READWRITE));
491 g_object_class_install_property (gobject_class,
493 g_param_spec_string ("role",
495 P_("Unique identifier for the window to be used when restoring a session"),
497 GTK_PARAM_READWRITE));
500 * GtkWindow:startup-id:
502 * The :startup-id is a write-only property for setting window's
503 * startup notification identifier. See gtk_window_set_startup_id()
508 g_object_class_install_property (gobject_class,
510 g_param_spec_string ("startup-id",
512 P_("Unique startup identifier for the window used by startup-notification"),
514 GTK_PARAM_WRITABLE));
516 g_object_class_install_property (gobject_class,
518 g_param_spec_boolean ("allow-shrink",
520 /* xgettext:no-c-format */
521 P_("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
523 GTK_PARAM_READWRITE));
525 g_object_class_install_property (gobject_class,
527 g_param_spec_boolean ("allow-grow",
529 P_("If TRUE, users can expand the window beyond its minimum size"),
531 GTK_PARAM_READWRITE));
533 g_object_class_install_property (gobject_class,
535 g_param_spec_boolean ("resizable",
537 P_("If TRUE, users can resize the window"),
539 GTK_PARAM_READWRITE));
541 g_object_class_install_property (gobject_class,
543 g_param_spec_boolean ("modal",
545 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
547 GTK_PARAM_READWRITE));
549 g_object_class_install_property (gobject_class,
551 g_param_spec_enum ("window-position",
552 P_("Window Position"),
553 P_("The initial position of the window"),
554 GTK_TYPE_WINDOW_POSITION,
556 GTK_PARAM_READWRITE));
558 g_object_class_install_property (gobject_class,
560 g_param_spec_int ("default-width",
562 P_("The default width of the window, used when initially showing the window"),
566 GTK_PARAM_READWRITE));
568 g_object_class_install_property (gobject_class,
570 g_param_spec_int ("default-height",
571 P_("Default Height"),
572 P_("The default height of the window, used when initially showing the window"),
576 GTK_PARAM_READWRITE));
578 g_object_class_install_property (gobject_class,
579 PROP_DESTROY_WITH_PARENT,
580 g_param_spec_boolean ("destroy-with-parent",
581 P_("Destroy with Parent"),
582 P_("If this window should be destroyed when the parent is destroyed"),
584 GTK_PARAM_READWRITE));
586 g_object_class_install_property (gobject_class,
588 g_param_spec_object ("icon",
590 P_("Icon for this window"),
592 GTK_PARAM_READWRITE));
595 * GtkWindow:icon-name:
597 * The :icon-name property specifies the name of the themed icon to
598 * use as the window icon. See #GtkIconTheme for more details.
602 g_object_class_install_property (gobject_class,
604 g_param_spec_string ("icon-name",
606 P_("Name of the themed icon for this window"),
608 GTK_PARAM_READWRITE));
610 g_object_class_install_property (gobject_class,
612 g_param_spec_object ("screen",
614 P_("The screen where this window will be displayed"),
616 GTK_PARAM_READWRITE));
618 g_object_class_install_property (gobject_class,
620 g_param_spec_boolean ("is-active",
622 P_("Whether the toplevel is the current active window"),
624 GTK_PARAM_READABLE));
626 g_object_class_install_property (gobject_class,
627 PROP_HAS_TOPLEVEL_FOCUS,
628 g_param_spec_boolean ("has-toplevel-focus",
629 P_("Focus in Toplevel"),
630 P_("Whether the input focus is within this GtkWindow"),
632 GTK_PARAM_READABLE));
634 g_object_class_install_property (gobject_class,
636 g_param_spec_enum ("type-hint",
638 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
639 GDK_TYPE_WINDOW_TYPE_HINT,
640 GDK_WINDOW_TYPE_HINT_NORMAL,
641 GTK_PARAM_READWRITE));
643 g_object_class_install_property (gobject_class,
644 PROP_SKIP_TASKBAR_HINT,
645 g_param_spec_boolean ("skip-taskbar-hint",
647 P_("TRUE if the window should not be in the task bar."),
649 GTK_PARAM_READWRITE));
651 g_object_class_install_property (gobject_class,
652 PROP_SKIP_PAGER_HINT,
653 g_param_spec_boolean ("skip-pager-hint",
655 P_("TRUE if the window should not be in the pager."),
657 GTK_PARAM_READWRITE));
659 g_object_class_install_property (gobject_class,
661 g_param_spec_boolean ("urgency-hint",
663 P_("TRUE if the window should be brought to the user's attention."),
665 GTK_PARAM_READWRITE));
668 * GtkWindow:accept-focus-hint:
670 * Whether the window should receive the input focus.
674 g_object_class_install_property (gobject_class,
676 g_param_spec_boolean ("accept-focus",
678 P_("TRUE if the window should receive the input focus."),
680 GTK_PARAM_READWRITE));
683 * GtkWindow:focus-on-map-hint:
685 * Whether the window should receive the input focus when mapped.
689 g_object_class_install_property (gobject_class,
691 g_param_spec_boolean ("focus-on-map",
693 P_("TRUE if the window should receive the input focus when mapped."),
695 GTK_PARAM_READWRITE));
698 * GtkWindow:decorated:
700 * Whether the window should be decorated by the window manager.
704 g_object_class_install_property (gobject_class,
706 g_param_spec_boolean ("decorated",
708 P_("Whether the window should be decorated by the window manager"),
710 GTK_PARAM_READWRITE));
713 * GtkWindow:deletable:
715 * Whether the window frame should have a close button.
719 g_object_class_install_property (gobject_class,
721 g_param_spec_boolean ("deletable",
723 P_("Whether the window frame should have a close button"),
725 GTK_PARAM_READWRITE));
731 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
732 * more details about window gravity.
736 g_object_class_install_property (gobject_class,
738 g_param_spec_enum ("gravity",
740 P_("The window gravity of the window"),
742 GDK_GRAVITY_NORTH_WEST,
743 GTK_PARAM_READWRITE));
747 * GtkWindow:transient-for:
749 * The transient parent of the window. See gtk_window_set_transient_for() for
750 * more details about transient windows.
754 g_object_class_install_property (gobject_class,
756 g_param_spec_object ("transient-for",
757 P_("Transient for Window"),
758 P_("The transient parent of the dialog"),
760 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
765 * The requested opacity of the window. See gtk_window_set_opacity() for
766 * more details about window opacity.
770 g_object_class_install_property (gobject_class,
772 g_param_spec_double ("opacity",
773 P_("Opacity for Window"),
774 P_("The opacity of the window, from 0 to 1"),
778 GTK_PARAM_READWRITE));
780 window_signals[SET_FOCUS] =
781 g_signal_new (I_("set-focus"),
782 G_TYPE_FROM_CLASS (gobject_class),
784 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
786 _gtk_marshal_VOID__OBJECT,
790 window_signals[FRAME_EVENT] =
791 g_signal_new (I_("frame-event"),
792 G_TYPE_FROM_CLASS (gobject_class),
794 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
795 _gtk_boolean_handled_accumulator, NULL,
796 _gtk_marshal_BOOLEAN__BOXED,
801 * GtkWindow::activate-focus:
802 * @window: the window which received the signal
804 * The ::activate-default signal is a
805 * <link linkend="keybinding-signals">keybinding signal</link>
806 * which gets emitted when the user activates the currently
807 * focused widget of @window.
809 window_signals[ACTIVATE_FOCUS] =
810 g_signal_new (I_("activate-focus"),
811 G_TYPE_FROM_CLASS (gobject_class),
812 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
813 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
815 _gtk_marshal_VOID__VOID,
820 * GtkWindow::activate-default:
821 * @window: the window which received the signal
823 * The ::activate-default signal is a
824 * <link linkend="keybinding-signals">keybinding signal</link>
825 * which gets emitted when the user activates the default widget
828 window_signals[ACTIVATE_DEFAULT] =
829 g_signal_new (I_("activate-default"),
830 G_TYPE_FROM_CLASS (gobject_class),
831 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
832 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
834 _gtk_marshal_VOID__VOID,
839 * GtkWindow::keys-changed:
840 * @window: the window which received the signal
842 * The ::keys-changed signal gets emitted when the set of accelerators
843 * or mnemonics that are associated with @window changes.
845 window_signals[KEYS_CHANGED] =
846 g_signal_new (I_("keys-changed"),
847 G_TYPE_FROM_CLASS (gobject_class),
849 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
851 _gtk_marshal_VOID__VOID,
859 binding_set = gtk_binding_set_by_class (klass);
861 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
862 "activate-focus", 0);
863 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
864 "activate-focus", 0);
866 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
867 "activate-default", 0);
868 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0,
869 "activate-default", 0);
870 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
871 "activate-default", 0);
873 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
874 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
875 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
876 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
878 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
879 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
880 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
881 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
885 gtk_window_init (GtkWindow *window)
887 GdkColormap *colormap;
888 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
890 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
891 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
893 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
895 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
897 window->title = NULL;
898 window->wmclass_name = g_strdup (g_get_prgname ());
899 window->wmclass_class = g_strdup (gdk_get_program_class ());
900 window->wm_role = NULL;
901 window->geometry_info = NULL;
902 window->type = GTK_WINDOW_TOPLEVEL;
903 window->focus_widget = NULL;
904 window->default_widget = NULL;
905 window->configure_request_count = 0;
906 window->allow_shrink = FALSE;
907 window->allow_grow = TRUE;
908 window->configure_notify_received = FALSE;
909 window->position = GTK_WIN_POS_NONE;
910 window->need_default_size = TRUE;
911 window->need_default_position = TRUE;
912 window->modal = FALSE;
913 window->frame = NULL;
914 window->has_frame = FALSE;
915 window->frame_left = 0;
916 window->frame_right = 0;
917 window->frame_top = 0;
918 window->frame_bottom = 0;
919 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
920 window->gravity = GDK_GRAVITY_NORTH_WEST;
921 window->decorated = TRUE;
922 window->mnemonic_modifier = GDK_MOD1_MASK;
923 window->screen = gdk_screen_get_default ();
925 priv->accept_focus = TRUE;
926 priv->focus_on_map = TRUE;
927 priv->deletable = TRUE;
928 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
930 priv->startup_id = NULL;
932 colormap = _gtk_widget_peek_colormap ();
934 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
936 g_object_ref_sink (window);
937 window->has_user_ref_count = TRUE;
938 toplevel_list = g_slist_prepend (toplevel_list, window);
940 gtk_decorated_window_init (window);
942 g_signal_connect (window->screen, "composited-changed",
943 G_CALLBACK (gtk_window_on_composited_changed), window);
947 gtk_window_set_property (GObject *object,
954 window = GTK_WINDOW (object);
959 window->type = g_value_get_enum (value);
962 gtk_window_set_title (window, g_value_get_string (value));
965 gtk_window_set_role (window, g_value_get_string (value));
967 case PROP_STARTUP_ID:
968 gtk_window_set_startup_id (window, g_value_get_string (value));
970 case PROP_ALLOW_SHRINK:
971 window->allow_shrink = g_value_get_boolean (value);
972 gtk_widget_queue_resize (GTK_WIDGET (window));
974 case PROP_ALLOW_GROW:
975 window->allow_grow = g_value_get_boolean (value);
976 gtk_widget_queue_resize (GTK_WIDGET (window));
977 g_object_notify (G_OBJECT (window), "resizable");
980 window->allow_grow = g_value_get_boolean (value);
981 gtk_widget_queue_resize (GTK_WIDGET (window));
982 g_object_notify (G_OBJECT (window), "allow-grow");
985 gtk_window_set_modal (window, g_value_get_boolean (value));
988 gtk_window_set_position (window, g_value_get_enum (value));
990 case PROP_DEFAULT_WIDTH:
991 gtk_window_set_default_size_internal (window,
992 TRUE, g_value_get_int (value),
995 case PROP_DEFAULT_HEIGHT:
996 gtk_window_set_default_size_internal (window,
998 TRUE, g_value_get_int (value), FALSE);
1000 case PROP_DESTROY_WITH_PARENT:
1001 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1004 gtk_window_set_icon (window,
1005 g_value_get_object (value));
1007 case PROP_ICON_NAME:
1008 gtk_window_set_icon_name (window, g_value_get_string (value));
1011 gtk_window_set_screen (window, g_value_get_object (value));
1013 case PROP_TYPE_HINT:
1014 gtk_window_set_type_hint (window,
1015 g_value_get_enum (value));
1017 case PROP_SKIP_TASKBAR_HINT:
1018 gtk_window_set_skip_taskbar_hint (window,
1019 g_value_get_boolean (value));
1021 case PROP_SKIP_PAGER_HINT:
1022 gtk_window_set_skip_pager_hint (window,
1023 g_value_get_boolean (value));
1025 case PROP_URGENCY_HINT:
1026 gtk_window_set_urgency_hint (window,
1027 g_value_get_boolean (value));
1029 case PROP_ACCEPT_FOCUS:
1030 gtk_window_set_accept_focus (window,
1031 g_value_get_boolean (value));
1033 case PROP_FOCUS_ON_MAP:
1034 gtk_window_set_focus_on_map (window,
1035 g_value_get_boolean (value));
1037 case PROP_DECORATED:
1038 gtk_window_set_decorated (window, g_value_get_boolean (value));
1040 case PROP_DELETABLE:
1041 gtk_window_set_deletable (window, g_value_get_boolean (value));
1044 gtk_window_set_gravity (window, g_value_get_enum (value));
1046 case PROP_TRANSIENT_FOR:
1047 gtk_window_set_transient_for (window, g_value_get_object (value));
1050 gtk_window_set_opacity (window, g_value_get_double (value));
1053 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1059 gtk_window_get_property (GObject *object,
1065 GtkWindowPrivate *priv;
1067 window = GTK_WINDOW (object);
1068 priv = GTK_WINDOW_GET_PRIVATE (window);
1072 GtkWindowGeometryInfo *info;
1074 g_value_set_enum (value, window->type);
1077 g_value_set_string (value, window->wm_role);
1080 g_value_set_string (value, window->title);
1082 case PROP_ALLOW_SHRINK:
1083 g_value_set_boolean (value, window->allow_shrink);
1085 case PROP_ALLOW_GROW:
1086 g_value_set_boolean (value, window->allow_grow);
1088 case PROP_RESIZABLE:
1089 g_value_set_boolean (value, window->allow_grow);
1092 g_value_set_boolean (value, window->modal);
1095 g_value_set_enum (value, window->position);
1097 case PROP_DEFAULT_WIDTH:
1098 info = gtk_window_get_geometry_info (window, FALSE);
1100 g_value_set_int (value, -1);
1102 g_value_set_int (value, info->default_width);
1104 case PROP_DEFAULT_HEIGHT:
1105 info = gtk_window_get_geometry_info (window, FALSE);
1107 g_value_set_int (value, -1);
1109 g_value_set_int (value, info->default_height);
1111 case PROP_DESTROY_WITH_PARENT:
1112 g_value_set_boolean (value, window->destroy_with_parent);
1115 g_value_set_object (value, gtk_window_get_icon (window));
1117 case PROP_ICON_NAME:
1118 g_value_set_string (value, gtk_window_get_icon_name (window));
1121 g_value_set_object (value, window->screen);
1123 case PROP_IS_ACTIVE:
1124 g_value_set_boolean (value, window->is_active);
1126 case PROP_HAS_TOPLEVEL_FOCUS:
1127 g_value_set_boolean (value, window->has_toplevel_focus);
1129 case PROP_TYPE_HINT:
1130 g_value_set_enum (value, priv->type_hint);
1132 case PROP_SKIP_TASKBAR_HINT:
1133 g_value_set_boolean (value,
1134 gtk_window_get_skip_taskbar_hint (window));
1136 case PROP_SKIP_PAGER_HINT:
1137 g_value_set_boolean (value,
1138 gtk_window_get_skip_pager_hint (window));
1140 case PROP_URGENCY_HINT:
1141 g_value_set_boolean (value,
1142 gtk_window_get_urgency_hint (window));
1144 case PROP_ACCEPT_FOCUS:
1145 g_value_set_boolean (value,
1146 gtk_window_get_accept_focus (window));
1148 case PROP_FOCUS_ON_MAP:
1149 g_value_set_boolean (value,
1150 gtk_window_get_focus_on_map (window));
1152 case PROP_DECORATED:
1153 g_value_set_boolean (value, gtk_window_get_decorated (window));
1155 case PROP_DELETABLE:
1156 g_value_set_boolean (value, gtk_window_get_deletable (window));
1159 g_value_set_enum (value, gtk_window_get_gravity (window));
1161 case PROP_TRANSIENT_FOR:
1162 g_value_set_object (value, gtk_window_get_transient_for (window));
1165 g_value_set_double (value, gtk_window_get_opacity (window));
1168 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1174 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1176 parent_buildable_iface = g_type_interface_peek_parent (iface);
1177 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1178 iface->parser_finished = gtk_window_buildable_parser_finished;
1179 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1180 iface->custom_finished = gtk_window_buildable_custom_finished;
1184 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1185 GtkBuilder *builder,
1187 const GValue *value)
1189 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (buildable);
1191 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1192 priv->builder_visible = TRUE;
1194 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1198 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1199 GtkBuilder *builder)
1201 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (buildable);
1205 if (priv->builder_visible)
1206 gtk_widget_show (GTK_WIDGET (buildable));
1208 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1209 for (l = accels; l; l = l->next)
1211 object = gtk_builder_get_object (builder, l->data);
1214 g_warning ("Unknown accel group %s specified in window %s",
1215 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1218 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1219 GTK_ACCEL_GROUP (object));
1223 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1225 parent_buildable_iface->parser_finished (buildable, builder);
1231 } GSListSubParserData;
1234 window_start_element (GMarkupParseContext *context,
1235 const gchar *element_name,
1236 const gchar **names,
1237 const gchar **values,
1242 GSListSubParserData *data = (GSListSubParserData*)user_data;
1244 if (strcmp (element_name, "group") == 0)
1246 for (i = 0; names[i]; i++)
1248 if (strcmp (names[i], "name") == 0)
1249 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1252 else if (strcmp (element_name, "accel-groups") == 0)
1255 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1260 static const GMarkupParser window_parser =
1262 window_start_element
1266 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1267 GtkBuilder *builder,
1269 const gchar *tagname,
1270 GMarkupParser *parser,
1273 GSListSubParserData *parser_data;
1275 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1276 tagname, parser, data))
1279 if (strcmp (tagname, "accel-groups") == 0)
1281 parser_data = g_slice_new0 (GSListSubParserData);
1282 parser_data->items = NULL;
1283 parser_data->object = G_OBJECT (buildable);
1285 *parser = window_parser;
1286 *data = parser_data;
1294 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1295 GtkBuilder *builder,
1297 const gchar *tagname,
1300 GSListSubParserData *data;
1302 parent_buildable_iface->custom_finished (buildable, builder, child,
1303 tagname, user_data);
1305 if (strcmp (tagname, "accel-groups") != 0)
1308 data = (GSListSubParserData*)user_data;
1310 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1311 data->items, (GDestroyNotify) g_slist_free);
1313 g_slice_free (GSListSubParserData, data);
1318 * @type: type of window
1320 * Creates a new #GtkWindow, which is a toplevel window that can
1321 * contain other widgets. Nearly always, the type of the window should
1322 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1323 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1324 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1325 * dialogs, though in some other toolkits dialogs are called "popups".
1326 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1327 * On X11, popup windows are not controlled by the <link
1328 * linkend="gtk-X11-arch">window manager</link>.
1330 * If you simply want an undecorated window (no window borders), use
1331 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1333 * Return value: a new #GtkWindow.
1336 gtk_window_new (GtkWindowType type)
1340 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1342 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1344 window->type = type;
1346 return GTK_WIDGET (window);
1350 * gtk_window_set_title:
1351 * @window: a #GtkWindow
1352 * @title: title of the window
1354 * Sets the title of the #GtkWindow. The title of a window will be
1355 * displayed in its title bar; on the X Window System, the title bar
1356 * is rendered by the <link linkend="gtk-X11-arch">window
1357 * manager</link>, so exactly how the title appears to users may vary
1358 * according to a user's exact configuration. The title should help a
1359 * user distinguish this window from other windows they may have
1360 * open. A good title might include the application name and current
1361 * document filename, for example.
1365 gtk_window_set_title (GtkWindow *window,
1370 g_return_if_fail (GTK_IS_WINDOW (window));
1372 new_title = g_strdup (title);
1373 g_free (window->title);
1374 window->title = new_title;
1376 if (GTK_WIDGET_REALIZED (window))
1378 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
1380 gtk_decorated_window_set_title (window, title);
1383 g_object_notify (G_OBJECT (window), "title");
1387 * gtk_window_get_title:
1388 * @window: a #GtkWindow
1390 * Retrieves the title of the window. See gtk_window_set_title().
1392 * Return value: the title of the window, or %NULL if none has
1393 * been set explicitely. The returned string is owned by the widget
1394 * and must not be modified or freed.
1396 G_CONST_RETURN gchar *
1397 gtk_window_get_title (GtkWindow *window)
1399 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1401 return window->title;
1405 * gtk_window_set_wmclass:
1406 * @window: a #GtkWindow
1407 * @wmclass_name: window name hint
1408 * @wmclass_class: window class hint
1410 * Don't use this function. It sets the X Window System "class" and
1411 * "name" hints for a window. According to the ICCCM, you should
1412 * always set these to the same value for all windows in an
1413 * application, and GTK+ sets them to that value by default, so calling
1414 * this function is sort of pointless. However, you may want to call
1415 * gtk_window_set_role() on each window in your application, for the
1416 * benefit of the session manager. Setting the role allows the window
1417 * manager to restore window positions when loading a saved session.
1421 gtk_window_set_wmclass (GtkWindow *window,
1422 const gchar *wmclass_name,
1423 const gchar *wmclass_class)
1425 g_return_if_fail (GTK_IS_WINDOW (window));
1427 g_free (window->wmclass_name);
1428 window->wmclass_name = g_strdup (wmclass_name);
1430 g_free (window->wmclass_class);
1431 window->wmclass_class = g_strdup (wmclass_class);
1433 if (GTK_WIDGET_REALIZED (window))
1434 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1438 * gtk_window_set_role:
1439 * @window: a #GtkWindow
1440 * @role: unique identifier for the window to be used when restoring a session
1442 * This function is only useful on X11, not with other GTK+ targets.
1444 * In combination with the window title, the window role allows a
1445 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1446 * same" window when an application is restarted. So for example you
1447 * might set the "toolbox" role on your app's toolbox window, so that
1448 * when the user restarts their session, the window manager can put
1449 * the toolbox back in the same place.
1451 * If a window already has a unique title, you don't need to set the
1452 * role, since the WM can use the title to identify the window when
1453 * restoring the session.
1457 gtk_window_set_role (GtkWindow *window,
1462 g_return_if_fail (GTK_IS_WINDOW (window));
1464 new_role = g_strdup (role);
1465 g_free (window->wm_role);
1466 window->wm_role = new_role;
1468 if (GTK_WIDGET_REALIZED (window))
1469 gdk_window_set_role (GTK_WIDGET (window)->window, window->wm_role);
1471 g_object_notify (G_OBJECT (window), "role");
1475 * gtk_window_set_startup_id:
1476 * @window: a #GtkWindow
1477 * @startup_id: a string with startup-notification identifier
1479 * Startup notification identifiers are used by desktop environment to
1480 * track application startup, to provide user feedback and other
1481 * features. This function changes the corresponding property on the
1482 * underlying GdkWindow. Normally, startup identifier is managed
1483 * automatically and you should only use this function in special cases
1484 * like transferring focus from other processes. You should use this
1485 * function before calling gtk_window_present() or any equivalent
1486 * function generating a window map event.
1488 * This function is only useful on X11, not with other GTK+ targets.
1493 gtk_window_set_startup_id (GtkWindow *window,
1494 const gchar *startup_id)
1496 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
1498 g_return_if_fail (GTK_IS_WINDOW (window));
1500 g_free (priv->startup_id);
1501 priv->startup_id = g_strdup (startup_id);
1503 if (GTK_WIDGET_REALIZED (window))
1505 /* Here we differentiate real and "fake" startup notification IDs,
1506 * constructed on purpose just to pass interaction timestamp
1508 if (startup_id_is_fake (priv->startup_id))
1510 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1512 gtk_window_present_with_time (window, timestamp);
1516 gdk_window_set_startup_id (GTK_WIDGET (window)->window,
1519 /* If window is mapped, terminate the startup-notification too */
1520 if (GTK_WIDGET_MAPPED (window) && !disable_startup_notification)
1521 gdk_notify_startup_complete_with_id (priv->startup_id);
1525 g_object_notify (G_OBJECT (window), "startup-id");
1529 * gtk_window_get_role:
1530 * @window: a #GtkWindow
1532 * Returns the role of the window. See gtk_window_set_role() for
1533 * further explanation.
1535 * Return value: the role of the window if set, or %NULL. The
1536 * returned is owned by the widget and must not be modified
1539 G_CONST_RETURN gchar *
1540 gtk_window_get_role (GtkWindow *window)
1542 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1544 return window->wm_role;
1548 * gtk_window_set_focus:
1549 * @window: a #GtkWindow
1550 * @focus: widget to be the new focus widget, or %NULL to unset
1551 * any focus widget for the toplevel window.
1553 * If @focus is not the current focus widget, and is focusable, sets
1554 * it as the focus widget for the window. If @focus is %NULL, unsets
1555 * the focus widget for this window. To set the focus to a particular
1556 * widget in the toplevel, it is usually more convenient to use
1557 * gtk_widget_grab_focus() instead of this function.
1560 gtk_window_set_focus (GtkWindow *window,
1563 g_return_if_fail (GTK_IS_WINDOW (window));
1566 g_return_if_fail (GTK_IS_WIDGET (focus));
1567 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1571 gtk_widget_grab_focus (focus);
1574 /* Clear the existing focus chain, so that when we focus into
1575 * the window again, we start at the beginnning.
1577 GtkWidget *widget = window->focus_widget;
1580 while (widget->parent)
1582 widget = widget->parent;
1583 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1587 _gtk_window_internal_set_focus (window, NULL);
1592 _gtk_window_internal_set_focus (GtkWindow *window,
1595 g_return_if_fail (GTK_IS_WINDOW (window));
1597 if ((window->focus_widget != focus) ||
1598 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1599 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1603 * gtk_window_set_default:
1604 * @window: a #GtkWindow
1605 * @default_widget: widget to be the default, or %NULL to unset the
1606 * default widget for the toplevel.
1608 * The default widget is the widget that's activated when the user
1609 * presses Enter in a dialog (for example). This function sets or
1610 * unsets the default widget for a #GtkWindow about. When setting
1611 * (rather than unsetting) the default widget it's generally easier to
1612 * call gtk_widget_grab_focus() on the widget. Before making a widget
1613 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1614 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1617 gtk_window_set_default (GtkWindow *window,
1618 GtkWidget *default_widget)
1620 g_return_if_fail (GTK_IS_WINDOW (window));
1623 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1625 if (window->default_widget != default_widget)
1627 GtkWidget *old_default_widget = NULL;
1630 g_object_ref (default_widget);
1632 if (window->default_widget)
1634 old_default_widget = window->default_widget;
1636 if (window->focus_widget != window->default_widget ||
1637 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1638 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1639 gtk_widget_queue_draw (window->default_widget);
1642 window->default_widget = default_widget;
1644 if (window->default_widget)
1646 if (window->focus_widget == NULL ||
1647 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1648 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1649 gtk_widget_queue_draw (window->default_widget);
1652 if (old_default_widget)
1653 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1657 g_object_notify (G_OBJECT (default_widget), "has-default");
1658 g_object_unref (default_widget);
1664 * gtk_window_get_default_widget:
1665 * @window: a #GtkWindow
1667 * Returns the default widget for @window. See gtk_window_set_default()
1670 * Returns: the default widget, or %NULL if there is none.
1675 gtk_window_get_default_widget (GtkWindow *window)
1677 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1679 return window->default_widget;
1683 gtk_window_set_policy_internal (GtkWindow *window,
1684 gboolean allow_shrink,
1685 gboolean allow_grow,
1686 gboolean auto_shrink)
1688 window->allow_shrink = (allow_shrink != FALSE);
1689 window->allow_grow = (allow_grow != FALSE);
1691 g_object_freeze_notify (G_OBJECT (window));
1692 g_object_notify (G_OBJECT (window), "allow-shrink");
1693 g_object_notify (G_OBJECT (window), "allow-grow");
1694 g_object_notify (G_OBJECT (window), "resizable");
1695 g_object_thaw_notify (G_OBJECT (window));
1697 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
1701 gtk_window_set_policy (GtkWindow *window,
1702 gboolean allow_shrink,
1703 gboolean allow_grow,
1704 gboolean auto_shrink)
1706 g_return_if_fail (GTK_IS_WINDOW (window));
1708 gtk_window_set_policy_internal (window, allow_shrink, allow_grow, auto_shrink);
1712 handle_keys_changed (gpointer data)
1716 window = GTK_WINDOW (data);
1718 if (window->keys_changed_handler)
1720 g_source_remove (window->keys_changed_handler);
1721 window->keys_changed_handler = 0;
1724 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1730 gtk_window_notify_keys_changed (GtkWindow *window)
1732 if (!window->keys_changed_handler)
1733 window->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1737 * gtk_window_add_accel_group:
1738 * @window: window to attach accelerator group to
1739 * @accel_group: a #GtkAccelGroup
1741 * Associate @accel_group with @window, such that calling
1742 * gtk_accel_groups_activate() on @window will activate accelerators
1746 gtk_window_add_accel_group (GtkWindow *window,
1747 GtkAccelGroup *accel_group)
1749 g_return_if_fail (GTK_IS_WINDOW (window));
1750 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1752 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1753 g_signal_connect_object (accel_group, "accel-changed",
1754 G_CALLBACK (gtk_window_notify_keys_changed),
1755 window, G_CONNECT_SWAPPED);
1756 gtk_window_notify_keys_changed (window);
1760 * gtk_window_remove_accel_group:
1761 * @window: a #GtkWindow
1762 * @accel_group: a #GtkAccelGroup
1764 * Reverses the effects of gtk_window_add_accel_group().
1767 gtk_window_remove_accel_group (GtkWindow *window,
1768 GtkAccelGroup *accel_group)
1770 g_return_if_fail (GTK_IS_WINDOW (window));
1771 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1773 g_signal_handlers_disconnect_by_func (accel_group,
1774 gtk_window_notify_keys_changed,
1776 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1777 gtk_window_notify_keys_changed (window);
1780 static GtkMnemonicHash *
1781 gtk_window_get_mnemonic_hash (GtkWindow *window,
1784 GtkWindowPrivate *private = GTK_WINDOW_GET_PRIVATE (window);
1785 if (!private->mnemonic_hash && create)
1786 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1788 return private->mnemonic_hash;
1792 * gtk_window_add_mnemonic:
1793 * @window: a #GtkWindow
1794 * @keyval: the mnemonic
1795 * @target: the widget that gets activated by the mnemonic
1797 * Adds a mnemonic to this window.
1800 gtk_window_add_mnemonic (GtkWindow *window,
1804 g_return_if_fail (GTK_IS_WINDOW (window));
1805 g_return_if_fail (GTK_IS_WIDGET (target));
1807 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1809 gtk_window_notify_keys_changed (window);
1813 * gtk_window_remove_mnemonic:
1814 * @window: a #GtkWindow
1815 * @keyval: the mnemonic
1816 * @target: the widget that gets activated by the mnemonic
1818 * Removes a mnemonic from this window.
1821 gtk_window_remove_mnemonic (GtkWindow *window,
1825 g_return_if_fail (GTK_IS_WINDOW (window));
1826 g_return_if_fail (GTK_IS_WIDGET (target));
1828 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
1830 gtk_window_notify_keys_changed (window);
1834 * gtk_window_mnemonic_activate:
1835 * @window: a #GtkWindow
1836 * @keyval: the mnemonic
1837 * @modifier: the modifiers
1838 * @returns: %TRUE if the activation is done.
1840 * Activates the targets associated with the mnemonic.
1843 gtk_window_mnemonic_activate (GtkWindow *window,
1845 GdkModifierType modifier)
1847 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1849 if (window->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
1851 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
1853 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
1860 * gtk_window_set_mnemonic_modifier:
1861 * @window: a #GtkWindow
1862 * @modifier: the modifier mask used to activate
1863 * mnemonics on this window.
1865 * Sets the mnemonic modifier for this window.
1868 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1869 GdkModifierType modifier)
1871 g_return_if_fail (GTK_IS_WINDOW (window));
1872 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1874 window->mnemonic_modifier = modifier;
1875 gtk_window_notify_keys_changed (window);
1879 * gtk_window_get_mnemonic_modifier:
1880 * @window: a #GtkWindow
1882 * Returns the mnemonic modifier for this window. See
1883 * gtk_window_set_mnemonic_modifier().
1885 * Return value: the modifier mask used to activate
1886 * mnemonics on this window.
1889 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1891 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1893 return window->mnemonic_modifier;
1897 * gtk_window_set_position:
1898 * @window: a #GtkWindow.
1899 * @position: a position constraint.
1901 * Sets a position constraint for this window. If the old or new
1902 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1903 * the window to be repositioned to satisfy the new constraint.
1906 gtk_window_set_position (GtkWindow *window,
1907 GtkWindowPosition position)
1909 g_return_if_fail (GTK_IS_WINDOW (window));
1911 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1912 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1914 GtkWindowGeometryInfo *info;
1916 info = gtk_window_get_geometry_info (window, TRUE);
1918 /* this flag causes us to re-request the CENTER_ALWAYS
1919 * constraint in gtk_window_move_resize(), see
1920 * comment in that function.
1922 info->position_constraints_changed = TRUE;
1924 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
1927 window->position = position;
1929 g_object_notify (G_OBJECT (window), "window-position");
1933 * gtk_window_activate_focus:
1934 * @window: a #GtkWindow
1936 * Activates the current focused widget within the window.
1938 * Return value: %TRUE if a widget got activated.
1941 gtk_window_activate_focus (GtkWindow *window)
1943 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1945 if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1946 return gtk_widget_activate (window->focus_widget);
1952 * gtk_window_get_focus:
1953 * @window: a #GtkWindow
1955 * Retrieves the current focused widget within the window.
1956 * Note that this is the widget that would have the focus
1957 * if the toplevel window focused; if the toplevel window
1958 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1959 * not be %TRUE for the widget.
1961 * Return value: the currently focused widget, or %NULL if there is none.
1964 gtk_window_get_focus (GtkWindow *window)
1966 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1968 return window->focus_widget;
1972 * gtk_window_activate_default:
1973 * @window: a #GtkWindow
1975 * Activates the default widget for the window, unless the current
1976 * focused widget has been configured to receive the default action
1977 * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
1978 * focused widget is activated.
1980 * Return value: %TRUE if a widget got activated.
1983 gtk_window_activate_default (GtkWindow *window)
1985 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1987 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1988 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1989 return gtk_widget_activate (window->default_widget);
1990 else if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1991 return gtk_widget_activate (window->focus_widget);
1997 * gtk_window_set_modal:
1998 * @window: a #GtkWindow
1999 * @modal: whether the window is modal
2001 * Sets a window modal or non-modal. Modal windows prevent interaction
2002 * with other windows in the same application. To keep modal dialogs
2003 * on top of main application windows, use
2004 * gtk_window_set_transient_for() to make the dialog transient for the
2005 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2006 * will then disallow lowering the dialog below the parent.
2011 gtk_window_set_modal (GtkWindow *window,
2014 g_return_if_fail (GTK_IS_WINDOW (window));
2016 modal = modal != FALSE;
2017 if (window->modal == modal)
2020 window->modal = modal;
2022 /* adjust desired modality state */
2023 if (GTK_WIDGET_REALIZED (window))
2025 GtkWidget *widget = GTK_WIDGET (window);
2028 gdk_window_set_modal_hint (widget->window, TRUE);
2030 gdk_window_set_modal_hint (widget->window, FALSE);
2033 if (GTK_WIDGET_VISIBLE (window))
2036 gtk_grab_add (GTK_WIDGET (window));
2038 gtk_grab_remove (GTK_WIDGET (window));
2041 g_object_notify (G_OBJECT (window), "modal");
2045 * gtk_window_get_modal:
2046 * @window: a #GtkWindow
2048 * Returns whether the window is modal. See gtk_window_set_modal().
2050 * Return value: %TRUE if the window is set to be modal and
2051 * establishes a grab when shown
2054 gtk_window_get_modal (GtkWindow *window)
2056 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2058 return window->modal;
2062 * gtk_window_list_toplevels:
2064 * Returns a list of all existing toplevel windows. The widgets
2065 * in the list are not individually referenced. If you want
2066 * to iterate through the list and perform actions involving
2067 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2068 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2069 * then unref all the widgets afterwards.
2071 * Return value: list of toplevel widgets
2074 gtk_window_list_toplevels (void)
2079 for (slist = toplevel_list; slist; slist = slist->next)
2080 list = g_list_prepend (list, slist->data);
2086 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2088 GList *embedded_windows;
2090 g_return_if_fail (GTK_IS_WINDOW (window));
2092 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2093 if (embedded_windows)
2094 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2095 embedded_windows = g_list_prepend (embedded_windows,
2096 GUINT_TO_POINTER (xid));
2098 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2101 (GDestroyNotify) g_list_free : NULL);
2105 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2107 GList *embedded_windows;
2110 g_return_if_fail (GTK_IS_WINDOW (window));
2112 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2113 if (embedded_windows)
2114 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2116 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2119 embedded_windows = g_list_remove_link (embedded_windows, node);
2120 g_list_free_1 (node);
2123 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2126 (GDestroyNotify) g_list_free : NULL);
2130 _gtk_window_reposition (GtkWindow *window,
2134 g_return_if_fail (GTK_IS_WINDOW (window));
2136 gtk_window_move (window, x, y);
2140 gtk_window_dispose (GObject *object)
2142 GtkWindow *window = GTK_WINDOW (object);
2144 gtk_window_set_focus (window, NULL);
2145 gtk_window_set_default (window, NULL);
2147 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2151 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2153 gtk_widget_destroy (GTK_WIDGET (child));
2157 connect_parent_destroyed (GtkWindow *window)
2159 if (window->transient_parent)
2161 g_signal_connect (window->transient_parent,
2163 G_CALLBACK (parent_destroyed_callback),
2169 disconnect_parent_destroyed (GtkWindow *window)
2171 if (window->transient_parent)
2173 g_signal_handlers_disconnect_by_func (window->transient_parent,
2174 parent_destroyed_callback,
2180 gtk_window_transient_parent_realized (GtkWidget *parent,
2183 if (GTK_WIDGET_REALIZED (window))
2184 gdk_window_set_transient_for (window->window, parent->window);
2188 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2191 if (GTK_WIDGET_REALIZED (window))
2192 gdk_property_delete (window->window,
2193 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2197 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2201 gtk_window_set_screen (window, parent->screen);
2205 gtk_window_unset_transient_for (GtkWindow *window)
2207 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
2209 if (window->transient_parent)
2211 g_signal_handlers_disconnect_by_func (window->transient_parent,
2212 gtk_window_transient_parent_realized,
2214 g_signal_handlers_disconnect_by_func (window->transient_parent,
2215 gtk_window_transient_parent_unrealized,
2217 g_signal_handlers_disconnect_by_func (window->transient_parent,
2218 gtk_window_transient_parent_screen_changed,
2220 g_signal_handlers_disconnect_by_func (window->transient_parent,
2221 gtk_widget_destroyed,
2222 &window->transient_parent);
2224 if (window->destroy_with_parent)
2225 disconnect_parent_destroyed (window);
2227 window->transient_parent = NULL;
2229 if (priv->transient_parent_group)
2231 priv->transient_parent_group = FALSE;
2232 gtk_window_group_remove_window (window->group,
2239 * gtk_window_set_transient_for:
2240 * @window: a #GtkWindow
2241 * @parent: parent window
2243 * Dialog windows should be set transient for the main application
2244 * window they were spawned from. This allows <link
2245 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2246 * dialog on top of the main window, or center the dialog over the
2247 * main window. gtk_dialog_new_with_buttons() and other convenience
2248 * functions in GTK+ will sometimes call
2249 * gtk_window_set_transient_for() on your behalf.
2251 * On Windows, this function puts the child window on top of the parent,
2252 * much as the window manager would have done on X.
2256 gtk_window_set_transient_for (GtkWindow *window,
2259 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
2261 g_return_if_fail (GTK_IS_WINDOW (window));
2262 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2263 g_return_if_fail (window != parent);
2265 if (window->transient_parent)
2267 if (GTK_WIDGET_REALIZED (window) &&
2268 GTK_WIDGET_REALIZED (window->transient_parent) &&
2269 (!parent || !GTK_WIDGET_REALIZED (parent)))
2270 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
2271 GTK_WIDGET (window));
2273 gtk_window_unset_transient_for (window);
2276 window->transient_parent = parent;
2280 g_signal_connect (parent, "destroy",
2281 G_CALLBACK (gtk_widget_destroyed),
2282 &window->transient_parent);
2283 g_signal_connect (parent, "realize",
2284 G_CALLBACK (gtk_window_transient_parent_realized),
2286 g_signal_connect (parent, "unrealize",
2287 G_CALLBACK (gtk_window_transient_parent_unrealized),
2289 g_signal_connect (parent, "notify::screen",
2290 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2293 gtk_window_set_screen (window, parent->screen);
2295 if (window->destroy_with_parent)
2296 connect_parent_destroyed (window);
2298 if (GTK_WIDGET_REALIZED (window) &&
2299 GTK_WIDGET_REALIZED (parent))
2300 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2301 GTK_WIDGET (window));
2305 gtk_window_group_add_window (parent->group, window);
2306 priv->transient_parent_group = TRUE;
2312 * gtk_window_get_transient_for:
2313 * @window: a #GtkWindow
2315 * Fetches the transient parent for this window. See
2316 * gtk_window_set_transient_for().
2318 * Return value: the transient parent for this window, or %NULL
2319 * if no transient parent has been set.
2322 gtk_window_get_transient_for (GtkWindow *window)
2324 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2326 return window->transient_parent;
2330 * gtk_window_set_opacity:
2331 * @window: a #GtkWindow
2332 * @opacity: desired opacity, between 0 and 1
2334 * Request the windowing system to make @window partially transparent,
2335 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2336 * of the opacity parameter are clamped to the [0,1] range.) On X11
2337 * this has any effect only on X screens with a compositing manager
2338 * running. See gtk_widget_is_composited(). On Windows it should work
2341 * Note that setting a window's opacity after the window has been
2342 * shown causes it to flicker once on Windows.
2347 gtk_window_set_opacity (GtkWindow *window,
2350 GtkWindowPrivate *priv;
2352 g_return_if_fail (GTK_IS_WINDOW (window));
2354 priv = GTK_WINDOW_GET_PRIVATE (window);
2358 else if (opacity > 1.0)
2361 priv->opacity_set = TRUE;
2362 priv->opacity = opacity;
2364 if (GTK_WIDGET_REALIZED (window))
2365 gdk_window_set_opacity (GTK_WIDGET (window)->window, priv->opacity);
2369 * gtk_window_get_opacity:
2370 * @window: a #GtkWindow
2372 * Fetches the requested opacity for this window. See
2373 * gtk_window_set_opacity().
2375 * Return value: the requested opacity for this window.
2380 gtk_window_get_opacity (GtkWindow *window)
2382 GtkWindowPrivate *priv;
2384 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2386 priv = GTK_WINDOW_GET_PRIVATE (window);
2388 return priv->opacity;
2392 * gtk_window_set_type_hint:
2393 * @window: a #GtkWindow
2394 * @hint: the window type
2396 * By setting the type hint for the window, you allow the window
2397 * manager to decorate and handle the window in a way which is
2398 * suitable to the function of the window in your application.
2400 * This function should be called before the window becomes visible.
2402 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2403 * will sometimes call gtk_window_set_type_hint() on your behalf.
2407 gtk_window_set_type_hint (GtkWindow *window,
2408 GdkWindowTypeHint hint)
2410 GtkWindowPrivate *priv;
2412 g_return_if_fail (GTK_IS_WINDOW (window));
2413 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
2415 priv = GTK_WINDOW_GET_PRIVATE (window);
2417 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2418 window->type_hint = hint;
2420 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2422 priv->reset_type_hint = TRUE;
2423 priv->type_hint = hint;
2427 * gtk_window_get_type_hint:
2428 * @window: a #GtkWindow
2430 * Gets the type hint for this window. See gtk_window_set_type_hint().
2432 * Return value: the type hint for @window.
2435 gtk_window_get_type_hint (GtkWindow *window)
2437 GtkWindowPrivate *priv;
2439 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2441 priv = GTK_WINDOW_GET_PRIVATE (window);
2443 return priv->type_hint;
2447 * gtk_window_set_skip_taskbar_hint:
2448 * @window: a #GtkWindow
2449 * @setting: %TRUE to keep this window from appearing in the task bar
2451 * Windows may set a hint asking the desktop environment not to display
2452 * the window in the task bar. This function sets this hint.
2457 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2460 GtkWindowPrivate *priv;
2462 g_return_if_fail (GTK_IS_WINDOW (window));
2464 priv = GTK_WINDOW_GET_PRIVATE (window);
2466 setting = setting != FALSE;
2468 if (priv->skips_taskbar != setting)
2470 priv->skips_taskbar = setting;
2471 if (GTK_WIDGET_REALIZED (window))
2472 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
2473 priv->skips_taskbar);
2474 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2479 * gtk_window_get_skip_taskbar_hint:
2480 * @window: a #GtkWindow
2482 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2484 * Return value: %TRUE if window shouldn't be in taskbar
2489 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2491 GtkWindowPrivate *priv;
2493 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2495 priv = GTK_WINDOW_GET_PRIVATE (window);
2497 return priv->skips_taskbar;
2501 * gtk_window_set_skip_pager_hint:
2502 * @window: a #GtkWindow
2503 * @setting: %TRUE to keep this window from appearing in the pager
2505 * Windows may set a hint asking the desktop environment not to display
2506 * the window in the pager. This function sets this hint.
2507 * (A "pager" is any desktop navigation tool such as a workspace
2508 * switcher that displays a thumbnail representation of the windows
2514 gtk_window_set_skip_pager_hint (GtkWindow *window,
2517 GtkWindowPrivate *priv;
2519 g_return_if_fail (GTK_IS_WINDOW (window));
2521 priv = GTK_WINDOW_GET_PRIVATE (window);
2523 setting = setting != FALSE;
2525 if (priv->skips_pager != setting)
2527 priv->skips_pager = setting;
2528 if (GTK_WIDGET_REALIZED (window))
2529 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2531 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2536 * gtk_window_get_skip_pager_hint:
2537 * @window: a #GtkWindow
2539 * Gets the value set by gtk_window_set_skip_pager_hint().
2541 * Return value: %TRUE if window shouldn't be in pager
2546 gtk_window_get_skip_pager_hint (GtkWindow *window)
2548 GtkWindowPrivate *priv;
2550 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2552 priv = GTK_WINDOW_GET_PRIVATE (window);
2554 return priv->skips_pager;
2558 * gtk_window_set_urgency_hint:
2559 * @window: a #GtkWindow
2560 * @setting: %TRUE to mark this window as urgent
2562 * Windows may set a hint asking the desktop environment to draw
2563 * the users attention to the window. This function sets this hint.
2568 gtk_window_set_urgency_hint (GtkWindow *window,
2571 GtkWindowPrivate *priv;
2573 g_return_if_fail (GTK_IS_WINDOW (window));
2575 priv = GTK_WINDOW_GET_PRIVATE (window);
2577 setting = setting != FALSE;
2579 if (priv->urgent != setting)
2581 priv->urgent = setting;
2582 if (GTK_WIDGET_REALIZED (window))
2583 gdk_window_set_urgency_hint (GTK_WIDGET (window)->window,
2585 g_object_notify (G_OBJECT (window), "urgency-hint");
2590 * gtk_window_get_urgency_hint:
2591 * @window: a #GtkWindow
2593 * Gets the value set by gtk_window_set_urgency_hint()
2595 * Return value: %TRUE if window is urgent
2600 gtk_window_get_urgency_hint (GtkWindow *window)
2602 GtkWindowPrivate *priv;
2604 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2606 priv = GTK_WINDOW_GET_PRIVATE (window);
2608 return priv->urgent;
2612 * gtk_window_set_accept_focus:
2613 * @window: a #GtkWindow
2614 * @setting: %TRUE to let this window receive input focus
2616 * Windows may set a hint asking the desktop environment not to receive
2617 * the input focus. This function sets this hint.
2622 gtk_window_set_accept_focus (GtkWindow *window,
2625 GtkWindowPrivate *priv;
2627 g_return_if_fail (GTK_IS_WINDOW (window));
2629 priv = GTK_WINDOW_GET_PRIVATE (window);
2631 setting = setting != FALSE;
2633 if (priv->accept_focus != setting)
2635 priv->accept_focus = setting;
2636 if (GTK_WIDGET_REALIZED (window))
2637 gdk_window_set_accept_focus (GTK_WIDGET (window)->window,
2638 priv->accept_focus);
2639 g_object_notify (G_OBJECT (window), "accept-focus");
2644 * gtk_window_get_accept_focus:
2645 * @window: a #GtkWindow
2647 * Gets the value set by gtk_window_set_accept_focus().
2649 * Return value: %TRUE if window should receive the input focus
2654 gtk_window_get_accept_focus (GtkWindow *window)
2656 GtkWindowPrivate *priv;
2658 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2660 priv = GTK_WINDOW_GET_PRIVATE (window);
2662 return priv->accept_focus;
2666 * gtk_window_set_focus_on_map:
2667 * @window: a #GtkWindow
2668 * @setting: %TRUE to let this window receive input focus on map
2670 * Windows may set a hint asking the desktop environment not to receive
2671 * the input focus when the window is mapped. This function sets this
2677 gtk_window_set_focus_on_map (GtkWindow *window,
2680 GtkWindowPrivate *priv;
2682 g_return_if_fail (GTK_IS_WINDOW (window));
2684 priv = GTK_WINDOW_GET_PRIVATE (window);
2686 setting = setting != FALSE;
2688 if (priv->focus_on_map != setting)
2690 priv->focus_on_map = setting;
2691 if (GTK_WIDGET_REALIZED (window))
2692 gdk_window_set_focus_on_map (GTK_WIDGET (window)->window,
2693 priv->focus_on_map);
2694 g_object_notify (G_OBJECT (window), "focus-on-map");
2699 * gtk_window_get_focus_on_map:
2700 * @window: a #GtkWindow
2702 * Gets the value set by gtk_window_set_focus_on_map().
2704 * Return value: %TRUE if window should receive the input focus when
2710 gtk_window_get_focus_on_map (GtkWindow *window)
2712 GtkWindowPrivate *priv;
2714 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2716 priv = GTK_WINDOW_GET_PRIVATE (window);
2718 return priv->focus_on_map;
2722 * gtk_window_set_destroy_with_parent:
2723 * @window: a #GtkWindow
2724 * @setting: whether to destroy @window with its transient parent
2726 * If @setting is %TRUE, then destroying the transient parent of @window
2727 * will also destroy @window itself. This is useful for dialogs that
2728 * shouldn't persist beyond the lifetime of the main window they're
2729 * associated with, for example.
2732 gtk_window_set_destroy_with_parent (GtkWindow *window,
2735 g_return_if_fail (GTK_IS_WINDOW (window));
2737 if (window->destroy_with_parent == (setting != FALSE))
2740 if (window->destroy_with_parent)
2742 disconnect_parent_destroyed (window);
2746 connect_parent_destroyed (window);
2749 window->destroy_with_parent = setting;
2751 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2755 * gtk_window_get_destroy_with_parent:
2756 * @window: a #GtkWindow
2758 * Returns whether the window will be destroyed with its transient parent. See
2759 * gtk_window_set_destroy_with_parent ().
2761 * Return value: %TRUE if the window will be destroyed with its transient parent.
2764 gtk_window_get_destroy_with_parent (GtkWindow *window)
2766 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2768 return window->destroy_with_parent;
2771 static GtkWindowGeometryInfo*
2772 gtk_window_get_geometry_info (GtkWindow *window,
2775 GtkWindowGeometryInfo *info;
2777 info = window->geometry_info;
2778 if (!info && create)
2780 info = g_new0 (GtkWindowGeometryInfo, 1);
2782 info->default_width = -1;
2783 info->default_height = -1;
2784 info->resize_width = -1;
2785 info->resize_height = -1;
2786 info->initial_x = 0;
2787 info->initial_y = 0;
2788 info->initial_pos_set = FALSE;
2789 info->default_is_geometry = FALSE;
2790 info->position_constraints_changed = FALSE;
2791 info->last.configure_request.x = 0;
2792 info->last.configure_request.y = 0;
2793 info->last.configure_request.width = -1;
2794 info->last.configure_request.height = -1;
2795 info->widget = NULL;
2797 window->geometry_info = info;
2804 * gtk_window_set_geometry_hints:
2805 * @window: a #GtkWindow
2806 * @geometry_widget: widget the geometry hints will be applied to
2807 * @geometry: struct containing geometry information
2808 * @geom_mask: mask indicating which struct fields should be paid attention to
2810 * This function sets up hints about how a window can be resized by
2811 * the user. You can set a minimum and maximum size; allowed resize
2812 * increments (e.g. for xterm, you can only resize by the size of a
2813 * character); aspect ratios; and more. See the #GdkGeometry struct.
2817 gtk_window_set_geometry_hints (GtkWindow *window,
2818 GtkWidget *geometry_widget,
2819 GdkGeometry *geometry,
2820 GdkWindowHints geom_mask)
2822 GtkWindowGeometryInfo *info;
2824 g_return_if_fail (GTK_IS_WINDOW (window));
2825 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2827 info = gtk_window_get_geometry_info (window, TRUE);
2830 g_signal_handlers_disconnect_by_func (info->widget,
2831 gtk_widget_destroyed,
2834 info->widget = geometry_widget;
2836 g_signal_connect (geometry_widget, "destroy",
2837 G_CALLBACK (gtk_widget_destroyed),
2841 info->geometry = *geometry;
2843 /* We store gravity in window->gravity not in the hints. */
2844 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2846 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2848 gtk_window_set_gravity (window, geometry->win_gravity);
2851 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2855 * gtk_window_set_decorated:
2856 * @window: a #GtkWindow
2857 * @setting: %TRUE to decorate the window
2859 * By default, windows are decorated with a title bar, resize
2860 * controls, etc. Some <link linkend="gtk-X11-arch">window
2861 * managers</link> allow GTK+ to disable these decorations, creating a
2862 * borderless window. If you set the decorated property to %FALSE
2863 * using this function, GTK+ will do its best to convince the window
2864 * manager not to decorate the window. Depending on the system, this
2865 * function may not have any effect when called on a window that is
2866 * already visible, so you should call it before calling gtk_window_show().
2868 * On Windows, this function always works, since there's no window manager
2873 gtk_window_set_decorated (GtkWindow *window,
2876 g_return_if_fail (GTK_IS_WINDOW (window));
2878 setting = setting != FALSE;
2880 if (setting == window->decorated)
2883 window->decorated = setting;
2885 if (GTK_WIDGET (window)->window)
2887 if (window->decorated)
2888 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2891 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2895 g_object_notify (G_OBJECT (window), "decorated");
2899 * gtk_window_get_decorated:
2900 * @window: a #GtkWindow
2902 * Returns whether the window has been set to have decorations
2903 * such as a title bar via gtk_window_set_decorated().
2905 * Return value: %TRUE if the window has been set to have decorations
2908 gtk_window_get_decorated (GtkWindow *window)
2910 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2912 return window->decorated;
2916 * gtk_window_set_deletable:
2917 * @window: a #GtkWindow
2918 * @setting: %TRUE to decorate the window as deletable
2920 * By default, windows have a close button in the window frame. Some
2921 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
2922 * disable this button. If you set the deletable property to %FALSE
2923 * using this function, GTK+ will do its best to convince the window
2924 * manager not to show a close button. Depending on the system, this
2925 * function may not have any effect when called on a window that is
2926 * already visible, so you should call it before calling gtk_window_show().
2928 * On Windows, this function always works, since there's no window manager
2934 gtk_window_set_deletable (GtkWindow *window,
2937 GtkWindowPrivate *priv;
2939 g_return_if_fail (GTK_IS_WINDOW (window));
2941 priv = GTK_WINDOW_GET_PRIVATE (window);
2943 setting = setting != FALSE;
2945 if (setting == priv->deletable)
2948 priv->deletable = setting;
2950 if (GTK_WIDGET (window)->window)
2952 if (priv->deletable)
2953 gdk_window_set_functions (GTK_WIDGET (window)->window,
2956 gdk_window_set_functions (GTK_WIDGET (window)->window,
2957 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
2960 g_object_notify (G_OBJECT (window), "deletable");
2964 * gtk_window_get_deletable:
2965 * @window: a #GtkWindow
2967 * Returns whether the window has been set to have a close button
2968 * via gtk_window_set_deletable().
2970 * Return value: %TRUE if the window has been set to have a close button
2975 gtk_window_get_deletable (GtkWindow *window)
2977 GtkWindowPrivate *priv;
2979 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2981 priv = GTK_WINDOW_GET_PRIVATE (window);
2983 return priv->deletable;
2986 static GtkWindowIconInfo*
2987 get_icon_info (GtkWindow *window)
2989 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
2993 free_icon_info (GtkWindowIconInfo *info)
2995 g_free (info->icon_name);
2996 g_slice_free (GtkWindowIconInfo, info);
3000 static GtkWindowIconInfo*
3001 ensure_icon_info (GtkWindow *window)
3003 GtkWindowIconInfo *info;
3005 info = get_icon_info (window);
3009 info = g_slice_new0 (GtkWindowIconInfo);
3010 g_object_set_qdata_full (G_OBJECT (window),
3011 quark_gtk_window_icon_info,
3013 (GDestroyNotify)free_icon_info);
3025 static ScreenIconInfo *
3026 get_screen_icon_info (GdkScreen *screen)
3028 ScreenIconInfo *info = g_object_get_qdata (G_OBJECT (screen),
3029 quark_gtk_window_default_icon_pixmap);
3032 info = g_slice_new0 (ScreenIconInfo);
3033 g_object_set_qdata (G_OBJECT (screen),
3034 quark_gtk_window_default_icon_pixmap, info);
3037 if (info->serial != default_icon_serial)
3041 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
3042 info->pixmap = NULL;
3047 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
3051 info->serial = default_icon_serial;
3058 get_pixmap_and_mask (GdkWindow *window,
3059 GtkWindowIconInfo *parent_info,
3060 gboolean is_default_list,
3062 GdkPixmap **pmap_return,
3063 GdkBitmap **mask_return)
3065 GdkScreen *screen = gdk_drawable_get_screen (window);
3066 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
3067 GdkPixbuf *best_icon;
3071 *pmap_return = NULL;
3072 *mask_return = NULL;
3074 if (is_default_list &&
3075 default_icon_info->pixmap != NULL)
3077 /* Use shared icon pixmap for all windows on this screen.
3079 if (default_icon_info->pixmap)
3080 g_object_ref (default_icon_info->pixmap);
3081 if (default_icon_info->mask)
3082 g_object_ref (default_icon_info->mask);
3084 *pmap_return = default_icon_info->pixmap;
3085 *mask_return = default_icon_info->mask;
3087 else if (parent_info && parent_info->icon_pixmap)
3089 if (parent_info->icon_pixmap)
3090 g_object_ref (parent_info->icon_pixmap);
3091 if (parent_info->icon_mask)
3092 g_object_ref (parent_info->icon_mask);
3094 *pmap_return = parent_info->icon_pixmap;
3095 *mask_return = parent_info->icon_mask;
3099 #define IDEAL_SIZE 48
3101 best_size = G_MAXINT;
3103 tmp_list = icon_list;
3104 while (tmp_list != NULL)
3106 GdkPixbuf *pixbuf = tmp_list->data;
3109 /* average width and height - if someone passes in a rectangular
3110 * icon they deserve what they get.
3112 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
3115 if (best_icon == NULL)
3122 /* icon is better if it's 32 pixels or larger, and closer to
3123 * the ideal size than the current best.
3126 (ABS (best_size - IDEAL_SIZE) <
3127 ABS (this - IDEAL_SIZE)))
3134 tmp_list = tmp_list->next;
3138 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
3139 gdk_screen_get_system_colormap (screen),
3144 /* Save pmap/mask for others to use if appropriate */
3147 parent_info->icon_pixmap = *pmap_return;
3148 parent_info->icon_mask = *mask_return;
3150 if (parent_info->icon_pixmap)
3151 g_object_ref (parent_info->icon_pixmap);
3152 if (parent_info->icon_mask)
3153 g_object_ref (parent_info->icon_mask);
3155 else if (is_default_list)
3157 default_icon_info->pixmap = *pmap_return;
3158 default_icon_info->mask = *mask_return;
3160 if (default_icon_info->pixmap)
3161 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
3162 (gpointer*)&default_icon_info->pixmap);
3163 if (default_icon_info->mask)
3164 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
3165 (gpointer*)&default_icon_info->mask);
3171 icon_list_from_theme (GtkWidget *widget,
3176 GtkIconTheme *icon_theme;
3181 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3183 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3186 for (i = 0; sizes[i]; i++)
3189 * We need an EWMH extension to handle scalable icons
3190 * by passing their name to the WM. For now just use a
3194 icon = gtk_icon_theme_load_icon (icon_theme, name,
3197 icon = gtk_icon_theme_load_icon (icon_theme, name,
3200 list = g_list_append (list, icon);
3210 gtk_window_realize_icon (GtkWindow *window)
3213 GtkWindowIconInfo *info;
3216 widget = GTK_WIDGET (window);
3218 g_return_if_fail (widget->window != NULL);
3220 /* no point setting an icon on override-redirect */
3221 if (window->type == GTK_WINDOW_POPUP)
3226 info = ensure_icon_info (window);
3231 g_return_if_fail (info->icon_pixmap == NULL);
3232 g_return_if_fail (info->icon_mask == NULL);
3234 info->using_default_icon = FALSE;
3235 info->using_parent_icon = FALSE;
3236 info->using_themed_icon = FALSE;
3238 icon_list = info->icon_list;
3240 /* Look up themed icon */
3241 if (icon_list == NULL && info->icon_name)
3243 icon_list = icon_list_from_theme (widget, info->icon_name);
3245 info->using_themed_icon = TRUE;
3248 /* Inherit from transient parent */
3249 if (icon_list == NULL && window->transient_parent)
3251 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
3253 info->using_parent_icon = TRUE;
3256 /* Inherit from default */
3257 if (icon_list == NULL)
3259 icon_list = default_icon_list;
3261 info->using_default_icon = TRUE;
3264 /* Look up themed icon */
3265 if (icon_list == NULL && default_icon_name)
3267 icon_list = icon_list_from_theme (widget, default_icon_name);
3268 info->using_default_icon = TRUE;
3269 info->using_themed_icon = TRUE;
3272 gdk_window_set_icon_list (widget->window, icon_list);
3274 get_pixmap_and_mask (widget->window,
3275 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
3276 info->using_default_icon,
3281 /* This is a slight ICCCM violation since it's a color pixmap not
3282 * a bitmap, but everyone does it.
3284 gdk_window_set_icon (widget->window,
3289 info->realized = TRUE;
3291 if (info->using_themed_icon)
3293 GtkIconTheme *icon_theme;
3295 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3296 g_list_free (icon_list);
3298 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3299 g_signal_connect (icon_theme, "changed",
3300 G_CALLBACK (update_themed_icon), window);
3305 gtk_window_unrealize_icon (GtkWindow *window)
3307 GtkWindowIconInfo *info;
3309 info = get_icon_info (window);
3314 if (info->icon_pixmap)
3315 g_object_unref (info->icon_pixmap);
3317 if (info->icon_mask)
3318 g_object_unref (info->icon_mask);
3320 info->icon_pixmap = NULL;
3321 info->icon_mask = NULL;
3323 if (info->using_themed_icon)
3325 GtkIconTheme *icon_theme;
3327 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3329 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3332 /* We don't clear the properties on the window, just figure the
3333 * window is going away.
3336 info->realized = FALSE;
3341 * gtk_window_set_icon_list:
3342 * @window: a #GtkWindow
3343 * @list: list of #GdkPixbuf
3345 * Sets up the icon representing a #GtkWindow. The icon is used when
3346 * the window is minimized (also known as iconified). Some window
3347 * managers or desktop environments may also place it in the window
3348 * frame, or display it in other contexts.
3350 * gtk_window_set_icon_list() allows you to pass in the same icon in
3351 * several hand-drawn sizes. The list should contain the natural sizes
3352 * your icon is available in; that is, don't scale the image before
3353 * passing it to GTK+. Scaling is postponed until the last minute,
3354 * when the desired final size is known, to allow best quality.
3356 * By passing several sizes, you may improve the final image quality
3357 * of the icon, by reducing or eliminating automatic image scaling.
3359 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3360 * larger images (64x64, 128x128) if you have them.
3362 * See also gtk_window_set_default_icon_list() to set the icon
3363 * for all windows in your application in one go.
3365 * Note that transient windows (those who have been set transient for another
3366 * window using gtk_window_set_transient_for()) will inherit their
3367 * icon from their transient parent. So there's no need to explicitly
3368 * set the icon on transient windows.
3371 gtk_window_set_icon_list (GtkWindow *window,
3374 GtkWindowIconInfo *info;
3376 g_return_if_fail (GTK_IS_WINDOW (window));
3378 info = ensure_icon_info (window);
3380 if (info->icon_list == list) /* check for NULL mostly */
3383 g_list_foreach (list,
3384 (GFunc) g_object_ref, NULL);
3386 g_list_foreach (info->icon_list,
3387 (GFunc) g_object_unref, NULL);
3389 g_list_free (info->icon_list);
3391 info->icon_list = g_list_copy (list);
3393 g_object_notify (G_OBJECT (window), "icon");
3395 gtk_window_unrealize_icon (window);
3397 if (GTK_WIDGET_REALIZED (window))
3398 gtk_window_realize_icon (window);
3400 /* We could try to update our transient children, but I don't think
3401 * it's really worth it. If we did it, the best way would probably
3402 * be to have children connect to notify::icon-list
3407 * gtk_window_get_icon_list:
3408 * @window: a #GtkWindow
3410 * Retrieves the list of icons set by gtk_window_set_icon_list().
3411 * The list is copied, but the reference count on each
3412 * member won't be incremented.
3414 * Return value: copy of window's icon list
3417 gtk_window_get_icon_list (GtkWindow *window)
3419 GtkWindowIconInfo *info;
3421 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3423 info = get_icon_info (window);
3426 return g_list_copy (info->icon_list);
3432 * gtk_window_set_icon:
3433 * @window: a #GtkWindow
3434 * @icon: icon image, or %NULL
3436 * Sets up the icon representing a #GtkWindow. This icon is used when
3437 * the window is minimized (also known as iconified). Some window
3438 * managers or desktop environments may also place it in the window
3439 * frame, or display it in other contexts.
3441 * The icon should be provided in whatever size it was naturally
3442 * drawn; that is, don't scale the image before passing it to
3443 * GTK+. Scaling is postponed until the last minute, when the desired
3444 * final size is known, to allow best quality.
3446 * If you have your icon hand-drawn in multiple sizes, use
3447 * gtk_window_set_icon_list(). Then the best size will be used.
3449 * This function is equivalent to calling gtk_window_set_icon_list()
3450 * with a 1-element list.
3452 * See also gtk_window_set_default_icon_list() to set the icon
3453 * for all windows in your application in one go.
3456 gtk_window_set_icon (GtkWindow *window,
3461 g_return_if_fail (GTK_IS_WINDOW (window));
3462 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3467 list = g_list_append (list, icon);
3469 gtk_window_set_icon_list (window, list);
3475 update_themed_icon (GtkIconTheme *icon_theme,
3478 g_object_notify (G_OBJECT (window), "icon");
3480 gtk_window_unrealize_icon (window);
3482 if (GTK_WIDGET_REALIZED (window))
3483 gtk_window_realize_icon (window);
3487 * gtk_window_set_icon_name:
3488 * @window: a #GtkWindow
3489 * @name: the name of the themed icon
3491 * Sets the icon for the window from a named themed icon. See
3492 * the docs for #GtkIconTheme for more details.
3494 * Note that this has nothing to do with the WM_ICON_NAME
3495 * property which is mentioned in the ICCCM.
3500 gtk_window_set_icon_name (GtkWindow *window,
3503 GtkWindowIconInfo *info;
3506 g_return_if_fail (GTK_IS_WINDOW (window));
3508 info = ensure_icon_info (window);
3510 if (g_strcmp0 (info->icon_name, name) == 0)
3513 tmp = info->icon_name;
3514 info->icon_name = g_strdup (name);
3517 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3518 g_list_free (info->icon_list);
3519 info->icon_list = NULL;
3521 update_themed_icon (NULL, window);
3523 g_object_notify (G_OBJECT (window), "icon-name");
3527 * gtk_window_get_icon_name:
3528 * @window: a #GtkWindow
3530 * Returns the name of the themed icon for the window,
3531 * see gtk_window_set_icon_name().
3533 * Returns: the icon name or %NULL if the window has
3538 G_CONST_RETURN gchar *
3539 gtk_window_get_icon_name (GtkWindow *window)
3541 GtkWindowIconInfo *info;
3543 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3545 info = ensure_icon_info (window);
3547 return info->icon_name;
3551 * gtk_window_get_icon:
3552 * @window: a #GtkWindow
3554 * Gets the value set by gtk_window_set_icon() (or if you've
3555 * called gtk_window_set_icon_list(), gets the first icon in
3558 * Return value: icon for window
3561 gtk_window_get_icon (GtkWindow *window)
3563 GtkWindowIconInfo *info;
3565 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3567 info = get_icon_info (window);
3568 if (info && info->icon_list)
3569 return GDK_PIXBUF (info->icon_list->data);
3574 /* Load pixbuf, printing warning on failure if error == NULL
3577 load_pixbuf_verbosely (const char *filename,
3580 GError *local_err = NULL;
3583 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3591 g_warning ("Error loading icon from file '%s':\n\t%s",
3592 filename, local_err->message);
3593 g_error_free (local_err);
3601 * gtk_window_set_icon_from_file:
3602 * @window: a #GtkWindow
3603 * @filename: location of icon file
3604 * @err: location to store error, or %NULL.
3606 * Sets the icon for @window.
3607 * Warns on failure if @err is %NULL.
3609 * This function is equivalent to calling gtk_window_set_icon()
3610 * with a pixbuf created by loading the image from @filename.
3612 * Returns: %TRUE if setting the icon succeeded.
3617 gtk_window_set_icon_from_file (GtkWindow *window,
3618 const gchar *filename,
3621 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3625 gtk_window_set_icon (window, pixbuf);
3626 g_object_unref (pixbuf);
3635 * gtk_window_set_default_icon_list:
3636 * @list: a list of #GdkPixbuf
3638 * Sets an icon list to be used as fallback for windows that haven't
3639 * had gtk_window_set_icon_list() called on them to set up a
3640 * window-specific icon list. This function allows you to set up the
3641 * icon for all windows in your app at once.
3643 * See gtk_window_set_icon_list() for more details.
3647 gtk_window_set_default_icon_list (GList *list)
3651 if (list == default_icon_list)
3654 /* Update serial so we don't used cached pixmaps/masks
3656 default_icon_serial++;
3658 g_list_foreach (list,
3659 (GFunc) g_object_ref, NULL);
3661 g_list_foreach (default_icon_list,
3662 (GFunc) g_object_unref, NULL);
3664 g_list_free (default_icon_list);
3666 default_icon_list = g_list_copy (list);
3668 /* Update all toplevels */
3669 toplevels = gtk_window_list_toplevels ();
3670 tmp_list = toplevels;
3671 while (tmp_list != NULL)
3673 GtkWindowIconInfo *info;
3674 GtkWindow *w = tmp_list->data;
3676 info = get_icon_info (w);
3677 if (info && info->using_default_icon)
3679 gtk_window_unrealize_icon (w);
3680 if (GTK_WIDGET_REALIZED (w))
3681 gtk_window_realize_icon (w);
3684 tmp_list = tmp_list->next;
3686 g_list_free (toplevels);
3690 * gtk_window_set_default_icon:
3693 * Sets an icon to be used as fallback for windows that haven't
3694 * had gtk_window_set_icon() called on them from a pixbuf.
3699 gtk_window_set_default_icon (GdkPixbuf *icon)
3703 g_return_if_fail (GDK_IS_PIXBUF (icon));
3705 list = g_list_prepend (NULL, icon);
3706 gtk_window_set_default_icon_list (list);
3711 * gtk_window_set_default_icon_name:
3712 * @name: the name of the themed icon
3714 * Sets an icon to be used as fallback for windows that haven't
3715 * had gtk_window_set_icon_list() called on them from a named
3716 * themed icon, see gtk_window_set_icon_name().
3721 gtk_window_set_default_icon_name (const gchar *name)
3726 /* Update serial so we don't used cached pixmaps/masks
3728 default_icon_serial++;
3730 g_free (default_icon_name);
3731 default_icon_name = g_strdup (name);
3733 g_list_foreach (default_icon_list,
3734 (GFunc) g_object_unref, NULL);
3736 g_list_free (default_icon_list);
3737 default_icon_list = NULL;
3739 /* Update all toplevels */
3740 toplevels = gtk_window_list_toplevels ();
3741 tmp_list = toplevels;
3742 while (tmp_list != NULL)
3744 GtkWindowIconInfo *info;
3745 GtkWindow *w = tmp_list->data;
3747 info = get_icon_info (w);
3748 if (info && info->using_default_icon && info->using_themed_icon)
3750 gtk_window_unrealize_icon (w);
3751 if (GTK_WIDGET_REALIZED (w))
3752 gtk_window_realize_icon (w);
3755 tmp_list = tmp_list->next;
3757 g_list_free (toplevels);
3761 * gtk_window_get_default_icon_name:
3763 * Returns the fallback icon name for windows that has been set
3764 * with gtk_window_set_default_icon_name(). The returned
3765 * string is owned by GTK+ and should not be modified. It
3766 * is only valid until the next call to
3767 * gtk_window_set_default_icon_name().
3769 * Returns: the fallback icon name for windows
3774 gtk_window_get_default_icon_name (void)
3776 return default_icon_name;
3780 * gtk_window_set_default_icon_from_file:
3781 * @filename: location of icon file
3782 * @err: location to store error, or %NULL.
3784 * Sets an icon to be used as fallback for windows that haven't
3785 * had gtk_window_set_icon_list() called on them from a file
3786 * on disk. Warns on failure if @err is %NULL.
3788 * Returns: %TRUE if setting the icon succeeded.
3793 gtk_window_set_default_icon_from_file (const gchar *filename,
3796 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3800 gtk_window_set_default_icon (pixbuf);
3801 g_object_unref (pixbuf);
3810 * gtk_window_get_default_icon_list:
3812 * Gets the value set by gtk_window_set_default_icon_list().
3813 * The list is a copy and should be freed with g_list_free(),
3814 * but the pixbufs in the list have not had their reference count
3817 * Return value: copy of default icon list
3820 gtk_window_get_default_icon_list (void)
3822 return g_list_copy (default_icon_list);
3826 gtk_window_set_default_size_internal (GtkWindow *window,
3827 gboolean change_width,
3829 gboolean change_height,
3831 gboolean is_geometry)
3833 GtkWindowGeometryInfo *info;
3835 g_return_if_fail (change_width == FALSE || width >= -1);
3836 g_return_if_fail (change_height == FALSE || height >= -1);
3838 info = gtk_window_get_geometry_info (window, TRUE);
3840 g_object_freeze_notify (G_OBJECT (window));
3842 info->default_is_geometry = is_geometry != FALSE;
3852 info->default_width = width;
3854 g_object_notify (G_OBJECT (window), "default-width");
3865 info->default_height = height;
3867 g_object_notify (G_OBJECT (window), "default-height");
3870 g_object_thaw_notify (G_OBJECT (window));
3872 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3876 * gtk_window_set_default_size:
3877 * @window: a #GtkWindow
3878 * @width: width in pixels, or -1 to unset the default width
3879 * @height: height in pixels, or -1 to unset the default height
3881 * Sets the default size of a window. If the window's "natural" size
3882 * (its size request) is larger than the default, the default will be
3883 * ignored. More generally, if the default size does not obey the
3884 * geometry hints for the window (gtk_window_set_geometry_hints() can
3885 * be used to set these explicitly), the default size will be clamped
3886 * to the nearest permitted size.
3888 * Unlike gtk_widget_set_size_request(), which sets a size request for
3889 * a widget and thus would keep users from shrinking the window, this
3890 * function only sets the initial size, just as if the user had
3891 * resized the window themselves. Users can still shrink the window
3892 * again as they normally would. Setting a default size of -1 means to
3893 * use the "natural" default size (the size request of the window).
3895 * For more control over a window's initial size and how resizing works,
3896 * investigate gtk_window_set_geometry_hints().
3898 * For some uses, gtk_window_resize() is a more appropriate function.
3899 * gtk_window_resize() changes the current size of the window, rather
3900 * than the size to be used on initial display. gtk_window_resize() always
3901 * affects the window itself, not the geometry widget.
3903 * The default size of a window only affects the first time a window is
3904 * shown; if a window is hidden and re-shown, it will remember the size
3905 * it had prior to hiding, rather than using the default size.
3907 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3908 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3911 gtk_window_set_default_size (GtkWindow *window,
3915 g_return_if_fail (GTK_IS_WINDOW (window));
3916 g_return_if_fail (width >= -1);
3917 g_return_if_fail (height >= -1);
3919 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3923 * gtk_window_get_default_size:
3924 * @window: a #GtkWindow
3925 * @width: location to store the default width, or %NULL
3926 * @height: location to store the default height, or %NULL
3928 * Gets the default size of the window. A value of -1 for the width or
3929 * height indicates that a default size has not been explicitly set
3930 * for that dimension, so the "natural" size of the window will be
3935 gtk_window_get_default_size (GtkWindow *window,
3939 GtkWindowGeometryInfo *info;
3941 g_return_if_fail (GTK_IS_WINDOW (window));
3943 info = gtk_window_get_geometry_info (window, FALSE);
3946 *width = info ? info->default_width : -1;
3949 *height = info ? info->default_height : -1;
3953 * gtk_window_resize:
3954 * @window: a #GtkWindow
3955 * @width: width in pixels to resize the window to
3956 * @height: height in pixels to resize the window to
3958 * Resizes the window as if the user had done so, obeying geometry
3959 * constraints. The default geometry constraint is that windows may
3960 * not be smaller than their size request; to override this
3961 * constraint, call gtk_widget_set_size_request() to set the window's
3962 * request to a smaller value.
3964 * If gtk_window_resize() is called before showing a window for the
3965 * first time, it overrides any default size set with
3966 * gtk_window_set_default_size().
3968 * Windows may not be resized smaller than 1 by 1 pixels.
3972 gtk_window_resize (GtkWindow *window,
3976 GtkWindowGeometryInfo *info;
3978 g_return_if_fail (GTK_IS_WINDOW (window));
3979 g_return_if_fail (width > 0);
3980 g_return_if_fail (height > 0);
3982 info = gtk_window_get_geometry_info (window, TRUE);
3984 info->resize_width = width;
3985 info->resize_height = height;
3987 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3991 * gtk_window_get_size:
3992 * @window: a #GtkWindow
3993 * @width: return location for width, or %NULL
3994 * @height: return location for height, or %NULL
3996 * Obtains the current size of @window. If @window is not onscreen,
3997 * it returns the size GTK+ will suggest to the <link
3998 * linkend="gtk-X11-arch">window manager</link> for the initial window
3999 * size (but this is not reliably the same as the size the window
4000 * manager will actually select). The size obtained by
4001 * gtk_window_get_size() is the last size received in a
4002 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4003 * rather than querying the X server for the size. As a result, if you
4004 * call gtk_window_resize() then immediately call
4005 * gtk_window_get_size(), the size won't have taken effect yet. After
4006 * the window manager processes the resize request, GTK+ receives
4007 * notification that the size has changed via a configure event, and
4008 * the size of the window gets updated.
4010 * Note 1: Nearly any use of this function creates a race condition,
4011 * because the size of the window may change between the time that you
4012 * get the size and the time that you perform some action assuming
4013 * that size is the current size. To avoid race conditions, connect to
4014 * "configure-event" on the window and adjust your size-dependent
4015 * state to match the size delivered in the #GdkEventConfigure.
4017 * Note 2: The returned size does <emphasis>not</emphasis> include the
4018 * size of the window manager decorations (aka the window frame or
4019 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4020 * method of determining their size.
4022 * Note 3: If you are getting a window size in order to position
4023 * the window onscreen, there may be a better way. The preferred
4024 * way is to simply set the window's semantic type with
4025 * gtk_window_set_type_hint(), which allows the window manager to
4026 * e.g. center dialogs. Also, if you set the transient parent of
4027 * dialogs with gtk_window_set_transient_for() window managers
4028 * will often center the dialog over its parent window. It's
4029 * much preferred to let the window manager handle these
4030 * things rather than doing it yourself, because all apps will
4031 * behave consistently and according to user prefs if the window
4032 * manager handles it. Also, the window manager can take the size
4033 * of the window decorations/border into account, while your
4034 * application cannot.
4036 * In any case, if you insist on application-specified window
4037 * positioning, there's <emphasis>still</emphasis> a better way than
4038 * doing it yourself - gtk_window_set_position() will frequently
4039 * handle the details for you.
4043 gtk_window_get_size (GtkWindow *window,
4049 g_return_if_fail (GTK_IS_WINDOW (window));
4051 if (width == NULL && height == NULL)
4054 if (GTK_WIDGET_MAPPED (window))
4056 gdk_drawable_get_size (GTK_WIDGET (window)->window,
4061 GdkRectangle configure_request;
4063 gtk_window_compute_configure_request (window,
4067 w = configure_request.width;
4068 h = configure_request.height;
4079 * @window: a #GtkWindow
4080 * @x: X coordinate to move window to
4081 * @y: Y coordinate to move window to
4083 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4084 * @window to the given position. Window managers are free to ignore
4085 * this; most window managers ignore requests for initial window
4086 * positions (instead using a user-defined placement algorithm) and
4087 * honor requests after the window has already been shown.
4089 * Note: the position is the position of the gravity-determined
4090 * reference point for the window. The gravity determines two things:
4091 * first, the location of the reference point in root window
4092 * coordinates; and second, which point on the window is positioned at
4093 * the reference point.
4095 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4096 * point is simply the @x, @y supplied to gtk_window_move(). The
4097 * top-left corner of the window decorations (aka window frame or
4098 * border) will be placed at @x, @y. Therefore, to position a window
4099 * at the top left of the screen, you want to use the default gravity
4100 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4102 * To position a window at the bottom right corner of the screen, you
4103 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4104 * point is at @x + the window width and @y + the window height, and
4105 * the bottom-right corner of the window border will be placed at that
4106 * reference point. So, to place a window in the bottom right corner
4107 * you would first set gravity to south east, then write:
4108 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4109 * gdk_screen_height () - window_height)</literal> (note that this
4110 * example does not take multi-head scenarios into account).
4112 * The Extended Window Manager Hints specification at <ulink
4113 * url="http://www.freedesktop.org/Standards/wm-spec">
4114 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4115 * nice table of gravities in the "implementation notes" section.
4117 * The gtk_window_get_position() documentation may also be relevant.
4120 gtk_window_move (GtkWindow *window,
4124 GtkWindowGeometryInfo *info;
4127 g_return_if_fail (GTK_IS_WINDOW (window));
4129 widget = GTK_WIDGET (window);
4131 info = gtk_window_get_geometry_info (window, TRUE);
4133 if (GTK_WIDGET_MAPPED (window))
4135 /* we have now sent a request with this position
4136 * with currently-active constraints, so toggle flag.
4138 info->position_constraints_changed = FALSE;
4140 /* we only constrain if mapped - if not mapped,
4141 * then gtk_window_compute_configure_request()
4142 * will apply the constraints later, and we
4143 * don't want to lose information about
4144 * what position the user set before then.
4145 * i.e. if you do a move() then turn off POS_CENTER
4146 * then show the window, your move() will work.
4148 gtk_window_constrain_position (window,
4149 widget->allocation.width,
4150 widget->allocation.height,
4153 /* Note that this request doesn't go through our standard request
4154 * framework, e.g. doesn't increment configure_request_count,
4155 * doesn't set info->last, etc.; that's because
4156 * we don't save the info needed to arrive at this same request
4159 * To gtk_window_move_resize(), this will end up looking exactly
4160 * the same as the position being changed by the window
4164 /* FIXME are we handling gravity properly for framed windows? */
4166 gdk_window_move (window->frame,
4167 x - window->frame_left,
4168 y - window->frame_top);
4170 gdk_window_move (GTK_WIDGET (window)->window,
4175 /* Save this position to apply on mapping */
4176 info->initial_x = x;
4177 info->initial_y = y;
4178 info->initial_pos_set = TRUE;
4183 * gtk_window_get_position:
4184 * @window: a #GtkWindow
4185 * @root_x: return location for X coordinate of gravity-determined reference point
4186 * @root_y: return location for Y coordinate of gravity-determined reference point
4188 * This function returns the position you need to pass to
4189 * gtk_window_move() to keep @window in its current position. This
4190 * means that the meaning of the returned value varies with window
4191 * gravity. See gtk_window_move() for more details.
4193 * If you haven't changed the window gravity, its gravity will be
4194 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4195 * gets the position of the top-left corner of the window manager
4196 * frame for the window. gtk_window_move() sets the position of this
4197 * same top-left corner.
4199 * gtk_window_get_position() is not 100% reliable because the X Window System
4200 * does not specify a way to obtain the geometry of the
4201 * decorations placed on a window by the window manager.
4202 * Thus GTK+ is using a "best guess" that works with most
4205 * Moreover, nearly all window managers are historically broken with
4206 * respect to their handling of window gravity. So moving a window to
4207 * its current position as returned by gtk_window_get_position() tends
4208 * to result in moving the window slightly. Window managers are
4209 * slowly getting better over time.
4211 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4212 * frame is not relevant, and thus gtk_window_get_position() will
4213 * always produce accurate results. However you can't use static
4214 * gravity to do things like place a window in a corner of the screen,
4215 * because static gravity ignores the window manager decorations.
4217 * If you are saving and restoring your application's window
4218 * positions, you should know that it's impossible for applications to
4219 * do this without getting it somewhat wrong because applications do
4220 * not have sufficient knowledge of window manager state. The Correct
4221 * Mechanism is to support the session management protocol (see the
4222 * "GnomeClient" object in the GNOME libraries for example) and allow
4223 * the window manager to save your window sizes and positions.
4228 gtk_window_get_position (GtkWindow *window,
4234 g_return_if_fail (GTK_IS_WINDOW (window));
4236 widget = GTK_WIDGET (window);
4238 if (window->gravity == GDK_GRAVITY_STATIC)
4240 if (GTK_WIDGET_MAPPED (widget))
4242 /* This does a server round-trip, which is sort of wrong;
4243 * but a server round-trip is inevitable for
4244 * gdk_window_get_frame_extents() in the usual
4245 * NorthWestGravity case below, so not sure what else to
4246 * do. We should likely be consistent about whether we get
4247 * the client-side info or the server-side info.
4249 gdk_window_get_origin (widget->window, root_x, root_y);
4253 GdkRectangle configure_request;
4255 gtk_window_compute_configure_request (window,
4259 *root_x = configure_request.x;
4260 *root_y = configure_request.y;
4265 GdkRectangle frame_extents;
4270 if (GTK_WIDGET_MAPPED (widget))
4273 gdk_window_get_frame_extents (window->frame, &frame_extents);
4275 gdk_window_get_frame_extents (widget->window, &frame_extents);
4276 x = frame_extents.x;
4277 y = frame_extents.y;
4278 gtk_window_get_size (window, &w, &h);
4282 /* We just say the frame has 0 size on all sides.
4283 * Not sure what else to do.
4285 gtk_window_compute_configure_request (window,
4288 x = frame_extents.x;
4289 y = frame_extents.y;
4290 w = frame_extents.width;
4291 h = frame_extents.height;
4294 switch (window->gravity)
4296 case GDK_GRAVITY_NORTH:
4297 case GDK_GRAVITY_CENTER:
4298 case GDK_GRAVITY_SOUTH:
4299 /* Find center of frame. */
4300 x += frame_extents.width / 2;
4301 /* Center client window on that point. */
4305 case GDK_GRAVITY_SOUTH_EAST:
4306 case GDK_GRAVITY_EAST:
4307 case GDK_GRAVITY_NORTH_EAST:
4308 /* Find right edge of frame */
4309 x += frame_extents.width;
4310 /* Align left edge of client at that point. */
4317 switch (window->gravity)
4319 case GDK_GRAVITY_WEST:
4320 case GDK_GRAVITY_CENTER:
4321 case GDK_GRAVITY_EAST:
4322 /* Find center of frame. */
4323 y += frame_extents.height / 2;
4324 /* Center client window there. */
4327 case GDK_GRAVITY_SOUTH_WEST:
4328 case GDK_GRAVITY_SOUTH:
4329 case GDK_GRAVITY_SOUTH_EAST:
4330 /* Find south edge of frame */
4331 y += frame_extents.height;
4332 /* Place bottom edge of client there */
4347 * gtk_window_reshow_with_initial_size:
4348 * @window: a #GtkWindow
4350 * Hides @window, then reshows it, resetting the
4351 * default size and position of the window. Used
4352 * by GUI builders only.
4355 gtk_window_reshow_with_initial_size (GtkWindow *window)
4359 g_return_if_fail (GTK_IS_WINDOW (window));
4361 widget = GTK_WIDGET (window);
4363 gtk_widget_hide (widget);
4364 gtk_widget_unrealize (widget);
4365 gtk_widget_show (widget);
4369 gtk_window_destroy (GtkObject *object)
4371 GtkWindow *window = GTK_WINDOW (object);
4373 toplevel_list = g_slist_remove (toplevel_list, window);
4375 if (window->transient_parent)
4376 gtk_window_set_transient_for (window, NULL);
4378 /* frees the icons */
4379 gtk_window_set_icon_list (window, NULL);
4381 if (window->has_user_ref_count)
4383 window->has_user_ref_count = FALSE;
4384 g_object_unref (window);
4388 gtk_window_group_remove_window (window->group, window);
4390 gtk_window_free_key_hash (window);
4392 GTK_OBJECT_CLASS (gtk_window_parent_class)->destroy (object);
4396 gtk_window_finalize (GObject *object)
4398 GtkWindow *window = GTK_WINDOW (object);
4399 GtkMnemonicHash *mnemonic_hash;
4401 g_free (window->title);
4402 g_free (window->wmclass_name);
4403 g_free (window->wmclass_class);
4404 g_free (window->wm_role);
4406 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4408 _gtk_mnemonic_hash_free (mnemonic_hash);
4410 if (window->geometry_info)
4412 if (window->geometry_info->widget)
4413 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
4414 gtk_widget_destroyed,
4415 &window->geometry_info->widget);
4416 g_free (window->geometry_info);
4419 if (window->keys_changed_handler)
4421 g_source_remove (window->keys_changed_handler);
4422 window->keys_changed_handler = 0;
4427 g_signal_handlers_disconnect_by_func (window->screen,
4428 gtk_window_on_composited_changed, window);
4431 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4435 gtk_window_show (GtkWidget *widget)
4437 GtkWindow *window = GTK_WINDOW (widget);
4438 GtkContainer *container = GTK_CONTAINER (window);
4439 gboolean need_resize;
4441 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
4443 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
4444 container->need_resize = FALSE;
4448 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4449 GtkAllocation allocation = { 0, 0 };
4450 GdkRectangle configure_request;
4451 GdkGeometry new_geometry;
4453 gboolean was_realized;
4455 /* We are going to go ahead and perform this configure request
4456 * and then emulate a configure notify by going ahead and
4457 * doing a size allocate. Sort of a synchronous
4458 * mini-copy of gtk_window_move_resize() here.
4460 gtk_window_compute_configure_request (window,
4465 /* We update this because we are going to go ahead
4466 * and gdk_window_resize() below, rather than
4469 info->last.configure_request.width = configure_request.width;
4470 info->last.configure_request.height = configure_request.height;
4472 /* and allocate the window - this is normally done
4473 * in move_resize in response to configure notify
4475 allocation.width = configure_request.width;
4476 allocation.height = configure_request.height;
4477 gtk_widget_size_allocate (widget, &allocation);
4479 /* Then we guarantee we have a realize */
4480 was_realized = FALSE;
4481 if (!GTK_WIDGET_REALIZED (widget))
4483 gtk_widget_realize (widget);
4484 was_realized = TRUE;
4487 /* Must be done after the windows are realized,
4488 * so that the decorations can be read
4490 gtk_decorated_window_calculate_frame_size (window);
4492 /* We only send configure request if we didn't just finish
4493 * creating the window; if we just created the window
4494 * then we created it with widget->allocation anyhow.
4497 gdk_window_move_resize (widget->window,
4498 configure_request.x,
4499 configure_request.y,
4500 configure_request.width,
4501 configure_request.height);
4504 gtk_container_check_resize (container);
4506 gtk_widget_map (widget);
4508 /* Try to make sure that we have some focused widget
4510 if (!window->focus_widget && !GTK_IS_PLUG (window))
4511 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4514 gtk_grab_add (widget);
4518 gtk_window_hide (GtkWidget *widget)
4520 GtkWindow *window = GTK_WINDOW (widget);
4522 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4523 gtk_widget_unmap (widget);
4526 gtk_grab_remove (widget);
4530 gtk_window_map (GtkWidget *widget)
4532 GtkWindow *window = GTK_WINDOW (widget);
4533 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4534 GdkWindow *toplevel;
4536 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4538 if (window->bin.child &&
4539 GTK_WIDGET_VISIBLE (window->bin.child) &&
4540 !GTK_WIDGET_MAPPED (window->bin.child))
4541 gtk_widget_map (window->bin.child);
4544 toplevel = window->frame;
4546 toplevel = widget->window;
4548 if (window->maximize_initially)
4549 gdk_window_maximize (toplevel);
4551 gdk_window_unmaximize (toplevel);
4553 if (window->stick_initially)
4554 gdk_window_stick (toplevel);
4556 gdk_window_unstick (toplevel);
4558 if (window->iconify_initially)
4559 gdk_window_iconify (toplevel);
4561 gdk_window_deiconify (toplevel);
4563 if (priv->fullscreen_initially)
4564 gdk_window_fullscreen (toplevel);
4566 gdk_window_unfullscreen (toplevel);
4568 gdk_window_set_keep_above (toplevel, priv->above_initially);
4570 gdk_window_set_keep_below (toplevel, priv->below_initially);
4572 /* No longer use the default settings */
4573 window->need_default_size = FALSE;
4574 window->need_default_position = FALSE;
4576 if (priv->reset_type_hint)
4578 /* We should only reset the type hint when the application
4579 * used gtk_window_set_type_hint() to change the hint.
4580 * Some applications use X directly to change the properties;
4581 * in that case, we shouldn't overwrite what they did.
4583 gdk_window_set_type_hint (widget->window, priv->type_hint);
4584 priv->reset_type_hint = FALSE;
4587 gdk_window_show (widget->window);
4590 gdk_window_show (window->frame);
4592 if (!disable_startup_notification)
4594 /* Do we have a custom startup-notification id? */
4595 if (priv->startup_id != NULL)
4597 /* Make sure we have a "real" id */
4598 if (!startup_id_is_fake (priv->startup_id))
4599 gdk_notify_startup_complete_with_id (priv->startup_id);
4601 priv->startup_id = NULL;
4603 else if (!sent_startup_notification)
4605 sent_startup_notification = TRUE;
4606 gdk_notify_startup_complete ();
4612 gtk_window_map_event (GtkWidget *widget,
4615 if (!GTK_WIDGET_MAPPED (widget))
4617 /* we should be be unmapped, but are getting a MapEvent, this may happen
4618 * to toplevel XWindows if mapping was intercepted by a window manager
4619 * and an unmap request occoured while the MapRequestEvent was still
4620 * being handled. we work around this situaiton here by re-requesting
4621 * the window being unmapped. more details can be found in:
4622 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4624 gdk_window_hide (widget->window);
4630 gtk_window_unmap (GtkWidget *widget)
4632 GtkWindow *window = GTK_WINDOW (widget);
4633 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
4634 GtkWindowGeometryInfo *info;
4635 GdkWindowState state;
4637 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4639 gdk_window_withdraw (window->frame);
4641 gdk_window_withdraw (widget->window);
4643 window->configure_request_count = 0;
4644 window->configure_notify_received = FALSE;
4646 /* on unmap, we reset the default positioning of the window,
4647 * so it's placed again, but we don't reset the default
4648 * size of the window, so it's remembered.
4650 window->need_default_position = TRUE;
4652 info = gtk_window_get_geometry_info (window, FALSE);
4655 info->initial_pos_set = FALSE;
4656 info->position_constraints_changed = FALSE;
4659 state = gdk_window_get_state (widget->window);
4660 window->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4661 window->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4662 window->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4663 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4664 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4668 gtk_window_realize (GtkWidget *widget)
4671 GdkWindow *parent_window;
4672 GdkWindowAttr attributes;
4673 gint attributes_mask;
4674 GtkWindowPrivate *priv;
4676 window = GTK_WINDOW (widget);
4677 priv = GTK_WINDOW_GET_PRIVATE (window);
4679 /* ensure widget tree is properly size allocated */
4680 if (widget->allocation.x == -1 &&
4681 widget->allocation.y == -1 &&
4682 widget->allocation.width == 1 &&
4683 widget->allocation.height == 1)
4685 GtkRequisition requisition;
4686 GtkAllocation allocation = { 0, 0, 200, 200 };
4688 gtk_widget_size_request (widget, &requisition);
4689 if (requisition.width || requisition.height)
4691 /* non-empty window */
4692 allocation.width = requisition.width;
4693 allocation.height = requisition.height;
4695 gtk_widget_size_allocate (widget, &allocation);
4697 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4699 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
4702 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4704 switch (window->type)
4706 case GTK_WINDOW_TOPLEVEL:
4707 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4709 case GTK_WINDOW_POPUP:
4710 attributes.window_type = GDK_WINDOW_TEMP;
4713 g_warning (G_STRLOC": Unknown window type %d!", window->type);
4717 attributes.title = window->title;
4718 attributes.wmclass_name = window->wmclass_name;
4719 attributes.wmclass_class = window->wmclass_class;
4720 attributes.wclass = GDK_INPUT_OUTPUT;
4721 attributes.visual = gtk_widget_get_visual (widget);
4722 attributes.colormap = gtk_widget_get_colormap (widget);
4724 if (window->has_frame)
4726 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
4727 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
4728 attributes.event_mask = (GDK_EXPOSURE_MASK |
4729 GDK_KEY_PRESS_MASK |
4730 GDK_ENTER_NOTIFY_MASK |
4731 GDK_LEAVE_NOTIFY_MASK |
4732 GDK_FOCUS_CHANGE_MASK |
4733 GDK_STRUCTURE_MASK |
4734 GDK_BUTTON_MOTION_MASK |
4735 GDK_POINTER_MOTION_HINT_MASK |
4736 GDK_BUTTON_PRESS_MASK |
4737 GDK_BUTTON_RELEASE_MASK);
4739 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4741 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4742 &attributes, attributes_mask);
4744 if (priv->opacity_set)
4745 gdk_window_set_opacity (window->frame, priv->opacity);
4747 gdk_window_set_user_data (window->frame, widget);
4749 attributes.window_type = GDK_WINDOW_CHILD;
4750 attributes.x = window->frame_left;
4751 attributes.y = window->frame_top;
4753 attributes_mask = GDK_WA_X | GDK_WA_Y;
4755 parent_window = window->frame;
4757 g_signal_connect (window,
4759 G_CALLBACK (gtk_window_event),
4764 attributes_mask = 0;
4765 parent_window = gtk_widget_get_root_window (widget);
4768 attributes.width = widget->allocation.width;
4769 attributes.height = widget->allocation.height;
4770 attributes.event_mask = gtk_widget_get_events (widget);
4771 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4772 GDK_KEY_PRESS_MASK |
4773 GDK_KEY_RELEASE_MASK |
4774 GDK_ENTER_NOTIFY_MASK |
4775 GDK_LEAVE_NOTIFY_MASK |
4776 GDK_FOCUS_CHANGE_MASK |
4777 GDK_STRUCTURE_MASK);
4778 attributes.type_hint = priv->type_hint;
4780 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_TYPE_HINT;
4781 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
4782 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
4784 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
4786 if (!window->has_frame && priv->opacity_set)
4787 gdk_window_set_opacity (widget->window, priv->opacity);
4789 gdk_window_enable_synchronized_configure (widget->window);
4791 gdk_window_set_user_data (widget->window, window);
4793 widget->style = gtk_style_attach (widget->style, widget->window);
4794 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4796 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
4798 /* This is a bad hack to set the window background. */
4799 gtk_window_paint (widget, NULL);
4801 if (window->transient_parent &&
4802 GTK_WIDGET_REALIZED (window->transient_parent))
4803 gdk_window_set_transient_for (widget->window,
4804 GTK_WIDGET (window->transient_parent)->window);
4806 if (window->wm_role)
4807 gdk_window_set_role (widget->window, window->wm_role);
4809 if (!window->decorated)
4810 gdk_window_set_decorations (widget->window, 0);
4812 if (!priv->deletable)
4813 gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4815 if (gtk_window_get_skip_pager_hint (window))
4816 gdk_window_set_skip_pager_hint (widget->window, TRUE);
4818 if (gtk_window_get_skip_taskbar_hint (window))
4819 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
4821 if (gtk_window_get_accept_focus (window))
4822 gdk_window_set_accept_focus (widget->window, TRUE);
4824 gdk_window_set_accept_focus (widget->window, FALSE);
4826 if (gtk_window_get_focus_on_map (window))
4827 gdk_window_set_focus_on_map (widget->window, TRUE);
4829 gdk_window_set_focus_on_map (widget->window, FALSE);
4832 gdk_window_set_modal_hint (widget->window, TRUE);
4834 gdk_window_set_modal_hint (widget->window, FALSE);
4836 if (priv->startup_id)
4838 #ifdef GDK_WINDOWING_X11
4839 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4840 if (timestamp != GDK_CURRENT_TIME)
4841 gdk_x11_window_set_user_time (widget->window, timestamp);
4843 if (!startup_id_is_fake (priv->startup_id))
4844 gdk_window_set_startup_id (widget->window, priv->startup_id);
4848 gtk_window_realize_icon (window);
4852 gtk_window_unrealize (GtkWidget *widget)
4855 GtkWindowGeometryInfo *info;
4857 window = GTK_WINDOW (widget);
4859 /* On unrealize, we reset the size of the window such
4860 * that we will re-apply the default sizing stuff
4861 * next time we show the window.
4863 * Default positioning is reset on unmap, instead of unrealize.
4865 window->need_default_size = TRUE;
4866 info = gtk_window_get_geometry_info (window, FALSE);
4869 info->resize_width = -1;
4870 info->resize_height = -1;
4871 info->last.configure_request.x = 0;
4872 info->last.configure_request.y = 0;
4873 info->last.configure_request.width = -1;
4874 info->last.configure_request.height = -1;
4875 /* be sure we reset geom hints on re-realize */
4876 info->last.flags = 0;
4881 gdk_window_set_user_data (window->frame, NULL);
4882 gdk_window_destroy (window->frame);
4883 window->frame = NULL;
4887 gtk_window_unrealize_icon (window);
4889 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
4893 gtk_window_size_request (GtkWidget *widget,
4894 GtkRequisition *requisition)
4899 window = GTK_WINDOW (widget);
4900 bin = GTK_BIN (window);
4902 requisition->width = GTK_CONTAINER (window)->border_width * 2;
4903 requisition->height = GTK_CONTAINER (window)->border_width * 2;
4905 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
4907 GtkRequisition child_requisition;
4909 gtk_widget_size_request (bin->child, &child_requisition);
4911 requisition->width += child_requisition.width;
4912 requisition->height += child_requisition.height;
4917 gtk_window_size_allocate (GtkWidget *widget,
4918 GtkAllocation *allocation)
4921 GtkAllocation child_allocation;
4923 window = GTK_WINDOW (widget);
4924 widget->allocation = *allocation;
4926 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
4928 child_allocation.x = GTK_CONTAINER (window)->border_width;
4929 child_allocation.y = GTK_CONTAINER (window)->border_width;
4930 child_allocation.width =
4931 MAX (1, (gint)allocation->width - child_allocation.x * 2);
4932 child_allocation.height =
4933 MAX (1, (gint)allocation->height - child_allocation.y * 2);
4935 gtk_widget_size_allocate (window->bin.child, &child_allocation);
4938 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4940 gdk_window_resize (window->frame,
4941 allocation->width + window->frame_left + window->frame_right,
4942 allocation->height + window->frame_top + window->frame_bottom);
4947 gtk_window_event (GtkWidget *widget, GdkEvent *event)
4950 gboolean return_val;
4952 window = GTK_WINDOW (widget);
4954 if (window->frame && (event->any.window == window->frame))
4956 if ((event->type != GDK_KEY_PRESS) &&
4957 (event->type != GDK_KEY_RELEASE) &&
4958 (event->type != GDK_FOCUS_CHANGE))
4960 g_signal_stop_emission_by_name (widget, "event");
4962 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
4967 g_object_unref (event->any.window);
4968 event->any.window = g_object_ref (widget->window);
4976 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
4978 GdkEventConfigure *configure_event;
4981 switch (event->type)
4984 configure_event = (GdkEventConfigure *)event;
4986 /* Invalidate the decorations */
4989 rect.width = configure_event->width;
4990 rect.height = configure_event->height;
4992 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
4994 /* Pass on the (modified) configure event */
4995 configure_event->width -= window->frame_left + window->frame_right;
4996 configure_event->height -= window->frame_top + window->frame_bottom;
4997 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
5006 gtk_window_configure_event (GtkWidget *widget,
5007 GdkEventConfigure *event)
5009 GtkWindow *window = GTK_WINDOW (widget);
5010 gboolean expected_reply = window->configure_request_count > 0;
5012 /* window->configure_request_count incremented for each
5013 * configure request, and decremented to a min of 0 for
5014 * each configure notify.
5016 * All it means is that we know we will get at least
5017 * window->configure_request_count more configure notifies.
5018 * We could get more configure notifies than that; some
5019 * of the configure notifies we get may be unrelated to
5020 * the configure requests. But we will get at least
5021 * window->configure_request_count notifies.
5024 if (window->configure_request_count > 0)
5026 window->configure_request_count -= 1;
5027 gdk_window_thaw_toplevel_updates_libgtk_only (widget->window);
5030 /* As an optimization, we avoid a resize when possible.
5032 * The only times we can avoid a resize are:
5033 * - we know only the position changed, not the size
5034 * - we know we have made more requests and so will get more
5035 * notifies and can wait to resize when we get them
5038 if (!expected_reply &&
5039 (widget->allocation.width == event->width &&
5040 widget->allocation.height == event->height))
5042 gdk_window_configure_finished (widget->window);
5047 * If we do need to resize, we do that by:
5048 * - filling in widget->allocation with the new size
5049 * - setting configure_notify_received to TRUE
5050 * for use in gtk_window_move_resize()
5051 * - queueing a resize, leading to invocation of
5052 * gtk_window_move_resize() in an idle handler
5056 window->configure_notify_received = TRUE;
5058 widget->allocation.width = event->width;
5059 widget->allocation.height = event->height;
5061 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5066 /* the accel_key and accel_mods fields of the key have to be setup
5067 * upon calling this function. it'll then return whether that key
5068 * is at all used as accelerator, and if so will OR in the
5069 * accel_flags member of the key.
5072 _gtk_window_query_nonaccels (GtkWindow *window,
5074 GdkModifierType accel_mods)
5076 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5078 /* movement keys are considered locked accels */
5081 static const guint bindings[] = {
5082 GDK_space, GDK_KP_Space, GDK_Return, GDK_ISO_Enter, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
5083 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
5087 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5088 if (bindings[i] == accel_key)
5092 /* mnemonics are considered locked accels */
5093 if (accel_mods == window->mnemonic_modifier)
5095 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5096 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5104 * gtk_window_propagate_key_event:
5105 * @window: a #GtkWindow
5106 * @event: a #GdkEventKey
5108 * Propagate a key press or release event to the focus widget and
5109 * up the focus container chain until a widget handles @event.
5110 * This is normally called by the default ::key_press_event and
5111 * ::key_release_event handlers for toplevel windows,
5112 * however in some cases it may be useful to call this directly when
5113 * overriding the standard key handling for a toplevel window.
5115 * Return value: %TRUE if a widget in the focus chain handled the event.
5118 gtk_window_propagate_key_event (GtkWindow *window,
5121 gboolean handled = FALSE;
5122 GtkWidget *widget, *focus;
5124 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5126 widget = GTK_WIDGET (window);
5127 focus = window->focus_widget;
5129 g_object_ref (focus);
5132 focus && focus != widget &&
5133 gtk_widget_get_toplevel (focus) == widget)
5137 if (GTK_WIDGET_IS_SENSITIVE (focus))
5138 handled = gtk_widget_event (focus, (GdkEvent*) event);
5140 parent = focus->parent;
5142 g_object_ref (parent);
5144 g_object_unref (focus);
5150 g_object_unref (focus);
5156 gtk_window_key_press_event (GtkWidget *widget,
5159 GtkWindow *window = GTK_WINDOW (widget);
5160 gboolean handled = FALSE;
5162 /* handle mnemonics and accelerators */
5164 handled = gtk_window_activate_key (window, event);
5166 /* handle focus widget key events */
5168 handled = gtk_window_propagate_key_event (window, event);
5170 /* Chain up, invokes binding set */
5172 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5178 gtk_window_key_release_event (GtkWidget *widget,
5181 GtkWindow *window = GTK_WINDOW (widget);
5182 gboolean handled = FALSE;
5184 /* handle focus widget key events */
5186 handled = gtk_window_propagate_key_event (window, event);
5188 /* Chain up, invokes binding set */
5190 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5196 gtk_window_real_activate_default (GtkWindow *window)
5198 gtk_window_activate_default (window);
5202 gtk_window_real_activate_focus (GtkWindow *window)
5204 gtk_window_activate_focus (window);
5208 gtk_window_move_focus (GtkWindow *window,
5209 GtkDirectionType dir)
5211 gtk_widget_child_focus (GTK_WIDGET (window), dir);
5213 if (!GTK_CONTAINER (window)->focus_child)
5214 gtk_window_set_focus (window, NULL);
5218 gtk_window_enter_notify_event (GtkWidget *widget,
5219 GdkEventCrossing *event)
5225 gtk_window_leave_notify_event (GtkWidget *widget,
5226 GdkEventCrossing *event)
5232 do_focus_change (GtkWidget *widget,
5235 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5237 g_object_ref (widget);
5240 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
5242 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
5244 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5245 fevent->focus_change.window = widget->window;
5247 g_object_ref (widget->window);
5248 fevent->focus_change.in = in;
5250 gtk_widget_event (widget, fevent);
5252 g_object_notify (G_OBJECT (widget), "has-focus");
5254 g_object_unref (widget);
5255 gdk_event_free (fevent);
5259 gtk_window_focus_in_event (GtkWidget *widget,
5260 GdkEventFocus *event)
5262 GtkWindow *window = GTK_WINDOW (widget);
5264 /* It appears spurious focus in events can occur when
5265 * the window is hidden. So we'll just check to see if
5266 * the window is visible before actually handling the
5269 if (GTK_WIDGET_VISIBLE (widget))
5271 _gtk_window_set_has_toplevel_focus (window, TRUE);
5272 _gtk_window_set_is_active (window, TRUE);
5279 gtk_window_focus_out_event (GtkWidget *widget,
5280 GdkEventFocus *event)
5282 GtkWindow *window = GTK_WINDOW (widget);
5284 _gtk_window_set_has_toplevel_focus (window, FALSE);
5285 _gtk_window_set_is_active (window, FALSE);
5290 static GdkAtom atom_rcfiles = GDK_NONE;
5291 static GdkAtom atom_iconthemes = GDK_NONE;
5294 send_client_message_to_embedded_windows (GtkWidget *widget,
5295 GdkAtom message_type)
5297 GList *embedded_windows;
5299 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5300 if (embedded_windows)
5302 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5305 for (i = 0; i < 5; i++)
5306 send_event->client.data.l[i] = 0;
5307 send_event->client.data_format = 32;
5308 send_event->client.message_type = message_type;
5310 while (embedded_windows)
5312 GdkNativeWindow xid = (GdkNativeWindow) embedded_windows->data;
5313 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5314 embedded_windows = embedded_windows->next;
5317 gdk_event_free (send_event);
5322 gtk_window_client_event (GtkWidget *widget,
5323 GdkEventClient *event)
5327 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5328 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5331 if (event->message_type == atom_rcfiles)
5333 send_client_message_to_embedded_windows (widget, atom_rcfiles);
5334 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
5337 if (event->message_type == atom_iconthemes)
5339 send_client_message_to_embedded_windows (widget, atom_iconthemes);
5340 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
5347 gtk_window_check_resize (GtkContainer *container)
5349 GtkWindow *window = GTK_WINDOW (container);
5351 if (GTK_WIDGET_VISIBLE (container))
5352 gtk_window_move_resize (window);
5356 gtk_window_focus (GtkWidget *widget,
5357 GtkDirectionType direction)
5361 GtkContainer *container;
5362 GtkWidget *old_focus_child;
5365 container = GTK_CONTAINER (widget);
5366 window = GTK_WINDOW (widget);
5367 bin = GTK_BIN (widget);
5369 old_focus_child = container->focus_child;
5371 /* We need a special implementation here to deal properly with wrapping
5372 * around in the tab chain without the danger of going into an
5375 if (old_focus_child)
5377 if (gtk_widget_child_focus (old_focus_child, direction))
5381 if (window->focus_widget)
5383 if (direction == GTK_DIR_LEFT ||
5384 direction == GTK_DIR_RIGHT ||
5385 direction == GTK_DIR_UP ||
5386 direction == GTK_DIR_DOWN)
5391 /* Wrapped off the end, clear the focus setting for the toplpevel */
5392 parent = window->focus_widget->parent;
5395 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5396 parent = GTK_WIDGET (parent)->parent;
5399 gtk_window_set_focus (GTK_WINDOW (container), NULL);
5402 /* Now try to focus the first widget in the window */
5405 if (gtk_widget_child_focus (bin->child, direction))
5413 gtk_window_real_set_focus (GtkWindow *window,
5416 GtkWidget *old_focus = window->focus_widget;
5417 gboolean had_default = FALSE;
5418 gboolean focus_had_default = FALSE;
5419 gboolean old_focus_had_default = FALSE;
5423 g_object_ref (old_focus);
5424 g_object_freeze_notify (G_OBJECT (old_focus));
5425 old_focus_had_default = GTK_WIDGET_HAS_DEFAULT (old_focus);
5429 g_object_ref (focus);
5430 g_object_freeze_notify (G_OBJECT (focus));
5431 focus_had_default = GTK_WIDGET_HAS_DEFAULT (focus);
5434 if (window->default_widget)
5435 had_default = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
5437 if (window->focus_widget)
5439 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
5440 (window->focus_widget != window->default_widget))
5442 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
5443 gtk_widget_queue_draw (window->focus_widget);
5445 if (window->default_widget)
5446 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
5449 window->focus_widget = NULL;
5451 if (window->has_focus)
5452 do_focus_change (old_focus, FALSE);
5454 g_object_notify (G_OBJECT (old_focus), "is-focus");
5457 /* The above notifications may have set a new focus widget,
5458 * if so, we don't want to override it.
5460 if (focus && !window->focus_widget)
5462 window->focus_widget = focus;
5464 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
5465 (window->focus_widget != window->default_widget))
5467 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
5468 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
5470 if (window->default_widget)
5471 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
5474 if (window->has_focus)
5475 do_focus_change (window->focus_widget, TRUE);
5477 g_object_notify (G_OBJECT (window->focus_widget), "is-focus");
5480 /* If the default widget changed, a redraw will have been queued
5481 * on the old and new default widgets by gtk_window_set_default(), so
5482 * we only have to worry about the case where it didn't change.
5483 * We'll sometimes queue a draw twice on the new widget but that
5486 if (window->default_widget &&
5487 (had_default != GTK_WIDGET_HAS_DEFAULT (window->default_widget)))
5488 gtk_widget_queue_draw (window->default_widget);
5492 if (old_focus_had_default != GTK_WIDGET_HAS_DEFAULT (old_focus))
5493 gtk_widget_queue_draw (old_focus);
5495 g_object_thaw_notify (G_OBJECT (old_focus));
5496 g_object_unref (old_focus);
5500 if (focus_had_default != GTK_WIDGET_HAS_DEFAULT (focus))
5501 gtk_widget_queue_draw (focus);
5503 g_object_thaw_notify (G_OBJECT (focus));
5504 g_object_unref (focus);
5509 * _gtk_window_unset_focus_and_default:
5510 * @window: a #GtkWindow
5511 * @widget: a widget inside of @window
5513 * Checks whether the focus and default widgets of @window are
5514 * @widget or a descendent of @widget, and if so, unset them.
5517 _gtk_window_unset_focus_and_default (GtkWindow *window,
5523 g_object_ref (window);
5524 g_object_ref (widget);
5526 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
5528 child = window->focus_widget;
5530 while (child && child != widget)
5531 child = child->parent;
5533 if (child == widget)
5534 gtk_window_set_focus (GTK_WINDOW (window), NULL);
5537 child = window->default_widget;
5539 while (child && child != widget)
5540 child = child->parent;
5542 if (child == widget)
5543 gtk_window_set_default (window, NULL);
5545 g_object_unref (widget);
5546 g_object_unref (window);
5549 /*********************************
5550 * Functions related to resizing *
5551 *********************************/
5553 /* This function doesn't constrain to geometry hints */
5555 gtk_window_compute_configure_request_size (GtkWindow *window,
5559 GtkRequisition requisition;
5560 GtkWindowGeometryInfo *info;
5564 * - we've done a size request
5567 widget = GTK_WIDGET (window);
5569 info = gtk_window_get_geometry_info (window, FALSE);
5571 if (window->need_default_size)
5573 gtk_widget_get_child_requisition (widget, &requisition);
5575 /* Default to requisition */
5576 *width = requisition.width;
5577 *height = requisition.height;
5579 /* If window is empty so requests 0, default to random nonzero size */
5580 if (*width == 0 && *height == 0)
5586 /* Override requisition with default size */
5590 gint base_width = 0;
5591 gint base_height = 0;
5593 gint min_height = 0;
5595 gint height_inc = 1;
5597 if (info->default_is_geometry &&
5598 (info->default_width > 0 || info->default_height > 0))
5600 GdkGeometry geometry;
5603 gtk_window_compute_hints (window, &geometry, &flags);
5605 if (flags & GDK_HINT_BASE_SIZE)
5607 base_width = geometry.base_width;
5608 base_height = geometry.base_height;
5610 if (flags & GDK_HINT_MIN_SIZE)
5612 min_width = geometry.min_width;
5613 min_height = geometry.min_height;
5615 if (flags & GDK_HINT_RESIZE_INC)
5617 width_inc = geometry.width_inc;
5618 height_inc = geometry.height_inc;
5622 if (info->default_width > 0)
5623 *width = MAX (info->default_width * width_inc + base_width, min_width);
5625 if (info->default_height > 0)
5626 *height = MAX (info->default_height * height_inc + base_height, min_height);
5631 /* Default to keeping current size */
5632 *width = widget->allocation.width;
5633 *height = widget->allocation.height;
5636 /* Override any size with gtk_window_resize() values */
5639 if (info->resize_width > 0)
5640 *width = info->resize_width;
5642 if (info->resize_height > 0)
5643 *height = info->resize_height;
5647 static GtkWindowPosition
5648 get_effective_position (GtkWindow *window)
5650 GtkWindowPosition pos = window->position;
5651 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5652 (window->transient_parent == NULL ||
5653 !GTK_WIDGET_MAPPED (window->transient_parent)))
5654 pos = GTK_WIN_POS_NONE;
5660 get_center_monitor_of_window (GtkWindow *window)
5662 /* We could try to sort out the relative positions of the monitors and
5663 * stuff, or we could just be losers and assume you have a row
5664 * or column of monitors.
5666 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5670 get_monitor_containing_pointer (GtkWindow *window)
5674 GdkScreen *window_screen;
5675 GdkScreen *pointer_screen;
5677 window_screen = gtk_window_check_screen (window);
5678 gdk_display_get_pointer (gdk_screen_get_display (window_screen),
5682 if (pointer_screen == window_screen)
5683 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5691 center_window_on_monitor (GtkWindow *window,
5697 GdkRectangle monitor;
5700 monitor_num = get_monitor_containing_pointer (window);
5702 if (monitor_num == -1)
5703 monitor_num = get_center_monitor_of_window (window);
5705 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5706 monitor_num, &monitor);
5708 *x = (monitor.width - w) / 2 + monitor.x;
5709 *y = (monitor.height - h) / 2 + monitor.y;
5711 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5712 * and WM decorations.
5726 if (extent > clamp_extent)
5728 *base = clamp_base + clamp_extent/2 - extent/2;
5729 else if (*base < clamp_base)
5731 else if (*base + extent > clamp_base + clamp_extent)
5732 *base = clamp_base + clamp_extent - extent;
5736 clamp_window_to_rectangle (gint *x,
5740 const GdkRectangle *rect)
5742 #ifdef DEBUGGING_OUTPUT
5743 g_print ("%s: %+d%+d %dx%d: %+d%+d: %dx%d", __FUNCTION__, rect->x, rect->y, rect->width, rect->height, *x, *y, w, h);
5746 /* If it is too large, center it. If it fits on the monitor but is
5747 * partially outside, move it to the closest edge. Do this
5748 * separately in x and y directions.
5750 clamp (x, w, rect->x, rect->width);
5751 clamp (y, h, rect->y, rect->height);
5752 #ifdef DEBUGGING_OUTPUT
5753 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
5759 gtk_window_compute_configure_request (GtkWindow *window,
5760 GdkRectangle *request,
5761 GdkGeometry *geometry,
5764 GdkGeometry new_geometry;
5768 GtkWindowPosition pos;
5769 GtkWidget *parent_widget;
5770 GtkWindowGeometryInfo *info;
5774 widget = GTK_WIDGET (window);
5776 screen = gtk_window_check_screen (window);
5778 gtk_widget_size_request (widget, NULL);
5779 gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
5781 gtk_window_compute_hints (window, &new_geometry, &new_flags);
5782 gtk_window_constrain_size (window,
5783 &new_geometry, new_flags,
5787 parent_widget = (GtkWidget*) window->transient_parent;
5789 pos = get_effective_position (window);
5790 info = gtk_window_get_geometry_info (window, FALSE);
5792 /* by default, don't change position requested */
5795 x = info->last.configure_request.x;
5796 y = info->last.configure_request.y;
5805 if (window->need_default_position)
5808 /* FIXME this all interrelates with window gravity.
5809 * For most of them I think we want to set GRAVITY_CENTER.
5811 * Not sure how to go about that.
5816 /* here we are only handling CENTER_ALWAYS
5817 * as it relates to default positioning,
5818 * where it's equivalent to simply CENTER
5820 case GTK_WIN_POS_CENTER_ALWAYS:
5821 case GTK_WIN_POS_CENTER:
5822 center_window_on_monitor (window, w, h, &x, &y);
5825 case GTK_WIN_POS_CENTER_ON_PARENT:
5828 GdkRectangle monitor;
5831 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
5833 if (parent_widget->window != NULL)
5834 monitor_num = gdk_screen_get_monitor_at_window (screen,
5835 parent_widget->window);
5839 gdk_window_get_origin (parent_widget->window,
5842 x = ox + (parent_widget->allocation.width - w) / 2;
5843 y = oy + (parent_widget->allocation.height - h) / 2;
5845 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5846 * WM decorations. If parent wasn't on a monitor, just
5849 if (monitor_num >= 0)
5851 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5852 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5857 case GTK_WIN_POS_MOUSE:
5859 gint screen_width = gdk_screen_get_width (screen);
5860 gint screen_height = gdk_screen_get_height (screen);
5862 GdkRectangle monitor;
5863 GdkScreen *pointer_screen;
5866 gdk_display_get_pointer (gdk_screen_get_display (screen),
5870 if (pointer_screen == screen)
5871 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
5877 x = CLAMP (x, 0, screen_width - w);
5878 y = CLAMP (y, 0, screen_height - h);
5880 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5881 * WM decorations. Don't try to figure out what's going
5882 * on if the mouse wasn't inside a monitor.
5884 if (monitor_num >= 0)
5886 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5887 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5895 } /* if (window->need_default_position) */
5897 if (window->need_default_position && info &&
5898 info->initial_pos_set)
5900 x = info->initial_x;
5901 y = info->initial_y;
5902 gtk_window_constrain_position (window, w, h, &x, &y);
5908 request->height = h;
5911 *geometry = new_geometry;
5917 gtk_window_constrain_position (GtkWindow *window,
5923 /* See long comments in gtk_window_move_resize()
5924 * on when it's safe to call this function.
5926 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
5928 gint center_x, center_y;
5930 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
5938 gtk_window_move_resize (GtkWindow *window)
5942 * First we determine whether any information has changed that would
5943 * cause us to revise our last configure request. If we would send
5944 * a different configure request from last time, then
5945 * configure_request_size_changed = TRUE or
5946 * configure_request_pos_changed = TRUE. configure_request_size_changed
5947 * may be true due to new hints, a gtk_window_resize(), or whatever.
5948 * configure_request_pos_changed may be true due to gtk_window_set_position()
5949 * or gtk_window_move().
5951 * If the configure request has changed, we send off a new one. To
5952 * ensure GTK+ invariants are maintained (resize queue does what it
5953 * should), we go ahead and size_allocate the requested size in this
5956 * If the configure request has not changed, we don't ever resend
5957 * it, because it could mean fighting the user or window manager.
5960 * To prepare the configure request, we come up with a base size/pos:
5961 * - the one from gtk_window_move()/gtk_window_resize()
5962 * - else default_width, default_height if we haven't ever
5964 * - else the size request if we haven't ever been mapped,
5965 * as a substitute default size
5966 * - else the current size of the window, as received from
5967 * configure notifies (i.e. the current allocation)
5969 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
5970 * the position request to be centered.
5973 GtkContainer *container;
5974 GtkWindowGeometryInfo *info;
5975 GdkGeometry new_geometry;
5977 GdkRectangle new_request;
5978 gboolean configure_request_size_changed;
5979 gboolean configure_request_pos_changed;
5980 gboolean hints_changed; /* do we need to send these again */
5981 GtkWindowLastGeometryInfo saved_last_info;
5983 widget = GTK_WIDGET (window);
5984 container = GTK_CONTAINER (widget);
5985 info = gtk_window_get_geometry_info (window, TRUE);
5987 configure_request_size_changed = FALSE;
5988 configure_request_pos_changed = FALSE;
5990 gtk_window_compute_configure_request (window, &new_request,
5991 &new_geometry, &new_flags);
5993 /* This check implies the invariant that we never set info->last
5994 * without setting the hints and sending off a configure request.
5996 * If we change info->last without sending the request, we may
5999 if (info->last.configure_request.x != new_request.x ||
6000 info->last.configure_request.y != new_request.y)
6001 configure_request_pos_changed = TRUE;
6003 if ((info->last.configure_request.width != new_request.width ||
6004 info->last.configure_request.height != new_request.height))
6005 configure_request_size_changed = TRUE;
6007 hints_changed = FALSE;
6009 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6010 &new_geometry, new_flags))
6012 hints_changed = TRUE;
6015 /* Position Constraints
6016 * ====================
6018 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6019 * a default. The other POS_ values are used only when the
6020 * window is shown, not after that.
6022 * However, we can't implement a position constraint as
6023 * "anytime the window size changes, center the window"
6024 * because this may well end up fighting the WM or user. In
6025 * fact it gets in an infinite loop with at least one WM.
6027 * Basically, applications are in no way in a position to
6028 * constrain the position of a window, with one exception:
6029 * override redirect windows. (Really the intended purpose
6030 * of CENTER_ALWAYS anyhow, I would think.)
6032 * So the way we implement this "constraint" is to say that when WE
6033 * cause a move or resize, i.e. we make a configure request changing
6034 * window size, we recompute the CENTER_ALWAYS position to reflect
6035 * the new window size, and include it in our request. Also, if we
6036 * just turned on CENTER_ALWAYS we snap to center with a new
6037 * request. Otherwise, if we are just NOTIFIED of a move or resize
6038 * done by someone else e.g. the window manager, we do NOT send a
6039 * new configure request.
6041 * For override redirect windows, this works fine; all window
6042 * sizes are from our configure requests. For managed windows,
6043 * it is at least semi-sane, though who knows what the
6044 * app author is thinking.
6047 /* This condition should be kept in sync with the condition later on
6048 * that determines whether we send a configure request. i.e. we
6049 * should do this position constraining anytime we were going to
6050 * send a configure request anyhow, plus when constraints have
6053 if (configure_request_pos_changed ||
6054 configure_request_size_changed ||
6056 info->position_constraints_changed)
6058 /* We request the constrained position if:
6059 * - we were changing position, and need to clamp
6060 * the change to the constraint
6061 * - we're changing the size anyway
6062 * - set_position() was called to toggle CENTER_ALWAYS on
6065 gtk_window_constrain_position (window,
6071 /* Update whether we need to request a move */
6072 if (info->last.configure_request.x != new_request.x ||
6073 info->last.configure_request.y != new_request.y)
6074 configure_request_pos_changed = TRUE;
6076 configure_request_pos_changed = FALSE;
6080 if (window->type == GTK_WINDOW_TOPLEVEL)
6082 int notify_x, notify_y;
6084 /* this is the position from the last configure notify */
6085 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6087 g_message ("--- %s ---\n"
6088 "last : %d,%d\t%d x %d\n"
6089 "this : %d,%d\t%d x %d\n"
6090 "alloc : %d,%d\t%d x %d\n"
6092 "resize: \t%d x %d\n"
6093 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6094 "configure_notify_received: %d\n"
6095 "configure_request_count: %d\n"
6096 "position_constraints_changed: %d\n",
6097 window->title ? window->title : "(no title)",
6098 info->last.configure_request.x,
6099 info->last.configure_request.y,
6100 info->last.configure_request.width,
6101 info->last.configure_request.height,
6107 widget->allocation.width,
6108 widget->allocation.height,
6109 widget->requisition.width,
6110 widget->requisition.height,
6112 info->resize_height,
6113 configure_request_pos_changed,
6114 configure_request_size_changed,
6116 window->configure_notify_received,
6117 window->configure_request_count,
6118 info->position_constraints_changed);
6122 saved_last_info = info->last;
6123 info->last.geometry = new_geometry;
6124 info->last.flags = new_flags;
6125 info->last.configure_request = new_request;
6127 /* need to set PPosition so the WM will look at our position,
6128 * but we don't want to count PPosition coming and going as a hints
6129 * change for future iterations. So we saved info->last prior to
6133 /* Also, if the initial position was explicitly set, then we always
6134 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6138 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6139 * this is an initial map
6142 if ((configure_request_pos_changed ||
6143 info->initial_pos_set ||
6144 (window->need_default_position &&
6145 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6146 (new_flags & GDK_HINT_POS) == 0)
6148 new_flags |= GDK_HINT_POS;
6149 hints_changed = TRUE;
6152 /* Set hints if necessary
6155 gdk_window_set_geometry_hints (widget->window,
6159 /* handle resizing/moving and widget tree allocation
6161 if (window->configure_notify_received)
6163 GtkAllocation allocation;
6165 /* If we have received a configure event since
6166 * the last time in this function, we need to
6167 * accept our new size and size_allocate child widgets.
6168 * (see gtk_window_configure_event() for more details).
6170 * 1 or more configure notifies may have been received.
6171 * Also, configure_notify_received will only be TRUE
6172 * if all expected configure notifies have been received
6173 * (one per configure request), as an optimization.
6176 window->configure_notify_received = FALSE;
6178 /* gtk_window_configure_event() filled in widget->allocation */
6179 allocation = widget->allocation;
6180 gtk_widget_size_allocate (widget, &allocation);
6182 gdk_window_process_updates (widget->window, TRUE);
6184 gdk_window_configure_finished (widget->window);
6186 /* If the configure request changed, it means that
6188 * 1) coincidentally changed hints or widget properties
6189 * impacting the configure request before getting
6190 * a configure notify, or
6191 * 2) some broken widget is changing its size request
6192 * during size allocation, resulting in
6193 * a false appearance of changed configure request.
6195 * For 1), we could just go ahead and ask for the
6196 * new size right now, but doing that for 2)
6197 * might well be fighting the user (and can even
6198 * trigger a loop). Since we really don't want to
6199 * do that, we requeue a resize in hopes that
6200 * by the time it gets handled, the child has seen
6201 * the light and is willing to go along with the
6202 * new size. (this happens for the zvt widget, since
6203 * the size_allocate() above will have stored the
6204 * requisition corresponding to the new size in the
6207 * This doesn't buy us anything for 1), but it shouldn't
6208 * hurt us too badly, since it is what would have
6209 * happened if we had gotten the configure event before
6210 * the new size had been set.
6213 if (configure_request_size_changed ||
6214 configure_request_pos_changed)
6216 /* Don't change the recorded last info after all, because we
6217 * haven't actually updated to the new info yet - we decided
6218 * to postpone our configure request until later.
6220 info->last = saved_last_info;
6222 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6225 return; /* Bail out, we didn't really process the move/resize */
6227 else if ((configure_request_size_changed || hints_changed) &&
6228 (widget->allocation.width != new_request.width ||
6229 widget->allocation.height != new_request.height))
6232 /* We are in one of the following situations:
6233 * A. configure_request_size_changed
6234 * our requisition has changed and we need a different window size,
6235 * so we request it from the window manager.
6236 * B. !configure_request_size_changed && hints_changed
6237 * the window manager rejects our size, but we have just changed the
6238 * window manager hints, so there's a chance our request will
6239 * be honoured this time, so we try again.
6241 * However, if the new requisition is the same as the current allocation,
6242 * we don't request it again, since we won't get a ConfigureNotify back from
6243 * the window manager unless it decides to change our requisition. If
6244 * we don't get the ConfigureNotify back, the resize queue will never be run.
6247 /* Now send the configure request */
6248 if (configure_request_pos_changed)
6252 gdk_window_move_resize (window->frame,
6253 new_request.x - window->frame_left,
6254 new_request.y - window->frame_top,
6255 new_request.width + window->frame_left + window->frame_right,
6256 new_request.height + window->frame_top + window->frame_bottom);
6257 gdk_window_resize (widget->window,
6258 new_request.width, new_request.height);
6261 gdk_window_move_resize (widget->window,
6262 new_request.x, new_request.y,
6263 new_request.width, new_request.height);
6265 else /* only size changed */
6268 gdk_window_resize (window->frame,
6269 new_request.width + window->frame_left + window->frame_right,
6270 new_request.height + window->frame_top + window->frame_bottom);
6271 gdk_window_resize (widget->window,
6272 new_request.width, new_request.height);
6275 if (window->type == GTK_WINDOW_POPUP)
6277 GtkAllocation allocation;
6279 /* Directly size allocate for override redirect (popup) windows. */
6282 allocation.width = new_request.width;
6283 allocation.height = new_request.height;
6285 gtk_widget_size_allocate (widget, &allocation);
6287 gdk_window_process_updates (widget->window, TRUE);
6289 if (container->resize_mode == GTK_RESIZE_QUEUE)
6290 gtk_widget_queue_draw (widget);
6294 /* Increment the number of have-not-yet-received-notify requests */
6295 window->configure_request_count += 1;
6296 gdk_window_freeze_toplevel_updates_libgtk_only (widget->window);
6298 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6299 * configure event in response to our resizing request.
6300 * the configure event will cause a new resize with
6301 * ->configure_notify_received=TRUE.
6302 * until then, we want to
6303 * - discard expose events
6304 * - coalesce resizes for our children
6305 * - defer any window resizes until the configure event arrived
6306 * to achieve this, we queue a resize for the window, but remove its
6307 * resizing handler, so resizing will not be handled from the next
6308 * idle handler but when the configure event arrives.
6310 * FIXME: we should also dequeue the pending redraws here, since
6311 * we handle those ourselves upon ->configure_notify_received==TRUE.
6313 if (container->resize_mode == GTK_RESIZE_QUEUE)
6315 gtk_widget_queue_resize_no_redraw (widget);
6316 _gtk_container_dequeue_resize_handler (container);
6322 /* Handle any position changes.
6324 if (configure_request_pos_changed)
6328 gdk_window_move (window->frame,
6329 new_request.x - window->frame_left,
6330 new_request.y - window->frame_top);
6333 gdk_window_move (widget->window,
6334 new_request.x, new_request.y);
6337 /* And run the resize queue.
6339 gtk_container_resize_children (container);
6342 /* We have now processed a move/resize since the last position
6343 * constraint change, setting of the initial position, or resize.
6344 * (Not resetting these flags here can lead to infinite loops for
6345 * GTK_RESIZE_IMMEDIATE containers)
6347 info->position_constraints_changed = FALSE;
6348 info->initial_pos_set = FALSE;
6349 info->resize_width = -1;
6350 info->resize_height = -1;
6353 /* Compare two sets of Geometry hints for equality.
6356 gtk_window_compare_hints (GdkGeometry *geometry_a,
6358 GdkGeometry *geometry_b,
6361 if (flags_a != flags_b)
6364 if ((flags_a & GDK_HINT_MIN_SIZE) &&
6365 (geometry_a->min_width != geometry_b->min_width ||
6366 geometry_a->min_height != geometry_b->min_height))
6369 if ((flags_a & GDK_HINT_MAX_SIZE) &&
6370 (geometry_a->max_width != geometry_b->max_width ||
6371 geometry_a->max_height != geometry_b->max_height))
6374 if ((flags_a & GDK_HINT_BASE_SIZE) &&
6375 (geometry_a->base_width != geometry_b->base_width ||
6376 geometry_a->base_height != geometry_b->base_height))
6379 if ((flags_a & GDK_HINT_ASPECT) &&
6380 (geometry_a->min_aspect != geometry_b->min_aspect ||
6381 geometry_a->max_aspect != geometry_b->max_aspect))
6384 if ((flags_a & GDK_HINT_RESIZE_INC) &&
6385 (geometry_a->width_inc != geometry_b->width_inc ||
6386 geometry_a->height_inc != geometry_b->height_inc))
6389 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
6390 geometry_a->win_gravity != geometry_b->win_gravity)
6397 _gtk_window_constrain_size (GtkWindow *window,
6403 GtkWindowGeometryInfo *info;
6405 g_return_if_fail (GTK_IS_WINDOW (window));
6407 info = window->geometry_info;
6410 GdkWindowHints flags = info->last.flags;
6411 GdkGeometry *geometry = &info->last.geometry;
6413 gtk_window_constrain_size (window,
6424 gtk_window_constrain_size (GtkWindow *window,
6425 GdkGeometry *geometry,
6432 gdk_window_constrain_size (geometry, flags, width, height,
6433 new_width, new_height);
6436 /* Compute the set of geometry hints and flags for a window
6437 * based on the application set geometry, and requisiition
6438 * of the window. gtk_widget_size_request() must have been
6442 gtk_window_compute_hints (GtkWindow *window,
6443 GdkGeometry *new_geometry,
6447 gint extra_width = 0;
6448 gint extra_height = 0;
6449 GtkWindowGeometryInfo *geometry_info;
6450 GtkRequisition requisition;
6452 widget = GTK_WIDGET (window);
6454 gtk_widget_get_child_requisition (widget, &requisition);
6455 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
6459 *new_flags = geometry_info->mask;
6460 *new_geometry = geometry_info->geometry;
6467 if (geometry_info && geometry_info->widget)
6469 GtkRequisition child_requisition;
6471 /* FIXME: This really isn't right. It gets the min size wrong and forces
6472 * callers to do horrible hacks like set a huge usize on the child requisition
6473 * to get the base size right. We really want to find the answers to:
6475 * - If the geometry widget was infinitely big, how much extra space
6476 * would be needed for the stuff around it.
6478 * - If the geometry widget was infinitely small, how big would the
6479 * window still have to be.
6481 * Finding these answers would be a bit of a mess here. (Bug #68668)
6483 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
6485 extra_width = widget->requisition.width - child_requisition.width;
6486 extra_height = widget->requisition.height - child_requisition.height;
6489 /* We don't want to set GDK_HINT_POS in here, we just set it
6490 * in gtk_window_move_resize() when we want the position
6494 if (*new_flags & GDK_HINT_BASE_SIZE)
6496 new_geometry->base_width += extra_width;
6497 new_geometry->base_height += extra_height;
6499 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
6500 (*new_flags & GDK_HINT_RESIZE_INC) &&
6501 ((extra_width != 0) || (extra_height != 0)))
6503 *new_flags |= GDK_HINT_BASE_SIZE;
6505 new_geometry->base_width = extra_width;
6506 new_geometry->base_height = extra_height;
6509 if (*new_flags & GDK_HINT_MIN_SIZE)
6511 if (new_geometry->min_width < 0)
6512 new_geometry->min_width = requisition.width;
6514 new_geometry->min_width += extra_width;
6516 if (new_geometry->min_height < 0)
6517 new_geometry->min_height = requisition.height;
6519 new_geometry->min_height += extra_height;
6521 else if (!window->allow_shrink)
6523 *new_flags |= GDK_HINT_MIN_SIZE;
6525 new_geometry->min_width = requisition.width;
6526 new_geometry->min_height = requisition.height;
6529 if (*new_flags & GDK_HINT_MAX_SIZE)
6531 if (new_geometry->max_width < 0)
6532 new_geometry->max_width = requisition.width;
6534 new_geometry->max_width += extra_width;
6536 if (new_geometry->max_height < 0)
6537 new_geometry->max_height = requisition.height;
6539 new_geometry->max_height += extra_height;
6541 else if (!window->allow_grow)
6543 *new_flags |= GDK_HINT_MAX_SIZE;
6545 new_geometry->max_width = requisition.width;
6546 new_geometry->max_height = requisition.height;
6549 *new_flags |= GDK_HINT_WIN_GRAVITY;
6550 new_geometry->win_gravity = window->gravity;
6553 /***********************
6554 * Redrawing functions *
6555 ***********************/
6558 gtk_window_paint (GtkWidget *widget,
6561 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
6562 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
6566 gtk_window_expose (GtkWidget *widget,
6567 GdkEventExpose *event)
6569 if (!GTK_WIDGET_APP_PAINTABLE (widget))
6570 gtk_window_paint (widget, &event->area);
6572 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event)
6573 return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event);
6579 * gtk_window_set_has_frame:
6580 * @window: a #GtkWindow
6581 * @setting: a boolean
6583 * (Note: this is a special-purpose function for the framebuffer port,
6584 * that causes GTK+ to draw its own window border. For most applications,
6585 * you want gtk_window_set_decorated() instead, which tells the window
6586 * manager whether to draw the window border.)
6588 * If this function is called on a window with setting of %TRUE, before
6589 * it is realized or showed, it will have a "frame" window around
6590 * @window->window, accessible in @window->frame. Using the signal
6591 * frame_event you can receive all events targeted at the frame.
6593 * This function is used by the linux-fb port to implement managed
6594 * windows, but it could conceivably be used by X-programs that
6595 * want to do their own window decorations.
6599 gtk_window_set_has_frame (GtkWindow *window,
6602 g_return_if_fail (GTK_IS_WINDOW (window));
6603 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
6605 window->has_frame = setting != FALSE;
6609 * gtk_window_get_has_frame:
6610 * @window: a #GtkWindow
6612 * Accessor for whether the window has a frame window exterior to
6613 * @window->window. Gets the value set by gtk_window_set_has_frame ().
6615 * Return value: %TRUE if a frame has been added to the window
6616 * via gtk_window_set_has_frame().
6619 gtk_window_get_has_frame (GtkWindow *window)
6621 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6623 return window->has_frame;
6627 * gtk_window_set_frame_dimensions:
6628 * @window: a #GtkWindow that has a frame
6629 * @left: The width of the left border
6630 * @top: The height of the top border
6631 * @right: The width of the right border
6632 * @bottom: The height of the bottom border
6634 * (Note: this is a special-purpose function intended for the framebuffer
6635 * port; see gtk_window_set_has_frame(). It will have no effect on the
6636 * window border drawn by the window manager, which is the normal
6637 * case when using the X Window system.)
6639 * For windows with frames (see gtk_window_set_has_frame()) this function
6640 * can be used to change the size of the frame border.
6643 gtk_window_set_frame_dimensions (GtkWindow *window,
6651 g_return_if_fail (GTK_IS_WINDOW (window));
6653 widget = GTK_WIDGET (window);
6655 if (window->frame_left == left &&
6656 window->frame_top == top &&
6657 window->frame_right == right &&
6658 window->frame_bottom == bottom)
6661 window->frame_left = left;
6662 window->frame_top = top;
6663 window->frame_right = right;
6664 window->frame_bottom = bottom;
6666 if (GTK_WIDGET_REALIZED (widget) && window->frame)
6668 gint width = widget->allocation.width + left + right;
6669 gint height = widget->allocation.height + top + bottom;
6670 gdk_window_resize (window->frame, width, height);
6671 gtk_decorated_window_move_resize_window (window,
6673 widget->allocation.width,
6674 widget->allocation.height);
6679 * gtk_window_present:
6680 * @window: a #GtkWindow
6682 * Presents a window to the user. This may mean raising the window
6683 * in the stacking order, deiconifying it, moving it to the current
6684 * desktop, and/or giving it the keyboard focus, possibly dependent
6685 * on the user's platform, window manager, and preferences.
6687 * If @window is hidden, this function calls gtk_widget_show()
6690 * This function should be used when the user tries to open a window
6691 * that's already open. Say for example the preferences dialog is
6692 * currently open, and the user chooses Preferences from the menu
6693 * a second time; use gtk_window_present() to move the already-open dialog
6694 * where the user can see it.
6696 * If you are calling this function in response to a user interaction,
6697 * it is preferable to use gtk_window_present_with_time().
6701 gtk_window_present (GtkWindow *window)
6703 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6707 * gtk_window_present_with_time:
6708 * @window: a #GtkWindow
6709 * @timestamp: the timestamp of the user interaction (typically a
6710 * button or key press event) which triggered this call
6712 * Presents a window to the user in response to a user interaction.
6713 * If you need to present a window without a timestamp, use
6714 * gtk_window_present(). See gtk_window_present() for details.
6719 gtk_window_present_with_time (GtkWindow *window,
6724 g_return_if_fail (GTK_IS_WINDOW (window));
6726 widget = GTK_WIDGET (window);
6728 if (GTK_WIDGET_VISIBLE (window))
6730 g_assert (widget->window != NULL);
6732 gdk_window_show (widget->window);
6734 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
6735 if (timestamp == GDK_CURRENT_TIME)
6737 #ifdef GDK_WINDOWING_X11
6738 GdkDisplay *display;
6740 display = gtk_widget_get_display (GTK_WIDGET (window));
6741 timestamp = gdk_x11_display_get_user_time (display);
6743 timestamp = gtk_get_current_event_time ();
6747 gdk_window_focus (widget->window, timestamp);
6751 gtk_widget_show (widget);
6756 * gtk_window_iconify:
6757 * @window: a #GtkWindow
6759 * Asks to iconify (i.e. minimize) the specified @window. Note that
6760 * you shouldn't assume the window is definitely iconified afterward,
6761 * because other entities (e.g. the user or <link
6762 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
6763 * again, or there may not be a window manager in which case
6764 * iconification isn't possible, etc. But normally the window will end
6765 * up iconified. Just don't write code that crashes if not.
6767 * It's permitted to call this function before showing a window,
6768 * in which case the window will be iconified before it ever appears
6771 * You can track iconification via the "window-state-event" signal
6776 gtk_window_iconify (GtkWindow *window)
6779 GdkWindow *toplevel;
6781 g_return_if_fail (GTK_IS_WINDOW (window));
6783 widget = GTK_WIDGET (window);
6785 window->iconify_initially = TRUE;
6788 toplevel = window->frame;
6790 toplevel = widget->window;
6792 if (toplevel != NULL)
6793 gdk_window_iconify (toplevel);
6797 * gtk_window_deiconify:
6798 * @window: a #GtkWindow
6800 * Asks to deiconify (i.e. unminimize) the specified @window. Note
6801 * that you shouldn't assume the window is definitely deiconified
6802 * afterward, because other entities (e.g. the user or <link
6803 * linkend="gtk-X11-arch">window manager</link>) could iconify it
6804 * again before your code which assumes deiconification gets to run.
6806 * You can track iconification via the "window-state-event" signal
6810 gtk_window_deiconify (GtkWindow *window)
6813 GdkWindow *toplevel;
6815 g_return_if_fail (GTK_IS_WINDOW (window));
6817 widget = GTK_WIDGET (window);
6819 window->iconify_initially = FALSE;
6822 toplevel = window->frame;
6824 toplevel = widget->window;
6826 if (toplevel != NULL)
6827 gdk_window_deiconify (toplevel);
6832 * @window: a #GtkWindow
6834 * Asks to stick @window, which means that it will appear on all user
6835 * desktops. Note that you shouldn't assume the window is definitely
6836 * stuck afterward, because other entities (e.g. the user or <link
6837 * linkend="gtk-X11-arch">window manager</link>) could unstick it
6838 * again, and some window managers do not support sticking
6839 * windows. But normally the window will end up stuck. Just don't
6840 * write code that crashes if not.
6842 * It's permitted to call this function before showing a window.
6844 * You can track stickiness via the "window-state-event" signal
6849 gtk_window_stick (GtkWindow *window)
6852 GdkWindow *toplevel;
6854 g_return_if_fail (GTK_IS_WINDOW (window));
6856 widget = GTK_WIDGET (window);
6858 window->stick_initially = TRUE;
6861 toplevel = window->frame;
6863 toplevel = widget->window;
6865 if (toplevel != NULL)
6866 gdk_window_stick (toplevel);
6870 * gtk_window_unstick:
6871 * @window: a #GtkWindow
6873 * Asks to unstick @window, which means that it will appear on only
6874 * one of the user's desktops. Note that you shouldn't assume the
6875 * window is definitely unstuck afterward, because other entities
6876 * (e.g. the user or <link linkend="gtk-X11-arch">window
6877 * manager</link>) could stick it again. But normally the window will
6878 * end up stuck. Just don't write code that crashes if not.
6880 * You can track stickiness via the "window-state-event" signal
6885 gtk_window_unstick (GtkWindow *window)
6888 GdkWindow *toplevel;
6890 g_return_if_fail (GTK_IS_WINDOW (window));
6892 widget = GTK_WIDGET (window);
6894 window->stick_initially = FALSE;
6897 toplevel = window->frame;
6899 toplevel = widget->window;
6901 if (toplevel != NULL)
6902 gdk_window_unstick (toplevel);
6906 * gtk_window_maximize:
6907 * @window: a #GtkWindow
6909 * Asks to maximize @window, so that it becomes full-screen. Note that
6910 * you shouldn't assume the window is definitely maximized afterward,
6911 * because other entities (e.g. the user or <link
6912 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
6913 * again, and not all window managers support maximization. But
6914 * normally the window will end up maximized. Just don't write code
6915 * that crashes if not.
6917 * It's permitted to call this function before showing a window,
6918 * in which case the window will be maximized when it appears onscreen
6921 * You can track maximization via the "window-state-event" signal
6926 gtk_window_maximize (GtkWindow *window)
6929 GdkWindow *toplevel;
6931 g_return_if_fail (GTK_IS_WINDOW (window));
6933 widget = GTK_WIDGET (window);
6935 window->maximize_initially = TRUE;
6938 toplevel = window->frame;
6940 toplevel = widget->window;
6942 if (toplevel != NULL)
6943 gdk_window_maximize (toplevel);
6947 * gtk_window_unmaximize:
6948 * @window: a #GtkWindow
6950 * Asks to unmaximize @window. Note that you shouldn't assume the
6951 * window is definitely unmaximized afterward, because other entities
6952 * (e.g. the user or <link linkend="gtk-X11-arch">window
6953 * manager</link>) could maximize it again, and not all window
6954 * managers honor requests to unmaximize. But normally the window will
6955 * end up unmaximized. Just don't write code that crashes if not.
6957 * You can track maximization via the "window-state-event" signal
6962 gtk_window_unmaximize (GtkWindow *window)
6965 GdkWindow *toplevel;
6967 g_return_if_fail (GTK_IS_WINDOW (window));
6969 widget = GTK_WIDGET (window);
6971 window->maximize_initially = FALSE;
6974 toplevel = window->frame;
6976 toplevel = widget->window;
6978 if (toplevel != NULL)
6979 gdk_window_unmaximize (toplevel);
6983 * gtk_window_fullscreen:
6984 * @window: a #GtkWindow
6986 * Asks to place @window in the fullscreen state. Note that you
6987 * shouldn't assume the window is definitely full screen afterward,
6988 * because other entities (e.g. the user or <link
6989 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
6990 * again, and not all window managers honor requests to fullscreen
6991 * windows. But normally the window will end up fullscreen. Just
6992 * don't write code that crashes if not.
6994 * You can track the fullscreen state via the "window-state-event" signal
7000 gtk_window_fullscreen (GtkWindow *window)
7003 GdkWindow *toplevel;
7004 GtkWindowPrivate *priv;
7006 g_return_if_fail (GTK_IS_WINDOW (window));
7008 widget = GTK_WIDGET (window);
7009 priv = GTK_WINDOW_GET_PRIVATE (window);
7011 priv->fullscreen_initially = TRUE;
7014 toplevel = window->frame;
7016 toplevel = widget->window;
7018 if (toplevel != NULL)
7019 gdk_window_fullscreen (toplevel);
7023 * gtk_window_unfullscreen:
7024 * @window: a #GtkWindow
7026 * Asks to toggle off the fullscreen state for @window. Note that you
7027 * shouldn't assume the window is definitely not full screen
7028 * afterward, because other entities (e.g. the user or <link
7029 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7030 * again, and not all window managers honor requests to unfullscreen
7031 * windows. But normally the window will end up restored to its normal
7032 * state. Just don't write code that crashes if not.
7034 * You can track the fullscreen state via the "window-state-event" signal
7040 gtk_window_unfullscreen (GtkWindow *window)
7043 GdkWindow *toplevel;
7044 GtkWindowPrivate *priv;
7046 g_return_if_fail (GTK_IS_WINDOW (window));
7048 widget = GTK_WIDGET (window);
7049 priv = GTK_WINDOW_GET_PRIVATE (window);
7051 priv->fullscreen_initially = FALSE;
7054 toplevel = window->frame;
7056 toplevel = widget->window;
7058 if (toplevel != NULL)
7059 gdk_window_unfullscreen (toplevel);
7063 * gtk_window_set_keep_above:
7064 * @window: a #GtkWindow
7065 * @setting: whether to keep @window above other windows
7067 * Asks to keep @window above, so that it stays on top. Note that
7068 * you shouldn't assume the window is definitely above afterward,
7069 * because other entities (e.g. the user or <link
7070 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7071 * and not all window managers support keeping windows above. But
7072 * normally the window will end kept above. Just don't write code
7073 * that crashes if not.
7075 * It's permitted to call this function before showing a window,
7076 * in which case the window will be kept above when it appears onscreen
7079 * You can track the above state via the "window-state-event" signal
7082 * Note that, according to the <ulink
7083 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7084 * Manager Hints</ulink> specification, the above state is mainly meant
7085 * for user preferences and should not be used by applications e.g. for
7086 * drawing attention to their dialogs.
7091 gtk_window_set_keep_above (GtkWindow *window,
7095 GtkWindowPrivate *priv;
7096 GdkWindow *toplevel;
7098 g_return_if_fail (GTK_IS_WINDOW (window));
7100 widget = GTK_WIDGET (window);
7101 priv = GTK_WINDOW_GET_PRIVATE (window);
7103 priv->above_initially = setting != FALSE;
7105 priv->below_initially = FALSE;
7108 toplevel = window->frame;
7110 toplevel = widget->window;
7112 if (toplevel != NULL)
7113 gdk_window_set_keep_above (toplevel, setting);
7117 * gtk_window_set_keep_below:
7118 * @window: a #GtkWindow
7119 * @setting: whether to keep @window below other windows
7121 * Asks to keep @window below, so that it stays in bottom. Note that
7122 * you shouldn't assume the window is definitely below afterward,
7123 * because other entities (e.g. the user or <link
7124 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7125 * and not all window managers support putting windows below. But
7126 * normally the window will be kept below. Just don't write code
7127 * that crashes if not.
7129 * It's permitted to call this function before showing a window,
7130 * in which case the window will be kept below when it appears onscreen
7133 * You can track the below state via the "window-state-event" signal
7136 * Note that, according to the <ulink
7137 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7138 * Manager Hints</ulink> specification, the above state is mainly meant
7139 * for user preferences and should not be used by applications e.g. for
7140 * drawing attention to their dialogs.
7145 gtk_window_set_keep_below (GtkWindow *window,
7149 GtkWindowPrivate *priv;
7150 GdkWindow *toplevel;
7152 g_return_if_fail (GTK_IS_WINDOW (window));
7154 widget = GTK_WIDGET (window);
7155 priv = GTK_WINDOW_GET_PRIVATE (window);
7157 priv->below_initially = setting != FALSE;
7159 priv->above_initially = FALSE;
7162 toplevel = window->frame;
7164 toplevel = widget->window;
7166 if (toplevel != NULL)
7167 gdk_window_set_keep_below (toplevel, setting);
7171 * gtk_window_set_resizable:
7172 * @window: a #GtkWindow
7173 * @resizable: %TRUE if the user can resize this window
7175 * Sets whether the user can resize a window. Windows are user resizable
7179 gtk_window_set_resizable (GtkWindow *window,
7182 g_return_if_fail (GTK_IS_WINDOW (window));
7184 gtk_window_set_policy_internal (window, FALSE, resizable, FALSE);
7188 * gtk_window_get_resizable:
7189 * @window: a #GtkWindow
7191 * Gets the value set by gtk_window_set_resizable().
7193 * Return value: %TRUE if the user can resize the window
7196 gtk_window_get_resizable (GtkWindow *window)
7198 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7200 /* allow_grow is most likely to indicate the semantic concept we
7201 * mean by "resizable" (and will be a reliable indicator if
7202 * set_policy() hasn't been called)
7204 return window->allow_grow;
7208 * gtk_window_set_gravity:
7209 * @window: a #GtkWindow
7210 * @gravity: window gravity
7212 * Window gravity defines the meaning of coordinates passed to
7213 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7216 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7217 * typically "do what you mean."
7221 gtk_window_set_gravity (GtkWindow *window,
7224 g_return_if_fail (GTK_IS_WINDOW (window));
7226 if (gravity != window->gravity)
7228 window->gravity = gravity;
7230 /* gtk_window_move_resize() will adapt gravity
7232 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7234 g_object_notify (G_OBJECT (window), "gravity");
7239 * gtk_window_get_gravity:
7240 * @window: a #GtkWindow
7242 * Gets the value set by gtk_window_set_gravity().
7244 * Return value: window gravity
7247 gtk_window_get_gravity (GtkWindow *window)
7249 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7251 return window->gravity;
7255 * gtk_window_begin_resize_drag:
7256 * @window: a #GtkWindow
7257 * @button: mouse button that initiated the drag
7258 * @edge: position of the resize control
7259 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7260 * @root_y: Y position where the user clicked to initiate the drag
7261 * @timestamp: timestamp from the click event that initiated the drag
7263 * Starts resizing a window. This function is used if an application
7264 * has window resizing controls. When GDK can support it, the resize
7265 * will be done using the standard mechanism for the <link
7266 * linkend="gtk-X11-arch">window manager</link> or windowing
7267 * system. Otherwise, GDK will try to emulate window resizing,
7268 * potentially not all that well, depending on the windowing system.
7272 gtk_window_begin_resize_drag (GtkWindow *window,
7280 GdkWindow *toplevel;
7282 g_return_if_fail (GTK_IS_WINDOW (window));
7283 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
7285 widget = GTK_WIDGET (window);
7288 toplevel = window->frame;
7290 toplevel = widget->window;
7292 gdk_window_begin_resize_drag (toplevel,
7299 * gtk_window_get_frame_dimensions:
7300 * @window: a #GtkWindow
7301 * @left: location to store the width of the frame at the left, or %NULL
7302 * @top: location to store the height of the frame at the top, or %NULL
7303 * @right: location to store the width of the frame at the returns, or %NULL
7304 * @bottom: location to store the height of the frame at the bottom, or %NULL
7306 * (Note: this is a special-purpose function intended for the
7307 * framebuffer port; see gtk_window_set_has_frame(). It will not
7308 * return the size of the window border drawn by the <link
7309 * linkend="gtk-X11-arch">window manager</link>, which is the normal
7310 * case when using a windowing system. See
7311 * gdk_window_get_frame_extents() to get the standard window border
7314 * Retrieves the dimensions of the frame window for this toplevel.
7315 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
7318 gtk_window_get_frame_dimensions (GtkWindow *window,
7324 g_return_if_fail (GTK_IS_WINDOW (window));
7327 *left = window->frame_left;
7329 *top = window->frame_top;
7331 *right = window->frame_right;
7333 *bottom = window->frame_bottom;
7337 * gtk_window_begin_move_drag:
7338 * @window: a #GtkWindow
7339 * @button: mouse button that initiated the drag
7340 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7341 * @root_y: Y position where the user clicked to initiate the drag
7342 * @timestamp: timestamp from the click event that initiated the drag
7344 * Starts moving a window. This function is used if an application has
7345 * window movement grips. When GDK can support it, the window movement
7346 * will be done using the standard mechanism for the <link
7347 * linkend="gtk-X11-arch">window manager</link> or windowing
7348 * system. Otherwise, GDK will try to emulate window movement,
7349 * potentially not all that well, depending on the windowing system.
7353 gtk_window_begin_move_drag (GtkWindow *window,
7360 GdkWindow *toplevel;
7362 g_return_if_fail (GTK_IS_WINDOW (window));
7363 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
7365 widget = GTK_WIDGET (window);
7368 toplevel = window->frame;
7370 toplevel = widget->window;
7372 gdk_window_begin_move_drag (toplevel,
7379 * gtk_window_set_screen:
7380 * @window: a #GtkWindow.
7381 * @screen: a #GdkScreen.
7383 * Sets the #GdkScreen where the @window is displayed; if
7384 * the window is already mapped, it will be unmapped, and
7385 * then remapped on the new screen.
7390 gtk_window_set_screen (GtkWindow *window,
7394 GdkScreen *previous_screen;
7395 gboolean was_mapped;
7397 g_return_if_fail (GTK_IS_WINDOW (window));
7398 g_return_if_fail (GDK_IS_SCREEN (screen));
7400 if (screen == window->screen)
7403 widget = GTK_WIDGET (window);
7405 previous_screen = window->screen;
7406 was_mapped = GTK_WIDGET_MAPPED (widget);
7409 gtk_widget_unmap (widget);
7410 if (GTK_WIDGET_REALIZED (widget))
7411 gtk_widget_unrealize (widget);
7413 gtk_window_free_key_hash (window);
7414 window->screen = screen;
7415 gtk_widget_reset_rc_styles (widget);
7416 if (screen != previous_screen)
7418 g_signal_handlers_disconnect_by_func (previous_screen,
7419 gtk_window_on_composited_changed, window);
7420 g_signal_connect (screen, "composited-changed",
7421 G_CALLBACK (gtk_window_on_composited_changed), window);
7423 _gtk_widget_propagate_screen_changed (widget, previous_screen);
7424 _gtk_widget_propagate_composited_changed (widget);
7426 g_object_notify (G_OBJECT (window), "screen");
7429 gtk_widget_map (widget);
7433 gtk_window_on_composited_changed (GdkScreen *screen,
7436 gtk_widget_queue_draw (GTK_WIDGET (window));
7438 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
7442 gtk_window_check_screen (GtkWindow *window)
7445 return window->screen;
7448 g_warning ("Screen for GtkWindow not set; you must always set\n"
7449 "a screen for a GtkWindow before using the window");
7455 * gtk_window_get_screen:
7456 * @window: a #GtkWindow.
7458 * Returns the #GdkScreen associated with @window.
7460 * Return value: a #GdkScreen.
7465 gtk_window_get_screen (GtkWindow *window)
7467 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
7469 return window->screen;
7473 * gtk_window_is_active:
7474 * @window: a #GtkWindow
7476 * Returns whether the window is part of the current active toplevel.
7477 * (That is, the toplevel window receiving keystrokes.)
7478 * The return value is %TRUE if the window is active toplevel
7479 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
7480 * You might use this function if you wanted to draw a widget
7481 * differently in an active window from a widget in an inactive window.
7482 * See gtk_window_has_toplevel_focus()
7484 * Return value: %TRUE if the window part of the current active window.
7489 gtk_window_is_active (GtkWindow *window)
7491 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7493 return window->is_active;
7497 * gtk_window_has_toplevel_focus:
7498 * @window: a #GtkWindow
7500 * Returns whether the input focus is within this GtkWindow.
7501 * For real toplevel windows, this is identical to gtk_window_is_active(),
7502 * but for embedded windows, like #GtkPlug, the results will differ.
7504 * Return value: %TRUE if the input focus is within this GtkWindow
7509 gtk_window_has_toplevel_focus (GtkWindow *window)
7511 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7513 return window->has_toplevel_focus;
7517 gtk_window_group_class_init (GtkWindowGroupClass *klass)
7522 gtk_window_group_get_type (void)
7524 static GType window_group_type = 0;
7526 if (!window_group_type)
7528 const GTypeInfo window_group_info =
7530 sizeof (GtkWindowGroupClass),
7531 NULL, /* base_init */
7532 NULL, /* base_finalize */
7533 (GClassInitFunc) gtk_window_group_class_init,
7534 NULL, /* class_finalize */
7535 NULL, /* class_data */
7536 sizeof (GtkWindowGroup),
7537 0, /* n_preallocs */
7538 (GInstanceInitFunc) NULL,
7541 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
7542 &window_group_info, 0);
7545 return window_group_type;
7549 * gtk_window_group_new:
7551 * Creates a new #GtkWindowGroup object. Grabs added with
7552 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
7554 * Return value: a new #GtkWindowGroup.
7557 gtk_window_group_new (void)
7559 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
7563 window_group_cleanup_grabs (GtkWindowGroup *group,
7567 GSList *to_remove = NULL;
7569 tmp_list = group->grabs;
7572 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
7573 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
7574 tmp_list = tmp_list->next;
7579 gtk_grab_remove (to_remove->data);
7580 g_object_unref (to_remove->data);
7581 to_remove = g_slist_delete_link (to_remove, to_remove);
7586 * gtk_window_group_add_window:
7587 * @window_group: a #GtkWindowGroup
7588 * @window: the #GtkWindow to add
7590 * Adds a window to a #GtkWindowGroup.
7593 gtk_window_group_add_window (GtkWindowGroup *window_group,
7596 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7597 g_return_if_fail (GTK_IS_WINDOW (window));
7599 if (window->group != window_group)
7601 g_object_ref (window);
7602 g_object_ref (window_group);
7605 gtk_window_group_remove_window (window->group, window);
7607 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
7609 window->group = window_group;
7611 g_object_unref (window);
7616 * gtk_window_group_remove_window:
7617 * @window_group: a #GtkWindowGroup
7618 * @window: the #GtkWindow to remove
7620 * Removes a window from a #GtkWindowGroup.
7623 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7626 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7627 g_return_if_fail (GTK_IS_WINDOW (window));
7628 g_return_if_fail (window->group == window_group);
7630 g_object_ref (window);
7632 window_group_cleanup_grabs (window_group, window);
7633 window->group = NULL;
7635 g_object_unref (window_group);
7636 g_object_unref (window);
7640 * gtk_window_group_list_windows:
7641 * @window_group: a #GtkWindowGroup
7643 * Returns a list of the #GtkWindows that belong to @window_group.
7645 * Returns: A newly-allocated list of windows inside the group.
7650 gtk_window_group_list_windows (GtkWindowGroup *window_group)
7652 GList *toplevels, *toplevel, *group_windows;
7654 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
7656 group_windows = NULL;
7657 toplevels = gtk_window_list_toplevels ();
7659 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
7661 GtkWindow *window = toplevel->data;
7663 if (window_group == window->group)
7664 group_windows = g_list_prepend (group_windows, window);
7667 return g_list_reverse (group_windows);
7671 * gtk_window_get_group:
7672 * @window: a #GtkWindow, or %NULL
7674 * Returns the group for @window or the default group, if
7675 * @window is %NULL or if @window does not have an explicit
7678 * Returns: the #GtkWindowGroup for a window or the default group
7683 gtk_window_get_group (GtkWindow *window)
7685 if (window && window->group)
7686 return window->group;
7689 static GtkWindowGroup *default_group = NULL;
7692 default_group = gtk_window_group_new ();
7694 return default_group;
7698 /* Return the current grab widget of the given group
7701 _gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
7703 if (window_group->grabs)
7704 return GTK_WIDGET (window_group->grabs->data);
7709 Derived from XParseGeometry() in XFree86
7711 Copyright 1985, 1986, 1987,1998 The Open Group
7713 All Rights Reserved.
7715 The above copyright notice and this permission notice shall be included
7716 in all copies or substantial portions of the Software.
7718 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
7719 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7720 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7721 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
7722 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7723 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
7724 OTHER DEALINGS IN THE SOFTWARE.
7726 Except as contained in this notice, the name of The Open Group shall
7727 not be used in advertising or otherwise to promote the sale, use or
7728 other dealings in this Software without prior written authorization
7729 from The Open Group.
7734 * XParseGeometry parses strings of the form
7735 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
7736 * width, height, xoffset, and yoffset are unsigned integers.
7737 * Example: "=80x24+300-49"
7738 * The equal sign is optional.
7739 * It returns a bitmask that indicates which of the four values
7740 * were actually found in the string. For each value found,
7741 * the corresponding argument is updated; for each value
7742 * not found, the corresponding argument is left unchanged.
7745 /* The following code is from Xlib, and is minimally modified, so we
7746 * can track any upstream changes if required. Don't change this
7747 * code. Or if you do, put in a huge comment marking which thing
7752 read_int (gchar *string,
7760 else if (*string == '-')
7766 for (; (*string >= '0') && (*string <= '9'); string++)
7768 result = (result * 10) + (*string - '0');
7780 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
7781 * value (x, y, width, height) was found in the parsed string.
7783 #define NoValue 0x0000
7784 #define XValue 0x0001
7785 #define YValue 0x0002
7786 #define WidthValue 0x0004
7787 #define HeightValue 0x0008
7788 #define AllValues 0x000F
7789 #define XNegative 0x0010
7790 #define YNegative 0x0020
7792 /* Try not to reformat/modify, so we can compare/sync with X sources */
7794 gtk_XParseGeometry (const char *string,
7797 unsigned int *width,
7798 unsigned int *height)
7802 unsigned int tempWidth, tempHeight;
7804 char *nextCharacter;
7806 /* These initializations are just to silence gcc */
7812 if ( (string == NULL) || (*string == '\0')) return(mask);
7814 string++; /* ignore possible '=' at beg of geometry spec */
7816 strind = (char *)string;
7817 if (*strind != '+' && *strind != '-' && *strind != 'x') {
7818 tempWidth = read_int(strind, &nextCharacter);
7819 if (strind == nextCharacter)
7821 strind = nextCharacter;
7825 if (*strind == 'x' || *strind == 'X') {
7827 tempHeight = read_int(strind, &nextCharacter);
7828 if (strind == nextCharacter)
7830 strind = nextCharacter;
7831 mask |= HeightValue;
7834 if ((*strind == '+') || (*strind == '-')) {
7835 if (*strind == '-') {
7837 tempX = -read_int(strind, &nextCharacter);
7838 if (strind == nextCharacter)
7840 strind = nextCharacter;
7846 tempX = read_int(strind, &nextCharacter);
7847 if (strind == nextCharacter)
7849 strind = nextCharacter;
7852 if ((*strind == '+') || (*strind == '-')) {
7853 if (*strind == '-') {
7855 tempY = -read_int(strind, &nextCharacter);
7856 if (strind == nextCharacter)
7858 strind = nextCharacter;
7865 tempY = read_int(strind, &nextCharacter);
7866 if (strind == nextCharacter)
7868 strind = nextCharacter;
7874 /* If strind isn't at the end of the string the it's an invalid
7875 geometry specification. */
7877 if (*strind != '\0') return (0);
7883 if (mask & WidthValue)
7885 if (mask & HeightValue)
7886 *height = tempHeight;
7891 * gtk_window_parse_geometry:
7892 * @window: a #GtkWindow
7893 * @geometry: geometry string
7895 * Parses a standard X Window System geometry string - see the
7896 * manual page for X (type 'man X') for details on this.
7897 * gtk_window_parse_geometry() does work on all GTK+ ports
7898 * including Win32 but is primarily intended for an X environment.
7900 * If either a size or a position can be extracted from the
7901 * geometry string, gtk_window_parse_geometry() returns %TRUE
7902 * and calls gtk_window_set_default_size() and/or gtk_window_move()
7903 * to resize/move the window.
7905 * If gtk_window_parse_geometry() returns %TRUE, it will also
7906 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
7907 * indicating to the window manager that the size/position of
7908 * the window was user-specified. This causes most window
7909 * managers to honor the geometry.
7911 * Note that for gtk_window_parse_geometry() to work as expected, it has
7912 * to be called when the window has its "final" size, i.e. after calling
7913 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
7916 * #include <gtk/gtk.h>
7919 * fill_with_content (GtkWidget *vbox)
7921 * /* fill with content... */
7925 * main (int argc, char *argv[])
7927 * GtkWidget *window, *vbox;
7928 * GdkGeometry size_hints = {
7929 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
7932 * gtk_init (&argc, &argv);
7934 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7935 * vbox = gtk_vbox_new (FALSE, 0);
7937 * gtk_container_add (GTK_CONTAINER (window), vbox);
7938 * fill_with_content (vbox);
7939 * gtk_widget_show_all (vbox);
7941 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
7944 * GDK_HINT_MIN_SIZE |
7945 * GDK_HINT_BASE_SIZE |
7946 * GDK_HINT_RESIZE_INC);
7950 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
7951 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
7954 * gtk_widget_show_all (window);
7961 * Return value: %TRUE if string was parsed successfully
7964 gtk_window_parse_geometry (GtkWindow *window,
7965 const gchar *geometry)
7967 gint result, x = 0, y = 0;
7970 gboolean size_set, pos_set;
7973 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7974 g_return_val_if_fail (geometry != NULL, FALSE);
7976 screen = gtk_window_check_screen (window);
7978 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
7981 if ((result & WidthValue) || (result & HeightValue))
7983 gtk_window_set_default_size_internal (window,
7984 TRUE, result & WidthValue ? w : -1,
7985 TRUE, result & HeightValue ? h : -1,
7990 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
7992 grav = GDK_GRAVITY_NORTH_WEST;
7994 if ((result & XNegative) && (result & YNegative))
7995 grav = GDK_GRAVITY_SOUTH_EAST;
7996 else if (result & XNegative)
7997 grav = GDK_GRAVITY_NORTH_EAST;
7998 else if (result & YNegative)
7999 grav = GDK_GRAVITY_SOUTH_WEST;
8001 if ((result & XValue) == 0)
8004 if ((result & YValue) == 0)
8007 if (grav == GDK_GRAVITY_SOUTH_WEST ||
8008 grav == GDK_GRAVITY_SOUTH_EAST)
8009 y = gdk_screen_get_height (screen) - h + y;
8011 if (grav == GDK_GRAVITY_SOUTH_EAST ||
8012 grav == GDK_GRAVITY_NORTH_EAST)
8013 x = gdk_screen_get_width (screen) - w + x;
8015 /* we don't let you put a window offscreen; maybe some people would
8016 * prefer to be able to, but it's kind of a bogus thing to do.
8025 if ((result & XValue) || (result & YValue))
8027 gtk_window_set_gravity (window, grav);
8028 gtk_window_move (window, x, y);
8032 if (size_set || pos_set)
8034 /* Set USSize, USPosition hints */
8035 GtkWindowGeometryInfo *info;
8037 info = gtk_window_get_geometry_info (window, TRUE);
8040 info->mask |= GDK_HINT_USER_POS;
8042 info->mask |= GDK_HINT_USER_SIZE;
8049 gtk_window_mnemonic_hash_foreach (guint keyval,
8055 GtkWindowKeysForeachFunc func;
8059 (*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
8063 _gtk_window_keys_foreach (GtkWindow *window,
8064 GtkWindowKeysForeachFunc func,
8068 GtkMnemonicHash *mnemonic_hash;
8072 GtkWindowKeysForeachFunc func;
8076 info.window = window;
8078 info.func_data = func_data;
8080 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8082 _gtk_mnemonic_hash_foreach (mnemonic_hash,
8083 gtk_window_mnemonic_hash_foreach, &info);
8085 groups = gtk_accel_groups_from_object (G_OBJECT (window));
8088 GtkAccelGroup *group = groups->data;
8091 for (i = 0; i < group->n_accels; i++)
8093 GtkAccelKey *key = &group->priv_accels[i].key;
8096 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8099 groups = groups->next;
8104 gtk_window_keys_changed (GtkWindow *window)
8106 gtk_window_free_key_hash (window);
8107 gtk_window_get_key_hash (window);
8110 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8112 struct _GtkWindowKeyEntry
8116 guint is_mnemonic : 1;
8120 window_key_entry_destroy (gpointer data)
8122 g_slice_free (GtkWindowKeyEntry, data);
8126 add_to_key_hash (GtkWindow *window,
8128 GdkModifierType modifiers,
8129 gboolean is_mnemonic,
8132 GtkKeyHash *key_hash = data;
8134 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8136 entry->keyval = keyval;
8137 entry->modifiers = modifiers;
8138 entry->is_mnemonic = is_mnemonic;
8140 /* GtkAccelGroup stores lowercased accelerators. To deal
8141 * with this, if <Shift> was specified, uppercase.
8143 if (modifiers & GDK_SHIFT_MASK)
8145 if (keyval == GDK_Tab)
8146 keyval = GDK_ISO_Left_Tab;
8148 keyval = gdk_keyval_to_upper (keyval);
8151 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
8155 gtk_window_get_key_hash (GtkWindow *window)
8157 GdkScreen *screen = gtk_window_check_screen (window);
8158 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8163 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
8164 (GDestroyNotify)window_key_entry_destroy);
8165 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
8166 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
8172 gtk_window_free_key_hash (GtkWindow *window)
8174 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8177 _gtk_key_hash_free (key_hash);
8178 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
8183 * gtk_window_activate_key:
8184 * @window: a #GtkWindow
8185 * @event: a #GdkEventKey
8187 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
8188 * called by the default ::key_press_event handler for toplevel windows,
8189 * however in some cases it may be useful to call this directly when
8190 * overriding the standard key handling for a toplevel window.
8192 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
8195 gtk_window_activate_key (GtkWindow *window,
8198 GtkKeyHash *key_hash;
8199 GtkWindowKeyEntry *found_entry = NULL;
8200 gboolean enable_mnemonics;
8201 gboolean enable_accels;
8203 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8204 g_return_val_if_fail (event != NULL, FALSE);
8206 key_hash = gtk_window_get_key_hash (window);
8211 GSList *entries = _gtk_key_hash_lookup (key_hash,
8212 event->hardware_keycode,
8214 gtk_accelerator_get_default_mod_mask (),
8217 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
8218 "gtk-enable-mnemonics", &enable_mnemonics,
8219 "gtk-enable-accels", &enable_accels,
8222 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
8224 GtkWindowKeyEntry *entry = tmp_list->data;
8225 if (entry->is_mnemonic)
8227 if (enable_mnemonics)
8229 found_entry = entry;
8235 if (enable_accels && !found_entry)
8237 found_entry = entry;
8242 g_slist_free (entries);
8247 if (found_entry->is_mnemonic)
8249 if (enable_mnemonics)
8250 return gtk_window_mnemonic_activate (window, found_entry->keyval,
8251 found_entry->modifiers);
8256 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
8257 found_entry->modifiers);
8265 window_update_has_focus (GtkWindow *window)
8267 GtkWidget *widget = GTK_WIDGET (window);
8268 gboolean has_focus = window->has_toplevel_focus && window->is_active;
8270 if (has_focus != window->has_focus)
8272 window->has_focus = has_focus;
8276 if (window->focus_widget &&
8277 window->focus_widget != widget &&
8278 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
8279 do_focus_change (window->focus_widget, TRUE);
8283 if (window->focus_widget &&
8284 window->focus_widget != widget &&
8285 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
8286 do_focus_change (window->focus_widget, FALSE);
8292 * _gtk_window_set_is_active:
8293 * @window: a #GtkWindow
8294 * @is_active: %TRUE if the window is in the currently active toplevel
8296 * Internal function that sets whether the #GtkWindow is part
8297 * of the currently active toplevel window (taking into account inter-process
8301 _gtk_window_set_is_active (GtkWindow *window,
8304 g_return_if_fail (GTK_IS_WINDOW (window));
8306 is_active = is_active != FALSE;
8308 if (is_active != window->is_active)
8310 window->is_active = is_active;
8311 window_update_has_focus (window);
8313 g_object_notify (G_OBJECT (window), "is-active");
8318 * _gtk_windwo_set_is_toplevel:
8319 * @window: a #GtkWindow
8320 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
8321 * parent of the root window); %FALSE if it is not (for example, for an
8322 * in-process, parented GtkPlug)
8324 * Internal function used by #GtkPlug when it gets parented/unparented by a
8325 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
8326 * global list of toplevel windows.
8329 _gtk_window_set_is_toplevel (GtkWindow *window,
8330 gboolean is_toplevel)
8332 if (GTK_WIDGET_TOPLEVEL (window))
8333 g_assert (g_list_find (toplevel_list, window) != NULL);
8335 g_assert (g_list_find (toplevel_list, window) == NULL);
8337 if (is_toplevel == GTK_WIDGET_TOPLEVEL (window))
8342 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
8343 toplevel_list = g_slist_prepend (toplevel_list, window);
8347 GTK_WIDGET_UNSET_FLAGS (window, GTK_TOPLEVEL);
8348 toplevel_list = g_slist_remove (toplevel_list, window);
8353 * _gtk_window_set_has_toplevel_focus:
8354 * @window: a #GtkWindow
8355 * @has_toplevel_focus: %TRUE if the in
8357 * Internal function that sets whether the keyboard focus for the
8358 * toplevel window (taking into account inter-process embedding.)
8361 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
8362 gboolean has_toplevel_focus)
8364 g_return_if_fail (GTK_IS_WINDOW (window));
8366 has_toplevel_focus = has_toplevel_focus != FALSE;
8368 if (has_toplevel_focus != window->has_toplevel_focus)
8370 window->has_toplevel_focus = has_toplevel_focus;
8371 window_update_has_focus (window);
8373 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
8378 * gtk_window_set_auto_startup_notification:
8379 * @setting: %TRUE to automatically do startup notification
8381 * By default, after showing the first #GtkWindow, GTK+ calls
8382 * gdk_notify_startup_complete(). Call this function to disable
8383 * the automatic startup notification. You might do this if your
8384 * first window is a splash screen, and you want to delay notification
8385 * until after your real main window has been shown, for example.
8387 * In that example, you would disable startup notification
8388 * temporarily, show your splash screen, then re-enable it so that
8389 * showing the main window would automatically result in notification.
8394 gtk_window_set_auto_startup_notification (gboolean setting)
8396 disable_startup_notification = !setting;
8399 #if defined (G_OS_WIN32) && !defined (_WIN64)
8401 #undef gtk_window_set_icon_from_file
8404 gtk_window_set_icon_from_file (GtkWindow *window,
8405 const gchar *filename,
8408 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
8411 if (utf8_filename == NULL)
8414 retval = gtk_window_set_icon_from_file_utf8 (window, utf8_filename, err);
8416 g_free (utf8_filename);
8421 #undef gtk_window_set_default_icon_from_file
8424 gtk_window_set_default_icon_from_file (const gchar *filename,
8427 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
8430 if (utf8_filename == NULL)
8433 retval = gtk_window_set_default_icon_from_file_utf8 (utf8_filename, err);
8435 g_free (utf8_filename);
8442 #define __GTK_WINDOW_C__
8443 #include "gtkaliasdef.c"