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"
51 #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;
187 GdkWindowTypeHint type_hint;
194 static void gtk_window_dispose (GObject *object);
195 static void gtk_window_destroy (GtkObject *object);
196 static void gtk_window_finalize (GObject *object);
197 static void gtk_window_show (GtkWidget *widget);
198 static void gtk_window_hide (GtkWidget *widget);
199 static void gtk_window_map (GtkWidget *widget);
200 static void gtk_window_unmap (GtkWidget *widget);
201 static void gtk_window_realize (GtkWidget *widget);
202 static void gtk_window_unrealize (GtkWidget *widget);
203 static void gtk_window_size_request (GtkWidget *widget,
204 GtkRequisition *requisition);
205 static void gtk_window_size_allocate (GtkWidget *widget,
206 GtkAllocation *allocation);
207 static gint gtk_window_event (GtkWidget *widget,
209 static gboolean gtk_window_map_event (GtkWidget *widget,
211 static gboolean gtk_window_frame_event (GtkWindow *window,
213 static gint gtk_window_configure_event (GtkWidget *widget,
214 GdkEventConfigure *event);
215 static gint gtk_window_key_press_event (GtkWidget *widget,
217 static gint gtk_window_key_release_event (GtkWidget *widget,
219 static gint gtk_window_enter_notify_event (GtkWidget *widget,
220 GdkEventCrossing *event);
221 static gint gtk_window_leave_notify_event (GtkWidget *widget,
222 GdkEventCrossing *event);
223 static gint gtk_window_focus_in_event (GtkWidget *widget,
224 GdkEventFocus *event);
225 static gint gtk_window_focus_out_event (GtkWidget *widget,
226 GdkEventFocus *event);
227 static gint gtk_window_client_event (GtkWidget *widget,
228 GdkEventClient *event);
229 static void gtk_window_check_resize (GtkContainer *container);
230 static gint gtk_window_focus (GtkWidget *widget,
231 GtkDirectionType direction);
232 static void gtk_window_real_set_focus (GtkWindow *window,
235 static void gtk_window_real_activate_default (GtkWindow *window);
236 static void gtk_window_real_activate_focus (GtkWindow *window);
237 static void gtk_window_move_focus (GtkWindow *window,
238 GtkDirectionType dir);
239 static void gtk_window_keys_changed (GtkWindow *window);
240 static void gtk_window_paint (GtkWidget *widget,
242 static gint gtk_window_expose (GtkWidget *widget,
243 GdkEventExpose *event);
244 static void gtk_window_unset_transient_for (GtkWindow *window);
245 static void gtk_window_transient_parent_realized (GtkWidget *parent,
247 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
250 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
252 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
255 static void gtk_window_move_resize (GtkWindow *window);
256 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
258 GdkGeometry *geometry_b,
260 static void gtk_window_constrain_size (GtkWindow *window,
261 GdkGeometry *geometry,
267 static void gtk_window_constrain_position (GtkWindow *window,
272 static void gtk_window_compute_hints (GtkWindow *window,
273 GdkGeometry *new_geometry,
275 static void gtk_window_compute_configure_request (GtkWindow *window,
276 GdkRectangle *request,
277 GdkGeometry *geometry,
280 static void gtk_window_set_default_size_internal (GtkWindow *window,
281 gboolean change_width,
283 gboolean change_height,
285 gboolean is_geometry);
287 static void update_themed_icon (GtkIconTheme *theme,
289 static GList *icon_list_from_theme (GtkWidget *widget,
291 static void gtk_window_realize_icon (GtkWindow *window);
292 static void gtk_window_unrealize_icon (GtkWindow *window);
294 static void gtk_window_notify_keys_changed (GtkWindow *window);
295 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
296 static void gtk_window_free_key_hash (GtkWindow *window);
297 static void gtk_window_on_composited_changed (GdkScreen *screen,
300 static GSList *toplevel_list = NULL;
301 static guint window_signals[LAST_SIGNAL] = { 0 };
302 static GList *default_icon_list = NULL;
303 static gchar *default_icon_name = NULL;
304 static guint default_icon_serial = 0;
305 static gboolean disable_startup_notification = FALSE;
306 static gboolean sent_startup_notification = FALSE;
308 static GQuark quark_gtk_embedded = 0;
309 static GQuark quark_gtk_window_key_hash = 0;
310 static GQuark quark_gtk_window_default_icon_pixmap = 0;
311 static GQuark quark_gtk_window_icon_info = 0;
313 static void gtk_window_set_property (GObject *object,
317 static void gtk_window_get_property (GObject *object,
323 G_DEFINE_TYPE (GtkWindow, gtk_window, GTK_TYPE_BIN)
326 add_tab_bindings (GtkBindingSet *binding_set,
327 GdkModifierType modifiers,
328 GtkDirectionType direction)
330 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
332 GTK_TYPE_DIRECTION_TYPE, direction);
333 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
335 GTK_TYPE_DIRECTION_TYPE, direction);
339 add_arrow_bindings (GtkBindingSet *binding_set,
341 GtkDirectionType direction)
343 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
345 gtk_binding_entry_add_signal (binding_set, keysym, 0,
347 GTK_TYPE_DIRECTION_TYPE, direction);
348 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
350 GTK_TYPE_DIRECTION_TYPE, direction);
351 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
353 GTK_TYPE_DIRECTION_TYPE, direction);
354 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
356 GTK_TYPE_DIRECTION_TYPE, direction);
360 extract_time_from_startup_id (const gchar* startup_id)
362 gchar *timestr = g_strrstr (startup_id, "_TIME");
363 guint32 retval = GDK_CURRENT_TIME;
370 /* Skip past the "_TIME" part */
373 timestamp = strtoul (timestr, &end, 0);
374 if (end != timestr && errno == 0)
382 startup_id_is_fake (const gchar* startup_id)
384 return strncmp (startup_id, "_TIME", 5) == 0;
388 gtk_window_class_init (GtkWindowClass *klass)
390 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
391 GtkObjectClass *object_class;
392 GtkWidgetClass *widget_class;
393 GtkContainerClass *container_class;
394 GtkBindingSet *binding_set;
396 object_class = (GtkObjectClass*) klass;
397 widget_class = (GtkWidgetClass*) klass;
398 container_class = (GtkContainerClass*) klass;
400 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
401 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
402 quark_gtk_window_default_icon_pixmap = g_quark_from_static_string ("gtk-window-default-icon-pixmap");
403 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
405 gobject_class->dispose = gtk_window_dispose;
406 gobject_class->finalize = gtk_window_finalize;
408 gobject_class->set_property = gtk_window_set_property;
409 gobject_class->get_property = gtk_window_get_property;
411 object_class->destroy = gtk_window_destroy;
413 widget_class->show = gtk_window_show;
414 widget_class->hide = gtk_window_hide;
415 widget_class->map = gtk_window_map;
416 widget_class->map_event = gtk_window_map_event;
417 widget_class->unmap = gtk_window_unmap;
418 widget_class->realize = gtk_window_realize;
419 widget_class->unrealize = gtk_window_unrealize;
420 widget_class->size_request = gtk_window_size_request;
421 widget_class->size_allocate = gtk_window_size_allocate;
422 widget_class->configure_event = gtk_window_configure_event;
423 widget_class->key_press_event = gtk_window_key_press_event;
424 widget_class->key_release_event = gtk_window_key_release_event;
425 widget_class->enter_notify_event = gtk_window_enter_notify_event;
426 widget_class->leave_notify_event = gtk_window_leave_notify_event;
427 widget_class->focus_in_event = gtk_window_focus_in_event;
428 widget_class->focus_out_event = gtk_window_focus_out_event;
429 widget_class->client_event = gtk_window_client_event;
430 widget_class->focus = gtk_window_focus;
432 widget_class->expose_event = gtk_window_expose;
434 container_class->check_resize = gtk_window_check_resize;
436 klass->set_focus = gtk_window_real_set_focus;
437 klass->frame_event = gtk_window_frame_event;
439 klass->activate_default = gtk_window_real_activate_default;
440 klass->activate_focus = gtk_window_real_activate_focus;
441 klass->move_focus = gtk_window_move_focus;
442 klass->keys_changed = gtk_window_keys_changed;
444 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
447 g_object_class_install_property (gobject_class,
449 g_param_spec_enum ("type",
451 P_("The type of the window"),
452 GTK_TYPE_WINDOW_TYPE,
454 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
456 g_object_class_install_property (gobject_class,
458 g_param_spec_string ("title",
460 P_("The title of the window"),
462 GTK_PARAM_READWRITE));
464 g_object_class_install_property (gobject_class,
466 g_param_spec_string ("role",
468 P_("Unique identifier for the window to be used when restoring a session"),
470 GTK_PARAM_READWRITE));
473 * GtkWindow:startup-id:
475 * The :startup-id is a write-only property for setting window's
476 * startup notification identifier. See gtk_window_set_startup_id()
481 g_object_class_install_property (gobject_class,
483 g_param_spec_string ("startup-id",
485 P_("Unique startup identifier for the window used by startup-notification"),
487 GTK_PARAM_WRITABLE));
489 g_object_class_install_property (gobject_class,
491 g_param_spec_boolean ("allow-shrink",
493 /* xgettext:no-c-format */
494 P_("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
496 GTK_PARAM_READWRITE));
498 g_object_class_install_property (gobject_class,
500 g_param_spec_boolean ("allow-grow",
502 P_("If TRUE, users can expand the window beyond its minimum size"),
504 GTK_PARAM_READWRITE));
506 g_object_class_install_property (gobject_class,
508 g_param_spec_boolean ("resizable",
510 P_("If TRUE, users can resize the window"),
512 GTK_PARAM_READWRITE));
514 g_object_class_install_property (gobject_class,
516 g_param_spec_boolean ("modal",
518 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
520 GTK_PARAM_READWRITE));
522 g_object_class_install_property (gobject_class,
524 g_param_spec_enum ("window-position",
525 P_("Window Position"),
526 P_("The initial position of the window"),
527 GTK_TYPE_WINDOW_POSITION,
529 GTK_PARAM_READWRITE));
531 g_object_class_install_property (gobject_class,
533 g_param_spec_int ("default-width",
535 P_("The default width of the window, used when initially showing the window"),
539 GTK_PARAM_READWRITE));
541 g_object_class_install_property (gobject_class,
543 g_param_spec_int ("default-height",
544 P_("Default Height"),
545 P_("The default height of the window, used when initially showing the window"),
549 GTK_PARAM_READWRITE));
551 g_object_class_install_property (gobject_class,
552 PROP_DESTROY_WITH_PARENT,
553 g_param_spec_boolean ("destroy-with-parent",
554 P_("Destroy with Parent"),
555 P_("If this window should be destroyed when the parent is destroyed"),
557 GTK_PARAM_READWRITE));
559 g_object_class_install_property (gobject_class,
561 g_param_spec_object ("icon",
563 P_("Icon for this window"),
565 GTK_PARAM_READWRITE));
568 * GtkWindow:icon-name:
570 * The :icon-name property specifies the name of the themed icon to
571 * use as the window icon. See #GtkIconTheme for more details.
575 g_object_class_install_property (gobject_class,
577 g_param_spec_string ("icon-name",
579 P_("Name of the themed icon for this window"),
581 GTK_PARAM_READWRITE));
583 g_object_class_install_property (gobject_class,
585 g_param_spec_object ("screen",
587 P_("The screen where this window will be displayed"),
589 GTK_PARAM_READWRITE));
591 g_object_class_install_property (gobject_class,
593 g_param_spec_boolean ("is-active",
595 P_("Whether the toplevel is the current active window"),
597 GTK_PARAM_READABLE));
599 g_object_class_install_property (gobject_class,
600 PROP_HAS_TOPLEVEL_FOCUS,
601 g_param_spec_boolean ("has-toplevel-focus",
602 P_("Focus in Toplevel"),
603 P_("Whether the input focus is within this GtkWindow"),
605 GTK_PARAM_READABLE));
607 g_object_class_install_property (gobject_class,
609 g_param_spec_enum ("type-hint",
611 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
612 GDK_TYPE_WINDOW_TYPE_HINT,
613 GDK_WINDOW_TYPE_HINT_NORMAL,
614 GTK_PARAM_READWRITE));
616 g_object_class_install_property (gobject_class,
617 PROP_SKIP_TASKBAR_HINT,
618 g_param_spec_boolean ("skip-taskbar-hint",
620 P_("TRUE if the window should not be in the task bar."),
622 GTK_PARAM_READWRITE));
624 g_object_class_install_property (gobject_class,
625 PROP_SKIP_PAGER_HINT,
626 g_param_spec_boolean ("skip-pager-hint",
628 P_("TRUE if the window should not be in the pager."),
630 GTK_PARAM_READWRITE));
632 g_object_class_install_property (gobject_class,
634 g_param_spec_boolean ("urgency-hint",
636 P_("TRUE if the window should be brought to the user's attention."),
638 GTK_PARAM_READWRITE));
641 * GtkWindow:accept-focus-hint:
643 * Whether the window should receive the input focus.
647 g_object_class_install_property (gobject_class,
649 g_param_spec_boolean ("accept-focus",
651 P_("TRUE if the window should receive the input focus."),
653 GTK_PARAM_READWRITE));
656 * GtkWindow:focus-on-map-hint:
658 * Whether the window should receive the input focus when mapped.
662 g_object_class_install_property (gobject_class,
664 g_param_spec_boolean ("focus-on-map",
666 P_("TRUE if the window should receive the input focus when mapped."),
668 GTK_PARAM_READWRITE));
671 * GtkWindow:decorated:
673 * Whether the window should be decorated by the window manager.
677 g_object_class_install_property (gobject_class,
679 g_param_spec_boolean ("decorated",
681 P_("Whether the window should be decorated by the window manager"),
683 GTK_PARAM_READWRITE));
686 * GtkWindow:deletable:
688 * Whether the window frame should have a close button.
692 g_object_class_install_property (gobject_class,
694 g_param_spec_boolean ("deletable",
696 P_("Whether the window frame should have a close button"),
698 GTK_PARAM_READWRITE));
704 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
705 * more details about window gravity.
709 g_object_class_install_property (gobject_class,
711 g_param_spec_enum ("gravity",
713 P_("The window gravity of the window"),
715 GDK_GRAVITY_NORTH_WEST,
716 GTK_PARAM_READWRITE));
720 * GtkWindow:transient-for:
722 * The transient parent of the window. See gtk_window_set_transient_for() for
723 * more details about transient windows.
727 g_object_class_install_property (gobject_class,
729 g_param_spec_object ("transient-for",
730 P_("Transient for Window"),
731 P_("The transient parent of the dialog"),
733 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
737 * The requested opacity of the window. See gtk_window_set_opacity() for
738 * more details about window opacity.
742 g_object_class_install_property (gobject_class,
744 g_param_spec_double ("opacity",
745 P_("Opacity for Window"),
746 P_("The opacity of the window, from 0 to 1"),
750 GTK_PARAM_READWRITE));
752 window_signals[SET_FOCUS] =
753 g_signal_new (I_("set_focus"),
754 G_TYPE_FROM_CLASS (gobject_class),
756 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
758 _gtk_marshal_VOID__OBJECT,
762 window_signals[FRAME_EVENT] =
763 g_signal_new (I_("frame_event"),
764 G_TYPE_FROM_CLASS (gobject_class),
766 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
767 _gtk_boolean_handled_accumulator, NULL,
768 _gtk_marshal_BOOLEAN__BOXED,
772 window_signals[ACTIVATE_FOCUS] =
773 g_signal_new (I_("activate_focus"),
774 G_TYPE_FROM_CLASS (gobject_class),
775 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
776 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
778 _gtk_marshal_VOID__VOID,
782 window_signals[ACTIVATE_DEFAULT] =
783 g_signal_new (I_("activate_default"),
784 G_TYPE_FROM_CLASS (gobject_class),
785 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
786 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
788 _gtk_marshal_VOID__VOID,
792 window_signals[MOVE_FOCUS] =
793 g_signal_new (I_("move_focus"),
794 G_TYPE_FROM_CLASS (gobject_class),
795 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
796 G_STRUCT_OFFSET (GtkWindowClass, move_focus),
798 _gtk_marshal_VOID__ENUM,
801 GTK_TYPE_DIRECTION_TYPE);
803 window_signals[KEYS_CHANGED] =
804 g_signal_new (I_("keys_changed"),
805 G_TYPE_FROM_CLASS (gobject_class),
807 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
809 _gtk_marshal_VOID__VOID,
817 binding_set = gtk_binding_set_by_class (klass);
819 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
820 "activate_focus", 0);
821 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
822 "activate_focus", 0);
824 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
825 "activate_default", 0);
827 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
828 "activate_default", 0);
830 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
831 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
832 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
833 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
835 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
836 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
837 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
838 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
842 gtk_window_init (GtkWindow *window)
844 GdkColormap *colormap;
845 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
847 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
848 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
850 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
852 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
854 window->title = NULL;
855 window->wmclass_name = g_strdup (g_get_prgname ());
856 window->wmclass_class = g_strdup (gdk_get_program_class ());
857 window->wm_role = NULL;
858 window->geometry_info = NULL;
859 window->type = GTK_WINDOW_TOPLEVEL;
860 window->focus_widget = NULL;
861 window->default_widget = NULL;
862 window->configure_request_count = 0;
863 window->allow_shrink = FALSE;
864 window->allow_grow = TRUE;
865 window->configure_notify_received = FALSE;
866 window->position = GTK_WIN_POS_NONE;
867 window->need_default_size = TRUE;
868 window->need_default_position = TRUE;
869 window->modal = FALSE;
870 window->frame = NULL;
871 window->has_frame = FALSE;
872 window->frame_left = 0;
873 window->frame_right = 0;
874 window->frame_top = 0;
875 window->frame_bottom = 0;
876 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
877 window->gravity = GDK_GRAVITY_NORTH_WEST;
878 window->decorated = TRUE;
879 window->mnemonic_modifier = GDK_MOD1_MASK;
880 window->screen = gdk_screen_get_default ();
882 priv->accept_focus = TRUE;
883 priv->focus_on_map = TRUE;
884 priv->deletable = TRUE;
885 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
887 priv->startup_id = NULL;
889 colormap = _gtk_widget_peek_colormap ();
891 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
893 g_object_ref_sink (window);
894 window->has_user_ref_count = TRUE;
895 toplevel_list = g_slist_prepend (toplevel_list, window);
897 gtk_decorated_window_init (window);
899 g_signal_connect (window->screen, "composited_changed",
900 G_CALLBACK (gtk_window_on_composited_changed), window);
904 gtk_window_set_property (GObject *object,
911 window = GTK_WINDOW (object);
916 window->type = g_value_get_enum (value);
919 gtk_window_set_title (window, g_value_get_string (value));
922 gtk_window_set_role (window, g_value_get_string (value));
924 case PROP_STARTUP_ID:
925 gtk_window_set_startup_id (window, g_value_get_string (value));
927 case PROP_ALLOW_SHRINK:
928 window->allow_shrink = g_value_get_boolean (value);
929 gtk_widget_queue_resize (GTK_WIDGET (window));
931 case PROP_ALLOW_GROW:
932 window->allow_grow = g_value_get_boolean (value);
933 gtk_widget_queue_resize (GTK_WIDGET (window));
934 g_object_notify (G_OBJECT (window), "resizable");
937 window->allow_grow = g_value_get_boolean (value);
938 gtk_widget_queue_resize (GTK_WIDGET (window));
939 g_object_notify (G_OBJECT (window), "allow-grow");
942 gtk_window_set_modal (window, g_value_get_boolean (value));
945 gtk_window_set_position (window, g_value_get_enum (value));
947 case PROP_DEFAULT_WIDTH:
948 gtk_window_set_default_size_internal (window,
949 TRUE, g_value_get_int (value),
952 case PROP_DEFAULT_HEIGHT:
953 gtk_window_set_default_size_internal (window,
955 TRUE, g_value_get_int (value), FALSE);
957 case PROP_DESTROY_WITH_PARENT:
958 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
961 gtk_window_set_icon (window,
962 g_value_get_object (value));
965 gtk_window_set_icon_name (window, g_value_get_string (value));
968 gtk_window_set_screen (window, g_value_get_object (value));
971 gtk_window_set_type_hint (window,
972 g_value_get_enum (value));
974 case PROP_SKIP_TASKBAR_HINT:
975 gtk_window_set_skip_taskbar_hint (window,
976 g_value_get_boolean (value));
978 case PROP_SKIP_PAGER_HINT:
979 gtk_window_set_skip_pager_hint (window,
980 g_value_get_boolean (value));
982 case PROP_URGENCY_HINT:
983 gtk_window_set_urgency_hint (window,
984 g_value_get_boolean (value));
986 case PROP_ACCEPT_FOCUS:
987 gtk_window_set_accept_focus (window,
988 g_value_get_boolean (value));
990 case PROP_FOCUS_ON_MAP:
991 gtk_window_set_focus_on_map (window,
992 g_value_get_boolean (value));
995 gtk_window_set_decorated (window, g_value_get_boolean (value));
998 gtk_window_set_deletable (window, g_value_get_boolean (value));
1001 gtk_window_set_gravity (window, g_value_get_enum (value));
1003 case PROP_TRANSIENT_FOR:
1004 gtk_window_set_transient_for (window, g_value_get_object (value));
1007 gtk_window_set_opacity (window, g_value_get_double (value));
1015 gtk_window_get_property (GObject *object,
1021 GtkWindowPrivate *priv;
1023 window = GTK_WINDOW (object);
1024 priv = GTK_WINDOW_GET_PRIVATE (window);
1028 GtkWindowGeometryInfo *info;
1030 g_value_set_enum (value, window->type);
1033 g_value_set_string (value, window->wm_role);
1036 g_value_set_string (value, window->title);
1038 case PROP_ALLOW_SHRINK:
1039 g_value_set_boolean (value, window->allow_shrink);
1041 case PROP_ALLOW_GROW:
1042 g_value_set_boolean (value, window->allow_grow);
1044 case PROP_RESIZABLE:
1045 g_value_set_boolean (value, window->allow_grow);
1048 g_value_set_boolean (value, window->modal);
1051 g_value_set_enum (value, window->position);
1053 case PROP_DEFAULT_WIDTH:
1054 info = gtk_window_get_geometry_info (window, FALSE);
1056 g_value_set_int (value, -1);
1058 g_value_set_int (value, info->default_width);
1060 case PROP_DEFAULT_HEIGHT:
1061 info = gtk_window_get_geometry_info (window, FALSE);
1063 g_value_set_int (value, -1);
1065 g_value_set_int (value, info->default_height);
1067 case PROP_DESTROY_WITH_PARENT:
1068 g_value_set_boolean (value, window->destroy_with_parent);
1071 g_value_set_object (value, gtk_window_get_icon (window));
1073 case PROP_ICON_NAME:
1074 g_value_set_string (value, gtk_window_get_icon_name (window));
1077 g_value_set_object (value, window->screen);
1079 case PROP_IS_ACTIVE:
1080 g_value_set_boolean (value, window->is_active);
1082 case PROP_HAS_TOPLEVEL_FOCUS:
1083 g_value_set_boolean (value, window->has_toplevel_focus);
1085 case PROP_TYPE_HINT:
1086 g_value_set_enum (value, priv->type_hint);
1088 case PROP_SKIP_TASKBAR_HINT:
1089 g_value_set_boolean (value,
1090 gtk_window_get_skip_taskbar_hint (window));
1092 case PROP_SKIP_PAGER_HINT:
1093 g_value_set_boolean (value,
1094 gtk_window_get_skip_pager_hint (window));
1096 case PROP_URGENCY_HINT:
1097 g_value_set_boolean (value,
1098 gtk_window_get_urgency_hint (window));
1100 case PROP_ACCEPT_FOCUS:
1101 g_value_set_boolean (value,
1102 gtk_window_get_accept_focus (window));
1104 case PROP_FOCUS_ON_MAP:
1105 g_value_set_boolean (value,
1106 gtk_window_get_focus_on_map (window));
1108 case PROP_DECORATED:
1109 g_value_set_boolean (value, gtk_window_get_decorated (window));
1111 case PROP_DELETABLE:
1112 g_value_set_boolean (value, gtk_window_get_deletable (window));
1115 g_value_set_enum (value, gtk_window_get_gravity (window));
1117 case PROP_TRANSIENT_FOR:
1118 g_value_set_object (value, gtk_window_get_transient_for (window));
1121 g_value_set_double (value, gtk_window_get_opacity (window));
1124 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1131 * @type: type of window
1133 * Creates a new #GtkWindow, which is a toplevel window that can
1134 * contain other widgets. Nearly always, the type of the window should
1135 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1136 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1137 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1138 * dialogs, though in some other toolkits dialogs are called "popups".
1139 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1140 * On X11, popup windows are not controlled by the <link
1141 * linkend="gtk-X11-arch">window manager</link>.
1143 * If you simply want an undecorated window (no window borders), use
1144 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1146 * Return value: a new #GtkWindow.
1149 gtk_window_new (GtkWindowType type)
1153 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1155 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1157 window->type = type;
1159 return GTK_WIDGET (window);
1163 * gtk_window_set_title:
1164 * @window: a #GtkWindow
1165 * @title: title of the window
1167 * Sets the title of the #GtkWindow. The title of a window will be
1168 * displayed in its title bar; on the X Window System, the title bar
1169 * is rendered by the <link linkend="gtk-X11-arch">window
1170 * manager</link>, so exactly how the title appears to users may vary
1171 * according to a user's exact configuration. The title should help a
1172 * user distinguish this window from other windows they may have
1173 * open. A good title might include the application name and current
1174 * document filename, for example.
1178 gtk_window_set_title (GtkWindow *window,
1183 g_return_if_fail (GTK_IS_WINDOW (window));
1185 new_title = g_strdup (title);
1186 g_free (window->title);
1187 window->title = new_title;
1189 if (GTK_WIDGET_REALIZED (window))
1191 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
1193 gtk_decorated_window_set_title (window, title);
1196 g_object_notify (G_OBJECT (window), "title");
1200 * gtk_window_get_title:
1201 * @window: a #GtkWindow
1203 * Retrieves the title of the window. See gtk_window_set_title().
1205 * Return value: the title of the window, or %NULL if none has
1206 * been set explicitely. The returned string is owned by the widget
1207 * and must not be modified or freed.
1209 G_CONST_RETURN gchar *
1210 gtk_window_get_title (GtkWindow *window)
1212 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1214 return window->title;
1218 * gtk_window_set_wmclass:
1219 * @window: a #GtkWindow
1220 * @wmclass_name: window name hint
1221 * @wmclass_class: window class hint
1223 * Don't use this function. It sets the X Window System "class" and
1224 * "name" hints for a window. According to the ICCCM, you should
1225 * always set these to the same value for all windows in an
1226 * application, and GTK+ sets them to that value by default, so calling
1227 * this function is sort of pointless. However, you may want to call
1228 * gtk_window_set_role() on each window in your application, for the
1229 * benefit of the session manager. Setting the role allows the window
1230 * manager to restore window positions when loading a saved session.
1234 gtk_window_set_wmclass (GtkWindow *window,
1235 const gchar *wmclass_name,
1236 const gchar *wmclass_class)
1238 g_return_if_fail (GTK_IS_WINDOW (window));
1240 g_free (window->wmclass_name);
1241 window->wmclass_name = g_strdup (wmclass_name);
1243 g_free (window->wmclass_class);
1244 window->wmclass_class = g_strdup (wmclass_class);
1246 if (GTK_WIDGET_REALIZED (window))
1247 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1251 * gtk_window_set_role:
1252 * @window: a #GtkWindow
1253 * @role: unique identifier for the window to be used when restoring a session
1255 * This function is only useful on X11, not with other GTK+ targets.
1257 * In combination with the window title, the window role allows a
1258 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1259 * same" window when an application is restarted. So for example you
1260 * might set the "toolbox" role on your app's toolbox window, so that
1261 * when the user restarts their session, the window manager can put
1262 * the toolbox back in the same place.
1264 * If a window already has a unique title, you don't need to set the
1265 * role, since the WM can use the title to identify the window when
1266 * restoring the session.
1270 gtk_window_set_role (GtkWindow *window,
1275 g_return_if_fail (GTK_IS_WINDOW (window));
1277 new_role = g_strdup (role);
1278 g_free (window->wm_role);
1279 window->wm_role = new_role;
1281 if (GTK_WIDGET_REALIZED (window))
1282 gdk_window_set_role (GTK_WIDGET (window)->window, window->wm_role);
1284 g_object_notify (G_OBJECT (window), "role");
1288 * gtk_window_set_startup_id:
1289 * @window: a #GtkWindow
1290 * @startup_id: a string with startup-notification identifier
1292 * Startup notification identifiers are used by desktop environment to
1293 * track application startup, to provide user feedback and other
1294 * features. This function changes the corresponding property on the
1295 * underlying GdkWindow. Normally, startup identifier is managed
1296 * automatically and you should only use this function in special cases
1297 * like transferring focus from other processes. You should use this
1298 * function before calling gtk_window_present() or any equivalent
1299 * function generating a window map event.
1301 * This function is only useful on X11, not with other GTK+ targets.
1306 gtk_window_set_startup_id (GtkWindow *window,
1307 const gchar *startup_id)
1309 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
1311 g_return_if_fail (GTK_IS_WINDOW (window));
1313 g_free (priv->startup_id);
1314 priv->startup_id = g_strdup (startup_id);
1316 if (GTK_WIDGET_REALIZED (window))
1318 /* Here we differentiate real and "fake" startup notification IDs,
1319 * constructed on purpose just to pass interaction timestamp
1321 if (startup_id_is_fake (priv->startup_id))
1323 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1325 gtk_window_present_with_time (window, timestamp);
1329 gdk_window_set_startup_id (GTK_WIDGET (window)->window,
1332 /* If window is mapped, terminate the startup-notification too */
1333 if (GTK_WIDGET_MAPPED (window) && !disable_startup_notification)
1334 gdk_notify_startup_complete_with_id (priv->startup_id);
1338 g_object_notify (G_OBJECT (window), "startup-id");
1342 * gtk_window_get_role:
1343 * @window: a #GtkWindow
1345 * Returns the role of the window. See gtk_window_set_role() for
1346 * further explanation.
1348 * Return value: the role of the window if set, or %NULL. The
1349 * returned is owned by the widget and must not be modified
1352 G_CONST_RETURN gchar *
1353 gtk_window_get_role (GtkWindow *window)
1355 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1357 return window->wm_role;
1361 * gtk_window_set_focus:
1362 * @window: a #GtkWindow
1363 * @focus: widget to be the new focus widget, or %NULL to unset
1364 * any focus widget for the toplevel window.
1366 * If @focus is not the current focus widget, and is focusable, sets
1367 * it as the focus widget for the window. If @focus is %NULL, unsets
1368 * the focus widget for this window. To set the focus to a particular
1369 * widget in the toplevel, it is usually more convenient to use
1370 * gtk_widget_grab_focus() instead of this function.
1373 gtk_window_set_focus (GtkWindow *window,
1376 g_return_if_fail (GTK_IS_WINDOW (window));
1379 g_return_if_fail (GTK_IS_WIDGET (focus));
1380 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1384 gtk_widget_grab_focus (focus);
1387 /* Clear the existing focus chain, so that when we focus into
1388 * the window again, we start at the beginnning.
1390 GtkWidget *widget = window->focus_widget;
1393 while (widget->parent)
1395 widget = widget->parent;
1396 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1400 _gtk_window_internal_set_focus (window, NULL);
1405 _gtk_window_internal_set_focus (GtkWindow *window,
1408 g_return_if_fail (GTK_IS_WINDOW (window));
1410 if ((window->focus_widget != focus) ||
1411 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1412 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1416 * gtk_window_set_default:
1417 * @window: a #GtkWindow
1418 * @default_widget: widget to be the default, or %NULL to unset the
1419 * default widget for the toplevel.
1421 * The default widget is the widget that's activated when the user
1422 * presses Enter in a dialog (for example). This function sets or
1423 * unsets the default widget for a #GtkWindow about. When setting
1424 * (rather than unsetting) the default widget it's generally easier to
1425 * call gtk_widget_grab_focus() on the widget. Before making a widget
1426 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1427 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1430 gtk_window_set_default (GtkWindow *window,
1431 GtkWidget *default_widget)
1433 g_return_if_fail (GTK_IS_WINDOW (window));
1436 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1438 if (window->default_widget != default_widget)
1440 GtkWidget *old_default_widget = NULL;
1443 g_object_ref (default_widget);
1445 if (window->default_widget)
1447 old_default_widget = window->default_widget;
1449 if (window->focus_widget != window->default_widget ||
1450 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1451 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1452 gtk_widget_queue_draw (window->default_widget);
1455 window->default_widget = default_widget;
1457 if (window->default_widget)
1459 if (window->focus_widget == NULL ||
1460 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1461 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1462 gtk_widget_queue_draw (window->default_widget);
1465 if (old_default_widget)
1466 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1470 g_object_notify (G_OBJECT (default_widget), "has-default");
1471 g_object_unref (default_widget);
1477 gtk_window_set_policy (GtkWindow *window,
1478 gboolean allow_shrink,
1479 gboolean allow_grow,
1480 gboolean auto_shrink)
1482 g_return_if_fail (GTK_IS_WINDOW (window));
1484 window->allow_shrink = (allow_shrink != FALSE);
1485 window->allow_grow = (allow_grow != FALSE);
1487 g_object_freeze_notify (G_OBJECT (window));
1488 g_object_notify (G_OBJECT (window), "allow-shrink");
1489 g_object_notify (G_OBJECT (window), "allow-grow");
1490 g_object_notify (G_OBJECT (window), "resizable");
1491 g_object_thaw_notify (G_OBJECT (window));
1493 gtk_widget_queue_resize (GTK_WIDGET (window));
1497 handle_keys_changed (gpointer data)
1501 window = GTK_WINDOW (data);
1503 if (window->keys_changed_handler)
1505 g_source_remove (window->keys_changed_handler);
1506 window->keys_changed_handler = 0;
1509 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1515 gtk_window_notify_keys_changed (GtkWindow *window)
1517 if (!window->keys_changed_handler)
1518 window->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1522 * gtk_window_add_accel_group:
1523 * @window: window to attach accelerator group to
1524 * @accel_group: a #GtkAccelGroup
1526 * Associate @accel_group with @window, such that calling
1527 * gtk_accel_groups_activate() on @window will activate accelerators
1531 gtk_window_add_accel_group (GtkWindow *window,
1532 GtkAccelGroup *accel_group)
1534 g_return_if_fail (GTK_IS_WINDOW (window));
1535 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1537 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1538 g_signal_connect_object (accel_group, "accel_changed",
1539 G_CALLBACK (gtk_window_notify_keys_changed),
1540 window, G_CONNECT_SWAPPED);
1544 * gtk_window_remove_accel_group:
1545 * @window: a #GtkWindow
1546 * @accel_group: a #GtkAccelGroup
1548 * Reverses the effects of gtk_window_add_accel_group().
1551 gtk_window_remove_accel_group (GtkWindow *window,
1552 GtkAccelGroup *accel_group)
1554 g_return_if_fail (GTK_IS_WINDOW (window));
1555 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1557 g_signal_handlers_disconnect_by_func (accel_group,
1558 gtk_window_notify_keys_changed,
1560 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1563 static GtkMnemonicHash *
1564 gtk_window_get_mnemonic_hash (GtkWindow *window,
1567 GtkWindowPrivate *private = GTK_WINDOW_GET_PRIVATE (window);
1568 if (!private->mnemonic_hash && create)
1569 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1571 return private->mnemonic_hash;
1575 * gtk_window_add_mnemonic:
1576 * @window: a #GtkWindow
1577 * @keyval: the mnemonic
1578 * @target: the widget that gets activated by the mnemonic
1580 * Adds a mnemonic to this window.
1583 gtk_window_add_mnemonic (GtkWindow *window,
1587 g_return_if_fail (GTK_IS_WINDOW (window));
1588 g_return_if_fail (GTK_IS_WIDGET (target));
1590 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1592 gtk_window_notify_keys_changed (window);
1596 * gtk_window_remove_mnemonic:
1597 * @window: a #GtkWindow
1598 * @keyval: the mnemonic
1599 * @target: the widget that gets activated by the mnemonic
1601 * Removes a mnemonic from this window.
1604 gtk_window_remove_mnemonic (GtkWindow *window,
1608 g_return_if_fail (GTK_IS_WINDOW (window));
1609 g_return_if_fail (GTK_IS_WIDGET (target));
1611 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
1613 gtk_window_notify_keys_changed (window);
1617 * gtk_window_mnemonic_activate:
1618 * @window: a #GtkWindow
1619 * @keyval: the mnemonic
1620 * @modifier: the modifiers
1621 * @returns: %TRUE if the activation is done.
1623 * Activates the targets associated with the mnemonic.
1626 gtk_window_mnemonic_activate (GtkWindow *window,
1628 GdkModifierType modifier)
1630 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1632 if (window->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
1634 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
1636 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
1643 * gtk_window_set_mnemonic_modifier:
1644 * @window: a #GtkWindow
1645 * @modifier: the modifier mask used to activate
1646 * mnemonics on this window.
1648 * Sets the mnemonic modifier for this window.
1651 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1652 GdkModifierType modifier)
1654 g_return_if_fail (GTK_IS_WINDOW (window));
1655 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1657 window->mnemonic_modifier = modifier;
1658 gtk_window_notify_keys_changed (window);
1662 * gtk_window_get_mnemonic_modifier:
1663 * @window: a #GtkWindow
1665 * Returns the mnemonic modifier for this window. See
1666 * gtk_window_set_mnemonic_modifier().
1668 * Return value: the modifier mask used to activate
1669 * mnemonics on this window.
1672 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1674 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1676 return window->mnemonic_modifier;
1680 * gtk_window_set_position:
1681 * @window: a #GtkWindow.
1682 * @position: a position constraint.
1684 * Sets a position constraint for this window. If the old or new
1685 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1686 * the window to be repositioned to satisfy the new constraint.
1689 gtk_window_set_position (GtkWindow *window,
1690 GtkWindowPosition position)
1692 g_return_if_fail (GTK_IS_WINDOW (window));
1694 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1695 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1697 GtkWindowGeometryInfo *info;
1699 info = gtk_window_get_geometry_info (window, TRUE);
1701 /* this flag causes us to re-request the CENTER_ALWAYS
1702 * constraint in gtk_window_move_resize(), see
1703 * comment in that function.
1705 info->position_constraints_changed = TRUE;
1707 gtk_widget_queue_resize (GTK_WIDGET (window));
1710 window->position = position;
1712 g_object_notify (G_OBJECT (window), "window-position");
1716 * gtk_window_activate_focus:
1717 * @window: a #GtkWindow
1719 * Activates the current focused widget within the window.
1721 * Return value: %TRUE if a widget got activated.
1724 gtk_window_activate_focus (GtkWindow *window)
1726 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1728 if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1729 return gtk_widget_activate (window->focus_widget);
1735 * gtk_window_get_focus:
1736 * @window: a #GtkWindow
1738 * Retrieves the current focused widget within the window.
1739 * Note that this is the widget that would have the focus
1740 * if the toplevel window focused; if the toplevel window
1741 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1742 * not be %TRUE for the widget.
1744 * Return value: the currently focused widget, or %NULL if there is none.
1747 gtk_window_get_focus (GtkWindow *window)
1749 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1751 return window->focus_widget;
1755 * gtk_window_activate_default:
1756 * @window: a #GtkWindow
1758 * Activates the default widget for the window, unless the current
1759 * focused widget has been configured to receive the default action
1760 * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
1761 * focused widget is activated.
1763 * Return value: %TRUE if a widget got activated.
1766 gtk_window_activate_default (GtkWindow *window)
1768 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1770 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1771 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1772 return gtk_widget_activate (window->default_widget);
1773 else if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1774 return gtk_widget_activate (window->focus_widget);
1780 * gtk_window_set_modal:
1781 * @window: a #GtkWindow
1782 * @modal: whether the window is modal
1784 * Sets a window modal or non-modal. Modal windows prevent interaction
1785 * with other windows in the same application. To keep modal dialogs
1786 * on top of main application windows, use
1787 * gtk_window_set_transient_for() to make the dialog transient for the
1788 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1789 * will then disallow lowering the dialog below the parent.
1794 gtk_window_set_modal (GtkWindow *window,
1797 g_return_if_fail (GTK_IS_WINDOW (window));
1799 modal = modal != FALSE;
1800 if (window->modal == modal)
1803 window->modal = modal;
1805 /* adjust desired modality state */
1806 if (GTK_WIDGET_REALIZED (window))
1808 GtkWidget *widget = GTK_WIDGET (window);
1811 gdk_window_set_modal_hint (widget->window, TRUE);
1813 gdk_window_set_modal_hint (widget->window, FALSE);
1816 if (GTK_WIDGET_VISIBLE (window))
1819 gtk_grab_add (GTK_WIDGET (window));
1821 gtk_grab_remove (GTK_WIDGET (window));
1824 g_object_notify (G_OBJECT (window), "modal");
1828 * gtk_window_get_modal:
1829 * @window: a #GtkWindow
1831 * Returns whether the window is modal. See gtk_window_set_modal().
1833 * Return value: %TRUE if the window is set to be modal and
1834 * establishes a grab when shown
1837 gtk_window_get_modal (GtkWindow *window)
1839 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1841 return window->modal;
1845 * gtk_window_list_toplevels:
1847 * Returns a list of all existing toplevel windows. The widgets
1848 * in the list are not individually referenced. If you want
1849 * to iterate through the list and perform actions involving
1850 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1851 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1852 * then unref all the widgets afterwards.
1854 * Return value: list of toplevel widgets
1857 gtk_window_list_toplevels (void)
1862 for (slist = toplevel_list; slist; slist = slist->next)
1863 list = g_list_prepend (list, slist->data);
1869 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1871 GList *embedded_windows;
1873 g_return_if_fail (GTK_IS_WINDOW (window));
1875 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
1876 if (embedded_windows)
1877 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
1878 embedded_windows = g_list_prepend (embedded_windows,
1879 GUINT_TO_POINTER (xid));
1881 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
1884 (GDestroyNotify) g_list_free : NULL);
1888 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1890 GList *embedded_windows;
1893 g_return_if_fail (GTK_IS_WINDOW (window));
1895 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
1896 if (embedded_windows)
1897 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
1899 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1902 embedded_windows = g_list_remove_link (embedded_windows, node);
1903 g_list_free_1 (node);
1906 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
1909 (GDestroyNotify) g_list_free : NULL);
1913 _gtk_window_reposition (GtkWindow *window,
1917 g_return_if_fail (GTK_IS_WINDOW (window));
1919 gtk_window_move (window, x, y);
1923 gtk_window_dispose (GObject *object)
1925 GtkWindow *window = GTK_WINDOW (object);
1927 gtk_window_set_focus (window, NULL);
1928 gtk_window_set_default (window, NULL);
1930 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
1934 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1936 gtk_widget_destroy (GTK_WIDGET (child));
1940 connect_parent_destroyed (GtkWindow *window)
1942 if (window->transient_parent)
1944 g_signal_connect (window->transient_parent,
1946 G_CALLBACK (parent_destroyed_callback),
1952 disconnect_parent_destroyed (GtkWindow *window)
1954 if (window->transient_parent)
1956 g_signal_handlers_disconnect_by_func (window->transient_parent,
1957 parent_destroyed_callback,
1963 gtk_window_transient_parent_realized (GtkWidget *parent,
1966 if (GTK_WIDGET_REALIZED (window))
1967 gdk_window_set_transient_for (window->window, parent->window);
1971 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1974 if (GTK_WIDGET_REALIZED (window))
1975 gdk_property_delete (window->window,
1976 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
1980 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
1984 gtk_window_set_screen (window, parent->screen);
1988 gtk_window_unset_transient_for (GtkWindow *window)
1990 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
1992 if (window->transient_parent)
1994 if (priv->transient_parent_group)
1995 gtk_window_group_remove_window (window->group,
1998 g_signal_handlers_disconnect_by_func (window->transient_parent,
1999 gtk_window_transient_parent_realized,
2001 g_signal_handlers_disconnect_by_func (window->transient_parent,
2002 gtk_window_transient_parent_unrealized,
2004 g_signal_handlers_disconnect_by_func (window->transient_parent,
2005 gtk_window_transient_parent_screen_changed,
2007 g_signal_handlers_disconnect_by_func (window->transient_parent,
2008 gtk_widget_destroyed,
2009 &window->transient_parent);
2011 if (window->destroy_with_parent)
2012 disconnect_parent_destroyed (window);
2014 window->transient_parent = NULL;
2015 priv->transient_parent_group = FALSE;
2020 * gtk_window_set_transient_for:
2021 * @window: a #GtkWindow
2022 * @parent: parent window
2024 * Dialog windows should be set transient for the main application
2025 * window they were spawned from. This allows <link
2026 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2027 * dialog on top of the main window, or center the dialog over the
2028 * main window. gtk_dialog_new_with_buttons() and other convenience
2029 * functions in GTK+ will sometimes call
2030 * gtk_window_set_transient_for() on your behalf.
2032 * On Windows, this function puts the child window on top of the parent,
2033 * much as the window manager would have done on X.
2037 gtk_window_set_transient_for (GtkWindow *window,
2040 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
2042 g_return_if_fail (GTK_IS_WINDOW (window));
2043 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2044 g_return_if_fail (window != parent);
2046 if (window->transient_parent)
2048 if (GTK_WIDGET_REALIZED (window) &&
2049 GTK_WIDGET_REALIZED (window->transient_parent) &&
2050 (!parent || !GTK_WIDGET_REALIZED (parent)))
2051 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
2052 GTK_WIDGET (window));
2054 gtk_window_unset_transient_for (window);
2057 window->transient_parent = parent;
2061 g_signal_connect (parent, "destroy",
2062 G_CALLBACK (gtk_widget_destroyed),
2063 &window->transient_parent);
2064 g_signal_connect (parent, "realize",
2065 G_CALLBACK (gtk_window_transient_parent_realized),
2067 g_signal_connect (parent, "unrealize",
2068 G_CALLBACK (gtk_window_transient_parent_unrealized),
2070 g_signal_connect (parent, "notify::screen",
2071 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2074 gtk_window_set_screen (window, parent->screen);
2076 if (window->destroy_with_parent)
2077 connect_parent_destroyed (window);
2079 if (GTK_WIDGET_REALIZED (window) &&
2080 GTK_WIDGET_REALIZED (parent))
2081 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2082 GTK_WIDGET (window));
2086 gtk_window_group_add_window (parent->group, window);
2087 priv->transient_parent_group = TRUE;
2093 * gtk_window_get_transient_for:
2094 * @window: a #GtkWindow
2096 * Fetches the transient parent for this window. See
2097 * gtk_window_set_transient_for().
2099 * Return value: the transient parent for this window, or %NULL
2100 * if no transient parent has been set.
2103 gtk_window_get_transient_for (GtkWindow *window)
2105 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2107 return window->transient_parent;
2111 * gtk_window_set_opacity:
2112 * @window: a #GtkWindow
2113 * @opacity: desired opacity, between 0 and 1
2115 * Request the windowing system to make @window partially transparent,
2116 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2117 * of the opacity parameter are clamped to the [0,1] range.) On X11
2118 * this has any effect only on X screens with a compositing manager
2119 * running. See gtk_widget_is_composited(). On Windows it should work
2122 * Note that setting a window's opacity after the window has been
2123 * shown causes it to flicker once on Windows.
2128 gtk_window_set_opacity (GtkWindow *window,
2131 GtkWindowPrivate *priv;
2133 g_return_if_fail (GTK_IS_WINDOW (window));
2135 priv = GTK_WINDOW_GET_PRIVATE (window);
2139 else if (opacity > 1.0)
2142 priv->opacity_set = TRUE;
2143 priv->opacity = opacity;
2145 if (GTK_WIDGET_REALIZED (window))
2146 gdk_window_set_opacity (GTK_WIDGET (window)->window, priv->opacity);
2150 * gtk_window_get_opacity:
2151 * @window: a #GtkWindow
2153 * Fetches the requested opacity for this window. See
2154 * gtk_window_set_opacity().
2156 * Return value: the requested opacity for this window.
2161 gtk_window_get_opacity (GtkWindow *window)
2163 GtkWindowPrivate *priv;
2165 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2167 priv = GTK_WINDOW_GET_PRIVATE (window);
2169 return priv->opacity;
2173 * gtk_window_set_type_hint:
2174 * @window: a #GtkWindow
2175 * @hint: the window type
2177 * By setting the type hint for the window, you allow the window
2178 * manager to decorate and handle the window in a way which is
2179 * suitable to the function of the window in your application.
2181 * This function should be called before the window becomes visible.
2183 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2184 * will sometimes call gtk_window_set_type_hint() on your behalf.
2188 gtk_window_set_type_hint (GtkWindow *window,
2189 GdkWindowTypeHint hint)
2191 GtkWindowPrivate *priv;
2193 g_return_if_fail (GTK_IS_WINDOW (window));
2194 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
2196 priv = GTK_WINDOW_GET_PRIVATE (window);
2198 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2199 window->type_hint = hint;
2201 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2203 priv->reset_type_hint = TRUE;
2204 priv->type_hint = hint;
2208 * gtk_window_get_type_hint:
2209 * @window: a #GtkWindow
2211 * Gets the type hint for this window. See gtk_window_set_type_hint().
2213 * Return value: the type hint for @window.
2216 gtk_window_get_type_hint (GtkWindow *window)
2218 GtkWindowPrivate *priv;
2220 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2222 priv = GTK_WINDOW_GET_PRIVATE (window);
2224 return priv->type_hint;
2228 * gtk_window_set_skip_taskbar_hint:
2229 * @window: a #GtkWindow
2230 * @setting: %TRUE to keep this window from appearing in the task bar
2232 * Windows may set a hint asking the desktop environment not to display
2233 * the window in the task bar. This function sets this hint.
2238 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2241 GtkWindowPrivate *priv;
2243 g_return_if_fail (GTK_IS_WINDOW (window));
2245 priv = GTK_WINDOW_GET_PRIVATE (window);
2247 setting = setting != FALSE;
2249 if (priv->skips_taskbar != setting)
2251 priv->skips_taskbar = setting;
2252 if (GTK_WIDGET_REALIZED (window))
2253 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
2254 priv->skips_taskbar);
2255 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2260 * gtk_window_get_skip_taskbar_hint:
2261 * @window: a #GtkWindow
2263 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2265 * Return value: %TRUE if window shouldn't be in taskbar
2270 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2272 GtkWindowPrivate *priv;
2274 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2276 priv = GTK_WINDOW_GET_PRIVATE (window);
2278 return priv->skips_taskbar;
2282 * gtk_window_set_skip_pager_hint:
2283 * @window: a #GtkWindow
2284 * @setting: %TRUE to keep this window from appearing in the pager
2286 * Windows may set a hint asking the desktop environment not to display
2287 * the window in the pager. This function sets this hint.
2288 * (A "pager" is any desktop navigation tool such as a workspace
2289 * switcher that displays a thumbnail representation of the windows
2295 gtk_window_set_skip_pager_hint (GtkWindow *window,
2298 GtkWindowPrivate *priv;
2300 g_return_if_fail (GTK_IS_WINDOW (window));
2302 priv = GTK_WINDOW_GET_PRIVATE (window);
2304 setting = setting != FALSE;
2306 if (priv->skips_pager != setting)
2308 priv->skips_pager = setting;
2309 if (GTK_WIDGET_REALIZED (window))
2310 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2312 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2317 * gtk_window_get_skip_pager_hint:
2318 * @window: a #GtkWindow
2320 * Gets the value set by gtk_window_set_skip_pager_hint().
2322 * Return value: %TRUE if window shouldn't be in pager
2327 gtk_window_get_skip_pager_hint (GtkWindow *window)
2329 GtkWindowPrivate *priv;
2331 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2333 priv = GTK_WINDOW_GET_PRIVATE (window);
2335 return priv->skips_pager;
2339 * gtk_window_set_urgency_hint:
2340 * @window: a #GtkWindow
2341 * @setting: %TRUE to mark this window as urgent
2343 * Windows may set a hint asking the desktop environment to draw
2344 * the users attention to the window. This function sets this hint.
2349 gtk_window_set_urgency_hint (GtkWindow *window,
2352 GtkWindowPrivate *priv;
2354 g_return_if_fail (GTK_IS_WINDOW (window));
2356 priv = GTK_WINDOW_GET_PRIVATE (window);
2358 setting = setting != FALSE;
2360 if (priv->urgent != setting)
2362 priv->urgent = setting;
2363 if (GTK_WIDGET_REALIZED (window))
2364 gdk_window_set_urgency_hint (GTK_WIDGET (window)->window,
2366 g_object_notify (G_OBJECT (window), "urgency-hint");
2371 * gtk_window_get_urgency_hint:
2372 * @window: a #GtkWindow
2374 * Gets the value set by gtk_window_set_urgency_hint()
2376 * Return value: %TRUE if window is urgent
2381 gtk_window_get_urgency_hint (GtkWindow *window)
2383 GtkWindowPrivate *priv;
2385 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2387 priv = GTK_WINDOW_GET_PRIVATE (window);
2389 return priv->urgent;
2393 * gtk_window_set_accept_focus:
2394 * @window: a #GtkWindow
2395 * @setting: %TRUE to let this window receive input focus
2397 * Windows may set a hint asking the desktop environment not to receive
2398 * the input focus. This function sets this hint.
2403 gtk_window_set_accept_focus (GtkWindow *window,
2406 GtkWindowPrivate *priv;
2408 g_return_if_fail (GTK_IS_WINDOW (window));
2410 priv = GTK_WINDOW_GET_PRIVATE (window);
2412 setting = setting != FALSE;
2414 if (priv->accept_focus != setting)
2416 priv->accept_focus = setting;
2417 if (GTK_WIDGET_REALIZED (window))
2418 gdk_window_set_accept_focus (GTK_WIDGET (window)->window,
2419 priv->accept_focus);
2420 g_object_notify (G_OBJECT (window), "accept-focus");
2425 * gtk_window_get_accept_focus:
2426 * @window: a #GtkWindow
2428 * Gets the value set by gtk_window_set_accept_focus().
2430 * Return value: %TRUE if window should receive the input focus
2435 gtk_window_get_accept_focus (GtkWindow *window)
2437 GtkWindowPrivate *priv;
2439 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2441 priv = GTK_WINDOW_GET_PRIVATE (window);
2443 return priv->accept_focus;
2447 * gtk_window_set_focus_on_map:
2448 * @window: a #GtkWindow
2449 * @setting: %TRUE to let this window receive input focus on map
2451 * Windows may set a hint asking the desktop environment not to receive
2452 * the input focus when the window is mapped. This function sets this
2458 gtk_window_set_focus_on_map (GtkWindow *window,
2461 GtkWindowPrivate *priv;
2463 g_return_if_fail (GTK_IS_WINDOW (window));
2465 priv = GTK_WINDOW_GET_PRIVATE (window);
2467 setting = setting != FALSE;
2469 if (priv->focus_on_map != setting)
2471 priv->focus_on_map = setting;
2472 if (GTK_WIDGET_REALIZED (window))
2473 gdk_window_set_focus_on_map (GTK_WIDGET (window)->window,
2474 priv->focus_on_map);
2475 g_object_notify (G_OBJECT (window), "focus-on-map");
2480 * gtk_window_get_focus_on_map:
2481 * @window: a #GtkWindow
2483 * Gets the value set by gtk_window_set_focus_on_map().
2485 * Return value: %TRUE if window should receive the input focus when
2491 gtk_window_get_focus_on_map (GtkWindow *window)
2493 GtkWindowPrivate *priv;
2495 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2497 priv = GTK_WINDOW_GET_PRIVATE (window);
2499 return priv->focus_on_map;
2503 * gtk_window_set_destroy_with_parent:
2504 * @window: a #GtkWindow
2505 * @setting: whether to destroy @window with its transient parent
2507 * If @setting is %TRUE, then destroying the transient parent of @window
2508 * will also destroy @window itself. This is useful for dialogs that
2509 * shouldn't persist beyond the lifetime of the main window they're
2510 * associated with, for example.
2513 gtk_window_set_destroy_with_parent (GtkWindow *window,
2516 g_return_if_fail (GTK_IS_WINDOW (window));
2518 if (window->destroy_with_parent == (setting != FALSE))
2521 if (window->destroy_with_parent)
2523 disconnect_parent_destroyed (window);
2527 connect_parent_destroyed (window);
2530 window->destroy_with_parent = setting;
2532 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2536 * gtk_window_get_destroy_with_parent:
2537 * @window: a #GtkWindow
2539 * Returns whether the window will be destroyed with its transient parent. See
2540 * gtk_window_set_destroy_with_parent ().
2542 * Return value: %TRUE if the window will be destroyed with its transient parent.
2545 gtk_window_get_destroy_with_parent (GtkWindow *window)
2547 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2549 return window->destroy_with_parent;
2552 static GtkWindowGeometryInfo*
2553 gtk_window_get_geometry_info (GtkWindow *window,
2556 GtkWindowGeometryInfo *info;
2558 info = window->geometry_info;
2559 if (!info && create)
2561 info = g_new0 (GtkWindowGeometryInfo, 1);
2563 info->default_width = -1;
2564 info->default_height = -1;
2565 info->resize_width = -1;
2566 info->resize_height = -1;
2567 info->initial_x = 0;
2568 info->initial_y = 0;
2569 info->initial_pos_set = FALSE;
2570 info->default_is_geometry = FALSE;
2571 info->position_constraints_changed = FALSE;
2572 info->last.configure_request.x = 0;
2573 info->last.configure_request.y = 0;
2574 info->last.configure_request.width = -1;
2575 info->last.configure_request.height = -1;
2576 info->widget = NULL;
2578 window->geometry_info = info;
2585 * gtk_window_set_geometry_hints:
2586 * @window: a #GtkWindow
2587 * @geometry_widget: widget the geometry hints will be applied to
2588 * @geometry: struct containing geometry information
2589 * @geom_mask: mask indicating which struct fields should be paid attention to
2591 * This function sets up hints about how a window can be resized by
2592 * the user. You can set a minimum and maximum size; allowed resize
2593 * increments (e.g. for xterm, you can only resize by the size of a
2594 * character); aspect ratios; and more. See the #GdkGeometry struct.
2598 gtk_window_set_geometry_hints (GtkWindow *window,
2599 GtkWidget *geometry_widget,
2600 GdkGeometry *geometry,
2601 GdkWindowHints geom_mask)
2603 GtkWindowGeometryInfo *info;
2605 g_return_if_fail (GTK_IS_WINDOW (window));
2606 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2608 info = gtk_window_get_geometry_info (window, TRUE);
2611 g_signal_handlers_disconnect_by_func (info->widget,
2612 gtk_widget_destroyed,
2615 info->widget = geometry_widget;
2617 g_signal_connect (geometry_widget, "destroy",
2618 G_CALLBACK (gtk_widget_destroyed),
2622 info->geometry = *geometry;
2624 /* We store gravity in window->gravity not in the hints. */
2625 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2627 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2629 gtk_window_set_gravity (window, geometry->win_gravity);
2632 gtk_widget_queue_resize (GTK_WIDGET (window));
2636 * gtk_window_set_decorated:
2637 * @window: a #GtkWindow
2638 * @setting: %TRUE to decorate the window
2640 * By default, windows are decorated with a title bar, resize
2641 * controls, etc. Some <link linkend="gtk-X11-arch">window
2642 * managers</link> allow GTK+ to disable these decorations, creating a
2643 * borderless window. If you set the decorated property to %FALSE
2644 * using this function, GTK+ will do its best to convince the window
2645 * manager not to decorate the window. Depending on the system, this
2646 * function may not have any effect when called on a window that is
2647 * already visible, so you should call it before calling gtk_window_show().
2649 * On Windows, this function always works, since there's no window manager
2654 gtk_window_set_decorated (GtkWindow *window,
2657 g_return_if_fail (GTK_IS_WINDOW (window));
2659 setting = setting != FALSE;
2661 if (setting == window->decorated)
2664 window->decorated = setting;
2666 if (GTK_WIDGET (window)->window)
2668 if (window->decorated)
2669 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2672 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2676 g_object_notify (G_OBJECT (window), "decorated");
2680 * gtk_window_get_decorated:
2681 * @window: a #GtkWindow
2683 * Returns whether the window has been set to have decorations
2684 * such as a title bar via gtk_window_set_decorated().
2686 * Return value: %TRUE if the window has been set to have decorations
2689 gtk_window_get_decorated (GtkWindow *window)
2691 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2693 return window->decorated;
2697 * gtk_window_set_deletable:
2698 * @window: a #GtkWindow
2699 * @setting: %TRUE to decorate the window as deletable
2701 * By default, windows have a close button in the window frame. Some
2702 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
2703 * disable this button. If you set the deletable property to %FALSE
2704 * using this function, GTK+ will do its best to convince the window
2705 * manager not to show a close button. Depending on the system, this
2706 * function may not have any effect when called on a window that is
2707 * already visible, so you should call it before calling gtk_window_show().
2709 * On Windows, this function always works, since there's no window manager
2715 gtk_window_set_deletable (GtkWindow *window,
2718 GtkWindowPrivate *priv;
2720 g_return_if_fail (GTK_IS_WINDOW (window));
2722 priv = GTK_WINDOW_GET_PRIVATE (window);
2724 setting = setting != FALSE;
2726 if (setting == priv->deletable)
2729 priv->deletable = setting;
2731 if (GTK_WIDGET (window)->window)
2733 if (priv->deletable)
2734 gdk_window_set_functions (GTK_WIDGET (window)->window,
2737 gdk_window_set_functions (GTK_WIDGET (window)->window,
2738 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
2741 g_object_notify (G_OBJECT (window), "deletable");
2745 * gtk_window_get_deletable:
2746 * @window: a #GtkWindow
2748 * Returns whether the window has been set to have a close button
2749 * via gtk_window_set_deletable().
2751 * Return value: %TRUE if the window has been set to have a close button
2756 gtk_window_get_deletable (GtkWindow *window)
2758 GtkWindowPrivate *priv;
2760 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2762 priv = GTK_WINDOW_GET_PRIVATE (window);
2764 return priv->deletable;
2767 static GtkWindowIconInfo*
2768 get_icon_info (GtkWindow *window)
2770 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
2774 free_icon_info (GtkWindowIconInfo *info)
2776 g_free (info->icon_name);
2777 g_slice_free (GtkWindowIconInfo, info);
2781 static GtkWindowIconInfo*
2782 ensure_icon_info (GtkWindow *window)
2784 GtkWindowIconInfo *info;
2786 info = get_icon_info (window);
2790 info = g_slice_new0 (GtkWindowIconInfo);
2791 g_object_set_qdata_full (G_OBJECT (window),
2792 quark_gtk_window_icon_info,
2794 (GDestroyNotify)free_icon_info);
2806 static ScreenIconInfo *
2807 get_screen_icon_info (GdkScreen *screen)
2809 ScreenIconInfo *info = g_object_get_qdata (G_OBJECT (screen),
2810 quark_gtk_window_default_icon_pixmap);
2813 info = g_slice_new0 (ScreenIconInfo);
2814 g_object_set_qdata (G_OBJECT (screen),
2815 quark_gtk_window_default_icon_pixmap, info);
2818 if (info->serial != default_icon_serial)
2822 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2823 info->pixmap = NULL;
2828 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2832 info->serial = default_icon_serial;
2839 get_pixmap_and_mask (GdkWindow *window,
2840 GtkWindowIconInfo *parent_info,
2841 gboolean is_default_list,
2843 GdkPixmap **pmap_return,
2844 GdkBitmap **mask_return)
2846 GdkScreen *screen = gdk_drawable_get_screen (window);
2847 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2848 GdkPixbuf *best_icon;
2852 *pmap_return = NULL;
2853 *mask_return = NULL;
2855 if (is_default_list &&
2856 default_icon_info->pixmap != NULL)
2858 /* Use shared icon pixmap for all windows on this screen.
2860 if (default_icon_info->pixmap)
2861 g_object_ref (default_icon_info->pixmap);
2862 if (default_icon_info->mask)
2863 g_object_ref (default_icon_info->mask);
2865 *pmap_return = default_icon_info->pixmap;
2866 *mask_return = default_icon_info->mask;
2868 else if (parent_info && parent_info->icon_pixmap)
2870 if (parent_info->icon_pixmap)
2871 g_object_ref (parent_info->icon_pixmap);
2872 if (parent_info->icon_mask)
2873 g_object_ref (parent_info->icon_mask);
2875 *pmap_return = parent_info->icon_pixmap;
2876 *mask_return = parent_info->icon_mask;
2880 #define IDEAL_SIZE 48
2882 best_size = G_MAXINT;
2884 tmp_list = icon_list;
2885 while (tmp_list != NULL)
2887 GdkPixbuf *pixbuf = tmp_list->data;
2890 /* average width and height - if someone passes in a rectangular
2891 * icon they deserve what they get.
2893 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2896 if (best_icon == NULL)
2903 /* icon is better if it's 32 pixels or larger, and closer to
2904 * the ideal size than the current best.
2907 (ABS (best_size - IDEAL_SIZE) <
2908 ABS (this - IDEAL_SIZE)))
2915 tmp_list = tmp_list->next;
2919 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2920 gdk_screen_get_system_colormap (screen),
2925 /* Save pmap/mask for others to use if appropriate */
2928 parent_info->icon_pixmap = *pmap_return;
2929 parent_info->icon_mask = *mask_return;
2931 if (parent_info->icon_pixmap)
2932 g_object_ref (parent_info->icon_pixmap);
2933 if (parent_info->icon_mask)
2934 g_object_ref (parent_info->icon_mask);
2936 else if (is_default_list)
2938 default_icon_info->pixmap = *pmap_return;
2939 default_icon_info->mask = *mask_return;
2941 if (default_icon_info->pixmap)
2942 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2943 (gpointer*)&default_icon_info->pixmap);
2944 if (default_icon_info->mask)
2945 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2946 (gpointer*)&default_icon_info->mask);
2952 icon_list_from_theme (GtkWidget *widget,
2957 GtkIconTheme *icon_theme;
2962 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
2964 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
2967 for (i = 0; sizes[i]; i++)
2970 * We need an EWMH extension to handle scalable icons
2971 * by passing their name to the WM. For now just use a
2975 icon = gtk_icon_theme_load_icon (icon_theme, name,
2978 icon = gtk_icon_theme_load_icon (icon_theme, name,
2981 list = g_list_append (list, icon);
2991 gtk_window_realize_icon (GtkWindow *window)
2994 GtkWindowIconInfo *info;
2997 widget = GTK_WIDGET (window);
2999 g_return_if_fail (widget->window != NULL);
3001 /* no point setting an icon on override-redirect */
3002 if (window->type == GTK_WINDOW_POPUP)
3007 info = ensure_icon_info (window);
3012 g_return_if_fail (info->icon_pixmap == NULL);
3013 g_return_if_fail (info->icon_mask == NULL);
3015 info->using_default_icon = FALSE;
3016 info->using_parent_icon = FALSE;
3017 info->using_themed_icon = FALSE;
3019 icon_list = info->icon_list;
3021 /* Look up themed icon */
3022 if (icon_list == NULL && info->icon_name)
3024 icon_list = icon_list_from_theme (widget, info->icon_name);
3026 info->using_themed_icon = TRUE;
3029 /* Inherit from transient parent */
3030 if (icon_list == NULL && window->transient_parent)
3032 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
3034 info->using_parent_icon = TRUE;
3037 /* Inherit from default */
3038 if (icon_list == NULL)
3040 icon_list = default_icon_list;
3042 info->using_default_icon = TRUE;
3045 /* Look up themed icon */
3046 if (icon_list == NULL && default_icon_name)
3048 icon_list = icon_list_from_theme (widget, default_icon_name);
3049 info->using_default_icon = TRUE;
3050 info->using_themed_icon = TRUE;
3053 gdk_window_set_icon_list (widget->window, icon_list);
3055 get_pixmap_and_mask (widget->window,
3056 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
3057 info->using_default_icon,
3062 /* This is a slight ICCCM violation since it's a color pixmap not
3063 * a bitmap, but everyone does it.
3065 gdk_window_set_icon (widget->window,
3070 info->realized = TRUE;
3072 if (info->using_themed_icon)
3074 GtkIconTheme *icon_theme;
3076 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3077 g_list_free (icon_list);
3079 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3080 g_signal_connect (icon_theme, "changed",
3081 G_CALLBACK (update_themed_icon), window);
3086 gtk_window_unrealize_icon (GtkWindow *window)
3088 GtkWindowIconInfo *info;
3090 info = get_icon_info (window);
3095 if (info->icon_pixmap)
3096 g_object_unref (info->icon_pixmap);
3098 if (info->icon_mask)
3099 g_object_unref (info->icon_mask);
3101 info->icon_pixmap = NULL;
3102 info->icon_mask = NULL;
3104 if (info->using_themed_icon)
3106 GtkIconTheme *icon_theme;
3108 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3110 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3113 /* We don't clear the properties on the window, just figure the
3114 * window is going away.
3117 info->realized = FALSE;
3122 * gtk_window_set_icon_list:
3123 * @window: a #GtkWindow
3124 * @list: list of #GdkPixbuf
3126 * Sets up the icon representing a #GtkWindow. The icon is used when
3127 * the window is minimized (also known as iconified). Some window
3128 * managers or desktop environments may also place it in the window
3129 * frame, or display it in other contexts.
3131 * gtk_window_set_icon_list() allows you to pass in the same icon in
3132 * several hand-drawn sizes. The list should contain the natural sizes
3133 * your icon is available in; that is, don't scale the image before
3134 * passing it to GTK+. Scaling is postponed until the last minute,
3135 * when the desired final size is known, to allow best quality.
3137 * By passing several sizes, you may improve the final image quality
3138 * of the icon, by reducing or eliminating automatic image scaling.
3140 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3141 * larger images (64x64, 128x128) if you have them.
3143 * See also gtk_window_set_default_icon_list() to set the icon
3144 * for all windows in your application in one go.
3146 * Note that transient windows (those who have been set transient for another
3147 * window using gtk_window_set_transient_for()) will inherit their
3148 * icon from their transient parent. So there's no need to explicitly
3149 * set the icon on transient windows.
3152 gtk_window_set_icon_list (GtkWindow *window,
3155 GtkWindowIconInfo *info;
3157 g_return_if_fail (GTK_IS_WINDOW (window));
3159 info = ensure_icon_info (window);
3161 if (info->icon_list == list) /* check for NULL mostly */
3164 g_list_foreach (list,
3165 (GFunc) g_object_ref, NULL);
3167 g_list_foreach (info->icon_list,
3168 (GFunc) g_object_unref, NULL);
3170 g_list_free (info->icon_list);
3172 info->icon_list = g_list_copy (list);
3174 g_object_notify (G_OBJECT (window), "icon");
3176 gtk_window_unrealize_icon (window);
3178 if (GTK_WIDGET_REALIZED (window))
3179 gtk_window_realize_icon (window);
3181 /* We could try to update our transient children, but I don't think
3182 * it's really worth it. If we did it, the best way would probably
3183 * be to have children connect to notify::icon-list
3188 * gtk_window_get_icon_list:
3189 * @window: a #GtkWindow
3191 * Retrieves the list of icons set by gtk_window_set_icon_list().
3192 * The list is copied, but the reference count on each
3193 * member won't be incremented.
3195 * Return value: copy of window's icon list
3198 gtk_window_get_icon_list (GtkWindow *window)
3200 GtkWindowIconInfo *info;
3202 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3204 info = get_icon_info (window);
3207 return g_list_copy (info->icon_list);
3213 * gtk_window_set_icon:
3214 * @window: a #GtkWindow
3215 * @icon: icon image, or %NULL
3217 * Sets up the icon representing a #GtkWindow. This icon is used when
3218 * the window is minimized (also known as iconified). Some window
3219 * managers or desktop environments may also place it in the window
3220 * frame, or display it in other contexts.
3222 * The icon should be provided in whatever size it was naturally
3223 * drawn; that is, don't scale the image before passing it to
3224 * GTK+. Scaling is postponed until the last minute, when the desired
3225 * final size is known, to allow best quality.
3227 * If you have your icon hand-drawn in multiple sizes, use
3228 * gtk_window_set_icon_list(). Then the best size will be used.
3230 * This function is equivalent to calling gtk_window_set_icon_list()
3231 * with a 1-element list.
3233 * See also gtk_window_set_default_icon_list() to set the icon
3234 * for all windows in your application in one go.
3237 gtk_window_set_icon (GtkWindow *window,
3242 g_return_if_fail (GTK_IS_WINDOW (window));
3243 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3248 list = g_list_append (list, icon);
3250 gtk_window_set_icon_list (window, list);
3256 update_themed_icon (GtkIconTheme *icon_theme,
3259 g_object_notify (G_OBJECT (window), "icon");
3261 gtk_window_unrealize_icon (window);
3263 if (GTK_WIDGET_REALIZED (window))
3264 gtk_window_realize_icon (window);
3268 * gtk_window_set_icon_name:
3269 * @window: a #GtkWindow
3270 * @name: the name of the themed icon
3272 * Sets the icon for the window from a named themed icon. See
3273 * the docs for #GtkIconTheme for more details.
3275 * Note that this has nothing to do with the WM_ICON_NAME
3276 * property which is mentioned in the ICCCM.
3281 gtk_window_set_icon_name (GtkWindow *window,
3284 GtkWindowIconInfo *info;
3287 g_return_if_fail (GTK_IS_WINDOW (window));
3289 info = ensure_icon_info (window);
3291 tmp = info->icon_name;
3292 info->icon_name = g_strdup (name);
3295 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3296 g_list_free (info->icon_list);
3297 info->icon_list = NULL;
3299 update_themed_icon (NULL, window);
3301 g_object_notify (G_OBJECT (window), "icon-name");
3305 * gtk_window_get_icon_name:
3306 * @window: a #GtkWindow
3308 * Returns the name of the themed icon for the window,
3309 * see gtk_window_set_icon_name().
3311 * Returns: the icon name or %NULL if the window has
3316 G_CONST_RETURN gchar *
3317 gtk_window_get_icon_name (GtkWindow *window)
3319 GtkWindowIconInfo *info;
3321 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3323 info = ensure_icon_info (window);
3325 return info->icon_name;
3329 * gtk_window_get_icon:
3330 * @window: a #GtkWindow
3332 * Gets the value set by gtk_window_set_icon() (or if you've
3333 * called gtk_window_set_icon_list(), gets the first icon in
3336 * Return value: icon for window
3339 gtk_window_get_icon (GtkWindow *window)
3341 GtkWindowIconInfo *info;
3343 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3345 info = get_icon_info (window);
3346 if (info && info->icon_list)
3347 return GDK_PIXBUF (info->icon_list->data);
3352 /* Load pixbuf, printing warning on failure if error == NULL
3355 load_pixbuf_verbosely (const char *filename,
3358 GError *local_err = NULL;
3361 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3369 g_warning ("Error loading icon from file '%s':\n\t%s",
3370 filename, local_err->message);
3371 g_error_free (local_err);
3379 * gtk_window_set_icon_from_file:
3380 * @window: a #GtkWindow
3381 * @filename: location of icon file
3382 * @err: location to store error, or %NULL.
3384 * Sets the icon for @window.
3385 * Warns on failure if @err is %NULL.
3387 * This function is equivalent to calling gtk_window_set_icon()
3388 * with a pixbuf created by loading the image from @filename.
3390 * Returns: %TRUE if setting the icon succeeded.
3395 gtk_window_set_icon_from_file (GtkWindow *window,
3396 const gchar *filename,
3399 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3403 gtk_window_set_icon (window, pixbuf);
3404 g_object_unref (pixbuf);
3413 * gtk_window_set_default_icon_list:
3414 * @list: a list of #GdkPixbuf
3416 * Sets an icon list to be used as fallback for windows that haven't
3417 * had gtk_window_set_icon_list() called on them to set up a
3418 * window-specific icon list. This function allows you to set up the
3419 * icon for all windows in your app at once.
3421 * See gtk_window_set_icon_list() for more details.
3425 gtk_window_set_default_icon_list (GList *list)
3429 if (list == default_icon_list)
3432 /* Update serial so we don't used cached pixmaps/masks
3434 default_icon_serial++;
3436 g_list_foreach (list,
3437 (GFunc) g_object_ref, NULL);
3439 g_list_foreach (default_icon_list,
3440 (GFunc) g_object_unref, NULL);
3442 g_list_free (default_icon_list);
3444 default_icon_list = g_list_copy (list);
3446 /* Update all toplevels */
3447 toplevels = gtk_window_list_toplevels ();
3448 tmp_list = toplevels;
3449 while (tmp_list != NULL)
3451 GtkWindowIconInfo *info;
3452 GtkWindow *w = tmp_list->data;
3454 info = get_icon_info (w);
3455 if (info && info->using_default_icon)
3457 gtk_window_unrealize_icon (w);
3458 if (GTK_WIDGET_REALIZED (w))
3459 gtk_window_realize_icon (w);
3462 tmp_list = tmp_list->next;
3464 g_list_free (toplevels);
3468 * gtk_window_set_default_icon:
3471 * Sets an icon to be used as fallback for windows that haven't
3472 * had gtk_window_set_icon() called on them from a pixbuf.
3477 gtk_window_set_default_icon (GdkPixbuf *icon)
3481 g_return_if_fail (GDK_IS_PIXBUF (icon));
3483 list = g_list_prepend (NULL, icon);
3484 gtk_window_set_default_icon_list (list);
3489 * gtk_window_set_default_icon_name:
3490 * @name: the name of the themed icon
3492 * Sets an icon to be used as fallback for windows that haven't
3493 * had gtk_window_set_icon_list() called on them from a named
3494 * themed icon, see gtk_window_set_icon_name().
3499 gtk_window_set_default_icon_name (const gchar *name)
3504 /* Update serial so we don't used cached pixmaps/masks
3506 default_icon_serial++;
3508 g_free (default_icon_name);
3509 default_icon_name = g_strdup (name);
3511 g_list_foreach (default_icon_list,
3512 (GFunc) g_object_unref, NULL);
3514 g_list_free (default_icon_list);
3515 default_icon_list = NULL;
3517 /* Update all toplevels */
3518 toplevels = gtk_window_list_toplevels ();
3519 tmp_list = toplevels;
3520 while (tmp_list != NULL)
3522 GtkWindowIconInfo *info;
3523 GtkWindow *w = tmp_list->data;
3525 info = get_icon_info (w);
3526 if (info && info->using_default_icon && info->using_themed_icon)
3528 gtk_window_unrealize_icon (w);
3529 if (GTK_WIDGET_REALIZED (w))
3530 gtk_window_realize_icon (w);
3533 tmp_list = tmp_list->next;
3535 g_list_free (toplevels);
3539 * gtk_window_set_default_icon_from_file:
3540 * @filename: location of icon file
3541 * @err: location to store error, or %NULL.
3543 * Sets an icon to be used as fallback for windows that haven't
3544 * had gtk_window_set_icon_list() called on them from a file
3545 * on disk. Warns on failure if @err is %NULL.
3547 * Returns: %TRUE if setting the icon succeeded.
3552 gtk_window_set_default_icon_from_file (const gchar *filename,
3555 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3559 gtk_window_set_default_icon (pixbuf);
3560 g_object_unref (pixbuf);
3569 * gtk_window_get_default_icon_list:
3571 * Gets the value set by gtk_window_set_default_icon_list().
3572 * The list is a copy and should be freed with g_list_free(),
3573 * but the pixbufs in the list have not had their reference count
3576 * Return value: copy of default icon list
3579 gtk_window_get_default_icon_list (void)
3581 return g_list_copy (default_icon_list);
3585 gtk_window_set_default_size_internal (GtkWindow *window,
3586 gboolean change_width,
3588 gboolean change_height,
3590 gboolean is_geometry)
3592 GtkWindowGeometryInfo *info;
3594 g_return_if_fail (change_width == FALSE || width >= -1);
3595 g_return_if_fail (change_height == FALSE || height >= -1);
3597 info = gtk_window_get_geometry_info (window, TRUE);
3599 g_object_freeze_notify (G_OBJECT (window));
3601 info->default_is_geometry = is_geometry != FALSE;
3611 info->default_width = width;
3613 g_object_notify (G_OBJECT (window), "default-width");
3624 info->default_height = height;
3626 g_object_notify (G_OBJECT (window), "default-height");
3629 g_object_thaw_notify (G_OBJECT (window));
3631 gtk_widget_queue_resize (GTK_WIDGET (window));
3635 * gtk_window_set_default_size:
3636 * @window: a #GtkWindow
3637 * @width: width in pixels, or -1 to unset the default width
3638 * @height: height in pixels, or -1 to unset the default height
3640 * Sets the default size of a window. If the window's "natural" size
3641 * (its size request) is larger than the default, the default will be
3642 * ignored. More generally, if the default size does not obey the
3643 * geometry hints for the window (gtk_window_set_geometry_hints() can
3644 * be used to set these explicitly), the default size will be clamped
3645 * to the nearest permitted size.
3647 * Unlike gtk_widget_set_size_request(), which sets a size request for
3648 * a widget and thus would keep users from shrinking the window, this
3649 * function only sets the initial size, just as if the user had
3650 * resized the window themselves. Users can still shrink the window
3651 * again as they normally would. Setting a default size of -1 means to
3652 * use the "natural" default size (the size request of the window).
3654 * For more control over a window's initial size and how resizing works,
3655 * investigate gtk_window_set_geometry_hints().
3657 * For some uses, gtk_window_resize() is a more appropriate function.
3658 * gtk_window_resize() changes the current size of the window, rather
3659 * than the size to be used on initial display. gtk_window_resize() always
3660 * affects the window itself, not the geometry widget.
3662 * The default size of a window only affects the first time a window is
3663 * shown; if a window is hidden and re-shown, it will remember the size
3664 * it had prior to hiding, rather than using the default size.
3666 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3667 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3670 gtk_window_set_default_size (GtkWindow *window,
3674 g_return_if_fail (GTK_IS_WINDOW (window));
3675 g_return_if_fail (width >= -1);
3676 g_return_if_fail (height >= -1);
3678 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3682 * gtk_window_get_default_size:
3683 * @window: a #GtkWindow
3684 * @width: location to store the default width, or %NULL
3685 * @height: location to store the default height, or %NULL
3687 * Gets the default size of the window. A value of -1 for the width or
3688 * height indicates that a default size has not been explicitly set
3689 * for that dimension, so the "natural" size of the window will be
3694 gtk_window_get_default_size (GtkWindow *window,
3698 GtkWindowGeometryInfo *info;
3700 g_return_if_fail (GTK_IS_WINDOW (window));
3702 info = gtk_window_get_geometry_info (window, FALSE);
3705 *width = info ? info->default_width : -1;
3708 *height = info ? info->default_height : -1;
3712 * gtk_window_resize:
3713 * @window: a #GtkWindow
3714 * @width: width in pixels to resize the window to
3715 * @height: height in pixels to resize the window to
3717 * Resizes the window as if the user had done so, obeying geometry
3718 * constraints. The default geometry constraint is that windows may
3719 * not be smaller than their size request; to override this
3720 * constraint, call gtk_widget_set_size_request() to set the window's
3721 * request to a smaller value.
3723 * If gtk_window_resize() is called before showing a window for the
3724 * first time, it overrides any default size set with
3725 * gtk_window_set_default_size().
3727 * Windows may not be resized smaller than 1 by 1 pixels.
3731 gtk_window_resize (GtkWindow *window,
3735 GtkWindowGeometryInfo *info;
3737 g_return_if_fail (GTK_IS_WINDOW (window));
3738 g_return_if_fail (width > 0);
3739 g_return_if_fail (height > 0);
3741 info = gtk_window_get_geometry_info (window, TRUE);
3743 info->resize_width = width;
3744 info->resize_height = height;
3746 gtk_widget_queue_resize (GTK_WIDGET (window));
3750 * gtk_window_get_size:
3751 * @window: a #GtkWindow
3752 * @width: return location for width, or %NULL
3753 * @height: return location for height, or %NULL
3755 * Obtains the current size of @window. If @window is not onscreen,
3756 * it returns the size GTK+ will suggest to the <link
3757 * linkend="gtk-X11-arch">window manager</link> for the initial window
3758 * size (but this is not reliably the same as the size the window
3759 * manager will actually select). The size obtained by
3760 * gtk_window_get_size() is the last size received in a
3761 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
3762 * rather than querying the X server for the size. As a result, if you
3763 * call gtk_window_resize() then immediately call
3764 * gtk_window_get_size(), the size won't have taken effect yet. After
3765 * the window manager processes the resize request, GTK+ receives
3766 * notification that the size has changed via a configure event, and
3767 * the size of the window gets updated.
3769 * Note 1: Nearly any use of this function creates a race condition,
3770 * because the size of the window may change between the time that you
3771 * get the size and the time that you perform some action assuming
3772 * that size is the current size. To avoid race conditions, connect to
3773 * "configure_event" on the window and adjust your size-dependent
3774 * state to match the size delivered in the #GdkEventConfigure.
3776 * Note 2: The returned size does <emphasis>not</emphasis> include the
3777 * size of the window manager decorations (aka the window frame or
3778 * border). Those are not drawn by GTK+ and GTK+ has no reliable
3779 * method of determining their size.
3781 * Note 3: If you are getting a window size in order to position
3782 * the window onscreen, there may be a better way. The preferred
3783 * way is to simply set the window's semantic type with
3784 * gtk_window_set_type_hint(), which allows the window manager to
3785 * e.g. center dialogs. Also, if you set the transient parent of
3786 * dialogs with gtk_window_set_transient_for() window managers
3787 * will often center the dialog over its parent window. It's
3788 * much preferred to let the window manager handle these
3789 * things rather than doing it yourself, because all apps will
3790 * behave consistently and according to user prefs if the window
3791 * manager handles it. Also, the window manager can take the size
3792 * of the window decorations/border into account, while your
3793 * application cannot.
3795 * In any case, if you insist on application-specified window
3796 * positioning, there's <emphasis>still</emphasis> a better way than
3797 * doing it yourself - gtk_window_set_position() will frequently
3798 * handle the details for you.
3802 gtk_window_get_size (GtkWindow *window,
3808 g_return_if_fail (GTK_IS_WINDOW (window));
3810 if (width == NULL && height == NULL)
3813 if (GTK_WIDGET_MAPPED (window))
3815 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3820 GdkRectangle configure_request;
3822 gtk_window_compute_configure_request (window,
3826 w = configure_request.width;
3827 h = configure_request.height;
3838 * @window: a #GtkWindow
3839 * @x: X coordinate to move window to
3840 * @y: Y coordinate to move window to
3842 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3843 * @window to the given position. Window managers are free to ignore
3844 * this; most window managers ignore requests for initial window
3845 * positions (instead using a user-defined placement algorithm) and
3846 * honor requests after the window has already been shown.
3848 * Note: the position is the position of the gravity-determined
3849 * reference point for the window. The gravity determines two things:
3850 * first, the location of the reference point in root window
3851 * coordinates; and second, which point on the window is positioned at
3852 * the reference point.
3854 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3855 * point is simply the @x, @y supplied to gtk_window_move(). The
3856 * top-left corner of the window decorations (aka window frame or
3857 * border) will be placed at @x, @y. Therefore, to position a window
3858 * at the top left of the screen, you want to use the default gravity
3859 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3861 * To position a window at the bottom right corner of the screen, you
3862 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3863 * point is at @x + the window width and @y + the window height, and
3864 * the bottom-right corner of the window border will be placed at that
3865 * reference point. So, to place a window in the bottom right corner
3866 * you would first set gravity to south east, then write:
3867 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3868 * gdk_screen_height () - window_height)</literal> (note that this
3869 * example does not take multi-head scenarios into account).
3871 * The Extended Window Manager Hints specification at <ulink
3872 * url="http://www.freedesktop.org/Standards/wm-spec">
3873 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
3874 * nice table of gravities in the "implementation notes" section.
3876 * The gtk_window_get_position() documentation may also be relevant.
3879 gtk_window_move (GtkWindow *window,
3883 GtkWindowGeometryInfo *info;
3886 g_return_if_fail (GTK_IS_WINDOW (window));
3888 widget = GTK_WIDGET (window);
3890 info = gtk_window_get_geometry_info (window, TRUE);
3892 if (GTK_WIDGET_MAPPED (window))
3894 /* we have now sent a request with this position
3895 * with currently-active constraints, so toggle flag.
3897 info->position_constraints_changed = FALSE;
3899 /* we only constrain if mapped - if not mapped,
3900 * then gtk_window_compute_configure_request()
3901 * will apply the constraints later, and we
3902 * don't want to lose information about
3903 * what position the user set before then.
3904 * i.e. if you do a move() then turn off POS_CENTER
3905 * then show the window, your move() will work.
3907 gtk_window_constrain_position (window,
3908 widget->allocation.width,
3909 widget->allocation.height,
3912 /* Note that this request doesn't go through our standard request
3913 * framework, e.g. doesn't increment configure_request_count,
3914 * doesn't set info->last, etc.; that's because
3915 * we don't save the info needed to arrive at this same request
3918 * To gtk_window_move_resize(), this will end up looking exactly
3919 * the same as the position being changed by the window
3923 /* FIXME are we handling gravity properly for framed windows? */
3925 gdk_window_move (window->frame,
3926 x - window->frame_left,
3927 y - window->frame_top);
3929 gdk_window_move (GTK_WIDGET (window)->window,
3934 /* Save this position to apply on mapping */
3935 info->initial_x = x;
3936 info->initial_y = y;
3937 info->initial_pos_set = TRUE;
3942 * gtk_window_get_position:
3943 * @window: a #GtkWindow
3944 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3945 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3947 * This function returns the position you need to pass to
3948 * gtk_window_move() to keep @window in its current position. This
3949 * means that the meaning of the returned value varies with window
3950 * gravity. See gtk_window_move() for more details.
3952 * If you haven't changed the window gravity, its gravity will be
3953 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3954 * gets the position of the top-left corner of the window manager
3955 * frame for the window. gtk_window_move() sets the position of this
3956 * same top-left corner.
3958 * gtk_window_get_position() is not 100% reliable because the X Window System
3959 * does not specify a way to obtain the geometry of the
3960 * decorations placed on a window by the window manager.
3961 * Thus GTK+ is using a "best guess" that works with most
3964 * Moreover, nearly all window managers are historically broken with
3965 * respect to their handling of window gravity. So moving a window to
3966 * its current position as returned by gtk_window_get_position() tends
3967 * to result in moving the window slightly. Window managers are
3968 * slowly getting better over time.
3970 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3971 * frame is not relevant, and thus gtk_window_get_position() will
3972 * always produce accurate results. However you can't use static
3973 * gravity to do things like place a window in a corner of the screen,
3974 * because static gravity ignores the window manager decorations.
3976 * If you are saving and restoring your application's window
3977 * positions, you should know that it's impossible for applications to
3978 * do this without getting it somewhat wrong because applications do
3979 * not have sufficient knowledge of window manager state. The Correct
3980 * Mechanism is to support the session management protocol (see the
3981 * "GnomeClient" object in the GNOME libraries for example) and allow
3982 * the window manager to save your window sizes and positions.
3987 gtk_window_get_position (GtkWindow *window,
3993 g_return_if_fail (GTK_IS_WINDOW (window));
3995 widget = GTK_WIDGET (window);
3997 if (window->gravity == GDK_GRAVITY_STATIC)
3999 if (GTK_WIDGET_MAPPED (widget))
4001 /* This does a server round-trip, which is sort of wrong;
4002 * but a server round-trip is inevitable for
4003 * gdk_window_get_frame_extents() in the usual
4004 * NorthWestGravity case below, so not sure what else to
4005 * do. We should likely be consistent about whether we get
4006 * the client-side info or the server-side info.
4008 gdk_window_get_origin (widget->window, root_x, root_y);
4012 GdkRectangle configure_request;
4014 gtk_window_compute_configure_request (window,
4018 *root_x = configure_request.x;
4019 *root_y = configure_request.y;
4024 GdkRectangle frame_extents;
4029 if (GTK_WIDGET_MAPPED (widget))
4032 gdk_window_get_frame_extents (window->frame, &frame_extents);
4034 gdk_window_get_frame_extents (widget->window, &frame_extents);
4035 x = frame_extents.x;
4036 y = frame_extents.y;
4037 gtk_window_get_size (window, &w, &h);
4041 /* We just say the frame has 0 size on all sides.
4042 * Not sure what else to do.
4044 gtk_window_compute_configure_request (window,
4047 x = frame_extents.x;
4048 y = frame_extents.y;
4049 w = frame_extents.width;
4050 h = frame_extents.height;
4053 switch (window->gravity)
4055 case GDK_GRAVITY_NORTH:
4056 case GDK_GRAVITY_CENTER:
4057 case GDK_GRAVITY_SOUTH:
4058 /* Find center of frame. */
4059 x += frame_extents.width / 2;
4060 /* Center client window on that point. */
4064 case GDK_GRAVITY_SOUTH_EAST:
4065 case GDK_GRAVITY_EAST:
4066 case GDK_GRAVITY_NORTH_EAST:
4067 /* Find right edge of frame */
4068 x += frame_extents.width;
4069 /* Align left edge of client at that point. */
4076 switch (window->gravity)
4078 case GDK_GRAVITY_WEST:
4079 case GDK_GRAVITY_CENTER:
4080 case GDK_GRAVITY_EAST:
4081 /* Find center of frame. */
4082 y += frame_extents.height / 2;
4083 /* Center client window there. */
4086 case GDK_GRAVITY_SOUTH_WEST:
4087 case GDK_GRAVITY_SOUTH:
4088 case GDK_GRAVITY_SOUTH_EAST:
4089 /* Find south edge of frame */
4090 y += frame_extents.height;
4091 /* Place bottom edge of client there */
4106 * gtk_window_reshow_with_initial_size:
4107 * @window: a #GtkWindow
4109 * Hides @window, then reshows it, resetting the
4110 * default size and position of the window. Used
4111 * by GUI builders only.
4114 gtk_window_reshow_with_initial_size (GtkWindow *window)
4118 g_return_if_fail (GTK_IS_WINDOW (window));
4120 widget = GTK_WIDGET (window);
4122 gtk_widget_hide (widget);
4123 gtk_widget_unrealize (widget);
4124 gtk_widget_show (widget);
4128 gtk_window_destroy (GtkObject *object)
4130 GtkWindow *window = GTK_WINDOW (object);
4132 toplevel_list = g_slist_remove (toplevel_list, window);
4134 if (window->transient_parent)
4135 gtk_window_set_transient_for (window, NULL);
4137 /* frees the icons */
4138 gtk_window_set_icon_list (window, NULL);
4140 if (window->has_user_ref_count)
4142 window->has_user_ref_count = FALSE;
4143 g_object_unref (window);
4147 gtk_window_group_remove_window (window->group, window);
4149 gtk_window_free_key_hash (window);
4151 GTK_OBJECT_CLASS (gtk_window_parent_class)->destroy (object);
4155 gtk_window_finalize (GObject *object)
4157 GtkWindow *window = GTK_WINDOW (object);
4158 GtkMnemonicHash *mnemonic_hash;
4160 g_free (window->title);
4161 g_free (window->wmclass_name);
4162 g_free (window->wmclass_class);
4163 g_free (window->wm_role);
4165 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4167 _gtk_mnemonic_hash_free (mnemonic_hash);
4169 if (window->geometry_info)
4171 if (window->geometry_info->widget)
4172 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
4173 gtk_widget_destroyed,
4174 &window->geometry_info->widget);
4175 g_free (window->geometry_info);
4178 if (window->keys_changed_handler)
4180 g_source_remove (window->keys_changed_handler);
4181 window->keys_changed_handler = 0;
4186 g_signal_handlers_disconnect_by_func (window->screen,
4187 gtk_window_on_composited_changed, window);
4190 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4194 gtk_window_show (GtkWidget *widget)
4196 GtkWindow *window = GTK_WINDOW (widget);
4197 GtkContainer *container = GTK_CONTAINER (window);
4198 gboolean need_resize;
4200 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
4202 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
4203 container->need_resize = FALSE;
4207 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4208 GtkAllocation allocation = { 0, 0 };
4209 GdkRectangle configure_request;
4210 GdkGeometry new_geometry;
4212 gboolean was_realized;
4214 /* We are going to go ahead and perform this configure request
4215 * and then emulate a configure notify by going ahead and
4216 * doing a size allocate. Sort of a synchronous
4217 * mini-copy of gtk_window_move_resize() here.
4219 gtk_window_compute_configure_request (window,
4224 /* We update this because we are going to go ahead
4225 * and gdk_window_resize() below, rather than
4228 info->last.configure_request.width = configure_request.width;
4229 info->last.configure_request.height = configure_request.height;
4231 /* and allocate the window - this is normally done
4232 * in move_resize in response to configure notify
4234 allocation.width = configure_request.width;
4235 allocation.height = configure_request.height;
4236 gtk_widget_size_allocate (widget, &allocation);
4238 /* Then we guarantee we have a realize */
4239 was_realized = FALSE;
4240 if (!GTK_WIDGET_REALIZED (widget))
4242 gtk_widget_realize (widget);
4243 was_realized = TRUE;
4246 /* Must be done after the windows are realized,
4247 * so that the decorations can be read
4249 gtk_decorated_window_calculate_frame_size (window);
4251 /* We only send configure request if we didn't just finish
4252 * creating the window; if we just created the window
4253 * then we created it with widget->allocation anyhow.
4256 gdk_window_move_resize (widget->window,
4257 configure_request.x,
4258 configure_request.y,
4259 configure_request.width,
4260 configure_request.height);
4263 gtk_container_check_resize (container);
4265 gtk_widget_map (widget);
4267 /* Try to make sure that we have some focused widget
4269 if (!window->focus_widget && !GTK_IS_PLUG (window))
4270 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4273 gtk_grab_add (widget);
4277 gtk_window_hide (GtkWidget *widget)
4279 GtkWindow *window = GTK_WINDOW (widget);
4281 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4282 gtk_widget_unmap (widget);
4285 gtk_grab_remove (widget);
4289 gtk_window_map (GtkWidget *widget)
4291 GtkWindow *window = GTK_WINDOW (widget);
4292 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4293 GdkWindow *toplevel;
4295 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4297 if (window->bin.child &&
4298 GTK_WIDGET_VISIBLE (window->bin.child) &&
4299 !GTK_WIDGET_MAPPED (window->bin.child))
4300 gtk_widget_map (window->bin.child);
4303 toplevel = window->frame;
4305 toplevel = widget->window;
4307 if (window->maximize_initially)
4308 gdk_window_maximize (toplevel);
4310 gdk_window_unmaximize (toplevel);
4312 if (window->stick_initially)
4313 gdk_window_stick (toplevel);
4315 gdk_window_unstick (toplevel);
4317 if (window->iconify_initially)
4318 gdk_window_iconify (toplevel);
4320 gdk_window_deiconify (toplevel);
4322 if (priv->fullscreen_initially)
4323 gdk_window_fullscreen (toplevel);
4325 gdk_window_unfullscreen (toplevel);
4327 gdk_window_set_keep_above (toplevel, priv->above_initially);
4329 gdk_window_set_keep_below (toplevel, priv->below_initially);
4331 /* No longer use the default settings */
4332 window->need_default_size = FALSE;
4333 window->need_default_position = FALSE;
4335 if (priv->reset_type_hint)
4337 /* We should only reset the type hint when the application
4338 * used gtk_window_set_type_hint() to change the hint.
4339 * Some applications use X directly to change the properties;
4340 * in that case, we shouldn't overwrite what they did.
4342 gdk_window_set_type_hint (widget->window, priv->type_hint);
4343 priv->reset_type_hint = FALSE;
4346 gdk_window_show (widget->window);
4349 gdk_window_show (window->frame);
4351 if (!disable_startup_notification)
4353 /* Do we have a custom startup-notification id? */
4354 if (priv->startup_id != NULL)
4356 /* Make sure we have a "real" id */
4357 if (!startup_id_is_fake (priv->startup_id))
4358 gdk_notify_startup_complete_with_id (priv->startup_id);
4360 priv->startup_id = NULL;
4362 else if (!sent_startup_notification)
4364 sent_startup_notification = TRUE;
4365 gdk_notify_startup_complete ();
4371 gtk_window_map_event (GtkWidget *widget,
4374 if (!GTK_WIDGET_MAPPED (widget))
4376 /* we should be be unmapped, but are getting a MapEvent, this may happen
4377 * to toplevel XWindows if mapping was intercepted by a window manager
4378 * and an unmap request occoured while the MapRequestEvent was still
4379 * being handled. we work around this situaiton here by re-requesting
4380 * the window being unmapped. more details can be found in:
4381 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4383 gdk_window_hide (widget->window);
4389 gtk_window_unmap (GtkWidget *widget)
4391 GtkWindow *window = GTK_WINDOW (widget);
4392 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
4393 GtkWindowGeometryInfo *info;
4394 GdkWindowState state;
4396 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4398 gdk_window_withdraw (window->frame);
4400 gdk_window_withdraw (widget->window);
4402 window->configure_request_count = 0;
4403 window->configure_notify_received = FALSE;
4405 /* on unmap, we reset the default positioning of the window,
4406 * so it's placed again, but we don't reset the default
4407 * size of the window, so it's remembered.
4409 window->need_default_position = TRUE;
4411 info = gtk_window_get_geometry_info (window, FALSE);
4414 info->initial_pos_set = FALSE;
4415 info->position_constraints_changed = FALSE;
4418 state = gdk_window_get_state (widget->window);
4419 window->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4420 window->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4421 window->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4422 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4423 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4427 gtk_window_realize (GtkWidget *widget)
4430 GdkWindow *parent_window;
4431 GdkWindowAttr attributes;
4432 gint attributes_mask;
4433 GtkWindowPrivate *priv;
4435 window = GTK_WINDOW (widget);
4436 priv = GTK_WINDOW_GET_PRIVATE (window);
4438 /* ensure widget tree is properly size allocated */
4439 if (widget->allocation.x == -1 &&
4440 widget->allocation.y == -1 &&
4441 widget->allocation.width == 1 &&
4442 widget->allocation.height == 1)
4444 GtkRequisition requisition;
4445 GtkAllocation allocation = { 0, 0, 200, 200 };
4447 gtk_widget_size_request (widget, &requisition);
4448 if (requisition.width || requisition.height)
4450 /* non-empty window */
4451 allocation.width = requisition.width;
4452 allocation.height = requisition.height;
4454 gtk_widget_size_allocate (widget, &allocation);
4456 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4458 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
4461 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4463 switch (window->type)
4465 case GTK_WINDOW_TOPLEVEL:
4466 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4468 case GTK_WINDOW_POPUP:
4469 attributes.window_type = GDK_WINDOW_TEMP;
4472 g_warning (G_STRLOC": Unknown window type %d!", window->type);
4476 attributes.title = window->title;
4477 attributes.wmclass_name = window->wmclass_name;
4478 attributes.wmclass_class = window->wmclass_class;
4479 attributes.wclass = GDK_INPUT_OUTPUT;
4480 attributes.visual = gtk_widget_get_visual (widget);
4481 attributes.colormap = gtk_widget_get_colormap (widget);
4483 if (window->has_frame)
4485 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
4486 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
4487 attributes.event_mask = (GDK_EXPOSURE_MASK |
4488 GDK_KEY_PRESS_MASK |
4489 GDK_ENTER_NOTIFY_MASK |
4490 GDK_LEAVE_NOTIFY_MASK |
4491 GDK_FOCUS_CHANGE_MASK |
4492 GDK_STRUCTURE_MASK |
4493 GDK_BUTTON_MOTION_MASK |
4494 GDK_POINTER_MOTION_HINT_MASK |
4495 GDK_BUTTON_PRESS_MASK |
4496 GDK_BUTTON_RELEASE_MASK);
4498 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4500 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4501 &attributes, attributes_mask);
4503 if (priv->opacity_set)
4504 gdk_window_set_opacity (window->frame, priv->opacity);
4506 gdk_window_set_user_data (window->frame, widget);
4508 attributes.window_type = GDK_WINDOW_CHILD;
4509 attributes.x = window->frame_left;
4510 attributes.y = window->frame_top;
4512 attributes_mask = GDK_WA_X | GDK_WA_Y;
4514 parent_window = window->frame;
4516 g_signal_connect (window,
4518 G_CALLBACK (gtk_window_event),
4523 attributes_mask = 0;
4524 parent_window = gtk_widget_get_root_window (widget);
4527 attributes.width = widget->allocation.width;
4528 attributes.height = widget->allocation.height;
4529 attributes.event_mask = gtk_widget_get_events (widget);
4530 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4531 GDK_KEY_PRESS_MASK |
4532 GDK_KEY_RELEASE_MASK |
4533 GDK_ENTER_NOTIFY_MASK |
4534 GDK_LEAVE_NOTIFY_MASK |
4535 GDK_FOCUS_CHANGE_MASK |
4536 GDK_STRUCTURE_MASK);
4537 attributes.type_hint = priv->type_hint;
4539 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_TYPE_HINT;
4540 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
4541 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
4543 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
4545 if (!window->has_frame && priv->opacity_set)
4546 gdk_window_set_opacity (widget->window, priv->opacity);
4548 gdk_window_enable_synchronized_configure (widget->window);
4550 gdk_window_set_user_data (widget->window, window);
4552 widget->style = gtk_style_attach (widget->style, widget->window);
4553 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4555 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
4557 /* This is a bad hack to set the window background. */
4558 gtk_window_paint (widget, NULL);
4560 if (window->transient_parent &&
4561 GTK_WIDGET_REALIZED (window->transient_parent))
4562 gdk_window_set_transient_for (widget->window,
4563 GTK_WIDGET (window->transient_parent)->window);
4565 if (window->wm_role)
4566 gdk_window_set_role (widget->window, window->wm_role);
4568 if (!window->decorated)
4569 gdk_window_set_decorations (widget->window, 0);
4571 if (!priv->deletable)
4572 gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4574 if (gtk_window_get_skip_pager_hint (window))
4575 gdk_window_set_skip_pager_hint (widget->window, TRUE);
4577 if (gtk_window_get_skip_taskbar_hint (window))
4578 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
4580 if (gtk_window_get_accept_focus (window))
4581 gdk_window_set_accept_focus (widget->window, TRUE);
4583 gdk_window_set_accept_focus (widget->window, FALSE);
4585 if (gtk_window_get_focus_on_map (window))
4586 gdk_window_set_focus_on_map (widget->window, TRUE);
4588 gdk_window_set_focus_on_map (widget->window, FALSE);
4591 gdk_window_set_modal_hint (widget->window, TRUE);
4593 gdk_window_set_modal_hint (widget->window, FALSE);
4595 if (priv->startup_id)
4597 #ifdef GDK_WINDOWING_X11
4598 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4599 if (timestamp != GDK_CURRENT_TIME)
4600 gdk_x11_window_set_user_time (widget->window, timestamp);
4602 if (!startup_id_is_fake (priv->startup_id))
4603 gdk_window_set_startup_id (widget->window, priv->startup_id);
4607 gtk_window_realize_icon (window);
4611 gtk_window_unrealize (GtkWidget *widget)
4614 GtkWindowGeometryInfo *info;
4616 window = GTK_WINDOW (widget);
4618 /* On unrealize, we reset the size of the window such
4619 * that we will re-apply the default sizing stuff
4620 * next time we show the window.
4622 * Default positioning is reset on unmap, instead of unrealize.
4624 window->need_default_size = TRUE;
4625 info = gtk_window_get_geometry_info (window, FALSE);
4628 info->resize_width = -1;
4629 info->resize_height = -1;
4630 info->last.configure_request.x = 0;
4631 info->last.configure_request.y = 0;
4632 info->last.configure_request.width = -1;
4633 info->last.configure_request.height = -1;
4634 /* be sure we reset geom hints on re-realize */
4635 info->last.flags = 0;
4640 gdk_window_set_user_data (window->frame, NULL);
4641 gdk_window_destroy (window->frame);
4642 window->frame = NULL;
4646 gtk_window_unrealize_icon (window);
4648 (* GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize) (widget);
4652 gtk_window_size_request (GtkWidget *widget,
4653 GtkRequisition *requisition)
4658 window = GTK_WINDOW (widget);
4659 bin = GTK_BIN (window);
4661 requisition->width = GTK_CONTAINER (window)->border_width * 2;
4662 requisition->height = GTK_CONTAINER (window)->border_width * 2;
4664 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
4666 GtkRequisition child_requisition;
4668 gtk_widget_size_request (bin->child, &child_requisition);
4670 requisition->width += child_requisition.width;
4671 requisition->height += child_requisition.height;
4676 gtk_window_size_allocate (GtkWidget *widget,
4677 GtkAllocation *allocation)
4680 GtkAllocation child_allocation;
4682 window = GTK_WINDOW (widget);
4683 widget->allocation = *allocation;
4685 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
4687 child_allocation.x = GTK_CONTAINER (window)->border_width;
4688 child_allocation.y = GTK_CONTAINER (window)->border_width;
4689 child_allocation.width =
4690 MAX (1, (gint)allocation->width - child_allocation.x * 2);
4691 child_allocation.height =
4692 MAX (1, (gint)allocation->height - child_allocation.y * 2);
4694 gtk_widget_size_allocate (window->bin.child, &child_allocation);
4697 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4699 gdk_window_resize (window->frame,
4700 allocation->width + window->frame_left + window->frame_right,
4701 allocation->height + window->frame_top + window->frame_bottom);
4706 gtk_window_event (GtkWidget *widget, GdkEvent *event)
4709 gboolean return_val;
4711 window = GTK_WINDOW (widget);
4713 if (window->frame && (event->any.window == window->frame))
4715 if ((event->type != GDK_KEY_PRESS) &&
4716 (event->type != GDK_KEY_RELEASE) &&
4717 (event->type != GDK_FOCUS_CHANGE))
4719 g_signal_stop_emission_by_name (widget, "event");
4721 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
4726 g_object_unref (event->any.window);
4727 event->any.window = g_object_ref (widget->window);
4735 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
4737 GdkEventConfigure *configure_event;
4740 switch (event->type)
4743 configure_event = (GdkEventConfigure *)event;
4745 /* Invalidate the decorations */
4748 rect.width = configure_event->width;
4749 rect.height = configure_event->height;
4751 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
4753 /* Pass on the (modified) configure event */
4754 configure_event->width -= window->frame_left + window->frame_right;
4755 configure_event->height -= window->frame_top + window->frame_bottom;
4756 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
4765 gtk_window_configure_event (GtkWidget *widget,
4766 GdkEventConfigure *event)
4768 GtkWindow *window = GTK_WINDOW (widget);
4769 gboolean expected_reply = window->configure_request_count > 0;
4771 /* window->configure_request_count incremented for each
4772 * configure request, and decremented to a min of 0 for
4773 * each configure notify.
4775 * All it means is that we know we will get at least
4776 * window->configure_request_count more configure notifies.
4777 * We could get more configure notifies than that; some
4778 * of the configure notifies we get may be unrelated to
4779 * the configure requests. But we will get at least
4780 * window->configure_request_count notifies.
4783 if (window->configure_request_count > 0)
4784 window->configure_request_count -= 1;
4786 /* As an optimization, we avoid a resize when possible.
4788 * The only times we can avoid a resize are:
4789 * - we know only the position changed, not the size
4790 * - we know we have made more requests and so will get more
4791 * notifies and can wait to resize when we get them
4794 if (!expected_reply &&
4795 (widget->allocation.width == event->width &&
4796 widget->allocation.height == event->height))
4798 gdk_window_configure_finished (widget->window);
4803 * If we do need to resize, we do that by:
4804 * - filling in widget->allocation with the new size
4805 * - setting configure_notify_received to TRUE
4806 * for use in gtk_window_move_resize()
4807 * - queueing a resize, leading to invocation of
4808 * gtk_window_move_resize() in an idle handler
4812 window->configure_notify_received = TRUE;
4814 widget->allocation.width = event->width;
4815 widget->allocation.height = event->height;
4817 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4822 /* the accel_key and accel_mods fields of the key have to be setup
4823 * upon calling this function. it'll then return whether that key
4824 * is at all used as accelerator, and if so will OR in the
4825 * accel_flags member of the key.
4828 _gtk_window_query_nonaccels (GtkWindow *window,
4830 GdkModifierType accel_mods)
4832 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4834 /* movement keys are considered locked accels */
4837 static const guint bindings[] = {
4838 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
4839 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
4843 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
4844 if (bindings[i] == accel_key)
4848 /* mnemonics are considered locked accels */
4849 if (accel_mods == window->mnemonic_modifier)
4851 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4852 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
4860 * gtk_window_propagate_key_event:
4861 * @window: a #GtkWindow
4862 * @event: a #GdkEventKey
4864 * Propagate a key press or release event to the focus widget and
4865 * up the focus container chain until a widget handles @event.
4866 * This is normally called by the default ::key_press_event and
4867 * ::key_release_event handlers for toplevel windows,
4868 * however in some cases it may be useful to call this directly when
4869 * overriding the standard key handling for a toplevel window.
4871 * Return value: %TRUE if a widget in the focus chain handled the event.
4874 gtk_window_propagate_key_event (GtkWindow *window,
4877 gboolean handled = FALSE;
4878 GtkWidget *widget, *focus;
4880 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4882 widget = GTK_WIDGET (window);
4883 focus = window->focus_widget;
4885 g_object_ref (focus);
4888 focus && focus != widget &&
4889 gtk_widget_get_toplevel (focus) == widget)
4893 if (GTK_WIDGET_IS_SENSITIVE (focus))
4894 handled = gtk_widget_event (focus, (GdkEvent*) event);
4896 parent = focus->parent;
4898 g_object_ref (parent);
4900 g_object_unref (focus);
4906 g_object_unref (focus);
4912 gtk_window_key_press_event (GtkWidget *widget,
4915 GtkWindow *window = GTK_WINDOW (widget);
4916 gboolean handled = FALSE;
4918 /* handle mnemonics and accelerators */
4920 handled = gtk_window_activate_key (window, event);
4922 /* handle focus widget key events */
4924 handled = gtk_window_propagate_key_event (window, event);
4926 /* Chain up, invokes binding set */
4928 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
4934 gtk_window_key_release_event (GtkWidget *widget,
4937 GtkWindow *window = GTK_WINDOW (widget);
4938 gboolean handled = FALSE;
4940 /* handle focus widget key events */
4942 handled = gtk_window_propagate_key_event (window, event);
4944 /* Chain up, invokes binding set */
4946 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
4952 gtk_window_real_activate_default (GtkWindow *window)
4954 gtk_window_activate_default (window);
4958 gtk_window_real_activate_focus (GtkWindow *window)
4960 gtk_window_activate_focus (window);
4964 gtk_window_move_focus (GtkWindow *window,
4965 GtkDirectionType dir)
4967 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4969 if (!GTK_CONTAINER (window)->focus_child)
4970 gtk_window_set_focus (window, NULL);
4974 gtk_window_enter_notify_event (GtkWidget *widget,
4975 GdkEventCrossing *event)
4981 gtk_window_leave_notify_event (GtkWidget *widget,
4982 GdkEventCrossing *event)
4988 do_focus_change (GtkWidget *widget,
4991 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4993 g_object_ref (widget);
4996 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4998 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
5000 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5001 fevent->focus_change.window = widget->window;
5003 g_object_ref (widget->window);
5004 fevent->focus_change.in = in;
5006 gtk_widget_event (widget, fevent);
5008 g_object_notify (G_OBJECT (widget), "has-focus");
5010 g_object_unref (widget);
5011 gdk_event_free (fevent);
5015 gtk_window_focus_in_event (GtkWidget *widget,
5016 GdkEventFocus *event)
5018 GtkWindow *window = GTK_WINDOW (widget);
5020 /* It appears spurious focus in events can occur when
5021 * the window is hidden. So we'll just check to see if
5022 * the window is visible before actually handling the
5025 if (GTK_WIDGET_VISIBLE (widget))
5027 _gtk_window_set_has_toplevel_focus (window, TRUE);
5028 _gtk_window_set_is_active (window, TRUE);
5035 gtk_window_focus_out_event (GtkWidget *widget,
5036 GdkEventFocus *event)
5038 GtkWindow *window = GTK_WINDOW (widget);
5040 _gtk_window_set_has_toplevel_focus (window, FALSE);
5041 _gtk_window_set_is_active (window, FALSE);
5046 static GdkAtom atom_rcfiles = GDK_NONE;
5047 static GdkAtom atom_iconthemes = GDK_NONE;
5050 send_client_message_to_embedded_windows (GtkWidget *widget,
5051 GdkAtom message_type)
5053 GList *embedded_windows;
5055 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5056 if (embedded_windows)
5058 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5061 for (i = 0; i < 5; i++)
5062 send_event->client.data.l[i] = 0;
5063 send_event->client.data_format = 32;
5064 send_event->client.message_type = message_type;
5066 while (embedded_windows)
5068 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
5069 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5070 embedded_windows = embedded_windows->next;
5073 gdk_event_free (send_event);
5078 gtk_window_client_event (GtkWidget *widget,
5079 GdkEventClient *event)
5083 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5084 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5087 if (event->message_type == atom_rcfiles)
5089 send_client_message_to_embedded_windows (widget, atom_rcfiles);
5090 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
5093 if (event->message_type == atom_iconthemes)
5095 send_client_message_to_embedded_windows (widget, atom_iconthemes);
5096 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
5103 gtk_window_check_resize (GtkContainer *container)
5105 GtkWindow *window = GTK_WINDOW (container);
5107 if (GTK_WIDGET_VISIBLE (container))
5108 gtk_window_move_resize (window);
5112 gtk_window_focus (GtkWidget *widget,
5113 GtkDirectionType direction)
5117 GtkContainer *container;
5118 GtkWidget *old_focus_child;
5121 container = GTK_CONTAINER (widget);
5122 window = GTK_WINDOW (widget);
5123 bin = GTK_BIN (widget);
5125 old_focus_child = container->focus_child;
5127 /* We need a special implementation here to deal properly with wrapping
5128 * around in the tab chain without the danger of going into an
5131 if (old_focus_child)
5133 if (gtk_widget_child_focus (old_focus_child, direction))
5137 if (window->focus_widget)
5139 if (direction == GTK_DIR_LEFT ||
5140 direction == GTK_DIR_RIGHT ||
5141 direction == GTK_DIR_UP ||
5142 direction == GTK_DIR_DOWN)
5147 /* Wrapped off the end, clear the focus setting for the toplpevel */
5148 parent = window->focus_widget->parent;
5151 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5152 parent = GTK_WIDGET (parent)->parent;
5155 gtk_window_set_focus (GTK_WINDOW (container), NULL);
5158 /* Now try to focus the first widget in the window */
5161 if (gtk_widget_child_focus (bin->child, direction))
5169 gtk_window_real_set_focus (GtkWindow *window,
5172 GtkWidget *old_focus = window->focus_widget;
5173 gboolean had_default = FALSE;
5174 gboolean focus_had_default = FALSE;
5175 gboolean old_focus_had_default = FALSE;
5179 g_object_ref (old_focus);
5180 g_object_freeze_notify (G_OBJECT (old_focus));
5181 old_focus_had_default = GTK_WIDGET_HAS_DEFAULT (old_focus);
5185 g_object_ref (focus);
5186 g_object_freeze_notify (G_OBJECT (focus));
5187 focus_had_default = GTK_WIDGET_HAS_DEFAULT (focus);
5190 if (window->default_widget)
5191 had_default = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
5193 if (window->focus_widget)
5195 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
5196 (window->focus_widget != window->default_widget))
5198 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
5199 gtk_widget_queue_draw (window->focus_widget);
5201 if (window->default_widget)
5202 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
5205 window->focus_widget = NULL;
5207 if (window->has_focus)
5208 do_focus_change (old_focus, FALSE);
5210 g_object_notify (G_OBJECT (old_focus), "is-focus");
5213 /* The above notifications may have set a new focus widget,
5214 * if so, we don't want to override it.
5216 if (focus && !window->focus_widget)
5218 window->focus_widget = focus;
5220 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
5221 (window->focus_widget != window->default_widget))
5223 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
5224 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
5226 if (window->default_widget)
5227 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
5230 if (window->has_focus)
5231 do_focus_change (window->focus_widget, TRUE);
5233 g_object_notify (G_OBJECT (window->focus_widget), "is-focus");
5236 /* If the default widget changed, a redraw will have been queued
5237 * on the old and new default widgets by gtk_window_set_default(), so
5238 * we only have to worry about the case where it didn't change.
5239 * We'll sometimes queue a draw twice on the new widget but that
5242 if (window->default_widget &&
5243 (had_default != GTK_WIDGET_HAS_DEFAULT (window->default_widget)))
5244 gtk_widget_queue_draw (window->default_widget);
5248 if (old_focus_had_default != GTK_WIDGET_HAS_DEFAULT (old_focus))
5249 gtk_widget_queue_draw (old_focus);
5251 g_object_thaw_notify (G_OBJECT (old_focus));
5252 g_object_unref (old_focus);
5256 if (focus_had_default != GTK_WIDGET_HAS_DEFAULT (focus))
5257 gtk_widget_queue_draw (focus);
5259 g_object_thaw_notify (G_OBJECT (focus));
5260 g_object_unref (focus);
5265 * _gtk_window_unset_focus_and_default:
5266 * @window: a #GtkWindow
5267 * @widget: a widget inside of @window
5269 * Checks whether the focus and default widgets of @window are
5270 * @widget or a descendent of @widget, and if so, unset them.
5273 _gtk_window_unset_focus_and_default (GtkWindow *window,
5279 g_object_ref (window);
5280 g_object_ref (widget);
5282 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
5284 child = window->focus_widget;
5286 while (child && child != widget)
5287 child = child->parent;
5289 if (child == widget)
5290 gtk_window_set_focus (GTK_WINDOW (window), NULL);
5293 child = window->default_widget;
5295 while (child && child != widget)
5296 child = child->parent;
5298 if (child == widget)
5299 gtk_window_set_default (window, NULL);
5301 g_object_unref (widget);
5302 g_object_unref (window);
5305 /*********************************
5306 * Functions related to resizing *
5307 *********************************/
5309 /* This function doesn't constrain to geometry hints */
5311 gtk_window_compute_configure_request_size (GtkWindow *window,
5315 GtkRequisition requisition;
5316 GtkWindowGeometryInfo *info;
5320 * - we've done a size request
5323 widget = GTK_WIDGET (window);
5325 info = gtk_window_get_geometry_info (window, FALSE);
5327 if (window->need_default_size)
5329 gtk_widget_get_child_requisition (widget, &requisition);
5331 /* Default to requisition */
5332 *width = requisition.width;
5333 *height = requisition.height;
5335 /* If window is empty so requests 0, default to random nonzero size */
5336 if (*width == 0 && *height == 0)
5342 /* Override requisition with default size */
5346 gint base_width = 0;
5347 gint base_height = 0;
5349 gint min_height = 0;
5351 gint height_inc = 1;
5353 if (info->default_is_geometry &&
5354 (info->default_width > 0 || info->default_height > 0))
5356 GdkGeometry geometry;
5359 gtk_window_compute_hints (window, &geometry, &flags);
5361 if (flags & GDK_HINT_BASE_SIZE)
5363 base_width = geometry.base_width;
5364 base_height = geometry.base_height;
5366 if (flags & GDK_HINT_MIN_SIZE)
5368 min_width = geometry.min_width;
5369 min_height = geometry.min_height;
5371 if (flags & GDK_HINT_RESIZE_INC)
5373 width_inc = geometry.width_inc;
5374 height_inc = geometry.height_inc;
5378 if (info->default_width > 0)
5379 *width = MAX (info->default_width * width_inc + base_width, min_width);
5381 if (info->default_height > 0)
5382 *height = MAX (info->default_height * height_inc + base_height, min_height);
5387 /* Default to keeping current size */
5388 *width = widget->allocation.width;
5389 *height = widget->allocation.height;
5392 /* Override any size with gtk_window_resize() values */
5395 if (info->resize_width > 0)
5396 *width = info->resize_width;
5398 if (info->resize_height > 0)
5399 *height = info->resize_height;
5403 static GtkWindowPosition
5404 get_effective_position (GtkWindow *window)
5406 GtkWindowPosition pos = window->position;
5407 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5408 (window->transient_parent == NULL ||
5409 !GTK_WIDGET_MAPPED (window->transient_parent)))
5410 pos = GTK_WIN_POS_NONE;
5416 get_center_monitor_of_window (GtkWindow *window)
5418 /* We could try to sort out the relative positions of the monitors and
5419 * stuff, or we could just be losers and assume you have a row
5420 * or column of monitors.
5422 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5426 get_monitor_containing_pointer (GtkWindow *window)
5430 GdkScreen *window_screen;
5431 GdkScreen *pointer_screen;
5433 window_screen = gtk_window_check_screen (window);
5434 gdk_display_get_pointer (gdk_screen_get_display (window_screen),
5438 if (pointer_screen == window_screen)
5439 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5447 center_window_on_monitor (GtkWindow *window,
5453 GdkRectangle monitor;
5456 monitor_num = get_monitor_containing_pointer (window);
5458 if (monitor_num == -1)
5459 monitor_num = get_center_monitor_of_window (window);
5461 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5462 monitor_num, &monitor);
5464 *x = (monitor.width - w) / 2 + monitor.x;
5465 *y = (monitor.height - h) / 2 + monitor.y;
5467 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5468 * and WM decorations.
5477 clamp_window_to_rectangle (gint *x,
5481 const GdkRectangle *rect)
5483 gint outside_w, outside_h;
5485 outside_w = (*x + w) - (rect->x + rect->width);
5489 outside_h = (*y + h) - (rect->y + rect->height);
5493 /* if larger than the screen, center on the screen. */
5495 *x += (rect->x - *x) / 2;
5497 *y += (rect->y - *y) / 2;
5502 gtk_window_compute_configure_request (GtkWindow *window,
5503 GdkRectangle *request,
5504 GdkGeometry *geometry,
5507 GdkGeometry new_geometry;
5511 GtkWindowPosition pos;
5512 GtkWidget *parent_widget;
5513 GtkWindowGeometryInfo *info;
5517 widget = GTK_WIDGET (window);
5519 screen = gtk_window_check_screen (window);
5521 gtk_widget_size_request (widget, NULL);
5522 gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
5524 gtk_window_compute_hints (window, &new_geometry, &new_flags);
5525 gtk_window_constrain_size (window,
5526 &new_geometry, new_flags,
5530 parent_widget = (GtkWidget*) window->transient_parent;
5532 pos = get_effective_position (window);
5533 info = gtk_window_get_geometry_info (window, FALSE);
5535 /* by default, don't change position requested */
5538 x = info->last.configure_request.x;
5539 y = info->last.configure_request.y;
5548 if (window->need_default_position)
5551 /* FIXME this all interrelates with window gravity.
5552 * For most of them I think we want to set GRAVITY_CENTER.
5554 * Not sure how to go about that.
5559 /* here we are only handling CENTER_ALWAYS
5560 * as it relates to default positioning,
5561 * where it's equivalent to simply CENTER
5563 case GTK_WIN_POS_CENTER_ALWAYS:
5564 case GTK_WIN_POS_CENTER:
5565 center_window_on_monitor (window, w, h, &x, &y);
5568 case GTK_WIN_POS_CENTER_ON_PARENT:
5571 GdkRectangle monitor;
5574 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
5576 if (parent_widget->window != NULL)
5577 monitor_num = gdk_screen_get_monitor_at_window (screen,
5578 parent_widget->window);
5582 gdk_window_get_origin (parent_widget->window,
5585 x = ox + (parent_widget->allocation.width - w) / 2;
5586 y = oy + (parent_widget->allocation.height - h) / 2;
5588 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5589 * WM decorations. If parent wasn't on a monitor, just
5592 if (monitor_num >= 0)
5594 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5595 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5600 case GTK_WIN_POS_MOUSE:
5602 gint screen_width = gdk_screen_get_width (screen);
5603 gint screen_height = gdk_screen_get_height (screen);
5605 GdkRectangle monitor;
5606 GdkScreen *pointer_screen;
5609 gdk_display_get_pointer (gdk_screen_get_display (screen),
5613 if (pointer_screen == screen)
5614 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
5620 x = CLAMP (x, 0, screen_width - w);
5621 y = CLAMP (y, 0, screen_height - h);
5623 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5624 * WM decorations. Don't try to figure out what's going
5625 * on if the mouse wasn't inside a monitor.
5627 if (monitor_num >= 0)
5629 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5630 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5638 } /* if (window->need_default_position) */
5640 if (window->need_default_position && info &&
5641 info->initial_pos_set)
5643 x = info->initial_x;
5644 y = info->initial_y;
5645 gtk_window_constrain_position (window, w, h, &x, &y);
5651 request->height = h;
5654 *geometry = new_geometry;
5660 gtk_window_constrain_position (GtkWindow *window,
5666 /* See long comments in gtk_window_move_resize()
5667 * on when it's safe to call this function.
5669 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
5671 gint center_x, center_y;
5673 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
5681 gtk_window_move_resize (GtkWindow *window)
5685 * First we determine whether any information has changed that would
5686 * cause us to revise our last configure request. If we would send
5687 * a different configure request from last time, then
5688 * configure_request_size_changed = TRUE or
5689 * configure_request_pos_changed = TRUE. configure_request_size_changed
5690 * may be true due to new hints, a gtk_window_resize(), or whatever.
5691 * configure_request_pos_changed may be true due to gtk_window_set_position()
5692 * or gtk_window_move().
5694 * If the configure request has changed, we send off a new one. To
5695 * ensure GTK+ invariants are maintained (resize queue does what it
5696 * should), we go ahead and size_allocate the requested size in this
5699 * If the configure request has not changed, we don't ever resend
5700 * it, because it could mean fighting the user or window manager.
5703 * To prepare the configure request, we come up with a base size/pos:
5704 * - the one from gtk_window_move()/gtk_window_resize()
5705 * - else default_width, default_height if we haven't ever
5707 * - else the size request if we haven't ever been mapped,
5708 * as a substitute default size
5709 * - else the current size of the window, as received from
5710 * configure notifies (i.e. the current allocation)
5712 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
5713 * the position request to be centered.
5716 GtkContainer *container;
5717 GtkWindowGeometryInfo *info;
5718 GdkGeometry new_geometry;
5720 GdkRectangle new_request;
5721 gboolean configure_request_size_changed;
5722 gboolean configure_request_pos_changed;
5723 gboolean hints_changed; /* do we need to send these again */
5724 GtkWindowLastGeometryInfo saved_last_info;
5726 widget = GTK_WIDGET (window);
5727 container = GTK_CONTAINER (widget);
5728 info = gtk_window_get_geometry_info (window, TRUE);
5730 configure_request_size_changed = FALSE;
5731 configure_request_pos_changed = FALSE;
5733 gtk_window_compute_configure_request (window, &new_request,
5734 &new_geometry, &new_flags);
5736 /* This check implies the invariant that we never set info->last
5737 * without setting the hints and sending off a configure request.
5739 * If we change info->last without sending the request, we may
5742 if (info->last.configure_request.x != new_request.x ||
5743 info->last.configure_request.y != new_request.y)
5744 configure_request_pos_changed = TRUE;
5746 if ((info->last.configure_request.width != new_request.width ||
5747 info->last.configure_request.height != new_request.height))
5748 configure_request_size_changed = TRUE;
5750 hints_changed = FALSE;
5752 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
5753 &new_geometry, new_flags))
5755 hints_changed = TRUE;
5758 /* Position Constraints
5759 * ====================
5761 * POS_CENTER_ALWAYS is conceptually a constraint rather than
5762 * a default. The other POS_ values are used only when the
5763 * window is shown, not after that.
5765 * However, we can't implement a position constraint as
5766 * "anytime the window size changes, center the window"
5767 * because this may well end up fighting the WM or user. In
5768 * fact it gets in an infinite loop with at least one WM.
5770 * Basically, applications are in no way in a position to
5771 * constrain the position of a window, with one exception:
5772 * override redirect windows. (Really the intended purpose
5773 * of CENTER_ALWAYS anyhow, I would think.)
5775 * So the way we implement this "constraint" is to say that when WE
5776 * cause a move or resize, i.e. we make a configure request changing
5777 * window size, we recompute the CENTER_ALWAYS position to reflect
5778 * the new window size, and include it in our request. Also, if we
5779 * just turned on CENTER_ALWAYS we snap to center with a new
5780 * request. Otherwise, if we are just NOTIFIED of a move or resize
5781 * done by someone else e.g. the window manager, we do NOT send a
5782 * new configure request.
5784 * For override redirect windows, this works fine; all window
5785 * sizes are from our configure requests. For managed windows,
5786 * it is at least semi-sane, though who knows what the
5787 * app author is thinking.
5790 /* This condition should be kept in sync with the condition later on
5791 * that determines whether we send a configure request. i.e. we
5792 * should do this position constraining anytime we were going to
5793 * send a configure request anyhow, plus when constraints have
5796 if (configure_request_pos_changed ||
5797 configure_request_size_changed ||
5799 info->position_constraints_changed)
5801 /* We request the constrained position if:
5802 * - we were changing position, and need to clamp
5803 * the change to the constraint
5804 * - we're changing the size anyway
5805 * - set_position() was called to toggle CENTER_ALWAYS on
5808 gtk_window_constrain_position (window,
5814 /* Update whether we need to request a move */
5815 if (info->last.configure_request.x != new_request.x ||
5816 info->last.configure_request.y != new_request.y)
5817 configure_request_pos_changed = TRUE;
5819 configure_request_pos_changed = FALSE;
5823 if (window->type == GTK_WINDOW_TOPLEVEL)
5825 int notify_x, notify_y;
5827 /* this is the position from the last configure notify */
5828 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
5830 g_message ("--- %s ---\n"
5831 "last : %d,%d\t%d x %d\n"
5832 "this : %d,%d\t%d x %d\n"
5833 "alloc : %d,%d\t%d x %d\n"
5835 "resize: \t%d x %d\n"
5836 "size_changed: %d pos_changed: %d hints_changed: %d\n"
5837 "configure_notify_received: %d\n"
5838 "configure_request_count: %d\n"
5839 "position_constraints_changed: %d\n",
5840 window->title ? window->title : "(no title)",
5841 info->last.configure_request.x,
5842 info->last.configure_request.y,
5843 info->last.configure_request.width,
5844 info->last.configure_request.height,
5850 widget->allocation.width,
5851 widget->allocation.height,
5852 widget->requisition.width,
5853 widget->requisition.height,
5855 info->resize_height,
5856 configure_request_pos_changed,
5857 configure_request_size_changed,
5859 window->configure_notify_received,
5860 window->configure_request_count,
5861 info->position_constraints_changed);
5865 saved_last_info = info->last;
5866 info->last.geometry = new_geometry;
5867 info->last.flags = new_flags;
5868 info->last.configure_request = new_request;
5870 /* need to set PPosition so the WM will look at our position,
5871 * but we don't want to count PPosition coming and going as a hints
5872 * change for future iterations. So we saved info->last prior to
5876 /* Also, if the initial position was explicitly set, then we always
5877 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
5881 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
5882 * this is an initial map
5885 if ((configure_request_pos_changed ||
5886 info->initial_pos_set ||
5887 (window->need_default_position &&
5888 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
5889 (new_flags & GDK_HINT_POS) == 0)
5891 new_flags |= GDK_HINT_POS;
5892 hints_changed = TRUE;
5895 /* Set hints if necessary
5898 gdk_window_set_geometry_hints (widget->window,
5902 /* handle resizing/moving and widget tree allocation
5904 if (window->configure_notify_received)
5906 GtkAllocation allocation;
5908 /* If we have received a configure event since
5909 * the last time in this function, we need to
5910 * accept our new size and size_allocate child widgets.
5911 * (see gtk_window_configure_event() for more details).
5913 * 1 or more configure notifies may have been received.
5914 * Also, configure_notify_received will only be TRUE
5915 * if all expected configure notifies have been received
5916 * (one per configure request), as an optimization.
5919 window->configure_notify_received = FALSE;
5921 /* gtk_window_configure_event() filled in widget->allocation */
5922 allocation = widget->allocation;
5923 gtk_widget_size_allocate (widget, &allocation);
5925 gdk_window_process_updates (widget->window, TRUE);
5927 gdk_window_configure_finished (widget->window);
5929 /* If the configure request changed, it means that
5931 * 1) coincidentally changed hints or widget properties
5932 * impacting the configure request before getting
5933 * a configure notify, or
5934 * 2) some broken widget is changing its size request
5935 * during size allocation, resulting in
5936 * a false appearance of changed configure request.
5938 * For 1), we could just go ahead and ask for the
5939 * new size right now, but doing that for 2)
5940 * might well be fighting the user (and can even
5941 * trigger a loop). Since we really don't want to
5942 * do that, we requeue a resize in hopes that
5943 * by the time it gets handled, the child has seen
5944 * the light and is willing to go along with the
5945 * new size. (this happens for the zvt widget, since
5946 * the size_allocate() above will have stored the
5947 * requisition corresponding to the new size in the
5950 * This doesn't buy us anything for 1), but it shouldn't
5951 * hurt us too badly, since it is what would have
5952 * happened if we had gotten the configure event before
5953 * the new size had been set.
5956 if (configure_request_size_changed ||
5957 configure_request_pos_changed)
5959 /* Don't change the recorded last info after all, because we
5960 * haven't actually updated to the new info yet - we decided
5961 * to postpone our configure request until later.
5963 info->last = saved_last_info;
5965 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
5968 return; /* Bail out, we didn't really process the move/resize */
5970 else if ((configure_request_size_changed || hints_changed) &&
5971 (widget->allocation.width != new_request.width ||
5972 widget->allocation.height != new_request.height))
5975 /* We are in one of the following situations:
5976 * A. configure_request_size_changed
5977 * our requisition has changed and we need a different window size,
5978 * so we request it from the window manager.
5979 * B. !configure_request_size_changed && hints_changed
5980 * the window manager rejects our size, but we have just changed the
5981 * window manager hints, so there's a chance our request will
5982 * be honoured this time, so we try again.
5984 * However, if the new requisition is the same as the current allocation,
5985 * we don't request it again, since we won't get a ConfigureNotify back from
5986 * the window manager unless it decides to change our requisition. If
5987 * we don't get the ConfigureNotify back, the resize queue will never be run.
5990 /* Now send the configure request */
5991 if (configure_request_pos_changed)
5995 gdk_window_move_resize (window->frame,
5996 new_request.x - window->frame_left,
5997 new_request.y - window->frame_top,
5998 new_request.width + window->frame_left + window->frame_right,
5999 new_request.height + window->frame_top + window->frame_bottom);
6000 gdk_window_resize (widget->window,
6001 new_request.width, new_request.height);
6004 gdk_window_move_resize (widget->window,
6005 new_request.x, new_request.y,
6006 new_request.width, new_request.height);
6008 else /* only size changed */
6011 gdk_window_resize (window->frame,
6012 new_request.width + window->frame_left + window->frame_right,
6013 new_request.height + window->frame_top + window->frame_bottom);
6014 gdk_window_resize (widget->window,
6015 new_request.width, new_request.height);
6018 /* Increment the number of have-not-yet-received-notify requests */
6019 window->configure_request_count += 1;
6021 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6022 * configure event in response to our resizing request.
6023 * the configure event will cause a new resize with
6024 * ->configure_notify_received=TRUE.
6025 * until then, we want to
6026 * - discard expose events
6027 * - coalesce resizes for our children
6028 * - defer any window resizes until the configure event arrived
6029 * to achieve this, we queue a resize for the window, but remove its
6030 * resizing handler, so resizing will not be handled from the next
6031 * idle handler but when the configure event arrives.
6033 * FIXME: we should also dequeue the pending redraws here, since
6034 * we handle those ourselves upon ->configure_notify_received==TRUE.
6036 if (container->resize_mode == GTK_RESIZE_QUEUE)
6038 gtk_widget_queue_resize (widget);
6039 _gtk_container_dequeue_resize_handler (container);
6044 /* Handle any position changes.
6046 if (configure_request_pos_changed)
6050 gdk_window_move (window->frame,
6051 new_request.x - window->frame_left,
6052 new_request.y - window->frame_top);
6055 gdk_window_move (widget->window,
6056 new_request.x, new_request.y);
6059 /* And run the resize queue.
6061 gtk_container_resize_children (container);
6064 /* We have now processed a move/resize since the last position
6065 * constraint change, setting of the initial position, or resize.
6066 * (Not resetting these flags here can lead to infinite loops for
6067 * GTK_RESIZE_IMMEDIATE containers)
6069 info->position_constraints_changed = FALSE;
6070 info->initial_pos_set = FALSE;
6071 info->resize_width = -1;
6072 info->resize_height = -1;
6075 /* Compare two sets of Geometry hints for equality.
6078 gtk_window_compare_hints (GdkGeometry *geometry_a,
6080 GdkGeometry *geometry_b,
6083 if (flags_a != flags_b)
6086 if ((flags_a & GDK_HINT_MIN_SIZE) &&
6087 (geometry_a->min_width != geometry_b->min_width ||
6088 geometry_a->min_height != geometry_b->min_height))
6091 if ((flags_a & GDK_HINT_MAX_SIZE) &&
6092 (geometry_a->max_width != geometry_b->max_width ||
6093 geometry_a->max_height != geometry_b->max_height))
6096 if ((flags_a & GDK_HINT_BASE_SIZE) &&
6097 (geometry_a->base_width != geometry_b->base_width ||
6098 geometry_a->base_height != geometry_b->base_height))
6101 if ((flags_a & GDK_HINT_ASPECT) &&
6102 (geometry_a->min_aspect != geometry_b->min_aspect ||
6103 geometry_a->max_aspect != geometry_b->max_aspect))
6106 if ((flags_a & GDK_HINT_RESIZE_INC) &&
6107 (geometry_a->width_inc != geometry_b->width_inc ||
6108 geometry_a->height_inc != geometry_b->height_inc))
6111 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
6112 geometry_a->win_gravity != geometry_b->win_gravity)
6119 _gtk_window_constrain_size (GtkWindow *window,
6125 GtkWindowGeometryInfo *info;
6127 g_return_if_fail (GTK_IS_WINDOW (window));
6129 info = window->geometry_info;
6132 GdkWindowHints flags = info->last.flags;
6133 GdkGeometry *geometry = &info->last.geometry;
6135 gtk_window_constrain_size (window,
6146 gtk_window_constrain_size (GtkWindow *window,
6147 GdkGeometry *geometry,
6154 gdk_window_constrain_size (geometry, flags, width, height,
6155 new_width, new_height);
6158 /* Compute the set of geometry hints and flags for a window
6159 * based on the application set geometry, and requisiition
6160 * of the window. gtk_widget_size_request() must have been
6164 gtk_window_compute_hints (GtkWindow *window,
6165 GdkGeometry *new_geometry,
6169 gint extra_width = 0;
6170 gint extra_height = 0;
6171 GtkWindowGeometryInfo *geometry_info;
6172 GtkRequisition requisition;
6174 widget = GTK_WIDGET (window);
6176 gtk_widget_get_child_requisition (widget, &requisition);
6177 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
6181 *new_flags = geometry_info->mask;
6182 *new_geometry = geometry_info->geometry;
6189 if (geometry_info && geometry_info->widget)
6191 GtkRequisition child_requisition;
6193 /* FIXME: This really isn't right. It gets the min size wrong and forces
6194 * callers to do horrible hacks like set a huge usize on the child requisition
6195 * to get the base size right. We really want to find the answers to:
6197 * - If the geometry widget was infinitely big, how much extra space
6198 * would be needed for the stuff around it.
6200 * - If the geometry widget was infinitely small, how big would the
6201 * window still have to be.
6203 * Finding these answers would be a bit of a mess here. (Bug #68668)
6205 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
6207 extra_width = widget->requisition.width - child_requisition.width;
6208 extra_height = widget->requisition.height - child_requisition.height;
6211 /* We don't want to set GDK_HINT_POS in here, we just set it
6212 * in gtk_window_move_resize() when we want the position
6216 if (*new_flags & GDK_HINT_BASE_SIZE)
6218 new_geometry->base_width += extra_width;
6219 new_geometry->base_height += extra_height;
6221 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
6222 (*new_flags & GDK_HINT_RESIZE_INC) &&
6223 ((extra_width != 0) || (extra_height != 0)))
6225 *new_flags |= GDK_HINT_BASE_SIZE;
6227 new_geometry->base_width = extra_width;
6228 new_geometry->base_height = extra_height;
6231 if (*new_flags & GDK_HINT_MIN_SIZE)
6233 if (new_geometry->min_width < 0)
6234 new_geometry->min_width = requisition.width;
6236 new_geometry->min_width += extra_width;
6238 if (new_geometry->min_height < 0)
6239 new_geometry->min_height = requisition.height;
6241 new_geometry->min_height += extra_height;
6243 else if (!window->allow_shrink)
6245 *new_flags |= GDK_HINT_MIN_SIZE;
6247 new_geometry->min_width = requisition.width;
6248 new_geometry->min_height = requisition.height;
6251 if (*new_flags & GDK_HINT_MAX_SIZE)
6253 if (new_geometry->max_width < 0)
6254 new_geometry->max_width = requisition.width;
6256 new_geometry->max_width += extra_width;
6258 if (new_geometry->max_height < 0)
6259 new_geometry->max_height = requisition.height;
6261 new_geometry->max_height += extra_height;
6263 else if (!window->allow_grow)
6265 *new_flags |= GDK_HINT_MAX_SIZE;
6267 new_geometry->max_width = requisition.width;
6268 new_geometry->max_height = requisition.height;
6271 *new_flags |= GDK_HINT_WIN_GRAVITY;
6272 new_geometry->win_gravity = window->gravity;
6275 /***********************
6276 * Redrawing functions *
6277 ***********************/
6280 gtk_window_paint (GtkWidget *widget,
6283 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
6284 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
6288 gtk_window_expose (GtkWidget *widget,
6289 GdkEventExpose *event)
6291 if (!GTK_WIDGET_APP_PAINTABLE (widget))
6292 gtk_window_paint (widget, &event->area);
6294 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event)
6295 return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event);
6301 * gtk_window_set_has_frame:
6302 * @window: a #GtkWindow
6303 * @setting: a boolean
6305 * (Note: this is a special-purpose function for the framebuffer port,
6306 * that causes GTK+ to draw its own window border. For most applications,
6307 * you want gtk_window_set_decorated() instead, which tells the window
6308 * manager whether to draw the window border.)
6310 * If this function is called on a window with setting of %TRUE, before
6311 * it is realized or showed, it will have a "frame" window around
6312 * @window->window, accessible in @window->frame. Using the signal
6313 * frame_event you can receive all events targeted at the frame.
6315 * This function is used by the linux-fb port to implement managed
6316 * windows, but it could conceivably be used by X-programs that
6317 * want to do their own window decorations.
6321 gtk_window_set_has_frame (GtkWindow *window,
6324 g_return_if_fail (GTK_IS_WINDOW (window));
6325 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
6327 window->has_frame = setting != FALSE;
6331 * gtk_window_get_has_frame:
6332 * @window: a #GtkWindow
6334 * Accessor for whether the window has a frame window exterior to
6335 * @window->window. Gets the value set by gtk_window_set_has_frame ().
6337 * Return value: %TRUE if a frame has been added to the window
6338 * via gtk_window_set_has_frame().
6341 gtk_window_get_has_frame (GtkWindow *window)
6343 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6345 return window->has_frame;
6349 * gtk_window_set_frame_dimensions:
6350 * @window: a #GtkWindow that has a frame
6351 * @left: The width of the left border
6352 * @top: The height of the top border
6353 * @right: The width of the right border
6354 * @bottom: The height of the bottom border
6356 * (Note: this is a special-purpose function intended for the framebuffer
6357 * port; see gtk_window_set_has_frame(). It will have no effect on the
6358 * window border drawn by the window manager, which is the normal
6359 * case when using the X Window system.)
6361 * For windows with frames (see gtk_window_set_has_frame()) this function
6362 * can be used to change the size of the frame border.
6365 gtk_window_set_frame_dimensions (GtkWindow *window,
6373 g_return_if_fail (GTK_IS_WINDOW (window));
6375 widget = GTK_WIDGET (window);
6377 if (window->frame_left == left &&
6378 window->frame_top == top &&
6379 window->frame_right == right &&
6380 window->frame_bottom == bottom)
6383 window->frame_left = left;
6384 window->frame_top = top;
6385 window->frame_right = right;
6386 window->frame_bottom = bottom;
6388 if (GTK_WIDGET_REALIZED (widget) && window->frame)
6390 gint width = widget->allocation.width + left + right;
6391 gint height = widget->allocation.height + top + bottom;
6392 gdk_window_resize (window->frame, width, height);
6393 gtk_decorated_window_move_resize_window (window,
6395 widget->allocation.width,
6396 widget->allocation.height);
6401 * gtk_window_present:
6402 * @window: a #GtkWindow
6404 * Presents a window to the user. This may mean raising the window
6405 * in the stacking order, deiconifying it, moving it to the current
6406 * desktop, and/or giving it the keyboard focus, possibly dependent
6407 * on the user's platform, window manager, and preferences.
6409 * If @window is hidden, this function calls gtk_widget_show()
6412 * This function should be used when the user tries to open a window
6413 * that's already open. Say for example the preferences dialog is
6414 * currently open, and the user chooses Preferences from the menu
6415 * a second time; use gtk_window_present() to move the already-open dialog
6416 * where the user can see it.
6418 * If you are calling this function in response to a user interaction,
6419 * it is preferable to use gtk_window_present_with_time().
6423 gtk_window_present (GtkWindow *window)
6425 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6429 * gtk_window_present_with_time:
6430 * @window: a #GtkWindow
6431 * @timestamp: the timestamp of the user interaction (typically a
6432 * button or key press event) which triggered this call
6434 * Presents a window to the user in response to a user interaction.
6435 * If you need to present a window without a timestamp, use
6436 * gtk_window_present(). See gtk_window_present() for details.
6441 gtk_window_present_with_time (GtkWindow *window,
6446 g_return_if_fail (GTK_IS_WINDOW (window));
6448 widget = GTK_WIDGET (window);
6450 if (GTK_WIDGET_VISIBLE (window))
6452 g_assert (widget->window != NULL);
6454 gdk_window_show (widget->window);
6456 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
6457 if (timestamp == GDK_CURRENT_TIME)
6459 #ifdef GDK_WINDOWING_X11
6460 GdkDisplay *display;
6462 display = gtk_widget_get_display (GTK_WIDGET (window));
6463 timestamp = gdk_x11_display_get_user_time (display);
6465 timestamp = gtk_get_current_event_time ();
6469 gdk_window_focus (widget->window, timestamp);
6473 gtk_widget_show (widget);
6478 * gtk_window_iconify:
6479 * @window: a #GtkWindow
6481 * Asks to iconify (i.e. minimize) the specified @window. Note that
6482 * you shouldn't assume the window is definitely iconified afterward,
6483 * because other entities (e.g. the user or <link
6484 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
6485 * again, or there may not be a window manager in which case
6486 * iconification isn't possible, etc. But normally the window will end
6487 * up iconified. Just don't write code that crashes if not.
6489 * It's permitted to call this function before showing a window,
6490 * in which case the window will be iconified before it ever appears
6493 * You can track iconification via the "window_state_event" signal
6498 gtk_window_iconify (GtkWindow *window)
6501 GdkWindow *toplevel;
6503 g_return_if_fail (GTK_IS_WINDOW (window));
6505 widget = GTK_WIDGET (window);
6507 window->iconify_initially = TRUE;
6510 toplevel = window->frame;
6512 toplevel = widget->window;
6514 if (toplevel != NULL)
6515 gdk_window_iconify (toplevel);
6519 * gtk_window_deiconify:
6520 * @window: a #GtkWindow
6522 * Asks to deiconify (i.e. unminimize) the specified @window. Note
6523 * that you shouldn't assume the window is definitely deiconified
6524 * afterward, because other entities (e.g. the user or <link
6525 * linkend="gtk-X11-arch">window manager</link>) could iconify it
6526 * again before your code which assumes deiconification gets to run.
6528 * You can track iconification via the "window_state_event" signal
6532 gtk_window_deiconify (GtkWindow *window)
6535 GdkWindow *toplevel;
6537 g_return_if_fail (GTK_IS_WINDOW (window));
6539 widget = GTK_WIDGET (window);
6541 window->iconify_initially = FALSE;
6544 toplevel = window->frame;
6546 toplevel = widget->window;
6548 if (toplevel != NULL)
6549 gdk_window_deiconify (toplevel);
6554 * @window: a #GtkWindow
6556 * Asks to stick @window, which means that it will appear on all user
6557 * desktops. Note that you shouldn't assume the window is definitely
6558 * stuck afterward, because other entities (e.g. the user or <link
6559 * linkend="gtk-X11-arch">window manager</link>) could unstick it
6560 * again, and some window managers do not support sticking
6561 * windows. But normally the window will end up stuck. Just don't
6562 * write code that crashes if not.
6564 * It's permitted to call this function before showing a window.
6566 * You can track stickiness via the "window_state_event" signal
6571 gtk_window_stick (GtkWindow *window)
6574 GdkWindow *toplevel;
6576 g_return_if_fail (GTK_IS_WINDOW (window));
6578 widget = GTK_WIDGET (window);
6580 window->stick_initially = TRUE;
6583 toplevel = window->frame;
6585 toplevel = widget->window;
6587 if (toplevel != NULL)
6588 gdk_window_stick (toplevel);
6592 * gtk_window_unstick:
6593 * @window: a #GtkWindow
6595 * Asks to unstick @window, which means that it will appear on only
6596 * one of the user's desktops. Note that you shouldn't assume the
6597 * window is definitely unstuck afterward, because other entities
6598 * (e.g. the user or <link linkend="gtk-X11-arch">window
6599 * manager</link>) could stick it again. But normally the window will
6600 * end up stuck. Just don't write code that crashes if not.
6602 * You can track stickiness via the "window_state_event" signal
6607 gtk_window_unstick (GtkWindow *window)
6610 GdkWindow *toplevel;
6612 g_return_if_fail (GTK_IS_WINDOW (window));
6614 widget = GTK_WIDGET (window);
6616 window->stick_initially = FALSE;
6619 toplevel = window->frame;
6621 toplevel = widget->window;
6623 if (toplevel != NULL)
6624 gdk_window_unstick (toplevel);
6628 * gtk_window_maximize:
6629 * @window: a #GtkWindow
6631 * Asks to maximize @window, so that it becomes full-screen. Note that
6632 * you shouldn't assume the window is definitely maximized afterward,
6633 * because other entities (e.g. the user or <link
6634 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
6635 * again, and not all window managers support maximization. But
6636 * normally the window will end up maximized. Just don't write code
6637 * that crashes if not.
6639 * It's permitted to call this function before showing a window,
6640 * in which case the window will be maximized when it appears onscreen
6643 * You can track maximization via the "window_state_event" signal
6648 gtk_window_maximize (GtkWindow *window)
6651 GdkWindow *toplevel;
6653 g_return_if_fail (GTK_IS_WINDOW (window));
6655 widget = GTK_WIDGET (window);
6657 window->maximize_initially = TRUE;
6660 toplevel = window->frame;
6662 toplevel = widget->window;
6664 if (toplevel != NULL)
6665 gdk_window_maximize (toplevel);
6669 * gtk_window_unmaximize:
6670 * @window: a #GtkWindow
6672 * Asks to unmaximize @window. Note that you shouldn't assume the
6673 * window is definitely unmaximized afterward, because other entities
6674 * (e.g. the user or <link linkend="gtk-X11-arch">window
6675 * manager</link>) could maximize it again, and not all window
6676 * managers honor requests to unmaximize. But normally the window will
6677 * end up unmaximized. Just don't write code that crashes if not.
6679 * You can track maximization via the "window_state_event" signal
6684 gtk_window_unmaximize (GtkWindow *window)
6687 GdkWindow *toplevel;
6689 g_return_if_fail (GTK_IS_WINDOW (window));
6691 widget = GTK_WIDGET (window);
6693 window->maximize_initially = FALSE;
6696 toplevel = window->frame;
6698 toplevel = widget->window;
6700 if (toplevel != NULL)
6701 gdk_window_unmaximize (toplevel);
6705 * gtk_window_fullscreen:
6706 * @window: a #GtkWindow
6708 * Asks to place @window in the fullscreen state. Note that you
6709 * shouldn't assume the window is definitely full screen afterward,
6710 * because other entities (e.g. the user or <link
6711 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
6712 * again, and not all window managers honor requests to fullscreen
6713 * windows. But normally the window will end up fullscreen. Just
6714 * don't write code that crashes if not.
6716 * You can track the fullscreen state via the "window_state_event" signal
6722 gtk_window_fullscreen (GtkWindow *window)
6725 GdkWindow *toplevel;
6726 GtkWindowPrivate *priv;
6728 g_return_if_fail (GTK_IS_WINDOW (window));
6730 widget = GTK_WIDGET (window);
6731 priv = GTK_WINDOW_GET_PRIVATE (window);
6733 priv->fullscreen_initially = TRUE;
6736 toplevel = window->frame;
6738 toplevel = widget->window;
6740 if (toplevel != NULL)
6741 gdk_window_fullscreen (toplevel);
6745 * gtk_window_unfullscreen:
6746 * @window: a #GtkWindow
6748 * Asks to toggle off the fullscreen state for @window. Note that you
6749 * shouldn't assume the window is definitely not full screen
6750 * afterward, because other entities (e.g. the user or <link
6751 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
6752 * again, and not all window managers honor requests to unfullscreen
6753 * windows. But normally the window will end up restored to its normal
6754 * state. Just don't write code that crashes if not.
6756 * You can track the fullscreen state via the "window_state_event" signal
6762 gtk_window_unfullscreen (GtkWindow *window)
6765 GdkWindow *toplevel;
6766 GtkWindowPrivate *priv;
6768 g_return_if_fail (GTK_IS_WINDOW (window));
6770 widget = GTK_WIDGET (window);
6771 priv = GTK_WINDOW_GET_PRIVATE (window);
6773 priv->fullscreen_initially = FALSE;
6776 toplevel = window->frame;
6778 toplevel = widget->window;
6780 if (toplevel != NULL)
6781 gdk_window_unfullscreen (toplevel);
6785 * gtk_window_set_keep_above:
6786 * @window: a #GtkWindow
6787 * @setting: whether to keep @window above other windows
6789 * Asks to keep @window above, so that it stays on top. Note that
6790 * you shouldn't assume the window is definitely above afterward,
6791 * because other entities (e.g. the user or <link
6792 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
6793 * and not all window managers support keeping windows above. But
6794 * normally the window will end kept above. Just don't write code
6795 * that crashes if not.
6797 * It's permitted to call this function before showing a window,
6798 * in which case the window will be kept above when it appears onscreen
6801 * You can track the above state via the "window_state_event" signal
6804 * Note that, according to the <ulink
6805 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
6806 * Manager Hints</ulink> specification, the above state is mainly meant
6807 * for user preferences and should not be used by applications e.g. for
6808 * drawing attention to their dialogs.
6813 gtk_window_set_keep_above (GtkWindow *window,
6817 GtkWindowPrivate *priv;
6818 GdkWindow *toplevel;
6820 g_return_if_fail (GTK_IS_WINDOW (window));
6822 widget = GTK_WIDGET (window);
6823 priv = GTK_WINDOW_GET_PRIVATE (window);
6825 priv->above_initially = setting != FALSE;
6827 priv->below_initially = FALSE;
6830 toplevel = window->frame;
6832 toplevel = widget->window;
6834 if (toplevel != NULL)
6835 gdk_window_set_keep_above (toplevel, setting);
6839 * gtk_window_set_keep_below:
6840 * @window: a #GtkWindow
6841 * @setting: whether to keep @window below other windows
6843 * Asks to keep @window below, so that it stays in bottom. Note that
6844 * you shouldn't assume the window is definitely below afterward,
6845 * because other entities (e.g. the user or <link
6846 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
6847 * and not all window managers support putting windows below. But
6848 * normally the window will be kept below. Just don't write code
6849 * that crashes if not.
6851 * It's permitted to call this function before showing a window,
6852 * in which case the window will be kept below when it appears onscreen
6855 * You can track the below state via the "window_state_event" signal
6858 * Note that, according to the <ulink
6859 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
6860 * Manager Hints</ulink> specification, the above state is mainly meant
6861 * for user preferences and should not be used by applications e.g. for
6862 * drawing attention to their dialogs.
6867 gtk_window_set_keep_below (GtkWindow *window,
6871 GtkWindowPrivate *priv;
6872 GdkWindow *toplevel;
6874 g_return_if_fail (GTK_IS_WINDOW (window));
6876 widget = GTK_WIDGET (window);
6877 priv = GTK_WINDOW_GET_PRIVATE (window);
6879 priv->below_initially = setting != FALSE;
6881 priv->above_initially = FALSE;
6884 toplevel = window->frame;
6886 toplevel = widget->window;
6888 if (toplevel != NULL)
6889 gdk_window_set_keep_below (toplevel, setting);
6893 * gtk_window_set_resizable:
6894 * @window: a #GtkWindow
6895 * @resizable: %TRUE if the user can resize this window
6897 * Sets whether the user can resize a window. Windows are user resizable
6901 gtk_window_set_resizable (GtkWindow *window,
6904 g_return_if_fail (GTK_IS_WINDOW (window));
6906 gtk_window_set_policy (window, FALSE, resizable, FALSE);
6910 * gtk_window_get_resizable:
6911 * @window: a #GtkWindow
6913 * Gets the value set by gtk_window_set_resizable().
6915 * Return value: %TRUE if the user can resize the window
6918 gtk_window_get_resizable (GtkWindow *window)
6920 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6922 /* allow_grow is most likely to indicate the semantic concept we
6923 * mean by "resizable" (and will be a reliable indicator if
6924 * set_policy() hasn't been called)
6926 return window->allow_grow;
6930 * gtk_window_set_gravity:
6931 * @window: a #GtkWindow
6932 * @gravity: window gravity
6934 * Window gravity defines the meaning of coordinates passed to
6935 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
6938 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
6939 * typically "do what you mean."
6943 gtk_window_set_gravity (GtkWindow *window,
6946 g_return_if_fail (GTK_IS_WINDOW (window));
6948 if (gravity != window->gravity)
6950 window->gravity = gravity;
6952 /* gtk_window_move_resize() will adapt gravity
6954 gtk_widget_queue_resize (GTK_WIDGET (window));
6956 g_object_notify (G_OBJECT (window), "gravity");
6961 * gtk_window_get_gravity:
6962 * @window: a #GtkWindow
6964 * Gets the value set by gtk_window_set_gravity().
6966 * Return value: window gravity
6969 gtk_window_get_gravity (GtkWindow *window)
6971 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
6973 return window->gravity;
6977 * gtk_window_begin_resize_drag:
6978 * @window: a #GtkWindow
6979 * @button: mouse button that initiated the drag
6980 * @edge: position of the resize control
6981 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6982 * @root_y: Y position where the user clicked to initiate the drag
6983 * @timestamp: timestamp from the click event that initiated the drag
6985 * Starts resizing a window. This function is used if an application
6986 * has window resizing controls. When GDK can support it, the resize
6987 * will be done using the standard mechanism for the <link
6988 * linkend="gtk-X11-arch">window manager</link> or windowing
6989 * system. Otherwise, GDK will try to emulate window resizing,
6990 * potentially not all that well, depending on the windowing system.
6994 gtk_window_begin_resize_drag (GtkWindow *window,
7002 GdkWindow *toplevel;
7004 g_return_if_fail (GTK_IS_WINDOW (window));
7005 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
7007 widget = GTK_WIDGET (window);
7010 toplevel = window->frame;
7012 toplevel = widget->window;
7014 gdk_window_begin_resize_drag (toplevel,
7021 * gtk_window_get_frame_dimensions:
7022 * @window: a #GtkWindow
7023 * @left: location to store the width of the frame at the left, or %NULL
7024 * @top: location to store the height of the frame at the top, or %NULL
7025 * @right: location to store the width of the frame at the returns, or %NULL
7026 * @bottom: location to store the height of the frame at the bottom, or %NULL
7028 * (Note: this is a special-purpose function intended for the
7029 * framebuffer port; see gtk_window_set_has_frame(). It will not
7030 * return the size of the window border drawn by the <link
7031 * linkend="gtk-X11-arch">window manager</link>, which is the normal
7032 * case when using a windowing system. See
7033 * gdk_window_get_frame_extents() to get the standard window border
7036 * Retrieves the dimensions of the frame window for this toplevel.
7037 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
7040 gtk_window_get_frame_dimensions (GtkWindow *window,
7046 g_return_if_fail (GTK_IS_WINDOW (window));
7049 *left = window->frame_left;
7051 *top = window->frame_top;
7053 *right = window->frame_right;
7055 *bottom = window->frame_bottom;
7059 * gtk_window_begin_move_drag:
7060 * @window: a #GtkWindow
7061 * @button: mouse button that initiated the drag
7062 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7063 * @root_y: Y position where the user clicked to initiate the drag
7064 * @timestamp: timestamp from the click event that initiated the drag
7066 * Starts moving a window. This function is used if an application has
7067 * window movement grips. When GDK can support it, the window movement
7068 * will be done using the standard mechanism for the <link
7069 * linkend="gtk-X11-arch">window manager</link> or windowing
7070 * system. Otherwise, GDK will try to emulate window movement,
7071 * potentially not all that well, depending on the windowing system.
7075 gtk_window_begin_move_drag (GtkWindow *window,
7082 GdkWindow *toplevel;
7084 g_return_if_fail (GTK_IS_WINDOW (window));
7085 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
7087 widget = GTK_WIDGET (window);
7090 toplevel = window->frame;
7092 toplevel = widget->window;
7094 gdk_window_begin_move_drag (toplevel,
7101 * gtk_window_set_screen:
7102 * @window: a #GtkWindow.
7103 * @screen: a #GdkScreen.
7105 * Sets the #GdkScreen where the @window is displayed; if
7106 * the window is already mapped, it will be unmapped, and
7107 * then remapped on the new screen.
7112 gtk_window_set_screen (GtkWindow *window,
7116 GdkScreen *previous_screen;
7117 gboolean was_mapped;
7119 g_return_if_fail (GTK_IS_WINDOW (window));
7120 g_return_if_fail (GDK_IS_SCREEN (screen));
7122 if (screen == window->screen)
7125 widget = GTK_WIDGET (window);
7127 previous_screen = window->screen;
7128 was_mapped = GTK_WIDGET_MAPPED (widget);
7131 gtk_widget_unmap (widget);
7132 if (GTK_WIDGET_REALIZED (widget))
7133 gtk_widget_unrealize (widget);
7135 gtk_window_free_key_hash (window);
7136 window->screen = screen;
7137 gtk_widget_reset_rc_styles (widget);
7138 if (screen != previous_screen)
7140 g_signal_handlers_disconnect_by_func (previous_screen,
7141 gtk_window_on_composited_changed, window);
7142 g_signal_connect (screen, "composited_changed",
7143 G_CALLBACK (gtk_window_on_composited_changed), window);
7145 _gtk_widget_propagate_screen_changed (widget, previous_screen);
7146 _gtk_widget_propagate_composited_changed (widget);
7148 g_object_notify (G_OBJECT (window), "screen");
7151 gtk_widget_map (widget);
7155 gtk_window_on_composited_changed (GdkScreen *screen,
7158 gtk_widget_queue_draw (GTK_WIDGET (window));
7160 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
7164 gtk_window_check_screen (GtkWindow *window)
7167 return window->screen;
7170 g_warning ("Screen for GtkWindow not set; you must always set\n"
7171 "a screen for a GtkWindow before using the window");
7177 * gtk_window_get_screen:
7178 * @window: a #GtkWindow.
7180 * Returns the #GdkScreen associated with @window.
7182 * Return value: a #GdkScreen.
7187 gtk_window_get_screen (GtkWindow *window)
7189 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
7191 return window->screen;
7195 * gtk_window_is_active:
7196 * @window: a #GtkWindow
7198 * Returns whether the window is part of the current active toplevel.
7199 * (That is, the toplevel window receiving keystrokes.)
7200 * The return value is %TRUE if the window is active toplevel
7201 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
7202 * You might use this function if you wanted to draw a widget
7203 * differently in an active window from a widget in an inactive window.
7204 * See gtk_window_has_toplevel_focus()
7206 * Return value: %TRUE if the window part of the current active window.
7211 gtk_window_is_active (GtkWindow *window)
7213 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7215 return window->is_active;
7219 * gtk_window_has_toplevel_focus:
7220 * @window: a #GtkWindow
7222 * Returns whether the input focus is within this GtkWindow.
7223 * For real toplevel windows, this is identical to gtk_window_is_active(),
7224 * but for embedded windows, like #GtkPlug, the results will differ.
7226 * Return value: %TRUE if the input focus is within this GtkWindow
7231 gtk_window_has_toplevel_focus (GtkWindow *window)
7233 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7235 return window->has_toplevel_focus;
7239 gtk_window_group_class_init (GtkWindowGroupClass *klass)
7244 gtk_window_group_get_type (void)
7246 static GType window_group_type = 0;
7248 if (!window_group_type)
7250 const GTypeInfo window_group_info =
7252 sizeof (GtkWindowGroupClass),
7253 NULL, /* base_init */
7254 NULL, /* base_finalize */
7255 (GClassInitFunc) gtk_window_group_class_init,
7256 NULL, /* class_finalize */
7257 NULL, /* class_data */
7258 sizeof (GtkWindowGroup),
7259 0, /* n_preallocs */
7260 (GInstanceInitFunc) NULL,
7263 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
7264 &window_group_info, 0);
7267 return window_group_type;
7271 * gtk_window_group_new:
7273 * Creates a new #GtkWindowGroup object. Grabs added with
7274 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
7276 * Return value: a new #GtkWindowGroup.
7279 gtk_window_group_new (void)
7281 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
7285 window_group_cleanup_grabs (GtkWindowGroup *group,
7289 GSList *to_remove = NULL;
7291 tmp_list = group->grabs;
7294 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
7295 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
7296 tmp_list = tmp_list->next;
7301 gtk_grab_remove (to_remove->data);
7302 g_object_unref (to_remove->data);
7303 to_remove = g_slist_delete_link (to_remove, to_remove);
7308 * gtk_window_group_add_window:
7309 * @window_group: a #GtkWindowGroup
7310 * @window: the #GtkWindow to add
7312 * Adds a window to a #GtkWindowGroup.
7315 gtk_window_group_add_window (GtkWindowGroup *window_group,
7318 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7319 g_return_if_fail (GTK_IS_WINDOW (window));
7321 if (window->group != window_group)
7323 g_object_ref (window);
7324 g_object_ref (window_group);
7327 gtk_window_group_remove_window (window->group, window);
7329 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
7331 window->group = window_group;
7333 g_object_unref (window);
7338 * gtk_window_group_remove_window:
7339 * @window_group: a #GtkWindowGroup
7340 * @window: the #GtkWindow to remove
7342 * Removes a window from a #GtkWindowGroup.
7345 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7348 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7349 g_return_if_fail (GTK_IS_WIDGET (window));
7350 g_return_if_fail (window->group == window_group);
7352 g_object_ref (window);
7354 window_group_cleanup_grabs (window_group, window);
7355 window->group = NULL;
7357 g_object_unref (window_group);
7358 g_object_unref (window);
7362 * gtk_window_get_group:
7363 * @window: a #GtkWindow, or %NULL
7365 * Returns the group for @window or the default group, if
7366 * @window is %NULL or if @window does not have an explicit
7369 * Returns: the #GtkWindowGroup for a window or the default group
7374 gtk_window_get_group (GtkWindow *window)
7376 if (window && window->group)
7377 return window->group;
7380 static GtkWindowGroup *default_group = NULL;
7383 default_group = gtk_window_group_new ();
7385 return default_group;
7389 /* Return the current grab widget of the given group
7392 _gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
7394 if (window_group->grabs)
7395 return GTK_WIDGET (window_group->grabs->data);
7400 Derived from XParseGeometry() in XFree86
7402 Copyright 1985, 1986, 1987,1998 The Open Group
7404 All Rights Reserved.
7406 The above copyright notice and this permission notice shall be included
7407 in all copies or substantial portions of the Software.
7409 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
7410 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7411 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7412 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
7413 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7414 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
7415 OTHER DEALINGS IN THE SOFTWARE.
7417 Except as contained in this notice, the name of The Open Group shall
7418 not be used in advertising or otherwise to promote the sale, use or
7419 other dealings in this Software without prior written authorization
7420 from The Open Group.
7425 * XParseGeometry parses strings of the form
7426 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
7427 * width, height, xoffset, and yoffset are unsigned integers.
7428 * Example: "=80x24+300-49"
7429 * The equal sign is optional.
7430 * It returns a bitmask that indicates which of the four values
7431 * were actually found in the string. For each value found,
7432 * the corresponding argument is updated; for each value
7433 * not found, the corresponding argument is left unchanged.
7436 /* The following code is from Xlib, and is minimally modified, so we
7437 * can track any upstream changes if required. Don't change this
7438 * code. Or if you do, put in a huge comment marking which thing
7443 read_int (gchar *string,
7451 else if (*string == '-')
7457 for (; (*string >= '0') && (*string <= '9'); string++)
7459 result = (result * 10) + (*string - '0');
7471 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
7472 * value (x, y, width, height) was found in the parsed string.
7474 #define NoValue 0x0000
7475 #define XValue 0x0001
7476 #define YValue 0x0002
7477 #define WidthValue 0x0004
7478 #define HeightValue 0x0008
7479 #define AllValues 0x000F
7480 #define XNegative 0x0010
7481 #define YNegative 0x0020
7483 /* Try not to reformat/modify, so we can compare/sync with X sources */
7485 gtk_XParseGeometry (const char *string,
7488 unsigned int *width,
7489 unsigned int *height)
7493 unsigned int tempWidth, tempHeight;
7495 char *nextCharacter;
7497 /* These initializations are just to silence gcc */
7503 if ( (string == NULL) || (*string == '\0')) return(mask);
7505 string++; /* ignore possible '=' at beg of geometry spec */
7507 strind = (char *)string;
7508 if (*strind != '+' && *strind != '-' && *strind != 'x') {
7509 tempWidth = read_int(strind, &nextCharacter);
7510 if (strind == nextCharacter)
7512 strind = nextCharacter;
7516 if (*strind == 'x' || *strind == 'X') {
7518 tempHeight = read_int(strind, &nextCharacter);
7519 if (strind == nextCharacter)
7521 strind = nextCharacter;
7522 mask |= HeightValue;
7525 if ((*strind == '+') || (*strind == '-')) {
7526 if (*strind == '-') {
7528 tempX = -read_int(strind, &nextCharacter);
7529 if (strind == nextCharacter)
7531 strind = nextCharacter;
7537 tempX = read_int(strind, &nextCharacter);
7538 if (strind == nextCharacter)
7540 strind = nextCharacter;
7543 if ((*strind == '+') || (*strind == '-')) {
7544 if (*strind == '-') {
7546 tempY = -read_int(strind, &nextCharacter);
7547 if (strind == nextCharacter)
7549 strind = nextCharacter;
7556 tempY = read_int(strind, &nextCharacter);
7557 if (strind == nextCharacter)
7559 strind = nextCharacter;
7565 /* If strind isn't at the end of the string the it's an invalid
7566 geometry specification. */
7568 if (*strind != '\0') return (0);
7574 if (mask & WidthValue)
7576 if (mask & HeightValue)
7577 *height = tempHeight;
7582 * gtk_window_parse_geometry:
7583 * @window: a #GtkWindow
7584 * @geometry: geometry string
7586 * Parses a standard X Window System geometry string - see the
7587 * manual page for X (type 'man X') for details on this.
7588 * gtk_window_parse_geometry() does work on all GTK+ ports
7589 * including Win32 but is primarily intended for an X environment.
7591 * If either a size or a position can be extracted from the
7592 * geometry string, gtk_window_parse_geometry() returns %TRUE
7593 * and calls gtk_window_set_default_size() and/or gtk_window_move()
7594 * to resize/move the window.
7596 * If gtk_window_parse_geometry() returns %TRUE, it will also
7597 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
7598 * indicating to the window manager that the size/position of
7599 * the window was user-specified. This causes most window
7600 * managers to honor the geometry.
7602 * Note that for gtk_window_parse_geometry() to work as expected, it has
7603 * to be called when the window has its "final" size, i.e. after calling
7604 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
7607 * <informalexample><programlisting>
7608 * #include <gtk/gtk.h>
7611 * fill_with_content (GtkWidget *vbox)
7613 * /<!-- -->* fill with content... *<!-- -->/
7617 * main (int argc, char *argv[])
7619 * GtkWidget *window, *vbox;
7620 * GdkGeometry size_hints = {
7621 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
7624 * gtk_init (&argc, &argv);
7626 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7627 * vbox = gtk_vbox_new (FALSE, 0);
7629 * gtk_container_add (GTK_CONTAINER (window), vbox);
7630 * fill_with_content (vbox);
7631 * gtk_widget_show_all (vbox);
7633 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
7636 * GDK_HINT_MIN_SIZE |
7637 * GDK_HINT_BASE_SIZE |
7638 * GDK_HINT_RESIZE_INC);
7642 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
7643 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
7646 * gtk_widget_show_all (window);
7651 * </programlisting></informalexample>
7653 * Return value: %TRUE if string was parsed successfully
7656 gtk_window_parse_geometry (GtkWindow *window,
7657 const gchar *geometry)
7659 gint result, x = 0, y = 0;
7662 gboolean size_set, pos_set;
7665 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7666 g_return_val_if_fail (geometry != NULL, FALSE);
7668 screen = gtk_window_check_screen (window);
7670 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
7673 if ((result & WidthValue) || (result & HeightValue))
7675 gtk_window_set_default_size_internal (window,
7676 TRUE, result & WidthValue ? w : -1,
7677 TRUE, result & HeightValue ? h : -1,
7682 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
7684 grav = GDK_GRAVITY_NORTH_WEST;
7686 if ((result & XNegative) && (result & YNegative))
7687 grav = GDK_GRAVITY_SOUTH_EAST;
7688 else if (result & XNegative)
7689 grav = GDK_GRAVITY_NORTH_EAST;
7690 else if (result & YNegative)
7691 grav = GDK_GRAVITY_SOUTH_WEST;
7693 if ((result & XValue) == 0)
7696 if ((result & YValue) == 0)
7699 if (grav == GDK_GRAVITY_SOUTH_WEST ||
7700 grav == GDK_GRAVITY_SOUTH_EAST)
7701 y = gdk_screen_get_height (screen) - h + y;
7703 if (grav == GDK_GRAVITY_SOUTH_EAST ||
7704 grav == GDK_GRAVITY_NORTH_EAST)
7705 x = gdk_screen_get_width (screen) - w + x;
7707 /* we don't let you put a window offscreen; maybe some people would
7708 * prefer to be able to, but it's kind of a bogus thing to do.
7717 if ((result & XValue) || (result & YValue))
7719 gtk_window_set_gravity (window, grav);
7720 gtk_window_move (window, x, y);
7724 if (size_set || pos_set)
7726 /* Set USSize, USPosition hints */
7727 GtkWindowGeometryInfo *info;
7729 info = gtk_window_get_geometry_info (window, TRUE);
7732 info->mask |= GDK_HINT_USER_POS;
7734 info->mask |= GDK_HINT_USER_SIZE;
7741 gtk_window_mnemonic_hash_foreach (guint keyval,
7747 GtkWindowKeysForeachFunc func;
7751 (*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
7755 _gtk_window_keys_foreach (GtkWindow *window,
7756 GtkWindowKeysForeachFunc func,
7760 GtkMnemonicHash *mnemonic_hash;
7764 GtkWindowKeysForeachFunc func;
7768 info.window = window;
7770 info.func_data = func_data;
7772 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
7774 _gtk_mnemonic_hash_foreach (mnemonic_hash,
7775 gtk_window_mnemonic_hash_foreach, &info);
7777 groups = gtk_accel_groups_from_object (G_OBJECT (window));
7780 GtkAccelGroup *group = groups->data;
7783 for (i = 0; i < group->n_accels; i++)
7785 GtkAccelKey *key = &group->priv_accels[i].key;
7788 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
7791 groups = groups->next;
7796 gtk_window_keys_changed (GtkWindow *window)
7798 gtk_window_free_key_hash (window);
7799 gtk_window_get_key_hash (window);
7802 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
7804 struct _GtkWindowKeyEntry
7808 guint is_mnemonic : 1;
7812 window_key_entry_destroy (gpointer data)
7814 g_slice_free (GtkWindowKeyEntry, data);
7818 add_to_key_hash (GtkWindow *window,
7820 GdkModifierType modifiers,
7821 gboolean is_mnemonic,
7824 GtkKeyHash *key_hash = data;
7826 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
7828 entry->keyval = keyval;
7829 entry->modifiers = modifiers;
7830 entry->is_mnemonic = is_mnemonic;
7832 /* GtkAccelGroup stores lowercased accelerators. To deal
7833 * with this, if <Shift> was specified, uppercase.
7835 if (modifiers & GDK_SHIFT_MASK)
7837 if (keyval == GDK_Tab)
7838 keyval = GDK_ISO_Left_Tab;
7840 keyval = gdk_keyval_to_upper (keyval);
7843 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
7847 gtk_window_get_key_hash (GtkWindow *window)
7849 GdkScreen *screen = gtk_window_check_screen (window);
7850 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7855 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
7856 (GDestroyNotify)window_key_entry_destroy);
7857 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
7858 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
7864 gtk_window_free_key_hash (GtkWindow *window)
7866 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7869 _gtk_key_hash_free (key_hash);
7870 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
7875 * gtk_window_activate_key:
7876 * @window: a #GtkWindow
7877 * @event: a #GdkEventKey
7879 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
7880 * called by the default ::key_press_event handler for toplevel windows,
7881 * however in some cases it may be useful to call this directly when
7882 * overriding the standard key handling for a toplevel window.
7884 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
7887 gtk_window_activate_key (GtkWindow *window,
7890 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7891 GtkWindowKeyEntry *found_entry = NULL;
7895 gtk_window_keys_changed (window);
7896 key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7901 GSList *entries = _gtk_key_hash_lookup (key_hash,
7902 event->hardware_keycode,
7904 gtk_accelerator_get_default_mod_mask (),
7908 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
7910 GtkWindowKeyEntry *entry = tmp_list->data;
7911 if (entry->is_mnemonic)
7913 found_entry = entry;
7918 if (!found_entry && entries)
7919 found_entry = entries->data;
7921 g_slist_free (entries);
7926 gboolean enable_mnemonics;
7927 gboolean enable_accels;
7929 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
7930 "gtk-enable-mnemonics", &enable_mnemonics,
7931 "gtk-enable-accels", &enable_accels,
7934 if (found_entry->is_mnemonic)
7936 if (enable_mnemonics)
7937 return gtk_window_mnemonic_activate (window, found_entry->keyval,
7938 found_entry->modifiers);
7943 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
7944 found_entry->modifiers);
7952 window_update_has_focus (GtkWindow *window)
7954 GtkWidget *widget = GTK_WIDGET (window);
7955 gboolean has_focus = window->has_toplevel_focus && window->is_active;
7957 if (has_focus != window->has_focus)
7959 window->has_focus = has_focus;
7963 if (window->focus_widget &&
7964 window->focus_widget != widget &&
7965 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7966 do_focus_change (window->focus_widget, TRUE);
7970 if (window->focus_widget &&
7971 window->focus_widget != widget &&
7972 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7973 do_focus_change (window->focus_widget, FALSE);
7979 * _gtk_window_set_is_active:
7980 * @window: a #GtkWindow
7981 * @is_active: %TRUE if the window is in the currently active toplevel
7983 * Internal function that sets whether the #GtkWindow is part
7984 * of the currently active toplevel window (taking into account inter-process
7988 _gtk_window_set_is_active (GtkWindow *window,
7991 g_return_if_fail (GTK_IS_WINDOW (window));
7993 is_active = is_active != FALSE;
7995 if (is_active != window->is_active)
7997 window->is_active = is_active;
7998 window_update_has_focus (window);
8000 g_object_notify (G_OBJECT (window), "is-active");
8005 * _gtk_window_set_has_toplevel_focus:
8006 * @window: a #GtkWindow
8007 * @has_toplevel_focus: %TRUE if the in
8009 * Internal function that sets whether the keyboard focus for the
8010 * toplevel window (taking into account inter-process embedding.)
8013 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
8014 gboolean has_toplevel_focus)
8016 g_return_if_fail (GTK_IS_WINDOW (window));
8018 has_toplevel_focus = has_toplevel_focus != FALSE;
8020 if (has_toplevel_focus != window->has_toplevel_focus)
8022 window->has_toplevel_focus = has_toplevel_focus;
8023 window_update_has_focus (window);
8025 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
8030 * gtk_window_set_auto_startup_notification:
8031 * @setting: %TRUE to automatically do startup notification
8033 * By default, after showing the first #GtkWindow, GTK+ calls
8034 * gdk_notify_startup_complete(). Call this function to disable
8035 * the automatic startup notification. You might do this if your
8036 * first window is a splash screen, and you want to delay notification
8037 * until after your real main window has been shown, for example.
8039 * In that example, you would disable startup notification
8040 * temporarily, show your splash screen, then re-enable it so that
8041 * showing the main window would automatically result in notification.
8046 gtk_window_set_auto_startup_notification (gboolean setting)
8048 disable_startup_notification = !setting;
8053 #undef gtk_window_set_icon_from_file
8056 gtk_window_set_icon_from_file (GtkWindow *window,
8057 const gchar *filename,
8060 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
8063 if (utf8_filename == NULL)
8066 retval = gtk_window_set_icon_from_file_utf8 (window, utf8_filename, err);
8068 g_free (utf8_filename);
8073 #undef gtk_window_set_default_icon_from_file
8076 gtk_window_set_default_icon_from_file (const gchar *filename,
8079 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
8082 if (utf8_filename == NULL)
8085 retval = gtk_window_set_default_icon_from_file_utf8 (utf8_filename, err);
8087 g_free (utf8_filename);
8094 #define __GTK_WINDOW_C__
8095 #include "gtkaliasdef.c"