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/.
31 #include "gdk/gdkkeysyms.h"
35 #include "gtkprivate.h"
37 #include "gtkwindow.h"
38 #include "gtkwindow-decorate.h"
39 #include "gtkbindings.h"
40 #include "gtkkeyhash.h"
42 #include "gtkmnemonichash.h"
43 #include "gtkiconfactory.h"
44 #include "gtkicontheme.h"
45 #include "gtkmarshalers.h"
49 #ifdef GDK_WINDOWING_X11
79 PROP_DESTROY_WITH_PARENT,
84 PROP_SKIP_TASKBAR_HINT,
93 /* Readonly properties */
95 PROP_HAS_TOPLEVEL_FOCUS,
103 GdkPixmap *icon_pixmap;
104 GdkPixmap *icon_mask;
107 guint using_default_icon : 1;
108 guint using_parent_icon : 1;
109 guint using_themed_icon : 1;
113 GdkGeometry geometry; /* Last set of geometry hints we set */
114 GdkWindowHints flags;
115 GdkRectangle configure_request;
116 } GtkWindowLastGeometryInfo;
118 struct _GtkWindowGeometryInfo
120 /* Properties that the app has set on the window
122 GdkGeometry geometry; /* Geometry hints */
124 GtkWidget *widget; /* subwidget to which hints apply */
125 /* from last gtk_window_resize () - if > 0, indicates that
126 * we should resize to this size.
131 /* From last gtk_window_move () prior to mapping -
132 * only used if initial_pos_set
137 /* Default size - used only the FIRST time we map a window,
142 /* whether to use initial_x, initial_y */
143 guint initial_pos_set : 1;
144 /* CENTER_ALWAYS or other position constraint changed since
145 * we sent the last configure request.
147 guint position_constraints_changed : 1;
149 /* if true, default_width, height come from gtk_window_parse_geometry,
150 * and thus should be multiplied by the increments and affect the
151 * geometry widget only
153 guint default_is_geometry : 1;
155 GtkWindowLastGeometryInfo last;
158 #define GTK_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW, GtkWindowPrivate))
160 typedef struct _GtkWindowPrivate GtkWindowPrivate;
162 struct _GtkWindowPrivate
164 GtkMnemonicHash *mnemonic_hash;
166 guint above_initially : 1;
167 guint below_initially : 1;
168 guint fullscreen_initially : 1;
169 guint skips_taskbar : 1;
170 guint skips_pager : 1;
172 guint accept_focus : 1;
173 guint focus_on_map : 1;
177 static void gtk_window_class_init (GtkWindowClass *klass);
178 static void gtk_window_init (GtkWindow *window);
179 static void gtk_window_dispose (GObject *object);
180 static void gtk_window_destroy (GtkObject *object);
181 static void gtk_window_finalize (GObject *object);
182 static void gtk_window_show (GtkWidget *widget);
183 static void gtk_window_hide (GtkWidget *widget);
184 static void gtk_window_map (GtkWidget *widget);
185 static void gtk_window_unmap (GtkWidget *widget);
186 static void gtk_window_realize (GtkWidget *widget);
187 static void gtk_window_unrealize (GtkWidget *widget);
188 static void gtk_window_size_request (GtkWidget *widget,
189 GtkRequisition *requisition);
190 static void gtk_window_size_allocate (GtkWidget *widget,
191 GtkAllocation *allocation);
192 static gint gtk_window_event (GtkWidget *widget,
194 static gboolean gtk_window_map_event (GtkWidget *widget,
196 static gboolean gtk_window_frame_event (GtkWindow *window,
198 static gint gtk_window_configure_event (GtkWidget *widget,
199 GdkEventConfigure *event);
200 static gint gtk_window_key_press_event (GtkWidget *widget,
202 static gint gtk_window_key_release_event (GtkWidget *widget,
204 static gint gtk_window_enter_notify_event (GtkWidget *widget,
205 GdkEventCrossing *event);
206 static gint gtk_window_leave_notify_event (GtkWidget *widget,
207 GdkEventCrossing *event);
208 static gint gtk_window_focus_in_event (GtkWidget *widget,
209 GdkEventFocus *event);
210 static gint gtk_window_focus_out_event (GtkWidget *widget,
211 GdkEventFocus *event);
212 static gint gtk_window_client_event (GtkWidget *widget,
213 GdkEventClient *event);
214 static void gtk_window_check_resize (GtkContainer *container);
215 static gint gtk_window_focus (GtkWidget *widget,
216 GtkDirectionType direction);
217 static void gtk_window_real_set_focus (GtkWindow *window,
220 static void gtk_window_real_activate_default (GtkWindow *window);
221 static void gtk_window_real_activate_focus (GtkWindow *window);
222 static void gtk_window_move_focus (GtkWindow *window,
223 GtkDirectionType dir);
224 static void gtk_window_keys_changed (GtkWindow *window);
225 static void gtk_window_paint (GtkWidget *widget,
227 static gint gtk_window_expose (GtkWidget *widget,
228 GdkEventExpose *event);
229 static void gtk_window_unset_transient_for (GtkWindow *window);
230 static void gtk_window_transient_parent_realized (GtkWidget *parent,
232 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
235 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
237 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
240 static void gtk_window_move_resize (GtkWindow *window);
241 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
243 GdkGeometry *geometry_b,
245 static void gtk_window_constrain_size (GtkWindow *window,
246 GdkGeometry *geometry,
252 static void gtk_window_constrain_position (GtkWindow *window,
257 static void gtk_window_compute_hints (GtkWindow *window,
258 GdkGeometry *new_geometry,
260 static void gtk_window_compute_configure_request (GtkWindow *window,
261 GdkRectangle *request,
262 GdkGeometry *geometry,
265 static void gtk_window_set_default_size_internal (GtkWindow *window,
266 gboolean change_width,
268 gboolean change_height,
270 gboolean is_geometry);
272 static void update_themed_icon (GtkIconTheme *theme,
274 static GList *icon_list_from_theme (GtkWidget *widget,
276 static void gtk_window_realize_icon (GtkWindow *window);
277 static void gtk_window_unrealize_icon (GtkWindow *window);
279 static void gtk_window_notify_keys_changed (GtkWindow *window);
280 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
281 static void gtk_window_free_key_hash (GtkWindow *window);
283 static GSList *toplevel_list = NULL;
284 static GtkBinClass *parent_class = NULL;
285 static guint window_signals[LAST_SIGNAL] = { 0 };
286 static GList *default_icon_list = NULL;
287 static gchar *default_icon_name = NULL;
288 static guint default_icon_serial = 0;
289 static gboolean disable_startup_notification = FALSE;
290 static gboolean sent_startup_notification = FALSE;
292 static GQuark quark_gtk_embedded = 0;
293 static GQuark quark_gtk_window_key_hash = 0;
294 static GQuark quark_gtk_window_default_icon_pixmap = 0;
295 static GQuark quark_gtk_window_icon_info = 0;
297 static void gtk_window_set_property (GObject *object,
301 static void gtk_window_get_property (GObject *object,
308 gtk_window_get_type (void)
310 static GType window_type = 0;
314 static const GTypeInfo window_info =
316 sizeof (GtkWindowClass),
317 NULL, /* base_init */
318 NULL, /* base_finalize */
319 (GClassInitFunc) gtk_window_class_init,
320 NULL, /* class_finalize */
321 NULL, /* class_data */
324 (GInstanceInitFunc) gtk_window_init,
327 window_type = g_type_register_static (GTK_TYPE_BIN, I_("GtkWindow"),
335 add_tab_bindings (GtkBindingSet *binding_set,
336 GdkModifierType modifiers,
337 GtkDirectionType direction)
339 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
341 GTK_TYPE_DIRECTION_TYPE, direction);
342 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
344 GTK_TYPE_DIRECTION_TYPE, direction);
348 add_arrow_bindings (GtkBindingSet *binding_set,
350 GtkDirectionType direction)
352 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
354 gtk_binding_entry_add_signal (binding_set, keysym, 0,
356 GTK_TYPE_DIRECTION_TYPE, direction);
357 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
359 GTK_TYPE_DIRECTION_TYPE, direction);
360 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
362 GTK_TYPE_DIRECTION_TYPE, direction);
363 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
365 GTK_TYPE_DIRECTION_TYPE, direction);
370 gtk_window_class_init (GtkWindowClass *klass)
372 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
373 GtkObjectClass *object_class;
374 GtkWidgetClass *widget_class;
375 GtkContainerClass *container_class;
376 GtkBindingSet *binding_set;
378 object_class = (GtkObjectClass*) klass;
379 widget_class = (GtkWidgetClass*) klass;
380 container_class = (GtkContainerClass*) klass;
382 parent_class = g_type_class_peek_parent (klass);
384 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
385 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
386 quark_gtk_window_default_icon_pixmap = g_quark_from_static_string ("gtk-window-default-icon-pixmap");
387 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
389 gobject_class->dispose = gtk_window_dispose;
390 gobject_class->finalize = gtk_window_finalize;
392 gobject_class->set_property = gtk_window_set_property;
393 gobject_class->get_property = gtk_window_get_property;
395 object_class->destroy = gtk_window_destroy;
397 widget_class->show = gtk_window_show;
398 widget_class->hide = gtk_window_hide;
399 widget_class->map = gtk_window_map;
400 widget_class->map_event = gtk_window_map_event;
401 widget_class->unmap = gtk_window_unmap;
402 widget_class->realize = gtk_window_realize;
403 widget_class->unrealize = gtk_window_unrealize;
404 widget_class->size_request = gtk_window_size_request;
405 widget_class->size_allocate = gtk_window_size_allocate;
406 widget_class->configure_event = gtk_window_configure_event;
407 widget_class->key_press_event = gtk_window_key_press_event;
408 widget_class->key_release_event = gtk_window_key_release_event;
409 widget_class->enter_notify_event = gtk_window_enter_notify_event;
410 widget_class->leave_notify_event = gtk_window_leave_notify_event;
411 widget_class->focus_in_event = gtk_window_focus_in_event;
412 widget_class->focus_out_event = gtk_window_focus_out_event;
413 widget_class->client_event = gtk_window_client_event;
414 widget_class->focus = gtk_window_focus;
416 widget_class->expose_event = gtk_window_expose;
418 container_class->check_resize = gtk_window_check_resize;
420 klass->set_focus = gtk_window_real_set_focus;
421 klass->frame_event = gtk_window_frame_event;
423 klass->activate_default = gtk_window_real_activate_default;
424 klass->activate_focus = gtk_window_real_activate_focus;
425 klass->move_focus = gtk_window_move_focus;
426 klass->keys_changed = gtk_window_keys_changed;
428 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
431 g_object_class_install_property (gobject_class,
433 g_param_spec_enum ("type",
435 P_("The type of the window"),
436 GTK_TYPE_WINDOW_TYPE,
438 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
440 g_object_class_install_property (gobject_class,
442 g_param_spec_string ("title",
444 P_("The title of the window"),
446 GTK_PARAM_READWRITE));
448 g_object_class_install_property (gobject_class,
450 g_param_spec_string ("role",
452 P_("Unique identifier for the window to be used when restoring a session"),
454 GTK_PARAM_READWRITE));
456 g_object_class_install_property (gobject_class,
458 g_param_spec_boolean ("allow-shrink",
460 /* xgettext:no-c-format */
461 P_("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
463 GTK_PARAM_READWRITE));
465 g_object_class_install_property (gobject_class,
467 g_param_spec_boolean ("allow-grow",
469 P_("If TRUE, users can expand the window beyond its minimum size"),
471 GTK_PARAM_READWRITE));
473 g_object_class_install_property (gobject_class,
475 g_param_spec_boolean ("resizable",
477 P_("If TRUE, users can resize the window"),
479 GTK_PARAM_READWRITE));
481 g_object_class_install_property (gobject_class,
483 g_param_spec_boolean ("modal",
485 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
487 GTK_PARAM_READWRITE));
489 g_object_class_install_property (gobject_class,
491 g_param_spec_enum ("window-position",
492 P_("Window Position"),
493 P_("The initial position of the window"),
494 GTK_TYPE_WINDOW_POSITION,
496 GTK_PARAM_READWRITE));
498 g_object_class_install_property (gobject_class,
500 g_param_spec_int ("default-width",
502 P_("The default width of the window, used when initially showing the window"),
506 GTK_PARAM_READWRITE));
508 g_object_class_install_property (gobject_class,
510 g_param_spec_int ("default-height",
511 P_("Default Height"),
512 P_("The default height of the window, used when initially showing the window"),
516 GTK_PARAM_READWRITE));
518 g_object_class_install_property (gobject_class,
519 PROP_DESTROY_WITH_PARENT,
520 g_param_spec_boolean ("destroy-with-parent",
521 P_("Destroy with Parent"),
522 P_("If this window should be destroyed when the parent is destroyed"),
524 GTK_PARAM_READWRITE));
526 g_object_class_install_property (gobject_class,
528 g_param_spec_object ("icon",
530 P_("Icon for this window"),
532 GTK_PARAM_READWRITE));
535 * GtkWindow:icon-name:
537 * The :icon-name property specifies the name of the themed icon to
538 * use as the window icon. See #GtkIconTheme for more details.
542 g_object_class_install_property (gobject_class,
544 g_param_spec_string ("icon-name",
546 P_("Name of the themed icon for this window"),
548 GTK_PARAM_READWRITE));
550 g_object_class_install_property (gobject_class,
552 g_param_spec_object ("screen",
554 P_("The screen where this window will be displayed"),
556 GTK_PARAM_READWRITE));
558 g_object_class_install_property (gobject_class,
560 g_param_spec_boolean ("is-active",
562 P_("Whether the toplevel is the current active window"),
564 GTK_PARAM_READABLE));
566 g_object_class_install_property (gobject_class,
567 PROP_HAS_TOPLEVEL_FOCUS,
568 g_param_spec_boolean ("has-toplevel-focus",
569 P_("Focus in Toplevel"),
570 P_("Whether the input focus is within this GtkWindow"),
572 GTK_PARAM_READABLE));
574 g_object_class_install_property (gobject_class,
576 g_param_spec_enum ("type-hint",
578 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
579 GDK_TYPE_WINDOW_TYPE_HINT,
580 GDK_WINDOW_TYPE_HINT_NORMAL,
581 GTK_PARAM_READWRITE));
583 g_object_class_install_property (gobject_class,
584 PROP_SKIP_TASKBAR_HINT,
585 g_param_spec_boolean ("skip-taskbar-hint",
587 P_("TRUE if the window should not be in the task bar."),
589 GTK_PARAM_READWRITE));
591 g_object_class_install_property (gobject_class,
592 PROP_SKIP_PAGER_HINT,
593 g_param_spec_boolean ("skip-pager-hint",
595 P_("TRUE if the window should not be in the pager."),
597 GTK_PARAM_READWRITE));
599 g_object_class_install_property (gobject_class,
601 g_param_spec_boolean ("urgency-hint",
603 P_("TRUE if the window should be brought to the user's attention."),
605 GTK_PARAM_READWRITE));
608 * GtkWindow:accept-focus-hint:
610 * Whether the window should receive the input focus.
614 g_object_class_install_property (gobject_class,
616 g_param_spec_boolean ("accept-focus",
618 P_("TRUE if the window should receive the input focus."),
620 GTK_PARAM_READWRITE));
623 * GtkWindow:focus-on-map-hint:
625 * Whether the window should receive the input focus when mapped.
629 g_object_class_install_property (gobject_class,
631 g_param_spec_boolean ("focus-on-map",
633 P_("TRUE if the window should receive the input focus when mapped."),
635 GTK_PARAM_READWRITE));
638 * GtkWindow:decorated:
640 * Whether the window should be decorated by the window manager.
644 g_object_class_install_property (gobject_class,
646 g_param_spec_boolean ("decorated",
648 P_("Whether the window should be decorated by the window manager"),
650 GTK_PARAM_READWRITE));
653 * GtkWindow:deletable:
655 * Whether the window frame should have a close button.
659 g_object_class_install_property (gobject_class,
661 g_param_spec_boolean ("deletable",
663 P_("Whether the window frame should have a close button"),
665 GTK_PARAM_READWRITE));
671 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
672 * more details about window gravity.
676 g_object_class_install_property (gobject_class,
678 g_param_spec_enum ("gravity",
680 P_("The window gravity of the window"),
682 GDK_GRAVITY_NORTH_WEST,
683 GTK_PARAM_READWRITE));
685 window_signals[SET_FOCUS] =
686 g_signal_new (I_("set_focus"),
687 G_TYPE_FROM_CLASS (gobject_class),
689 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
691 _gtk_marshal_VOID__OBJECT,
695 window_signals[FRAME_EVENT] =
696 g_signal_new (I_("frame_event"),
697 G_TYPE_FROM_CLASS (gobject_class),
699 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
700 _gtk_boolean_handled_accumulator, NULL,
701 _gtk_marshal_BOOLEAN__BOXED,
705 window_signals[ACTIVATE_FOCUS] =
706 g_signal_new (I_("activate_focus"),
707 G_TYPE_FROM_CLASS (gobject_class),
708 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
709 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
711 _gtk_marshal_VOID__VOID,
715 window_signals[ACTIVATE_DEFAULT] =
716 g_signal_new (I_("activate_default"),
717 G_TYPE_FROM_CLASS (gobject_class),
718 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
719 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
721 _gtk_marshal_VOID__VOID,
725 window_signals[MOVE_FOCUS] =
726 g_signal_new (I_("move_focus"),
727 G_TYPE_FROM_CLASS (gobject_class),
728 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
729 G_STRUCT_OFFSET (GtkWindowClass, move_focus),
731 _gtk_marshal_VOID__ENUM,
734 GTK_TYPE_DIRECTION_TYPE);
736 window_signals[KEYS_CHANGED] =
737 g_signal_new (I_("keys_changed"),
738 G_TYPE_FROM_CLASS (gobject_class),
740 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
742 _gtk_marshal_VOID__VOID,
750 binding_set = gtk_binding_set_by_class (klass);
752 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
753 "activate_focus", 0);
754 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
755 "activate_focus", 0);
757 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
758 "activate_default", 0);
760 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
761 "activate_default", 0);
763 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
764 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
765 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
766 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
768 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
769 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
770 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
771 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
775 gtk_window_init (GtkWindow *window)
777 GdkColormap *colormap;
778 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
780 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
781 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
783 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
785 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
787 window->title = NULL;
788 window->wmclass_name = g_strdup (g_get_prgname ());
789 window->wmclass_class = g_strdup (gdk_get_program_class ());
790 window->wm_role = NULL;
791 window->geometry_info = NULL;
792 window->type = GTK_WINDOW_TOPLEVEL;
793 window->focus_widget = NULL;
794 window->default_widget = NULL;
795 window->configure_request_count = 0;
796 window->allow_shrink = FALSE;
797 window->allow_grow = TRUE;
798 window->configure_notify_received = FALSE;
799 window->position = GTK_WIN_POS_NONE;
800 window->need_default_size = TRUE;
801 window->need_default_position = TRUE;
802 window->modal = FALSE;
803 window->frame = NULL;
804 window->has_frame = FALSE;
805 window->frame_left = 0;
806 window->frame_right = 0;
807 window->frame_top = 0;
808 window->frame_bottom = 0;
809 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
810 window->gravity = GDK_GRAVITY_NORTH_WEST;
811 window->decorated = TRUE;
812 window->mnemonic_modifier = GDK_MOD1_MASK;
813 window->screen = gdk_screen_get_default ();
815 priv->accept_focus = TRUE;
816 priv->focus_on_map = TRUE;
817 priv->deletable = TRUE;
819 colormap = _gtk_widget_peek_colormap ();
821 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
823 g_object_ref_sink (window);
824 window->has_user_ref_count = TRUE;
825 toplevel_list = g_slist_prepend (toplevel_list, window);
827 gtk_decorated_window_init (window);
832 gtk_window_set_property (GObject *object,
839 window = GTK_WINDOW (object);
844 window->type = g_value_get_enum (value);
847 gtk_window_set_title (window, g_value_get_string (value));
850 gtk_window_set_role (window, g_value_get_string (value));
852 case PROP_ALLOW_SHRINK:
853 window->allow_shrink = g_value_get_boolean (value);
854 gtk_widget_queue_resize (GTK_WIDGET (window));
856 case PROP_ALLOW_GROW:
857 window->allow_grow = g_value_get_boolean (value);
858 gtk_widget_queue_resize (GTK_WIDGET (window));
859 g_object_notify (G_OBJECT (window), "resizable");
862 window->allow_grow = g_value_get_boolean (value);
863 gtk_widget_queue_resize (GTK_WIDGET (window));
864 g_object_notify (G_OBJECT (window), "allow-grow");
867 gtk_window_set_modal (window, g_value_get_boolean (value));
870 gtk_window_set_position (window, g_value_get_enum (value));
872 case PROP_DEFAULT_WIDTH:
873 gtk_window_set_default_size_internal (window,
874 TRUE, g_value_get_int (value),
877 case PROP_DEFAULT_HEIGHT:
878 gtk_window_set_default_size_internal (window,
880 TRUE, g_value_get_int (value), FALSE);
882 case PROP_DESTROY_WITH_PARENT:
883 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
886 gtk_window_set_icon (window,
887 g_value_get_object (value));
890 gtk_window_set_icon_name (window, g_value_get_string (value));
893 gtk_window_set_screen (window, g_value_get_object (value));
896 gtk_window_set_type_hint (window,
897 g_value_get_enum (value));
899 case PROP_SKIP_TASKBAR_HINT:
900 gtk_window_set_skip_taskbar_hint (window,
901 g_value_get_boolean (value));
903 case PROP_SKIP_PAGER_HINT:
904 gtk_window_set_skip_pager_hint (window,
905 g_value_get_boolean (value));
907 case PROP_URGENCY_HINT:
908 gtk_window_set_urgency_hint (window,
909 g_value_get_boolean (value));
911 case PROP_ACCEPT_FOCUS:
912 gtk_window_set_accept_focus (window,
913 g_value_get_boolean (value));
915 case PROP_FOCUS_ON_MAP:
916 gtk_window_set_focus_on_map (window,
917 g_value_get_boolean (value));
920 gtk_window_set_decorated (window, g_value_get_boolean (value));
923 gtk_window_set_deletable (window, g_value_get_boolean (value));
926 gtk_window_set_gravity (window, g_value_get_enum (value));
934 gtk_window_get_property (GObject *object,
941 window = GTK_WINDOW (object);
945 GtkWindowGeometryInfo *info;
947 g_value_set_enum (value, window->type);
950 g_value_set_string (value, window->wm_role);
953 g_value_set_string (value, window->title);
955 case PROP_ALLOW_SHRINK:
956 g_value_set_boolean (value, window->allow_shrink);
958 case PROP_ALLOW_GROW:
959 g_value_set_boolean (value, window->allow_grow);
962 g_value_set_boolean (value, window->allow_grow);
965 g_value_set_boolean (value, window->modal);
968 g_value_set_enum (value, window->position);
970 case PROP_DEFAULT_WIDTH:
971 info = gtk_window_get_geometry_info (window, FALSE);
973 g_value_set_int (value, -1);
975 g_value_set_int (value, info->default_width);
977 case PROP_DEFAULT_HEIGHT:
978 info = gtk_window_get_geometry_info (window, FALSE);
980 g_value_set_int (value, -1);
982 g_value_set_int (value, info->default_height);
984 case PROP_DESTROY_WITH_PARENT:
985 g_value_set_boolean (value, window->destroy_with_parent);
988 g_value_set_object (value, gtk_window_get_icon (window));
991 g_value_set_string (value, gtk_window_get_icon_name (window));
994 g_value_set_object (value, window->screen);
997 g_value_set_boolean (value, window->is_active);
999 case PROP_HAS_TOPLEVEL_FOCUS:
1000 g_value_set_boolean (value, window->has_toplevel_focus);
1002 case PROP_TYPE_HINT:
1003 g_value_set_enum (value,
1006 case PROP_SKIP_TASKBAR_HINT:
1007 g_value_set_boolean (value,
1008 gtk_window_get_skip_taskbar_hint (window));
1010 case PROP_SKIP_PAGER_HINT:
1011 g_value_set_boolean (value,
1012 gtk_window_get_skip_pager_hint (window));
1014 case PROP_URGENCY_HINT:
1015 g_value_set_boolean (value,
1016 gtk_window_get_urgency_hint (window));
1018 case PROP_ACCEPT_FOCUS:
1019 g_value_set_boolean (value,
1020 gtk_window_get_accept_focus (window));
1022 case PROP_FOCUS_ON_MAP:
1023 g_value_set_boolean (value,
1024 gtk_window_get_focus_on_map (window));
1026 case PROP_DECORATED:
1027 g_value_set_boolean (value, gtk_window_get_decorated (window));
1029 case PROP_DELETABLE:
1030 g_value_set_boolean (value, gtk_window_get_deletable (window));
1033 g_value_set_enum (value, gtk_window_get_gravity (window));
1036 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1043 * @type: type of window
1045 * Creates a new #GtkWindow, which is a toplevel window that can
1046 * contain other widgets. Nearly always, the type of the window should
1047 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1048 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1049 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1050 * dialogs, though in some other toolkits dialogs are called "popups".
1051 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1052 * On X11, popup windows are not controlled by the <link
1053 * linkend="gtk-X11-arch">window manager</link>.
1055 * If you simply want an undecorated window (no window borders), use
1056 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1058 * Return value: a new #GtkWindow.
1061 gtk_window_new (GtkWindowType type)
1065 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1067 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1069 window->type = type;
1071 return GTK_WIDGET (window);
1075 * gtk_window_set_title:
1076 * @window: a #GtkWindow
1077 * @title: title of the window
1079 * Sets the title of the #GtkWindow. The title of a window will be
1080 * displayed in its title bar; on the X Window System, the title bar
1081 * is rendered by the <link linkend="gtk-X11-arch">window
1082 * manager</link>, so exactly how the title appears to users may vary
1083 * according to a user's exact configuration. The title should help a
1084 * user distinguish this window from other windows they may have
1085 * open. A good title might include the application name and current
1086 * document filename, for example.
1090 gtk_window_set_title (GtkWindow *window,
1095 g_return_if_fail (GTK_IS_WINDOW (window));
1097 new_title = g_strdup (title);
1098 g_free (window->title);
1099 window->title = new_title;
1101 if (GTK_WIDGET_REALIZED (window))
1103 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
1105 gtk_decorated_window_set_title (window, title);
1108 g_object_notify (G_OBJECT (window), "title");
1112 * gtk_window_get_title:
1113 * @window: a #GtkWindow
1115 * Retrieves the title of the window. See gtk_window_set_title().
1117 * Return value: the title of the window, or %NULL if none has
1118 * been set explicitely. The returned string is owned by the widget
1119 * and must not be modified or freed.
1121 G_CONST_RETURN gchar *
1122 gtk_window_get_title (GtkWindow *window)
1124 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1126 return window->title;
1130 * gtk_window_set_wmclass:
1131 * @window: a #GtkWindow
1132 * @wmclass_name: window name hint
1133 * @wmclass_class: window class hint
1135 * Don't use this function. It sets the X Window System "class" and
1136 * "name" hints for a window. According to the ICCCM, you should
1137 * always set these to the same value for all windows in an
1138 * application, and GTK+ sets them to that value by default, so calling
1139 * this function is sort of pointless. However, you may want to call
1140 * gtk_window_set_role() on each window in your application, for the
1141 * benefit of the session manager. Setting the role allows the window
1142 * manager to restore window positions when loading a saved session.
1146 gtk_window_set_wmclass (GtkWindow *window,
1147 const gchar *wmclass_name,
1148 const gchar *wmclass_class)
1150 g_return_if_fail (GTK_IS_WINDOW (window));
1152 g_free (window->wmclass_name);
1153 window->wmclass_name = g_strdup (wmclass_name);
1155 g_free (window->wmclass_class);
1156 window->wmclass_class = g_strdup (wmclass_class);
1158 if (GTK_WIDGET_REALIZED (window))
1159 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1163 * gtk_window_set_role:
1164 * @window: a #GtkWindow
1165 * @role: unique identifier for the window to be used when restoring a session
1167 * This function is only useful on X11, not with other GTK+ targets.
1169 * In combination with the window title, the window role allows a
1170 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1171 * same" window when an application is restarted. So for example you
1172 * might set the "toolbox" role on your app's toolbox window, so that
1173 * when the user restarts their session, the window manager can put
1174 * the toolbox back in the same place.
1176 * If a window already has a unique title, you don't need to set the
1177 * role, since the WM can use the title to identify the window when
1178 * restoring the session.
1182 gtk_window_set_role (GtkWindow *window,
1187 g_return_if_fail (GTK_IS_WINDOW (window));
1189 new_role = g_strdup (role);
1190 g_free (window->wm_role);
1191 window->wm_role = new_role;
1193 if (GTK_WIDGET_REALIZED (window))
1194 gdk_window_set_role (GTK_WIDGET (window)->window, window->wm_role);
1196 g_object_notify (G_OBJECT (window), "role");
1200 * gtk_window_get_role:
1201 * @window: a #GtkWindow
1203 * Returns the role of the window. See gtk_window_set_role() for
1204 * further explanation.
1206 * Return value: the role of the window if set, or %NULL. The
1207 * returned is owned by the widget and must not be modified
1210 G_CONST_RETURN gchar *
1211 gtk_window_get_role (GtkWindow *window)
1213 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1215 return window->wm_role;
1219 * gtk_window_set_focus:
1220 * @window: a #GtkWindow
1221 * @focus: widget to be the new focus widget, or %NULL to unset
1222 * any focus widget for the toplevel window.
1224 * If @focus is not the current focus widget, and is focusable, sets
1225 * it as the focus widget for the window. If @focus is %NULL, unsets
1226 * the focus widget for this window. To set the focus to a particular
1227 * widget in the toplevel, it is usually more convenient to use
1228 * gtk_widget_grab_focus() instead of this function.
1231 gtk_window_set_focus (GtkWindow *window,
1234 g_return_if_fail (GTK_IS_WINDOW (window));
1237 g_return_if_fail (GTK_IS_WIDGET (focus));
1238 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1242 gtk_widget_grab_focus (focus);
1245 /* Clear the existing focus chain, so that when we focus into
1246 * the window again, we start at the beginnning.
1248 GtkWidget *widget = window->focus_widget;
1251 while (widget->parent)
1253 widget = widget->parent;
1254 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1258 _gtk_window_internal_set_focus (window, NULL);
1263 _gtk_window_internal_set_focus (GtkWindow *window,
1266 g_return_if_fail (GTK_IS_WINDOW (window));
1268 if ((window->focus_widget != focus) ||
1269 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1270 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1274 * gtk_window_set_default:
1275 * @window: a #GtkWindow
1276 * @default_widget: widget to be the default, or %NULL to unset the
1277 * default widget for the toplevel.
1279 * The default widget is the widget that's activated when the user
1280 * presses Enter in a dialog (for example). This function sets or
1281 * unsets the default widget for a #GtkWindow about. When setting
1282 * (rather than unsetting) the default widget it's generally easier to
1283 * call gtk_widget_grab_focus() on the widget. Before making a widget
1284 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1285 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1288 gtk_window_set_default (GtkWindow *window,
1289 GtkWidget *default_widget)
1291 g_return_if_fail (GTK_IS_WINDOW (window));
1294 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1296 if (window->default_widget != default_widget)
1298 GtkWidget *old_default_widget = NULL;
1301 g_object_ref (default_widget);
1303 if (window->default_widget)
1305 old_default_widget = window->default_widget;
1307 if (window->focus_widget != window->default_widget ||
1308 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1309 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1310 gtk_widget_queue_draw (window->default_widget);
1313 window->default_widget = default_widget;
1315 if (window->default_widget)
1317 if (window->focus_widget == NULL ||
1318 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1319 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1320 gtk_widget_queue_draw (window->default_widget);
1323 if (old_default_widget)
1324 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1328 g_object_notify (G_OBJECT (default_widget), "has-default");
1329 g_object_unref (default_widget);
1335 gtk_window_set_policy (GtkWindow *window,
1336 gboolean allow_shrink,
1337 gboolean allow_grow,
1338 gboolean auto_shrink)
1340 g_return_if_fail (GTK_IS_WINDOW (window));
1342 window->allow_shrink = (allow_shrink != FALSE);
1343 window->allow_grow = (allow_grow != FALSE);
1345 g_object_freeze_notify (G_OBJECT (window));
1346 g_object_notify (G_OBJECT (window), "allow-shrink");
1347 g_object_notify (G_OBJECT (window), "allow-grow");
1348 g_object_notify (G_OBJECT (window), "resizable");
1349 g_object_thaw_notify (G_OBJECT (window));
1351 gtk_widget_queue_resize (GTK_WIDGET (window));
1355 handle_keys_changed (gpointer data)
1359 GDK_THREADS_ENTER ();
1360 window = GTK_WINDOW (data);
1362 if (window->keys_changed_handler)
1364 g_source_remove (window->keys_changed_handler);
1365 window->keys_changed_handler = 0;
1368 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1369 GDK_THREADS_LEAVE ();
1375 gtk_window_notify_keys_changed (GtkWindow *window)
1377 if (!window->keys_changed_handler)
1378 window->keys_changed_handler = g_idle_add (handle_keys_changed, window);
1382 * gtk_window_add_accel_group:
1383 * @window: window to attach accelerator group to
1384 * @accel_group: a #GtkAccelGroup
1386 * Associate @accel_group with @window, such that calling
1387 * gtk_accel_groups_activate() on @window will activate accelerators
1391 gtk_window_add_accel_group (GtkWindow *window,
1392 GtkAccelGroup *accel_group)
1394 g_return_if_fail (GTK_IS_WINDOW (window));
1395 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1397 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1398 g_signal_connect_object (accel_group, "accel_changed",
1399 G_CALLBACK (gtk_window_notify_keys_changed),
1400 window, G_CONNECT_SWAPPED);
1404 * gtk_window_remove_accel_group:
1405 * @window: a #GtkWindow
1406 * @accel_group: a #GtkAccelGroup
1408 * Reverses the effects of gtk_window_add_accel_group().
1411 gtk_window_remove_accel_group (GtkWindow *window,
1412 GtkAccelGroup *accel_group)
1414 g_return_if_fail (GTK_IS_WINDOW (window));
1415 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1417 g_signal_handlers_disconnect_by_func (accel_group,
1418 gtk_window_notify_keys_changed,
1420 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1423 static GtkMnemonicHash *
1424 gtk_window_get_mnemonic_hash (GtkWindow *window,
1427 GtkWindowPrivate *private = GTK_WINDOW_GET_PRIVATE (window);
1428 if (!private->mnemonic_hash && create)
1429 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1431 return private->mnemonic_hash;
1435 * gtk_window_add_mnemonic:
1436 * @window: a #GtkWindow
1437 * @keyval: the mnemonic
1438 * @target: the widget that gets activated by the mnemonic
1440 * Adds a mnemonic to this window.
1443 gtk_window_add_mnemonic (GtkWindow *window,
1447 g_return_if_fail (GTK_IS_WINDOW (window));
1448 g_return_if_fail (GTK_IS_WIDGET (target));
1450 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1452 gtk_window_notify_keys_changed (window);
1456 * gtk_window_remove_mnemonic:
1457 * @window: a #GtkWindow
1458 * @keyval: the mnemonic
1459 * @target: the widget that gets activated by the mnemonic
1461 * Removes a mnemonic from this window.
1464 gtk_window_remove_mnemonic (GtkWindow *window,
1468 g_return_if_fail (GTK_IS_WINDOW (window));
1469 g_return_if_fail (GTK_IS_WIDGET (target));
1471 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
1473 gtk_window_notify_keys_changed (window);
1477 * gtk_window_mnemonic_activate:
1478 * @window: a #GtkWindow
1479 * @keyval: the mnemonic
1480 * @modifier: the modifiers
1481 * @returns: %TRUE if the activation is done.
1483 * Activates the targets associated with the mnemonic.
1486 gtk_window_mnemonic_activate (GtkWindow *window,
1488 GdkModifierType modifier)
1490 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1492 if (window->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
1494 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
1496 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
1503 * gtk_window_set_mnemonic_modifier:
1504 * @window: a #GtkWindow
1505 * @modifier: the modifier mask used to activate
1506 * mnemonics on this window.
1508 * Sets the mnemonic modifier for this window.
1511 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1512 GdkModifierType modifier)
1514 g_return_if_fail (GTK_IS_WINDOW (window));
1515 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1517 window->mnemonic_modifier = modifier;
1518 gtk_window_notify_keys_changed (window);
1522 * gtk_window_get_mnemonic_modifier:
1523 * @window: a #GtkWindow
1525 * Returns the mnemonic modifier for this window. See
1526 * gtk_window_set_mnemonic_modifier().
1528 * Return value: the modifier mask used to activate
1529 * mnemonics on this window.
1532 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1534 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1536 return window->mnemonic_modifier;
1540 * gtk_window_set_position:
1541 * @window: a #GtkWindow.
1542 * @position: a position constraint.
1544 * Sets a position constraint for this window. If the old or new
1545 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1546 * the window to be repositioned to satisfy the new constraint.
1549 gtk_window_set_position (GtkWindow *window,
1550 GtkWindowPosition position)
1552 g_return_if_fail (GTK_IS_WINDOW (window));
1554 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1555 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1557 GtkWindowGeometryInfo *info;
1559 info = gtk_window_get_geometry_info (window, TRUE);
1561 /* this flag causes us to re-request the CENTER_ALWAYS
1562 * constraint in gtk_window_move_resize(), see
1563 * comment in that function.
1565 info->position_constraints_changed = TRUE;
1567 gtk_widget_queue_resize (GTK_WIDGET (window));
1570 window->position = position;
1572 g_object_notify (G_OBJECT (window), "window-position");
1576 * gtk_window_activate_focus:
1577 * @window: a #GtkWindow
1579 * Activates the current focused widget within the window.
1581 * Return value: %TRUE if a widget got activated.
1584 gtk_window_activate_focus (GtkWindow *window)
1586 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1588 if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1589 return gtk_widget_activate (window->focus_widget);
1595 * gtk_window_get_focus:
1596 * @window: a #GtkWindow
1598 * Retrieves the current focused widget within the window.
1599 * Note that this is the widget that would have the focus
1600 * if the toplevel window focused; if the toplevel window
1601 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1602 * not be %TRUE for the widget.
1604 * Return value: the currently focused widget, or %NULL if there is none.
1607 gtk_window_get_focus (GtkWindow *window)
1609 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1611 return window->focus_widget;
1615 * gtk_window_activate_default:
1616 * @window: a #GtkWindow
1618 * Activates the default widget for the window, unless the current
1619 * focused widget has been configured to receive the default action
1620 * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
1621 * focused widget is activated.
1623 * Return value: %TRUE if a widget got activated.
1626 gtk_window_activate_default (GtkWindow *window)
1628 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1630 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1631 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1632 return gtk_widget_activate (window->default_widget);
1633 else if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1634 return gtk_widget_activate (window->focus_widget);
1640 * gtk_window_set_modal:
1641 * @window: a #GtkWindow
1642 * @modal: whether the window is modal
1644 * Sets a window modal or non-modal. Modal windows prevent interaction
1645 * with other windows in the same application. To keep modal dialogs
1646 * on top of main application windows, use
1647 * gtk_window_set_transient_for() to make the dialog transient for the
1648 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1649 * will then disallow lowering the dialog below the parent.
1654 gtk_window_set_modal (GtkWindow *window,
1657 g_return_if_fail (GTK_IS_WINDOW (window));
1659 modal = modal != FALSE;
1660 if (window->modal == modal)
1663 window->modal = modal;
1665 /* adjust desired modality state */
1666 if (GTK_WIDGET_REALIZED (window))
1668 GtkWidget *widget = GTK_WIDGET (window);
1671 gdk_window_set_modal_hint (widget->window, TRUE);
1673 gdk_window_set_modal_hint (widget->window, FALSE);
1676 if (GTK_WIDGET_VISIBLE (window))
1679 gtk_grab_add (GTK_WIDGET (window));
1681 gtk_grab_remove (GTK_WIDGET (window));
1684 g_object_notify (G_OBJECT (window), "modal");
1688 * gtk_window_get_modal:
1689 * @window: a #GtkWindow
1691 * Returns whether the window is modal. See gtk_window_set_modal().
1693 * Return value: %TRUE if the window is set to be modal and
1694 * establishes a grab when shown
1697 gtk_window_get_modal (GtkWindow *window)
1699 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1701 return window->modal;
1705 * gtk_window_list_toplevels:
1707 * Returns a list of all existing toplevel windows. The widgets
1708 * in the list are not individually referenced. If you want
1709 * to iterate through the list and perform actions involving
1710 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1711 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1712 * then unref all the widgets afterwards.
1714 * Return value: list of toplevel widgets
1717 gtk_window_list_toplevels (void)
1722 for (slist = toplevel_list; slist; slist = slist->next)
1723 list = g_list_prepend (list, slist->data);
1729 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1731 GList *embedded_windows;
1733 g_return_if_fail (GTK_IS_WINDOW (window));
1735 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
1736 if (embedded_windows)
1737 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
1738 embedded_windows = g_list_prepend (embedded_windows,
1739 GUINT_TO_POINTER (xid));
1741 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
1744 (GDestroyNotify) g_list_free : NULL);
1748 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1750 GList *embedded_windows;
1753 g_return_if_fail (GTK_IS_WINDOW (window));
1755 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
1756 if (embedded_windows)
1757 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
1759 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1762 embedded_windows = g_list_remove_link (embedded_windows, node);
1763 g_list_free_1 (node);
1766 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
1769 (GDestroyNotify) g_list_free : NULL);
1773 _gtk_window_reposition (GtkWindow *window,
1777 g_return_if_fail (GTK_IS_WINDOW (window));
1779 gtk_window_move (window, x, y);
1783 gtk_window_dispose (GObject *object)
1785 GtkWindow *window = GTK_WINDOW (object);
1787 gtk_window_set_focus (window, NULL);
1788 gtk_window_set_default (window, NULL);
1790 G_OBJECT_CLASS (parent_class)->dispose (object);
1794 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1796 gtk_widget_destroy (GTK_WIDGET (child));
1800 connect_parent_destroyed (GtkWindow *window)
1802 if (window->transient_parent)
1804 g_signal_connect (window->transient_parent,
1806 G_CALLBACK (parent_destroyed_callback),
1812 disconnect_parent_destroyed (GtkWindow *window)
1814 if (window->transient_parent)
1816 g_signal_handlers_disconnect_by_func (window->transient_parent,
1817 parent_destroyed_callback,
1823 gtk_window_transient_parent_realized (GtkWidget *parent,
1826 if (GTK_WIDGET_REALIZED (window))
1827 gdk_window_set_transient_for (window->window, parent->window);
1831 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1834 if (GTK_WIDGET_REALIZED (window))
1835 gdk_property_delete (window->window,
1836 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
1840 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
1844 gtk_window_set_screen (window, parent->screen);
1848 gtk_window_unset_transient_for (GtkWindow *window)
1850 if (window->transient_parent)
1852 if (window->transient_parent->group)
1853 gtk_window_group_remove_window (window->transient_parent->group,
1856 g_signal_handlers_disconnect_by_func (window->transient_parent,
1857 gtk_window_transient_parent_realized,
1859 g_signal_handlers_disconnect_by_func (window->transient_parent,
1860 gtk_window_transient_parent_unrealized,
1862 g_signal_handlers_disconnect_by_func (window->transient_parent,
1863 gtk_window_transient_parent_screen_changed,
1865 g_signal_handlers_disconnect_by_func (window->transient_parent,
1866 gtk_widget_destroyed,
1867 &window->transient_parent);
1869 if (window->destroy_with_parent)
1870 disconnect_parent_destroyed (window);
1872 window->transient_parent = NULL;
1877 * gtk_window_set_transient_for:
1878 * @window: a #GtkWindow
1879 * @parent: parent window
1881 * Dialog windows should be set transient for the main application
1882 * window they were spawned from. This allows <link
1883 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1884 * dialog on top of the main window, or center the dialog over the
1885 * main window. gtk_dialog_new_with_buttons() and other convenience
1886 * functions in GTK+ will sometimes call
1887 * gtk_window_set_transient_for() on your behalf.
1889 * On Windows, this function will and put the child window
1890 * on top of the parent, much as the window manager would have
1895 gtk_window_set_transient_for (GtkWindow *window,
1898 g_return_if_fail (GTK_IS_WINDOW (window));
1899 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1900 g_return_if_fail (window != parent);
1903 if (window->transient_parent)
1905 if (GTK_WIDGET_REALIZED (window) &&
1906 GTK_WIDGET_REALIZED (window->transient_parent) &&
1907 (!parent || !GTK_WIDGET_REALIZED (parent)))
1908 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1909 GTK_WIDGET (window));
1911 gtk_window_unset_transient_for (window);
1914 window->transient_parent = parent;
1918 g_signal_connect (parent, "destroy",
1919 G_CALLBACK (gtk_widget_destroyed),
1920 &window->transient_parent);
1921 g_signal_connect (parent, "realize",
1922 G_CALLBACK (gtk_window_transient_parent_realized),
1924 g_signal_connect (parent, "unrealize",
1925 G_CALLBACK (gtk_window_transient_parent_unrealized),
1927 g_signal_connect (parent, "notify::screen",
1928 G_CALLBACK (gtk_window_transient_parent_screen_changed),
1931 gtk_window_set_screen (window, parent->screen);
1933 if (window->destroy_with_parent)
1934 connect_parent_destroyed (window);
1936 if (GTK_WIDGET_REALIZED (window) &&
1937 GTK_WIDGET_REALIZED (parent))
1938 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1939 GTK_WIDGET (window));
1942 gtk_window_group_add_window (parent->group, window);
1947 * gtk_window_get_transient_for:
1948 * @window: a #GtkWindow
1950 * Fetches the transient parent for this window. See
1951 * gtk_window_set_transient_for().
1953 * Return value: the transient parent for this window, or %NULL
1954 * if no transient parent has been set.
1957 gtk_window_get_transient_for (GtkWindow *window)
1959 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1961 return window->transient_parent;
1965 * gtk_window_set_type_hint:
1966 * @window: a #GtkWindow
1967 * @hint: the window type
1969 * By setting the type hint for the window, you allow the window
1970 * manager to decorate and handle the window in a way which is
1971 * suitable to the function of the window in your application.
1973 * This function should be called before the window becomes visible.
1975 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1976 * will sometimes call gtk_window_set_type_hint() on your behalf.
1980 gtk_window_set_type_hint (GtkWindow *window,
1981 GdkWindowTypeHint hint)
1983 g_return_if_fail (GTK_IS_WINDOW (window));
1984 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1985 window->type_hint = hint;
1989 * gtk_window_get_type_hint:
1990 * @window: a #GtkWindow
1992 * Gets the type hint for this window. See gtk_window_set_type_hint().
1994 * Return value: the type hint for @window.
1997 gtk_window_get_type_hint (GtkWindow *window)
1999 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2001 return window->type_hint;
2005 * gtk_window_set_skip_taskbar_hint:
2006 * @window: a #GtkWindow
2007 * @setting: %TRUE to keep this window from appearing in the task bar
2009 * Windows may set a hint asking the desktop environment not to display
2010 * the window in the task bar. This function sets this hint.
2015 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2018 GtkWindowPrivate *priv;
2020 g_return_if_fail (GTK_IS_WINDOW (window));
2022 priv = GTK_WINDOW_GET_PRIVATE (window);
2024 setting = setting != FALSE;
2026 if (priv->skips_taskbar != setting)
2028 priv->skips_taskbar = setting;
2029 if (GTK_WIDGET_REALIZED (window))
2030 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
2031 priv->skips_taskbar);
2032 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2037 * gtk_window_get_skip_taskbar_hint:
2038 * @window: a #GtkWindow
2040 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2042 * Return value: %TRUE if window shouldn't be in taskbar
2047 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2049 GtkWindowPrivate *priv;
2051 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2053 priv = GTK_WINDOW_GET_PRIVATE (window);
2055 return priv->skips_taskbar;
2059 * gtk_window_set_skip_pager_hint:
2060 * @window: a #GtkWindow
2061 * @setting: %TRUE to keep this window from appearing in the pager
2063 * Windows may set a hint asking the desktop environment not to display
2064 * the window in the pager. This function sets this hint.
2065 * (A "pager" is any desktop navigation tool such as a workspace
2066 * switcher that displays a thumbnail representation of the windows
2072 gtk_window_set_skip_pager_hint (GtkWindow *window,
2075 GtkWindowPrivate *priv;
2077 g_return_if_fail (GTK_IS_WINDOW (window));
2079 priv = GTK_WINDOW_GET_PRIVATE (window);
2081 setting = setting != FALSE;
2083 if (priv->skips_pager != setting)
2085 priv->skips_pager = setting;
2086 if (GTK_WIDGET_REALIZED (window))
2087 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2089 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2094 * gtk_window_get_skip_pager_hint:
2095 * @window: a #GtkWindow
2097 * Gets the value set by gtk_window_set_skip_pager_hint().
2099 * Return value: %TRUE if window shouldn't be in pager
2104 gtk_window_get_skip_pager_hint (GtkWindow *window)
2106 GtkWindowPrivate *priv;
2108 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2110 priv = GTK_WINDOW_GET_PRIVATE (window);
2112 return priv->skips_pager;
2116 * gtk_window_set_urgency_hint:
2117 * @window: a #GtkWindow
2118 * @setting: %TRUE to mark this window as urgent
2120 * Windows may set a hint asking the desktop environment to draw
2121 * the users attention to the window. This function sets this hint.
2126 gtk_window_set_urgency_hint (GtkWindow *window,
2129 GtkWindowPrivate *priv;
2131 g_return_if_fail (GTK_IS_WINDOW (window));
2133 priv = GTK_WINDOW_GET_PRIVATE (window);
2135 setting = setting != FALSE;
2137 if (priv->urgent != setting)
2139 priv->urgent = setting;
2140 if (GTK_WIDGET_REALIZED (window))
2141 gdk_window_set_urgency_hint (GTK_WIDGET (window)->window,
2143 g_object_notify (G_OBJECT (window), "urgency-hint");
2148 * gtk_window_get_urgency_hint:
2149 * @window: a #GtkWindow
2151 * Gets the value set by gtk_window_set_urgency_hint()
2153 * Return value: %TRUE if window is urgent
2158 gtk_window_get_urgency_hint (GtkWindow *window)
2160 GtkWindowPrivate *priv;
2162 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2164 priv = GTK_WINDOW_GET_PRIVATE (window);
2166 return priv->urgent;
2170 * gtk_window_set_accept_focus:
2171 * @window: a #GtkWindow
2172 * @setting: %TRUE to let this window receive input focus
2174 * Windows may set a hint asking the desktop environment not to receive
2175 * the input focus. This function sets this hint.
2180 gtk_window_set_accept_focus (GtkWindow *window,
2183 GtkWindowPrivate *priv;
2185 g_return_if_fail (GTK_IS_WINDOW (window));
2187 priv = GTK_WINDOW_GET_PRIVATE (window);
2189 setting = setting != FALSE;
2191 if (priv->accept_focus != setting)
2193 priv->accept_focus = setting;
2194 if (GTK_WIDGET_REALIZED (window))
2195 gdk_window_set_accept_focus (GTK_WIDGET (window)->window,
2196 priv->accept_focus);
2197 g_object_notify (G_OBJECT (window), "accept-focus");
2202 * gtk_window_get_accept_focus:
2203 * @window: a #GtkWindow
2205 * Gets the value set by gtk_window_set_accept_focus().
2207 * Return value: %TRUE if window should receive the input focus
2212 gtk_window_get_accept_focus (GtkWindow *window)
2214 GtkWindowPrivate *priv;
2216 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2218 priv = GTK_WINDOW_GET_PRIVATE (window);
2220 return priv->accept_focus;
2224 * gtk_window_set_focus_on_map:
2225 * @window: a #GtkWindow
2226 * @setting: %TRUE to let this window receive input focus on map
2228 * Windows may set a hint asking the desktop environment not to receive
2229 * the input focus when the window is mapped. This function sets this
2235 gtk_window_set_focus_on_map (GtkWindow *window,
2238 GtkWindowPrivate *priv;
2240 g_return_if_fail (GTK_IS_WINDOW (window));
2242 priv = GTK_WINDOW_GET_PRIVATE (window);
2244 setting = setting != FALSE;
2246 if (priv->focus_on_map != setting)
2248 priv->focus_on_map = setting;
2249 if (GTK_WIDGET_REALIZED (window))
2250 gdk_window_set_focus_on_map (GTK_WIDGET (window)->window,
2251 priv->focus_on_map);
2252 g_object_notify (G_OBJECT (window), "focus-on-map");
2257 * gtk_window_get_focus_on_map:
2258 * @window: a #GtkWindow
2260 * Gets the value set by gtk_window_set_focus_on_map().
2262 * Return value: %TRUE if window should receive the input focus when
2268 gtk_window_get_focus_on_map (GtkWindow *window)
2270 GtkWindowPrivate *priv;
2272 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2274 priv = GTK_WINDOW_GET_PRIVATE (window);
2276 return priv->focus_on_map;
2280 * gtk_window_set_destroy_with_parent:
2281 * @window: a #GtkWindow
2282 * @setting: whether to destroy @window with its transient parent
2284 * If @setting is %TRUE, then destroying the transient parent of @window
2285 * will also destroy @window itself. This is useful for dialogs that
2286 * shouldn't persist beyond the lifetime of the main window they're
2287 * associated with, for example.
2290 gtk_window_set_destroy_with_parent (GtkWindow *window,
2293 g_return_if_fail (GTK_IS_WINDOW (window));
2295 if (window->destroy_with_parent == (setting != FALSE))
2298 if (window->destroy_with_parent)
2300 disconnect_parent_destroyed (window);
2304 connect_parent_destroyed (window);
2307 window->destroy_with_parent = setting;
2309 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2313 * gtk_window_get_destroy_with_parent:
2314 * @window: a #GtkWindow
2316 * Returns whether the window will be destroyed with its transient parent. See
2317 * gtk_window_set_destroy_with_parent ().
2319 * Return value: %TRUE if the window will be destroyed with its transient parent.
2322 gtk_window_get_destroy_with_parent (GtkWindow *window)
2324 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2326 return window->destroy_with_parent;
2329 static GtkWindowGeometryInfo*
2330 gtk_window_get_geometry_info (GtkWindow *window,
2333 GtkWindowGeometryInfo *info;
2335 info = window->geometry_info;
2336 if (!info && create)
2338 info = g_new0 (GtkWindowGeometryInfo, 1);
2340 info->default_width = -1;
2341 info->default_height = -1;
2342 info->resize_width = -1;
2343 info->resize_height = -1;
2344 info->initial_x = 0;
2345 info->initial_y = 0;
2346 info->initial_pos_set = FALSE;
2347 info->default_is_geometry = FALSE;
2348 info->position_constraints_changed = FALSE;
2349 info->last.configure_request.x = 0;
2350 info->last.configure_request.y = 0;
2351 info->last.configure_request.width = -1;
2352 info->last.configure_request.height = -1;
2353 info->widget = NULL;
2355 window->geometry_info = info;
2362 * gtk_window_set_geometry_hints:
2363 * @window: a #GtkWindow
2364 * @geometry_widget: widget the geometry hints will be applied to
2365 * @geometry: struct containing geometry information
2366 * @geom_mask: mask indicating which struct fields should be paid attention to
2368 * This function sets up hints about how a window can be resized by
2369 * the user. You can set a minimum and maximum size; allowed resize
2370 * increments (e.g. for xterm, you can only resize by the size of a
2371 * character); aspect ratios; and more. See the #GdkGeometry struct.
2375 gtk_window_set_geometry_hints (GtkWindow *window,
2376 GtkWidget *geometry_widget,
2377 GdkGeometry *geometry,
2378 GdkWindowHints geom_mask)
2380 GtkWindowGeometryInfo *info;
2382 g_return_if_fail (GTK_IS_WINDOW (window));
2383 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2385 info = gtk_window_get_geometry_info (window, TRUE);
2388 g_signal_handlers_disconnect_by_func (info->widget,
2389 gtk_widget_destroyed,
2392 info->widget = geometry_widget;
2394 g_signal_connect (geometry_widget, "destroy",
2395 G_CALLBACK (gtk_widget_destroyed),
2399 info->geometry = *geometry;
2401 /* We store gravity in window->gravity not in the hints. */
2402 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2404 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2406 gtk_window_set_gravity (window, geometry->win_gravity);
2409 gtk_widget_queue_resize (GTK_WIDGET (window));
2413 * gtk_window_set_decorated:
2414 * @window: a #GtkWindow
2415 * @setting: %TRUE to decorate the window
2417 * By default, windows are decorated with a title bar, resize
2418 * controls, etc. Some <link linkend="gtk-X11-arch">window
2419 * managers</link> allow GTK+ to disable these decorations, creating a
2420 * borderless window. If you set the decorated property to %FALSE
2421 * using this function, GTK+ will do its best to convince the window
2422 * manager not to decorate the window. Depending on the system, this
2423 * function may not have any effect when called on a window that is
2424 * already visible, so you should call it before calling gtk_window_show().
2426 * On Windows, this function always works, since there's no window manager
2431 gtk_window_set_decorated (GtkWindow *window,
2434 g_return_if_fail (GTK_IS_WINDOW (window));
2436 setting = setting != FALSE;
2438 if (setting == window->decorated)
2441 window->decorated = setting;
2443 if (GTK_WIDGET (window)->window)
2445 if (window->decorated)
2446 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2449 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2453 g_object_notify (G_OBJECT (window), "decorated");
2457 * gtk_window_get_decorated:
2458 * @window: a #GtkWindow
2460 * Returns whether the window has been set to have decorations
2461 * such as a title bar via gtk_window_set_decorated().
2463 * Return value: %TRUE if the window has been set to have decorations
2466 gtk_window_get_decorated (GtkWindow *window)
2468 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2470 return window->decorated;
2474 * gtk_window_set_deletable:
2475 * @window: a #GtkWindow
2476 * @setting: %TRUE to decorate the window as deletable
2478 * By default, windows have a close button in the window frame. Some
2479 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
2480 * disable this button. If you set the deletable property to %FALSE
2481 * using this function, GTK+ will do its best to convince the window
2482 * manager not to show a close button. Depending on the system, this
2483 * function may not have any effect when called on a window that is
2484 * already visible, so you should call it before calling gtk_window_show().
2486 * On Windows, this function always works, since there's no window manager
2492 gtk_window_set_deletable (GtkWindow *window,
2495 GtkWindowPrivate *priv;
2497 g_return_if_fail (GTK_IS_WINDOW (window));
2499 priv = GTK_WINDOW_GET_PRIVATE (window);
2501 setting = setting != FALSE;
2503 if (setting == priv->deletable)
2506 priv->deletable = setting;
2508 if (GTK_WIDGET (window)->window)
2510 if (priv->deletable)
2511 gdk_window_set_functions (GTK_WIDGET (window)->window,
2514 gdk_window_set_functions (GTK_WIDGET (window)->window,
2515 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
2518 g_object_notify (G_OBJECT (window), "deletable");
2522 * gtk_window_get_deletable:
2523 * @window: a #GtkWindow
2525 * Returns whether the window has been set to have a close button
2526 * via gtk_window_set_deletable().
2528 * Return value: %TRUE if the window has been set to have a close button
2531 gtk_window_get_deletable (GtkWindow *window)
2533 GtkWindowPrivate *priv;
2535 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2537 priv = GTK_WINDOW_GET_PRIVATE (window);
2539 return priv->deletable;
2542 static GtkWindowIconInfo*
2543 get_icon_info (GtkWindow *window)
2545 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
2549 free_icon_info (GtkWindowIconInfo *info)
2551 g_free (info->icon_name);
2552 g_slice_free (GtkWindowIconInfo, info);
2556 static GtkWindowIconInfo*
2557 ensure_icon_info (GtkWindow *window)
2559 GtkWindowIconInfo *info;
2561 info = get_icon_info (window);
2565 info = g_slice_new0 (GtkWindowIconInfo);
2566 g_object_set_qdata_full (G_OBJECT (window),
2567 quark_gtk_window_icon_info,
2569 (GDestroyNotify)free_icon_info);
2581 static ScreenIconInfo *
2582 get_screen_icon_info (GdkScreen *screen)
2584 ScreenIconInfo *info = g_object_get_qdata (G_OBJECT (screen),
2585 quark_gtk_window_default_icon_pixmap);
2588 info = g_slice_new0 (ScreenIconInfo);
2589 g_object_set_qdata (G_OBJECT (screen),
2590 quark_gtk_window_default_icon_pixmap, info);
2593 if (info->serial != default_icon_serial)
2597 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2598 info->pixmap = NULL;
2603 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2607 info->serial = default_icon_serial;
2614 get_pixmap_and_mask (GdkWindow *window,
2615 GtkWindowIconInfo *parent_info,
2616 gboolean is_default_list,
2618 GdkPixmap **pmap_return,
2619 GdkBitmap **mask_return)
2621 GdkScreen *screen = gdk_drawable_get_screen (window);
2622 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2623 GdkPixbuf *best_icon;
2627 *pmap_return = NULL;
2628 *mask_return = NULL;
2630 if (is_default_list &&
2631 default_icon_info->pixmap != NULL)
2633 /* Use shared icon pixmap for all windows on this screen.
2635 if (default_icon_info->pixmap)
2636 g_object_ref (default_icon_info->pixmap);
2637 if (default_icon_info->mask)
2638 g_object_ref (default_icon_info->mask);
2640 *pmap_return = default_icon_info->pixmap;
2641 *mask_return = default_icon_info->mask;
2643 else if (parent_info && parent_info->icon_pixmap)
2645 if (parent_info->icon_pixmap)
2646 g_object_ref (parent_info->icon_pixmap);
2647 if (parent_info->icon_mask)
2648 g_object_ref (parent_info->icon_mask);
2650 *pmap_return = parent_info->icon_pixmap;
2651 *mask_return = parent_info->icon_mask;
2655 #define IDEAL_SIZE 48
2657 best_size = G_MAXINT;
2659 tmp_list = icon_list;
2660 while (tmp_list != NULL)
2662 GdkPixbuf *pixbuf = tmp_list->data;
2665 /* average width and height - if someone passes in a rectangular
2666 * icon they deserve what they get.
2668 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2671 if (best_icon == NULL)
2678 /* icon is better if it's 32 pixels or larger, and closer to
2679 * the ideal size than the current best.
2682 (ABS (best_size - IDEAL_SIZE) <
2683 ABS (this - IDEAL_SIZE)))
2690 tmp_list = tmp_list->next;
2694 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2695 gdk_screen_get_system_colormap (screen),
2700 /* Save pmap/mask for others to use if appropriate */
2703 parent_info->icon_pixmap = *pmap_return;
2704 parent_info->icon_mask = *mask_return;
2706 if (parent_info->icon_pixmap)
2707 g_object_ref (parent_info->icon_pixmap);
2708 if (parent_info->icon_mask)
2709 g_object_ref (parent_info->icon_mask);
2711 else if (is_default_list)
2713 default_icon_info->pixmap = *pmap_return;
2714 default_icon_info->mask = *mask_return;
2716 if (default_icon_info->pixmap)
2717 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2718 (gpointer*)&default_icon_info->pixmap);
2719 if (default_icon_info->mask)
2720 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2721 (gpointer*)&default_icon_info->mask);
2727 icon_list_from_theme (GtkWidget *widget,
2732 GtkIconTheme *icon_theme;
2737 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
2739 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
2742 for (i = 0; sizes[i]; i++)
2745 * We need an EWMH extension to handle scalable icons
2746 * by passing their name to the WM. For now just use a
2750 icon = gtk_icon_theme_load_icon (icon_theme, name,
2753 icon = gtk_icon_theme_load_icon (icon_theme, name,
2756 list = g_list_append (list, icon);
2766 gtk_window_realize_icon (GtkWindow *window)
2769 GtkWindowIconInfo *info;
2772 widget = GTK_WIDGET (window);
2774 g_return_if_fail (widget->window != NULL);
2776 /* no point setting an icon on override-redirect */
2777 if (window->type == GTK_WINDOW_POPUP)
2782 info = ensure_icon_info (window);
2787 g_return_if_fail (info->icon_pixmap == NULL);
2788 g_return_if_fail (info->icon_mask == NULL);
2790 info->using_default_icon = FALSE;
2791 info->using_parent_icon = FALSE;
2792 info->using_themed_icon = FALSE;
2794 icon_list = info->icon_list;
2796 /* Look up themed icon */
2797 if (icon_list == NULL && info->icon_name)
2799 icon_list = icon_list_from_theme (widget, info->icon_name);
2801 info->using_themed_icon = TRUE;
2804 /* Inherit from transient parent */
2805 if (icon_list == NULL && window->transient_parent)
2807 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2809 info->using_parent_icon = TRUE;
2812 /* Inherit from default */
2813 if (icon_list == NULL)
2815 icon_list = default_icon_list;
2817 info->using_default_icon = TRUE;
2820 /* Look up themed icon */
2821 if (icon_list == NULL && default_icon_name)
2823 icon_list = icon_list_from_theme (widget, default_icon_name);
2824 info->using_default_icon = TRUE;
2825 info->using_themed_icon = TRUE;
2828 gdk_window_set_icon_list (widget->window, icon_list);
2830 get_pixmap_and_mask (widget->window,
2831 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2832 info->using_default_icon,
2837 /* This is a slight ICCCM violation since it's a color pixmap not
2838 * a bitmap, but everyone does it.
2840 gdk_window_set_icon (widget->window,
2845 info->realized = TRUE;
2847 if (info->using_themed_icon)
2849 GtkIconTheme *icon_theme;
2851 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
2852 g_list_free (icon_list);
2854 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2855 g_signal_connect (icon_theme, "changed",
2856 G_CALLBACK (update_themed_icon), window);
2861 gtk_window_unrealize_icon (GtkWindow *window)
2863 GtkWindowIconInfo *info;
2865 info = get_icon_info (window);
2870 if (info->icon_pixmap)
2871 g_object_unref (info->icon_pixmap);
2873 if (info->icon_mask)
2874 g_object_unref (info->icon_mask);
2876 info->icon_pixmap = NULL;
2877 info->icon_mask = NULL;
2879 if (info->using_themed_icon)
2881 GtkIconTheme *icon_theme;
2883 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2885 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
2888 /* We don't clear the properties on the window, just figure the
2889 * window is going away.
2892 info->realized = FALSE;
2897 * gtk_window_set_icon_list:
2898 * @window: a #GtkWindow
2899 * @list: list of #GdkPixbuf
2901 * Sets up the icon representing a #GtkWindow. The icon is used when
2902 * the window is minimized (also known as iconified). Some window
2903 * managers or desktop environments may also place it in the window
2904 * frame, or display it in other contexts.
2906 * gtk_window_set_icon_list() allows you to pass in the same icon in
2907 * several hand-drawn sizes. The list should contain the natural sizes
2908 * your icon is available in; that is, don't scale the image before
2909 * passing it to GTK+. Scaling is postponed until the last minute,
2910 * when the desired final size is known, to allow best quality.
2912 * By passing several sizes, you may improve the final image quality
2913 * of the icon, by reducing or eliminating automatic image scaling.
2915 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2916 * larger images (64x64, 128x128) if you have them.
2918 * See also gtk_window_set_default_icon_list() to set the icon
2919 * for all windows in your application in one go.
2921 * Note that transient windows (those who have been set transient for another
2922 * window using gtk_window_set_transient_for()) will inherit their
2923 * icon from their transient parent. So there's no need to explicitly
2924 * set the icon on transient windows.
2927 gtk_window_set_icon_list (GtkWindow *window,
2930 GtkWindowIconInfo *info;
2932 g_return_if_fail (GTK_IS_WINDOW (window));
2934 info = ensure_icon_info (window);
2936 if (info->icon_list == list) /* check for NULL mostly */
2939 g_list_foreach (list,
2940 (GFunc) g_object_ref, NULL);
2942 g_list_foreach (info->icon_list,
2943 (GFunc) g_object_unref, NULL);
2945 g_list_free (info->icon_list);
2947 info->icon_list = g_list_copy (list);
2949 g_object_notify (G_OBJECT (window), "icon");
2951 gtk_window_unrealize_icon (window);
2953 if (GTK_WIDGET_REALIZED (window))
2954 gtk_window_realize_icon (window);
2956 /* We could try to update our transient children, but I don't think
2957 * it's really worth it. If we did it, the best way would probably
2958 * be to have children connect to notify::icon-list
2963 * gtk_window_get_icon_list:
2964 * @window: a #GtkWindow
2966 * Retrieves the list of icons set by gtk_window_set_icon_list().
2967 * The list is copied, but the reference count on each
2968 * member won't be incremented.
2970 * Return value: copy of window's icon list
2973 gtk_window_get_icon_list (GtkWindow *window)
2975 GtkWindowIconInfo *info;
2977 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2979 info = get_icon_info (window);
2982 return g_list_copy (info->icon_list);
2988 * gtk_window_set_icon:
2989 * @window: a #GtkWindow
2990 * @icon: icon image, or %NULL
2992 * Sets up the icon representing a #GtkWindow. This icon is used when
2993 * the window is minimized (also known as iconified). Some window
2994 * managers or desktop environments may also place it in the window
2995 * frame, or display it in other contexts.
2997 * The icon should be provided in whatever size it was naturally
2998 * drawn; that is, don't scale the image before passing it to
2999 * GTK+. Scaling is postponed until the last minute, when the desired
3000 * final size is known, to allow best quality.
3002 * If you have your icon hand-drawn in multiple sizes, use
3003 * gtk_window_set_icon_list(). Then the best size will be used.
3005 * This function is equivalent to calling gtk_window_set_icon_list()
3006 * with a 1-element list.
3008 * See also gtk_window_set_default_icon_list() to set the icon
3009 * for all windows in your application in one go.
3012 gtk_window_set_icon (GtkWindow *window,
3017 g_return_if_fail (GTK_IS_WINDOW (window));
3018 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3023 list = g_list_append (list, icon);
3025 gtk_window_set_icon_list (window, list);
3031 update_themed_icon (GtkIconTheme *icon_theme,
3034 g_object_notify (G_OBJECT (window), "icon");
3036 gtk_window_unrealize_icon (window);
3038 if (GTK_WIDGET_REALIZED (window))
3039 gtk_window_realize_icon (window);
3043 * gtk_window_set_icon_name:
3044 * @window: a #GtkWindow
3045 * @name: the name of the themed icon
3047 * Sets the icon for the window from a named themed icon. See
3048 * the docs for #GtkIconTheme for more details.
3050 * Note that this has nothing to do with the WM_ICON_NAME
3051 * property which is mentioned in the ICCCM.
3056 gtk_window_set_icon_name (GtkWindow *window,
3059 GtkWindowIconInfo *info;
3062 g_return_if_fail (GTK_IS_WINDOW (window));
3064 info = ensure_icon_info (window);
3066 tmp = info->icon_name;
3067 info->icon_name = g_strdup (name);
3070 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3071 g_list_free (info->icon_list);
3072 info->icon_list = NULL;
3074 update_themed_icon (NULL, window);
3076 g_object_notify (G_OBJECT (window), "icon-name");
3080 * gtk_window_get_icon_name:
3081 * @window: a #GtkWindow
3083 * Returns the name of the themed icon for the window,
3084 * see gtk_window_set_icon_name().
3086 * Returns: the icon name or %NULL if the window has
3091 G_CONST_RETURN gchar *
3092 gtk_window_get_icon_name (GtkWindow *window)
3094 GtkWindowIconInfo *info;
3096 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3098 info = ensure_icon_info (window);
3100 return info->icon_name;
3104 * gtk_window_get_icon:
3105 * @window: a #GtkWindow
3107 * Gets the value set by gtk_window_set_icon() (or if you've
3108 * called gtk_window_set_icon_list(), gets the first icon in
3111 * Return value: icon for window
3114 gtk_window_get_icon (GtkWindow *window)
3116 GtkWindowIconInfo *info;
3118 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3120 info = get_icon_info (window);
3121 if (info && info->icon_list)
3122 return GDK_PIXBUF (info->icon_list->data);
3127 /* Load pixbuf, printing warning on failure if error == NULL
3130 load_pixbuf_verbosely (const char *filename,
3133 GError *local_err = NULL;
3136 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3144 g_warning ("Error loading icon from file '%s':\n\t%s",
3145 filename, local_err->message);
3146 g_error_free (local_err);
3154 * gtk_window_set_icon_from_file:
3155 * @window: a #GtkWindow
3156 * @filename: location of icon file
3157 * @err: location to store error, or %NULL.
3159 * Sets the icon for @window.
3160 * Warns on failure if @err is %NULL.
3162 * This function is equivalent to calling gtk_window_set_icon()
3163 * with a pixbuf created by loading the image from @filename.
3165 * Returns: %TRUE if setting the icon succeeded.
3170 gtk_window_set_icon_from_file (GtkWindow *window,
3171 const gchar *filename,
3174 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3178 gtk_window_set_icon (window, pixbuf);
3179 g_object_unref (pixbuf);
3188 * gtk_window_set_default_icon_list:
3189 * @list: a list of #GdkPixbuf
3191 * Sets an icon list to be used as fallback for windows that haven't
3192 * had gtk_window_set_icon_list() called on them to set up a
3193 * window-specific icon list. This function allows you to set up the
3194 * icon for all windows in your app at once.
3196 * See gtk_window_set_icon_list() for more details.
3200 gtk_window_set_default_icon_list (GList *list)
3204 if (list == default_icon_list)
3207 /* Update serial so we don't used cached pixmaps/masks
3209 default_icon_serial++;
3211 g_list_foreach (list,
3212 (GFunc) g_object_ref, NULL);
3214 g_list_foreach (default_icon_list,
3215 (GFunc) g_object_unref, NULL);
3217 g_list_free (default_icon_list);
3219 default_icon_list = g_list_copy (list);
3221 /* Update all toplevels */
3222 toplevels = gtk_window_list_toplevels ();
3223 tmp_list = toplevels;
3224 while (tmp_list != NULL)
3226 GtkWindowIconInfo *info;
3227 GtkWindow *w = tmp_list->data;
3229 info = get_icon_info (w);
3230 if (info && info->using_default_icon)
3232 gtk_window_unrealize_icon (w);
3233 if (GTK_WIDGET_REALIZED (w))
3234 gtk_window_realize_icon (w);
3237 tmp_list = tmp_list->next;
3239 g_list_free (toplevels);
3243 * gtk_window_set_default_icon:
3246 * Sets an icon to be used as fallback for windows that haven't
3247 * had gtk_window_set_icon() called on them from a pixbuf.
3252 gtk_window_set_default_icon (GdkPixbuf *icon)
3256 g_return_if_fail (GDK_IS_PIXBUF (icon));
3258 list = g_list_prepend (NULL, icon);
3259 gtk_window_set_default_icon_list (list);
3264 * gtk_window_set_default_icon_name:
3265 * @name: the name of the themed icon
3267 * Sets an icon to be used as fallback for windows that haven't
3268 * had gtk_window_set_icon_list() called on them from a named
3269 * themed icon, see gtk_window_set_icon_name().
3274 gtk_window_set_default_icon_name (const gchar *name)
3279 /* Update serial so we don't used cached pixmaps/masks
3281 default_icon_serial++;
3283 g_free (default_icon_name);
3284 default_icon_name = g_strdup (name);
3286 g_list_foreach (default_icon_list,
3287 (GFunc) g_object_unref, NULL);
3289 g_list_free (default_icon_list);
3290 default_icon_list = NULL;
3292 /* Update all toplevels */
3293 toplevels = gtk_window_list_toplevels ();
3294 tmp_list = toplevels;
3295 while (tmp_list != NULL)
3297 GtkWindowIconInfo *info;
3298 GtkWindow *w = tmp_list->data;
3300 info = get_icon_info (w);
3301 if (info && info->using_default_icon && info->using_themed_icon)
3303 gtk_window_unrealize_icon (w);
3304 if (GTK_WIDGET_REALIZED (w))
3305 gtk_window_realize_icon (w);
3308 tmp_list = tmp_list->next;
3310 g_list_free (toplevels);
3314 * gtk_window_set_default_icon_from_file:
3315 * @filename: location of icon file
3316 * @err: location to store error, or %NULL.
3318 * Sets an icon to be used as fallback for windows that haven't
3319 * had gtk_window_set_icon_list() called on them from a file
3320 * on disk. Warns on failure if @err is %NULL.
3322 * Returns: %TRUE if setting the icon succeeded.
3327 gtk_window_set_default_icon_from_file (const gchar *filename,
3330 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3334 gtk_window_set_default_icon (pixbuf);
3335 g_object_unref (pixbuf);
3344 * gtk_window_get_default_icon_list:
3346 * Gets the value set by gtk_window_set_default_icon_list().
3347 * The list is a copy and should be freed with g_list_free(),
3348 * but the pixbufs in the list have not had their reference count
3351 * Return value: copy of default icon list
3354 gtk_window_get_default_icon_list (void)
3356 return g_list_copy (default_icon_list);
3360 gtk_window_set_default_size_internal (GtkWindow *window,
3361 gboolean change_width,
3363 gboolean change_height,
3365 gboolean is_geometry)
3367 GtkWindowGeometryInfo *info;
3369 g_return_if_fail (change_width == FALSE || width >= -1);
3370 g_return_if_fail (change_height == FALSE || height >= -1);
3372 info = gtk_window_get_geometry_info (window, TRUE);
3374 g_object_freeze_notify (G_OBJECT (window));
3376 info->default_is_geometry = is_geometry != FALSE;
3386 info->default_width = width;
3388 g_object_notify (G_OBJECT (window), "default-width");
3399 info->default_height = height;
3401 g_object_notify (G_OBJECT (window), "default-height");
3404 g_object_thaw_notify (G_OBJECT (window));
3406 gtk_widget_queue_resize (GTK_WIDGET (window));
3410 * gtk_window_set_default_size:
3411 * @window: a #GtkWindow
3412 * @width: width in pixels, or -1 to unset the default width
3413 * @height: height in pixels, or -1 to unset the default height
3415 * Sets the default size of a window. If the window's "natural" size
3416 * (its size request) is larger than the default, the default will be
3417 * ignored. More generally, if the default size does not obey the
3418 * geometry hints for the window (gtk_window_set_geometry_hints() can
3419 * be used to set these explicitly), the default size will be clamped
3420 * to the nearest permitted size.
3422 * Unlike gtk_widget_set_size_request(), which sets a size request for
3423 * a widget and thus would keep users from shrinking the window, this
3424 * function only sets the initial size, just as if the user had
3425 * resized the window themselves. Users can still shrink the window
3426 * again as they normally would. Setting a default size of -1 means to
3427 * use the "natural" default size (the size request of the window).
3429 * For more control over a window's initial size and how resizing works,
3430 * investigate gtk_window_set_geometry_hints().
3432 * For some uses, gtk_window_resize() is a more appropriate function.
3433 * gtk_window_resize() changes the current size of the window, rather
3434 * than the size to be used on initial display. gtk_window_resize() always
3435 * affects the window itself, not the geometry widget.
3437 * The default size of a window only affects the first time a window is
3438 * shown; if a window is hidden and re-shown, it will remember the size
3439 * it had prior to hiding, rather than using the default size.
3441 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3442 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3445 gtk_window_set_default_size (GtkWindow *window,
3449 g_return_if_fail (GTK_IS_WINDOW (window));
3450 g_return_if_fail (width >= -1);
3451 g_return_if_fail (height >= -1);
3453 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3457 * gtk_window_get_default_size:
3458 * @window: a #GtkWindow
3459 * @width: location to store the default width, or %NULL
3460 * @height: location to store the default height, or %NULL
3462 * Gets the default size of the window. A value of -1 for the width or
3463 * height indicates that a default size has not been explicitly set
3464 * for that dimension, so the "natural" size of the window will be
3469 gtk_window_get_default_size (GtkWindow *window,
3473 GtkWindowGeometryInfo *info;
3475 g_return_if_fail (GTK_IS_WINDOW (window));
3477 info = gtk_window_get_geometry_info (window, FALSE);
3480 *width = info ? info->default_width : -1;
3483 *height = info ? info->default_height : -1;
3487 * gtk_window_resize:
3488 * @window: a #GtkWindow
3489 * @width: width in pixels to resize the window to
3490 * @height: height in pixels to resize the window to
3492 * Resizes the window as if the user had done so, obeying geometry
3493 * constraints. The default geometry constraint is that windows may
3494 * not be smaller than their size request; to override this
3495 * constraint, call gtk_widget_set_size_request() to set the window's
3496 * request to a smaller value.
3498 * If gtk_window_resize() is called before showing a window for the
3499 * first time, it overrides any default size set with
3500 * gtk_window_set_default_size().
3502 * Windows may not be resized smaller than 1 by 1 pixels.
3506 gtk_window_resize (GtkWindow *window,
3510 GtkWindowGeometryInfo *info;
3512 g_return_if_fail (GTK_IS_WINDOW (window));
3513 g_return_if_fail (width > 0);
3514 g_return_if_fail (height > 0);
3516 info = gtk_window_get_geometry_info (window, TRUE);
3518 info->resize_width = width;
3519 info->resize_height = height;
3521 gtk_widget_queue_resize (GTK_WIDGET (window));
3525 * gtk_window_get_size:
3526 * @window: a #GtkWindow
3527 * @width: return location for width, or %NULL
3528 * @height: return location for height, or %NULL
3530 * Obtains the current size of @window. If @window is not onscreen,
3531 * it returns the size GTK+ will suggest to the <link
3532 * linkend="gtk-X11-arch">window manager</link> for the initial window
3533 * size (but this is not reliably the same as the size the window
3534 * manager will actually select). The size obtained by
3535 * gtk_window_get_size() is the last size received in a
3536 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
3537 * rather than querying the X server for the size. As a result, if you
3538 * call gtk_window_resize() then immediately call
3539 * gtk_window_get_size(), the size won't have taken effect yet. After
3540 * the window manager processes the resize request, GTK+ receives
3541 * notification that the size has changed via a configure event, and
3542 * the size of the window gets updated.
3544 * Note 1: Nearly any use of this function creates a race condition,
3545 * because the size of the window may change between the time that you
3546 * get the size and the time that you perform some action assuming
3547 * that size is the current size. To avoid race conditions, connect to
3548 * "configure_event" on the window and adjust your size-dependent
3549 * state to match the size delivered in the #GdkEventConfigure.
3551 * Note 2: The returned size does <emphasis>not</emphasis> include the
3552 * size of the window manager decorations (aka the window frame or
3553 * border). Those are not drawn by GTK+ and GTK+ has no reliable
3554 * method of determining their size.
3556 * Note 3: If you are getting a window size in order to position
3557 * the window onscreen, there may be a better way. The preferred
3558 * way is to simply set the window's semantic type with
3559 * gtk_window_set_type_hint(), which allows the window manager to
3560 * e.g. center dialogs. Also, if you set the transient parent of
3561 * dialogs with gtk_window_set_transient_for() window managers
3562 * will often center the dialog over its parent window. It's
3563 * much preferred to let the window manager handle these
3564 * things rather than doing it yourself, because all apps will
3565 * behave consistently and according to user prefs if the window
3566 * manager handles it. Also, the window manager can take the size
3567 * of the window decorations/border into account, while your
3568 * application cannot.
3570 * In any case, if you insist on application-specified window
3571 * positioning, there's <emphasis>still</emphasis> a better way than
3572 * doing it yourself - gtk_window_set_position() will frequently
3573 * handle the details for you.
3577 gtk_window_get_size (GtkWindow *window,
3583 g_return_if_fail (GTK_IS_WINDOW (window));
3585 if (width == NULL && height == NULL)
3588 if (GTK_WIDGET_MAPPED (window))
3590 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3595 GdkRectangle configure_request;
3597 gtk_window_compute_configure_request (window,
3601 w = configure_request.width;
3602 h = configure_request.height;
3613 * @window: a #GtkWindow
3614 * @x: X coordinate to move window to
3615 * @y: Y coordinate to move window to
3617 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3618 * @window to the given position. Window managers are free to ignore
3619 * this; most window managers ignore requests for initial window
3620 * positions (instead using a user-defined placement algorithm) and
3621 * honor requests after the window has already been shown.
3623 * Note: the position is the position of the gravity-determined
3624 * reference point for the window. The gravity determines two things:
3625 * first, the location of the reference point in root window
3626 * coordinates; and second, which point on the window is positioned at
3627 * the reference point.
3629 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3630 * point is simply the @x, @y supplied to gtk_window_move(). The
3631 * top-left corner of the window decorations (aka window frame or
3632 * border) will be placed at @x, @y. Therefore, to position a window
3633 * at the top left of the screen, you want to use the default gravity
3634 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3636 * To position a window at the bottom right corner of the screen, you
3637 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3638 * point is at @x + the window width and @y + the window height, and
3639 * the bottom-right corner of the window border will be placed at that
3640 * reference point. So, to place a window in the bottom right corner
3641 * you would first set gravity to south east, then write:
3642 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3643 * gdk_screen_height () - window_height)</literal>.
3645 * The Extended Window Manager Hints specification at <ulink
3646 * url="http://www.freedesktop.org/Standards/wm-spec">
3647 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
3648 * nice table of gravities in the "implementation notes" section.
3650 * The gtk_window_get_position() documentation may also be relevant.
3654 gtk_window_move (GtkWindow *window,
3658 GtkWindowGeometryInfo *info;
3661 g_return_if_fail (GTK_IS_WINDOW (window));
3663 widget = GTK_WIDGET (window);
3665 info = gtk_window_get_geometry_info (window, TRUE);
3667 if (GTK_WIDGET_MAPPED (window))
3669 /* we have now sent a request with this position
3670 * with currently-active constraints, so toggle flag.
3672 info->position_constraints_changed = FALSE;
3674 /* we only constrain if mapped - if not mapped,
3675 * then gtk_window_compute_configure_request()
3676 * will apply the constraints later, and we
3677 * don't want to lose information about
3678 * what position the user set before then.
3679 * i.e. if you do a move() then turn off POS_CENTER
3680 * then show the window, your move() will work.
3682 gtk_window_constrain_position (window,
3683 widget->allocation.width,
3684 widget->allocation.height,
3687 /* Note that this request doesn't go through our standard request
3688 * framework, e.g. doesn't increment configure_request_count,
3689 * doesn't set info->last, etc.; that's because
3690 * we don't save the info needed to arrive at this same request
3693 * To gtk_window_move_resize(), this will end up looking exactly
3694 * the same as the position being changed by the window
3698 /* FIXME are we handling gravity properly for framed windows? */
3700 gdk_window_move (window->frame,
3701 x - window->frame_left,
3702 y - window->frame_top);
3704 gdk_window_move (GTK_WIDGET (window)->window,
3709 /* Save this position to apply on mapping */
3710 info->initial_x = x;
3711 info->initial_y = y;
3712 info->initial_pos_set = TRUE;
3717 * gtk_window_get_position:
3718 * @window: a #GtkWindow
3719 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3720 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3722 * This function returns the position you need to pass to
3723 * gtk_window_move() to keep @window in its current position. This
3724 * means that the meaning of the returned value varies with window
3725 * gravity. See gtk_window_move() for more details.
3727 * If you haven't changed the window gravity, its gravity will be
3728 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3729 * gets the position of the top-left corner of the window manager
3730 * frame for the window. gtk_window_move() sets the position of this
3731 * same top-left corner.
3733 * gtk_window_get_position() is not 100% reliable because the X Window System
3734 * does not specify a way to obtain the geometry of the
3735 * decorations placed on a window by the window manager.
3736 * Thus GTK+ is using a "best guess" that works with most
3739 * Moreover, nearly all window managers are historically broken with
3740 * respect to their handling of window gravity. So moving a window to
3741 * its current position as returned by gtk_window_get_position() tends
3742 * to result in moving the window slightly. Window managers are
3743 * slowly getting better over time.
3745 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3746 * frame is not relevant, and thus gtk_window_get_position() will
3747 * always produce accurate results. However you can't use static
3748 * gravity to do things like place a window in a corner of the screen,
3749 * because static gravity ignores the window manager decorations.
3751 * If you are saving and restoring your application's window
3752 * positions, you should know that it's impossible for applications to
3753 * do this without getting it somewhat wrong because applications do
3754 * not have sufficient knowledge of window manager state. The Correct
3755 * Mechanism is to support the session management protocol (see the
3756 * "GnomeClient" object in the GNOME libraries for example) and allow
3757 * the window manager to save your window sizes and positions.
3762 gtk_window_get_position (GtkWindow *window,
3768 g_return_if_fail (GTK_IS_WINDOW (window));
3770 widget = GTK_WIDGET (window);
3772 if (window->gravity == GDK_GRAVITY_STATIC)
3774 if (GTK_WIDGET_MAPPED (widget))
3776 /* This does a server round-trip, which is sort of wrong;
3777 * but a server round-trip is inevitable for
3778 * gdk_window_get_frame_extents() in the usual
3779 * NorthWestGravity case below, so not sure what else to
3780 * do. We should likely be consistent about whether we get
3781 * the client-side info or the server-side info.
3783 gdk_window_get_origin (widget->window, root_x, root_y);
3787 GdkRectangle configure_request;
3789 gtk_window_compute_configure_request (window,
3793 *root_x = configure_request.x;
3794 *root_y = configure_request.y;
3799 GdkRectangle frame_extents;
3804 if (GTK_WIDGET_MAPPED (widget))
3807 gdk_window_get_frame_extents (window->frame, &frame_extents);
3809 gdk_window_get_frame_extents (widget->window, &frame_extents);
3810 x = frame_extents.x;
3811 y = frame_extents.y;
3812 gtk_window_get_size (window, &w, &h);
3816 /* We just say the frame has 0 size on all sides.
3817 * Not sure what else to do.
3819 gtk_window_compute_configure_request (window,
3822 x = frame_extents.x;
3823 y = frame_extents.y;
3824 w = frame_extents.width;
3825 h = frame_extents.height;
3828 switch (window->gravity)
3830 case GDK_GRAVITY_NORTH:
3831 case GDK_GRAVITY_CENTER:
3832 case GDK_GRAVITY_SOUTH:
3833 /* Find center of frame. */
3834 x += frame_extents.width / 2;
3835 /* Center client window on that point. */
3839 case GDK_GRAVITY_SOUTH_EAST:
3840 case GDK_GRAVITY_EAST:
3841 case GDK_GRAVITY_NORTH_EAST:
3842 /* Find right edge of frame */
3843 x += frame_extents.width;
3844 /* Align left edge of client at that point. */
3851 switch (window->gravity)
3853 case GDK_GRAVITY_WEST:
3854 case GDK_GRAVITY_CENTER:
3855 case GDK_GRAVITY_EAST:
3856 /* Find center of frame. */
3857 y += frame_extents.height / 2;
3858 /* Center client window there. */
3861 case GDK_GRAVITY_SOUTH_WEST:
3862 case GDK_GRAVITY_SOUTH:
3863 case GDK_GRAVITY_SOUTH_EAST:
3864 /* Find south edge of frame */
3865 y += frame_extents.height;
3866 /* Place bottom edge of client there */
3881 * gtk_window_reshow_with_initial_size:
3882 * @window: a #GtkWindow
3884 * Hides @window, then reshows it, resetting the
3885 * default size and position of the window. Used
3886 * by GUI builders only.
3889 gtk_window_reshow_with_initial_size (GtkWindow *window)
3893 g_return_if_fail (GTK_IS_WINDOW (window));
3895 widget = GTK_WIDGET (window);
3897 gtk_widget_hide (widget);
3898 gtk_widget_unrealize (widget);
3899 gtk_widget_show (widget);
3903 gtk_window_destroy (GtkObject *object)
3905 GtkWindow *window = GTK_WINDOW (object);
3907 toplevel_list = g_slist_remove (toplevel_list, window);
3909 if (window->transient_parent)
3910 gtk_window_set_transient_for (window, NULL);
3912 /* frees the icons */
3913 gtk_window_set_icon_list (window, NULL);
3915 if (window->has_user_ref_count)
3917 window->has_user_ref_count = FALSE;
3918 g_object_unref (window);
3922 gtk_window_group_remove_window (window->group, window);
3924 gtk_window_free_key_hash (window);
3926 GTK_OBJECT_CLASS (parent_class)->destroy (object);
3930 gtk_window_finalize (GObject *object)
3932 GtkWindow *window = GTK_WINDOW (object);
3933 GtkMnemonicHash *mnemonic_hash;
3935 g_free (window->title);
3936 g_free (window->wmclass_name);
3937 g_free (window->wmclass_class);
3938 g_free (window->wm_role);
3940 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
3942 _gtk_mnemonic_hash_free (mnemonic_hash);
3944 if (window->geometry_info)
3946 if (window->geometry_info->widget)
3947 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3948 gtk_widget_destroyed,
3949 &window->geometry_info->widget);
3950 g_free (window->geometry_info);
3953 if (window->keys_changed_handler)
3955 g_source_remove (window->keys_changed_handler);
3956 window->keys_changed_handler = 0;
3959 G_OBJECT_CLASS (parent_class)->finalize (object);
3963 gtk_window_show (GtkWidget *widget)
3965 GtkWindow *window = GTK_WINDOW (widget);
3966 GtkContainer *container = GTK_CONTAINER (window);
3967 gboolean need_resize;
3969 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3971 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3972 container->need_resize = FALSE;
3976 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3977 GtkAllocation allocation = { 0, 0 };
3978 GdkRectangle configure_request;
3979 GdkGeometry new_geometry;
3981 gboolean was_realized;
3983 /* We are going to go ahead and perform this configure request
3984 * and then emulate a configure notify by going ahead and
3985 * doing a size allocate. Sort of a synchronous
3986 * mini-copy of gtk_window_move_resize() here.
3988 gtk_window_compute_configure_request (window,
3993 /* We update this because we are going to go ahead
3994 * and gdk_window_resize() below, rather than
3997 info->last.configure_request.width = configure_request.width;
3998 info->last.configure_request.height = configure_request.height;
4000 /* and allocate the window - this is normally done
4001 * in move_resize in response to configure notify
4003 allocation.width = configure_request.width;
4004 allocation.height = configure_request.height;
4005 gtk_widget_size_allocate (widget, &allocation);
4007 /* Then we guarantee we have a realize */
4008 was_realized = FALSE;
4009 if (!GTK_WIDGET_REALIZED (widget))
4011 gtk_widget_realize (widget);
4012 was_realized = TRUE;
4015 /* Must be done after the windows are realized,
4016 * so that the decorations can be read
4018 gtk_decorated_window_calculate_frame_size (window);
4020 /* We only send configure request if we didn't just finish
4021 * creating the window; if we just created the window
4022 * then we created it with widget->allocation anyhow.
4025 gdk_window_move_resize (widget->window,
4026 configure_request.x,
4027 configure_request.y,
4028 configure_request.width,
4029 configure_request.height);
4032 gtk_container_check_resize (container);
4034 gtk_widget_map (widget);
4036 /* Try to make sure that we have some focused widget
4038 if (!window->focus_widget && !GTK_IS_PLUG (window))
4039 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4042 gtk_grab_add (widget);
4046 gtk_window_hide (GtkWidget *widget)
4048 GtkWindow *window = GTK_WINDOW (widget);
4050 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4051 gtk_widget_unmap (widget);
4054 gtk_grab_remove (widget);
4058 gtk_window_map (GtkWidget *widget)
4060 GtkWindow *window = GTK_WINDOW (widget);
4061 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4062 GdkWindow *toplevel;
4064 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4066 if (window->bin.child &&
4067 GTK_WIDGET_VISIBLE (window->bin.child) &&
4068 !GTK_WIDGET_MAPPED (window->bin.child))
4069 gtk_widget_map (window->bin.child);
4072 toplevel = window->frame;
4074 toplevel = widget->window;
4076 if (window->maximize_initially)
4077 gdk_window_maximize (toplevel);
4079 gdk_window_unmaximize (toplevel);
4081 if (window->stick_initially)
4082 gdk_window_stick (toplevel);
4084 gdk_window_unstick (toplevel);
4086 if (window->iconify_initially)
4087 gdk_window_iconify (toplevel);
4089 gdk_window_deiconify (toplevel);
4091 if (priv->fullscreen_initially)
4092 gdk_window_fullscreen (toplevel);
4094 gdk_window_unfullscreen (toplevel);
4096 gdk_window_set_keep_above (toplevel, priv->above_initially);
4098 gdk_window_set_keep_below (toplevel, priv->below_initially);
4100 /* No longer use the default settings */
4101 window->need_default_size = FALSE;
4102 window->need_default_position = FALSE;
4104 gdk_window_show (widget->window);
4107 gdk_window_show (window->frame);
4109 if (!disable_startup_notification &&
4110 !sent_startup_notification)
4112 sent_startup_notification = TRUE;
4113 gdk_notify_startup_complete ();
4118 gtk_window_map_event (GtkWidget *widget,
4121 if (!GTK_WIDGET_MAPPED (widget))
4123 /* we should be be unmapped, but are getting a MapEvent, this may happen
4124 * to toplevel XWindows if mapping was intercepted by a window manager
4125 * and an unmap request occoured while the MapRequestEvent was still
4126 * being handled. we work around this situaiton here by re-requesting
4127 * the window being unmapped. more details can be found in:
4128 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4130 gdk_window_hide (widget->window);
4136 gtk_window_unmap (GtkWidget *widget)
4138 GtkWindow *window = GTK_WINDOW (widget);
4139 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
4140 GtkWindowGeometryInfo *info;
4141 GdkWindowState state;
4143 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4145 gdk_window_withdraw (window->frame);
4147 gdk_window_withdraw (widget->window);
4149 window->configure_request_count = 0;
4150 window->configure_notify_received = FALSE;
4152 /* on unmap, we reset the default positioning of the window,
4153 * so it's placed again, but we don't reset the default
4154 * size of the window, so it's remembered.
4156 window->need_default_position = TRUE;
4158 info = gtk_window_get_geometry_info (window, FALSE);
4161 info->initial_pos_set = FALSE;
4162 info->position_constraints_changed = FALSE;
4165 state = gdk_window_get_state (widget->window);
4166 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
4167 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
4168 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
4169 priv->above_initially = state & GDK_WINDOW_STATE_ABOVE;
4170 priv->below_initially = state & GDK_WINDOW_STATE_BELOW;
4174 gtk_window_realize (GtkWidget *widget)
4177 GdkWindow *parent_window;
4178 GdkWindowAttr attributes;
4179 gint attributes_mask;
4180 GtkWindowPrivate *priv;
4182 window = GTK_WINDOW (widget);
4184 priv = GTK_WINDOW_GET_PRIVATE (window);
4186 /* ensure widget tree is properly size allocated */
4187 if (widget->allocation.x == -1 &&
4188 widget->allocation.y == -1 &&
4189 widget->allocation.width == 1 &&
4190 widget->allocation.height == 1)
4192 GtkRequisition requisition;
4193 GtkAllocation allocation = { 0, 0, 200, 200 };
4195 gtk_widget_size_request (widget, &requisition);
4196 if (requisition.width || requisition.height)
4198 /* non-empty window */
4199 allocation.width = requisition.width;
4200 allocation.height = requisition.height;
4202 gtk_widget_size_allocate (widget, &allocation);
4204 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4206 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
4209 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4211 switch (window->type)
4213 case GTK_WINDOW_TOPLEVEL:
4214 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4216 case GTK_WINDOW_POPUP:
4217 attributes.window_type = GDK_WINDOW_TEMP;
4220 g_warning (G_STRLOC": Unknown window type %d!", window->type);
4224 attributes.title = window->title;
4225 attributes.wmclass_name = window->wmclass_name;
4226 attributes.wmclass_class = window->wmclass_class;
4227 attributes.wclass = GDK_INPUT_OUTPUT;
4228 attributes.visual = gtk_widget_get_visual (widget);
4229 attributes.colormap = gtk_widget_get_colormap (widget);
4231 if (window->has_frame)
4233 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
4234 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
4235 attributes.event_mask = (GDK_EXPOSURE_MASK |
4236 GDK_KEY_PRESS_MASK |
4237 GDK_ENTER_NOTIFY_MASK |
4238 GDK_LEAVE_NOTIFY_MASK |
4239 GDK_FOCUS_CHANGE_MASK |
4240 GDK_STRUCTURE_MASK |
4241 GDK_BUTTON_MOTION_MASK |
4242 GDK_POINTER_MOTION_HINT_MASK |
4243 GDK_BUTTON_PRESS_MASK |
4244 GDK_BUTTON_RELEASE_MASK);
4246 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4248 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4249 &attributes, attributes_mask);
4251 gdk_window_set_user_data (window->frame, widget);
4253 attributes.window_type = GDK_WINDOW_CHILD;
4254 attributes.x = window->frame_left;
4255 attributes.y = window->frame_top;
4257 attributes_mask = GDK_WA_X | GDK_WA_Y;
4259 parent_window = window->frame;
4261 g_signal_connect (window,
4263 G_CALLBACK (gtk_window_event),
4268 attributes_mask = 0;
4269 parent_window = gtk_widget_get_root_window (widget);
4272 attributes.width = widget->allocation.width;
4273 attributes.height = widget->allocation.height;
4274 attributes.event_mask = gtk_widget_get_events (widget);
4275 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4276 GDK_KEY_PRESS_MASK |
4277 GDK_KEY_RELEASE_MASK |
4278 GDK_ENTER_NOTIFY_MASK |
4279 GDK_LEAVE_NOTIFY_MASK |
4280 GDK_FOCUS_CHANGE_MASK |
4281 GDK_STRUCTURE_MASK);
4283 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
4284 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
4285 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
4287 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
4289 gdk_window_enable_synchronized_configure (widget->window);
4291 gdk_window_set_user_data (widget->window, window);
4293 widget->style = gtk_style_attach (widget->style, widget->window);
4294 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4296 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
4298 /* This is a bad hack to set the window background. */
4299 gtk_window_paint (widget, NULL);
4301 if (window->transient_parent &&
4302 GTK_WIDGET_REALIZED (window->transient_parent))
4303 gdk_window_set_transient_for (widget->window,
4304 GTK_WIDGET (window->transient_parent)->window);
4306 if (window->wm_role)
4307 gdk_window_set_role (widget->window, window->wm_role);
4309 if (!window->decorated)
4310 gdk_window_set_decorations (widget->window, 0);
4312 if (!priv->deletable)
4313 gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4315 gdk_window_set_type_hint (widget->window, window->type_hint);
4317 if (gtk_window_get_skip_pager_hint (window))
4318 gdk_window_set_skip_pager_hint (widget->window, TRUE);
4320 if (gtk_window_get_skip_taskbar_hint (window))
4321 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
4323 if (gtk_window_get_accept_focus (window))
4324 gdk_window_set_accept_focus (widget->window, TRUE);
4326 gdk_window_set_accept_focus (widget->window, FALSE);
4328 if (gtk_window_get_focus_on_map (window))
4329 gdk_window_set_focus_on_map (widget->window, TRUE);
4331 gdk_window_set_focus_on_map (widget->window, FALSE);
4334 gdk_window_set_modal_hint (widget->window, TRUE);
4336 gdk_window_set_modal_hint (widget->window, FALSE);
4339 gtk_window_realize_icon (window);
4343 gtk_window_unrealize (GtkWidget *widget)
4346 GtkWindowGeometryInfo *info;
4348 window = GTK_WINDOW (widget);
4350 /* On unrealize, we reset the size of the window such
4351 * that we will re-apply the default sizing stuff
4352 * next time we show the window.
4354 * Default positioning is reset on unmap, instead of unrealize.
4356 window->need_default_size = TRUE;
4357 info = gtk_window_get_geometry_info (window, FALSE);
4360 info->resize_width = -1;
4361 info->resize_height = -1;
4362 info->last.configure_request.x = 0;
4363 info->last.configure_request.y = 0;
4364 info->last.configure_request.width = -1;
4365 info->last.configure_request.height = -1;
4366 /* be sure we reset geom hints on re-realize */
4367 info->last.flags = 0;
4372 gdk_window_set_user_data (window->frame, NULL);
4373 gdk_window_destroy (window->frame);
4374 window->frame = NULL;
4378 gtk_window_unrealize_icon (window);
4380 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
4384 gtk_window_size_request (GtkWidget *widget,
4385 GtkRequisition *requisition)
4390 window = GTK_WINDOW (widget);
4391 bin = GTK_BIN (window);
4393 requisition->width = GTK_CONTAINER (window)->border_width * 2;
4394 requisition->height = GTK_CONTAINER (window)->border_width * 2;
4396 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
4398 GtkRequisition child_requisition;
4400 gtk_widget_size_request (bin->child, &child_requisition);
4402 requisition->width += child_requisition.width;
4403 requisition->height += child_requisition.height;
4408 gtk_window_size_allocate (GtkWidget *widget,
4409 GtkAllocation *allocation)
4412 GtkAllocation child_allocation;
4414 window = GTK_WINDOW (widget);
4415 widget->allocation = *allocation;
4417 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
4419 child_allocation.x = GTK_CONTAINER (window)->border_width;
4420 child_allocation.y = GTK_CONTAINER (window)->border_width;
4421 child_allocation.width =
4422 MAX (1, (gint)allocation->width - child_allocation.x * 2);
4423 child_allocation.height =
4424 MAX (1, (gint)allocation->height - child_allocation.y * 2);
4426 gtk_widget_size_allocate (window->bin.child, &child_allocation);
4429 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4431 gdk_window_resize (window->frame,
4432 allocation->width + window->frame_left + window->frame_right,
4433 allocation->height + window->frame_top + window->frame_bottom);
4438 gtk_window_event (GtkWidget *widget, GdkEvent *event)
4441 gboolean return_val;
4443 window = GTK_WINDOW (widget);
4445 if (window->frame && (event->any.window == window->frame))
4447 if ((event->type != GDK_KEY_PRESS) &&
4448 (event->type != GDK_KEY_RELEASE) &&
4449 (event->type != GDK_FOCUS_CHANGE))
4451 g_signal_stop_emission_by_name (widget, "event");
4453 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
4458 g_object_unref (event->any.window);
4459 event->any.window = g_object_ref (widget->window);
4467 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
4469 GdkEventConfigure *configure_event;
4472 switch (event->type)
4475 configure_event = (GdkEventConfigure *)event;
4477 /* Invalidate the decorations */
4480 rect.width = configure_event->width;
4481 rect.height = configure_event->height;
4483 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
4485 /* Pass on the (modified) configure event */
4486 configure_event->width -= window->frame_left + window->frame_right;
4487 configure_event->height -= window->frame_top + window->frame_bottom;
4488 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
4497 gtk_window_configure_event (GtkWidget *widget,
4498 GdkEventConfigure *event)
4500 GtkWindow *window = GTK_WINDOW (widget);
4501 gboolean expected_reply = window->configure_request_count > 0;
4503 /* window->configure_request_count incremented for each
4504 * configure request, and decremented to a min of 0 for
4505 * each configure notify.
4507 * All it means is that we know we will get at least
4508 * window->configure_request_count more configure notifies.
4509 * We could get more configure notifies than that; some
4510 * of the configure notifies we get may be unrelated to
4511 * the configure requests. But we will get at least
4512 * window->configure_request_count notifies.
4515 if (window->configure_request_count > 0)
4516 window->configure_request_count -= 1;
4518 /* As an optimization, we avoid a resize when possible.
4520 * The only times we can avoid a resize are:
4521 * - we know only the position changed, not the size
4522 * - we know we have made more requests and so will get more
4523 * notifies and can wait to resize when we get them
4526 if (!expected_reply &&
4527 (widget->allocation.width == event->width &&
4528 widget->allocation.height == event->height))
4530 gdk_window_configure_finished (widget->window);
4535 * If we do need to resize, we do that by:
4536 * - filling in widget->allocation with the new size
4537 * - setting configure_notify_received to TRUE
4538 * for use in gtk_window_move_resize()
4539 * - queueing a resize, leading to invocation of
4540 * gtk_window_move_resize() in an idle handler
4544 window->configure_notify_received = TRUE;
4546 widget->allocation.width = event->width;
4547 widget->allocation.height = event->height;
4549 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4554 /* the accel_key and accel_mods fields of the key have to be setup
4555 * upon calling this function. it'll then return whether that key
4556 * is at all used as accelerator, and if so will OR in the
4557 * accel_flags member of the key.
4560 _gtk_window_query_nonaccels (GtkWindow *window,
4562 GdkModifierType accel_mods)
4564 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4566 /* movement keys are considered locked accels */
4569 static const guint bindings[] = {
4570 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
4571 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
4575 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
4576 if (bindings[i] == accel_key)
4580 /* mnemonics are considered locked accels */
4581 if (accel_mods == window->mnemonic_modifier)
4583 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4584 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
4592 * gtk_window_propagate_key_event:
4593 * @window: a #GtkWindow
4594 * @event: a #GdkEventKey
4596 * Propagate a key press or release event to the focus widget and
4597 * up the focus container chain until a widget handles @event.
4598 * This is normally called by the default ::key_press_event and
4599 * ::key_release_event handlers for toplevel windows,
4600 * however in some cases it may be useful to call this directly when
4601 * overriding the standard key handling for a toplevel window.
4603 * Return value: %TRUE if a widget in the focus chain handled the event.
4606 gtk_window_propagate_key_event (GtkWindow *window,
4609 gboolean handled = FALSE;
4610 GtkWidget *widget, *focus;
4612 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4614 widget = GTK_WIDGET (window);
4615 focus = window->focus_widget;
4617 g_object_ref (focus);
4620 focus && focus != widget &&
4621 gtk_widget_get_toplevel (focus) == widget)
4625 if (GTK_WIDGET_IS_SENSITIVE (focus))
4626 handled = gtk_widget_event (focus, (GdkEvent*) event);
4628 parent = focus->parent;
4630 g_object_ref (parent);
4632 g_object_unref (focus);
4638 g_object_unref (focus);
4644 gtk_window_key_press_event (GtkWidget *widget,
4647 GtkWindow *window = GTK_WINDOW (widget);
4648 gboolean handled = FALSE;
4650 /* handle mnemonics and accelerators */
4652 handled = gtk_window_activate_key (window, event);
4654 /* handle focus widget key events */
4656 handled = gtk_window_propagate_key_event (window, event);
4658 /* Chain up, invokes binding set */
4660 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4666 gtk_window_key_release_event (GtkWidget *widget,
4669 GtkWindow *window = GTK_WINDOW (widget);
4670 gboolean handled = FALSE;
4672 /* handle focus widget key events */
4674 handled = gtk_window_propagate_key_event (window, event);
4676 /* Chain up, invokes binding set */
4678 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4684 gtk_window_real_activate_default (GtkWindow *window)
4686 gtk_window_activate_default (window);
4690 gtk_window_real_activate_focus (GtkWindow *window)
4692 gtk_window_activate_focus (window);
4696 gtk_window_move_focus (GtkWindow *window,
4697 GtkDirectionType dir)
4699 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4701 if (!GTK_CONTAINER (window)->focus_child)
4702 gtk_window_set_focus (window, NULL);
4706 gtk_window_enter_notify_event (GtkWidget *widget,
4707 GdkEventCrossing *event)
4713 gtk_window_leave_notify_event (GtkWidget *widget,
4714 GdkEventCrossing *event)
4720 do_focus_change (GtkWidget *widget,
4723 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4725 g_object_ref (widget);
4728 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4730 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4732 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4733 fevent->focus_change.window = widget->window;
4735 g_object_ref (widget->window);
4736 fevent->focus_change.in = in;
4738 gtk_widget_event (widget, fevent);
4740 g_object_notify (G_OBJECT (widget), "has-focus");
4742 g_object_unref (widget);
4743 gdk_event_free (fevent);
4747 gtk_window_focus_in_event (GtkWidget *widget,
4748 GdkEventFocus *event)
4750 GtkWindow *window = GTK_WINDOW (widget);
4752 /* It appears spurious focus in events can occur when
4753 * the window is hidden. So we'll just check to see if
4754 * the window is visible before actually handling the
4757 if (GTK_WIDGET_VISIBLE (widget))
4759 _gtk_window_set_has_toplevel_focus (window, TRUE);
4760 _gtk_window_set_is_active (window, TRUE);
4767 gtk_window_focus_out_event (GtkWidget *widget,
4768 GdkEventFocus *event)
4770 GtkWindow *window = GTK_WINDOW (widget);
4772 _gtk_window_set_has_toplevel_focus (window, FALSE);
4773 _gtk_window_set_is_active (window, FALSE);
4778 static GdkAtom atom_rcfiles = GDK_NONE;
4779 static GdkAtom atom_iconthemes = GDK_NONE;
4782 send_client_message_to_embedded_windows (GtkWidget *widget,
4783 GdkAtom message_type)
4785 GList *embedded_windows;
4787 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
4788 if (embedded_windows)
4790 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4793 for (i = 0; i < 5; i++)
4794 send_event->client.data.l[i] = 0;
4795 send_event->client.data_format = 32;
4796 send_event->client.message_type = message_type;
4798 while (embedded_windows)
4800 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4801 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4802 embedded_windows = embedded_windows->next;
4805 gdk_event_free (send_event);
4810 gtk_window_client_event (GtkWidget *widget,
4811 GdkEventClient *event)
4815 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
4816 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
4819 if (event->message_type == atom_rcfiles)
4821 send_client_message_to_embedded_windows (widget, atom_rcfiles);
4822 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4825 if (event->message_type == atom_iconthemes)
4827 send_client_message_to_embedded_windows (widget, atom_iconthemes);
4828 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
4835 gtk_window_check_resize (GtkContainer *container)
4837 GtkWindow *window = GTK_WINDOW (container);
4839 if (GTK_WIDGET_VISIBLE (container))
4840 gtk_window_move_resize (window);
4844 gtk_window_focus (GtkWidget *widget,
4845 GtkDirectionType direction)
4849 GtkContainer *container;
4850 GtkWidget *old_focus_child;
4853 container = GTK_CONTAINER (widget);
4854 window = GTK_WINDOW (widget);
4855 bin = GTK_BIN (widget);
4857 old_focus_child = container->focus_child;
4859 /* We need a special implementation here to deal properly with wrapping
4860 * around in the tab chain without the danger of going into an
4863 if (old_focus_child)
4865 if (gtk_widget_child_focus (old_focus_child, direction))
4869 if (window->focus_widget)
4871 if (direction == GTK_DIR_LEFT ||
4872 direction == GTK_DIR_RIGHT ||
4873 direction == GTK_DIR_UP ||
4874 direction == GTK_DIR_DOWN)
4879 /* Wrapped off the end, clear the focus setting for the toplpevel */
4880 parent = window->focus_widget->parent;
4883 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4884 parent = GTK_WIDGET (parent)->parent;
4887 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4890 /* Now try to focus the first widget in the window */
4893 if (gtk_widget_child_focus (bin->child, direction))
4901 gtk_window_real_set_focus (GtkWindow *window,
4904 GtkWidget *old_focus = window->focus_widget;
4905 gboolean had_default = FALSE;
4906 gboolean focus_had_default = FALSE;
4907 gboolean old_focus_had_default = FALSE;
4911 g_object_ref (old_focus);
4912 g_object_freeze_notify (G_OBJECT (old_focus));
4913 old_focus_had_default = GTK_WIDGET_HAS_DEFAULT (old_focus);
4917 g_object_ref (focus);
4918 g_object_freeze_notify (G_OBJECT (focus));
4919 focus_had_default = GTK_WIDGET_HAS_DEFAULT (focus);
4922 if (window->default_widget)
4923 had_default = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4925 if (window->focus_widget)
4927 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4928 (window->focus_widget != window->default_widget))
4930 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4931 gtk_widget_queue_draw (window->focus_widget);
4933 if (window->default_widget)
4934 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4937 window->focus_widget = NULL;
4939 if (window->has_focus)
4940 do_focus_change (old_focus, FALSE);
4942 g_object_notify (G_OBJECT (old_focus), "is-focus");
4945 /* The above notifications may have set a new focus widget,
4946 * if so, we don't want to override it.
4948 if (focus && !window->focus_widget)
4950 window->focus_widget = focus;
4952 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4953 (window->focus_widget != window->default_widget))
4955 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4956 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4958 if (window->default_widget)
4959 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4962 if (window->has_focus)
4963 do_focus_change (window->focus_widget, TRUE);
4965 g_object_notify (G_OBJECT (window->focus_widget), "is-focus");
4968 /* If the default widget changed, a redraw will have been queued
4969 * on the old and new default widgets by gtk_window_set_default(), so
4970 * we only have to worry about the case where it didn't change.
4971 * We'll sometimes queue a draw twice on the new widget but that
4974 if (window->default_widget &&
4975 (had_default != GTK_WIDGET_HAS_DEFAULT (window->default_widget)))
4976 gtk_widget_queue_draw (window->default_widget);
4980 if (old_focus_had_default != GTK_WIDGET_HAS_DEFAULT (old_focus))
4981 gtk_widget_queue_draw (old_focus);
4983 g_object_thaw_notify (G_OBJECT (old_focus));
4984 g_object_unref (old_focus);
4988 if (focus_had_default != GTK_WIDGET_HAS_DEFAULT (focus))
4989 gtk_widget_queue_draw (focus);
4991 g_object_thaw_notify (G_OBJECT (focus));
4992 g_object_unref (focus);
4997 * _gtk_window_unset_focus_and_default:
4998 * @window: a #GtkWindow
4999 * @widget: a widget inside of @window
5001 * Checks whether the focus and default widgets of @window are
5002 * @widget or a descendent of @widget, and if so, unset them.
5005 _gtk_window_unset_focus_and_default (GtkWindow *window,
5011 g_object_ref (window);
5012 g_object_ref (widget);
5014 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
5016 child = window->focus_widget;
5018 while (child && child != widget)
5019 child = child->parent;
5021 if (child == widget)
5022 gtk_window_set_focus (GTK_WINDOW (window), NULL);
5025 child = window->default_widget;
5027 while (child && child != widget)
5028 child = child->parent;
5030 if (child == widget)
5031 gtk_window_set_default (window, NULL);
5033 g_object_unref (widget);
5034 g_object_unref (window);
5037 /*********************************
5038 * Functions related to resizing *
5039 *********************************/
5041 /* This function doesn't constrain to geometry hints */
5043 gtk_window_compute_configure_request_size (GtkWindow *window,
5047 GtkRequisition requisition;
5048 GtkWindowGeometryInfo *info;
5052 * - we've done a size request
5055 widget = GTK_WIDGET (window);
5057 info = gtk_window_get_geometry_info (window, FALSE);
5059 if (window->need_default_size)
5061 gtk_widget_get_child_requisition (widget, &requisition);
5063 /* Default to requisition */
5064 *width = requisition.width;
5065 *height = requisition.height;
5067 /* If window is empty so requests 0, default to random nonzero size */
5068 if (*width == 0 && *height == 0)
5074 /* Override requisition with default size */
5078 gint base_width = 0;
5079 gint base_height = 0;
5081 gint height_inc = 1;
5083 if (info->default_is_geometry &&
5084 (info->default_width > 0 || info->default_height > 0))
5086 GdkGeometry geometry;
5089 gtk_window_compute_hints (window, &geometry, &flags);
5091 if (flags & GDK_HINT_BASE_SIZE)
5093 base_width = geometry.base_width;
5094 base_height = geometry.base_height;
5096 else if (flags & GDK_HINT_MIN_SIZE)
5098 base_width = geometry.min_width;
5099 base_height = geometry.min_height;
5101 if (flags & GDK_HINT_RESIZE_INC)
5103 width_inc = geometry.width_inc;
5104 height_inc = geometry.height_inc;
5108 if (info->default_width > 0)
5109 *width = info->default_width * width_inc + base_width;
5111 if (info->default_height > 0)
5112 *height = info->default_height * height_inc + base_height;
5117 /* Default to keeping current size */
5118 *width = widget->allocation.width;
5119 *height = widget->allocation.height;
5122 /* Override any size with gtk_window_resize() values */
5125 if (info->resize_width > 0)
5126 *width = info->resize_width;
5128 if (info->resize_height > 0)
5129 *height = info->resize_height;
5133 static GtkWindowPosition
5134 get_effective_position (GtkWindow *window)
5136 GtkWindowPosition pos = window->position;
5137 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5138 (window->transient_parent == NULL ||
5139 !GTK_WIDGET_MAPPED (window->transient_parent)))
5140 pos = GTK_WIN_POS_NONE;
5146 get_center_monitor_of_window (GtkWindow *window)
5148 /* We could try to sort out the relative positions of the monitors and
5149 * stuff, or we could just be losers and assume you have a row
5150 * or column of monitors.
5152 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5156 get_monitor_containing_pointer (GtkWindow *window)
5160 GdkScreen *window_screen;
5161 GdkScreen *pointer_screen;
5163 window_screen = gtk_window_check_screen (window);
5164 gdk_display_get_pointer (gdk_screen_get_display (window_screen),
5168 if (pointer_screen == window_screen)
5169 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5177 center_window_on_monitor (GtkWindow *window,
5183 GdkRectangle monitor;
5186 monitor_num = get_monitor_containing_pointer (window);
5188 if (monitor_num == -1)
5189 monitor_num = get_center_monitor_of_window (window);
5191 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5192 monitor_num, &monitor);
5194 *x = (monitor.width - w) / 2 + monitor.x;
5195 *y = (monitor.height - h) / 2 + monitor.y;
5197 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5198 * and WM decorations.
5207 clamp_window_to_rectangle (gint *x,
5211 const GdkRectangle *rect)
5213 gint outside_w, outside_h;
5215 outside_w = (*x + w) - (rect->x + rect->width);
5219 outside_h = (*y + h) - (rect->y + rect->height);
5223 /* if larger than the screen, center on the screen. */
5225 *x += (rect->x - *x) / 2;
5227 *y += (rect->y - *y) / 2;
5232 gtk_window_compute_configure_request (GtkWindow *window,
5233 GdkRectangle *request,
5234 GdkGeometry *geometry,
5237 GdkGeometry new_geometry;
5241 GtkWindowPosition pos;
5242 GtkWidget *parent_widget;
5243 GtkWindowGeometryInfo *info;
5247 widget = GTK_WIDGET (window);
5249 screen = gtk_window_check_screen (window);
5251 gtk_widget_size_request (widget, NULL);
5252 gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
5254 gtk_window_compute_hints (window, &new_geometry, &new_flags);
5255 gtk_window_constrain_size (window,
5256 &new_geometry, new_flags,
5260 parent_widget = (GtkWidget*) window->transient_parent;
5262 pos = get_effective_position (window);
5263 info = gtk_window_get_geometry_info (window, TRUE);
5265 /* by default, don't change position requested */
5266 x = info->last.configure_request.x;
5267 y = info->last.configure_request.y;
5269 if (window->need_default_position)
5272 /* FIXME this all interrelates with window gravity.
5273 * For most of them I think we want to set GRAVITY_CENTER.
5275 * Not sure how to go about that.
5280 /* here we are only handling CENTER_ALWAYS
5281 * as it relates to default positioning,
5282 * where it's equivalent to simply CENTER
5284 case GTK_WIN_POS_CENTER_ALWAYS:
5285 case GTK_WIN_POS_CENTER:
5286 center_window_on_monitor (window, w, h, &x, &y);
5289 case GTK_WIN_POS_CENTER_ON_PARENT:
5292 GdkRectangle monitor;
5295 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
5297 if (parent_widget->window != NULL)
5298 monitor_num = gdk_screen_get_monitor_at_window (screen,
5299 parent_widget->window);
5303 gdk_window_get_origin (parent_widget->window,
5306 x = ox + (parent_widget->allocation.width - w) / 2;
5307 y = oy + (parent_widget->allocation.height - h) / 2;
5309 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5310 * WM decorations. If parent wasn't on a monitor, just
5313 if (monitor_num >= 0)
5315 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5316 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5321 case GTK_WIN_POS_MOUSE:
5323 gint screen_width = gdk_screen_get_width (screen);
5324 gint screen_height = gdk_screen_get_height (screen);
5326 GdkRectangle monitor;
5327 GdkScreen *pointer_screen;
5330 gdk_display_get_pointer (gdk_screen_get_display (screen),
5334 if (pointer_screen == screen)
5335 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
5341 x = CLAMP (x, 0, screen_width - w);
5342 y = CLAMP (y, 0, screen_height - h);
5344 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5345 * WM decorations. Don't try to figure out what's going
5346 * on if the mouse wasn't inside a monitor.
5348 if (monitor_num >= 0)
5350 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5351 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5359 } /* if (window->need_default_position) */
5361 if (window->need_default_position &&
5362 info->initial_pos_set)
5364 x = info->initial_x;
5365 y = info->initial_y;
5366 gtk_window_constrain_position (window, w, h, &x, &y);
5372 request->height = h;
5375 *geometry = new_geometry;
5381 gtk_window_constrain_position (GtkWindow *window,
5387 /* See long comments in gtk_window_move_resize()
5388 * on when it's safe to call this function.
5390 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
5392 gint center_x, center_y;
5394 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
5402 gtk_window_move_resize (GtkWindow *window)
5406 * First we determine whether any information has changed that would
5407 * cause us to revise our last configure request. If we would send
5408 * a different configure request from last time, then
5409 * configure_request_size_changed = TRUE or
5410 * configure_request_pos_changed = TRUE. configure_request_size_changed
5411 * may be true due to new hints, a gtk_window_resize(), or whatever.
5412 * configure_request_pos_changed may be true due to gtk_window_set_position()
5413 * or gtk_window_move().
5415 * If the configure request has changed, we send off a new one. To
5416 * ensure GTK+ invariants are maintained (resize queue does what it
5417 * should), we go ahead and size_allocate the requested size in this
5420 * If the configure request has not changed, we don't ever resend
5421 * it, because it could mean fighting the user or window manager.
5424 * To prepare the configure request, we come up with a base size/pos:
5425 * - the one from gtk_window_move()/gtk_window_resize()
5426 * - else default_width, default_height if we haven't ever
5428 * - else the size request if we haven't ever been mapped,
5429 * as a substitute default size
5430 * - else the current size of the window, as received from
5431 * configure notifies (i.e. the current allocation)
5433 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
5434 * the position request to be centered.
5437 GtkContainer *container;
5438 GtkWindowGeometryInfo *info;
5439 GdkGeometry new_geometry;
5441 GdkRectangle new_request;
5442 gboolean configure_request_size_changed;
5443 gboolean configure_request_pos_changed;
5444 gboolean hints_changed; /* do we need to send these again */
5445 GtkWindowLastGeometryInfo saved_last_info;
5447 widget = GTK_WIDGET (window);
5448 container = GTK_CONTAINER (widget);
5449 info = gtk_window_get_geometry_info (window, TRUE);
5451 configure_request_size_changed = FALSE;
5452 configure_request_pos_changed = FALSE;
5454 gtk_window_compute_configure_request (window, &new_request,
5455 &new_geometry, &new_flags);
5457 /* This check implies the invariant that we never set info->last
5458 * without setting the hints and sending off a configure request.
5460 * If we change info->last without sending the request, we may
5463 if (info->last.configure_request.x != new_request.x ||
5464 info->last.configure_request.y != new_request.y)
5465 configure_request_pos_changed = TRUE;
5467 if ((info->last.configure_request.width != new_request.width ||
5468 info->last.configure_request.height != new_request.height))
5469 configure_request_size_changed = TRUE;
5471 hints_changed = FALSE;
5473 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
5474 &new_geometry, new_flags))
5476 hints_changed = TRUE;
5479 /* Position Constraints
5480 * ====================
5482 * POS_CENTER_ALWAYS is conceptually a constraint rather than
5483 * a default. The other POS_ values are used only when the
5484 * window is shown, not after that.
5486 * However, we can't implement a position constraint as
5487 * "anytime the window size changes, center the window"
5488 * because this may well end up fighting the WM or user. In
5489 * fact it gets in an infinite loop with at least one WM.
5491 * Basically, applications are in no way in a position to
5492 * constrain the position of a window, with one exception:
5493 * override redirect windows. (Really the intended purpose
5494 * of CENTER_ALWAYS anyhow, I would think.)
5496 * So the way we implement this "constraint" is to say that when WE
5497 * cause a move or resize, i.e. we make a configure request changing
5498 * window size, we recompute the CENTER_ALWAYS position to reflect
5499 * the new window size, and include it in our request. Also, if we
5500 * just turned on CENTER_ALWAYS we snap to center with a new
5501 * request. Otherwise, if we are just NOTIFIED of a move or resize
5502 * done by someone else e.g. the window manager, we do NOT send a
5503 * new configure request.
5505 * For override redirect windows, this works fine; all window
5506 * sizes are from our configure requests. For managed windows,
5507 * it is at least semi-sane, though who knows what the
5508 * app author is thinking.
5511 /* This condition should be kept in sync with the condition later on
5512 * that determines whether we send a configure request. i.e. we
5513 * should do this position constraining anytime we were going to
5514 * send a configure request anyhow, plus when constraints have
5517 if (configure_request_pos_changed ||
5518 configure_request_size_changed ||
5520 info->position_constraints_changed)
5522 /* We request the constrained position if:
5523 * - we were changing position, and need to clamp
5524 * the change to the constraint
5525 * - we're changing the size anyway
5526 * - set_position() was called to toggle CENTER_ALWAYS on
5529 gtk_window_constrain_position (window,
5535 /* Update whether we need to request a move */
5536 if (info->last.configure_request.x != new_request.x ||
5537 info->last.configure_request.y != new_request.y)
5538 configure_request_pos_changed = TRUE;
5540 configure_request_pos_changed = FALSE;
5544 if (window->type == GTK_WINDOW_TOPLEVEL)
5546 int notify_x, notify_y;
5548 /* this is the position from the last configure notify */
5549 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
5551 g_message ("--- %s ---\n"
5552 "last : %d,%d\t%d x %d\n"
5553 "this : %d,%d\t%d x %d\n"
5554 "alloc : %d,%d\t%d x %d\n"
5556 "resize: \t%d x %d\n"
5557 "size_changed: %d pos_changed: %d hints_changed: %d\n"
5558 "configure_notify_received: %d\n"
5559 "configure_request_count: %d\n"
5560 "position_constraints_changed: %d\n",
5561 window->title ? window->title : "(no title)",
5562 info->last.configure_request.x,
5563 info->last.configure_request.y,
5564 info->last.configure_request.width,
5565 info->last.configure_request.height,
5571 widget->allocation.width,
5572 widget->allocation.height,
5573 widget->requisition.width,
5574 widget->requisition.height,
5576 info->resize_height,
5577 configure_request_pos_changed,
5578 configure_request_size_changed,
5580 window->configure_notify_received,
5581 window->configure_request_count,
5582 info->position_constraints_changed);
5586 saved_last_info = info->last;
5587 info->last.geometry = new_geometry;
5588 info->last.flags = new_flags;
5589 info->last.configure_request = new_request;
5591 /* need to set PPosition so the WM will look at our position,
5592 * but we don't want to count PPosition coming and going as a hints
5593 * change for future iterations. So we saved info->last prior to
5597 /* Also, if the initial position was explicitly set, then we always
5598 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
5602 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
5603 * this is an initial map
5606 if ((configure_request_pos_changed ||
5607 info->initial_pos_set ||
5608 (window->need_default_position &&
5609 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
5610 (new_flags & GDK_HINT_POS) == 0)
5612 new_flags |= GDK_HINT_POS;
5613 hints_changed = TRUE;
5616 /* Set hints if necessary
5619 gdk_window_set_geometry_hints (widget->window,
5623 /* handle resizing/moving and widget tree allocation
5625 if (window->configure_notify_received)
5627 GtkAllocation allocation;
5629 /* If we have received a configure event since
5630 * the last time in this function, we need to
5631 * accept our new size and size_allocate child widgets.
5632 * (see gtk_window_configure_event() for more details).
5634 * 1 or more configure notifies may have been received.
5635 * Also, configure_notify_received will only be TRUE
5636 * if all expected configure notifies have been received
5637 * (one per configure request), as an optimization.
5640 window->configure_notify_received = FALSE;
5642 /* gtk_window_configure_event() filled in widget->allocation */
5643 allocation = widget->allocation;
5644 gtk_widget_size_allocate (widget, &allocation);
5646 gdk_window_process_all_updates ();
5648 gdk_window_configure_finished (widget->window);
5650 /* If the configure request changed, it means that
5652 * 1) coincidentally changed hints or widget properties
5653 * impacting the configure request before getting
5654 * a configure notify, or
5655 * 2) some broken widget is changing its size request
5656 * during size allocation, resulting in
5657 * a false appearance of changed configure request.
5659 * For 1), we could just go ahead and ask for the
5660 * new size right now, but doing that for 2)
5661 * might well be fighting the user (and can even
5662 * trigger a loop). Since we really don't want to
5663 * do that, we requeue a resize in hopes that
5664 * by the time it gets handled, the child has seen
5665 * the light and is willing to go along with the
5666 * new size. (this happens for the zvt widget, since
5667 * the size_allocate() above will have stored the
5668 * requisition corresponding to the new size in the
5671 * This doesn't buy us anything for 1), but it shouldn't
5672 * hurt us too badly, since it is what would have
5673 * happened if we had gotten the configure event before
5674 * the new size had been set.
5677 if (configure_request_size_changed ||
5678 configure_request_pos_changed)
5680 /* Don't change the recorded last info after all, because we
5681 * haven't actually updated to the new info yet - we decided
5682 * to postpone our configure request until later.
5684 info->last = saved_last_info;
5686 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
5689 return; /* Bail out, we didn't really process the move/resize */
5691 else if ((configure_request_size_changed || hints_changed) &&
5692 (widget->allocation.width != new_request.width ||
5693 widget->allocation.height != new_request.height))
5696 /* We are in one of the following situations:
5697 * A. configure_request_size_changed
5698 * our requisition has changed and we need a different window size,
5699 * so we request it from the window manager.
5700 * B. !configure_request_size_changed && hints_changed
5701 * the window manager rejects our size, but we have just changed the
5702 * window manager hints, so there's a chance our request will
5703 * be honoured this time, so we try again.
5705 * However, if the new requisition is the same as the current allocation,
5706 * we don't request it again, since we won't get a ConfigureNotify back from
5707 * the window manager unless it decides to change our requisition. If
5708 * we don't get the ConfigureNotify back, the resize queue will never be run.
5711 /* Now send the configure request */
5712 if (configure_request_pos_changed)
5716 gdk_window_move_resize (window->frame,
5717 new_request.x - window->frame_left,
5718 new_request.y - window->frame_top,
5719 new_request.width + window->frame_left + window->frame_right,
5720 new_request.height + window->frame_top + window->frame_bottom);
5721 gdk_window_resize (widget->window,
5722 new_request.width, new_request.height);
5725 gdk_window_move_resize (widget->window,
5726 new_request.x, new_request.y,
5727 new_request.width, new_request.height);
5729 else /* only size changed */
5732 gdk_window_resize (window->frame,
5733 new_request.width + window->frame_left + window->frame_right,
5734 new_request.height + window->frame_top + window->frame_bottom);
5735 gdk_window_resize (widget->window,
5736 new_request.width, new_request.height);
5739 /* Increment the number of have-not-yet-received-notify requests */
5740 window->configure_request_count += 1;
5742 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5743 * configure event in response to our resizing request.
5744 * the configure event will cause a new resize with
5745 * ->configure_notify_received=TRUE.
5746 * until then, we want to
5747 * - discard expose events
5748 * - coalesce resizes for our children
5749 * - defer any window resizes until the configure event arrived
5750 * to achieve this, we queue a resize for the window, but remove its
5751 * resizing handler, so resizing will not be handled from the next
5752 * idle handler but when the configure event arrives.
5754 * FIXME: we should also dequeue the pending redraws here, since
5755 * we handle those ourselves upon ->configure_notify_received==TRUE.
5757 if (container->resize_mode == GTK_RESIZE_QUEUE)
5759 gtk_widget_queue_resize (widget);
5760 _gtk_container_dequeue_resize_handler (container);
5765 /* Handle any position changes.
5767 if (configure_request_pos_changed)
5771 gdk_window_move (window->frame,
5772 new_request.x - window->frame_left,
5773 new_request.y - window->frame_top);
5776 gdk_window_move (widget->window,
5777 new_request.x, new_request.y);
5780 /* And run the resize queue.
5782 gtk_container_resize_children (container);
5785 /* We have now processed a move/resize since the last position
5786 * constraint change, setting of the initial position, or resize.
5787 * (Not resetting these flags here can lead to infinite loops for
5788 * GTK_RESIZE_IMMEDIATE containers)
5790 info->position_constraints_changed = FALSE;
5791 info->initial_pos_set = FALSE;
5792 info->resize_width = -1;
5793 info->resize_height = -1;
5796 /* Compare two sets of Geometry hints for equality.
5799 gtk_window_compare_hints (GdkGeometry *geometry_a,
5801 GdkGeometry *geometry_b,
5804 if (flags_a != flags_b)
5807 if ((flags_a & GDK_HINT_MIN_SIZE) &&
5808 (geometry_a->min_width != geometry_b->min_width ||
5809 geometry_a->min_height != geometry_b->min_height))
5812 if ((flags_a & GDK_HINT_MAX_SIZE) &&
5813 (geometry_a->max_width != geometry_b->max_width ||
5814 geometry_a->max_height != geometry_b->max_height))
5817 if ((flags_a & GDK_HINT_BASE_SIZE) &&
5818 (geometry_a->base_width != geometry_b->base_width ||
5819 geometry_a->base_height != geometry_b->base_height))
5822 if ((flags_a & GDK_HINT_ASPECT) &&
5823 (geometry_a->min_aspect != geometry_b->min_aspect ||
5824 geometry_a->max_aspect != geometry_b->max_aspect))
5827 if ((flags_a & GDK_HINT_RESIZE_INC) &&
5828 (geometry_a->width_inc != geometry_b->width_inc ||
5829 geometry_a->height_inc != geometry_b->height_inc))
5832 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5833 geometry_a->win_gravity != geometry_b->win_gravity)
5840 _gtk_window_constrain_size (GtkWindow *window,
5846 GtkWindowGeometryInfo *info;
5848 g_return_if_fail (GTK_IS_WINDOW (window));
5850 info = window->geometry_info;
5853 GdkWindowHints flags = info->last.flags;
5854 GdkGeometry *geometry = &info->last.geometry;
5856 gtk_window_constrain_size (window,
5867 gtk_window_constrain_size (GtkWindow *window,
5868 GdkGeometry *geometry,
5875 gdk_window_constrain_size (geometry, flags, width, height,
5876 new_width, new_height);
5879 /* Compute the set of geometry hints and flags for a window
5880 * based on the application set geometry, and requisiition
5881 * of the window. gtk_widget_size_request() must have been
5885 gtk_window_compute_hints (GtkWindow *window,
5886 GdkGeometry *new_geometry,
5890 gint extra_width = 0;
5891 gint extra_height = 0;
5892 GtkWindowGeometryInfo *geometry_info;
5893 GtkRequisition requisition;
5895 widget = GTK_WIDGET (window);
5897 gtk_widget_get_child_requisition (widget, &requisition);
5898 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5902 *new_flags = geometry_info->mask;
5903 *new_geometry = geometry_info->geometry;
5910 if (geometry_info && geometry_info->widget)
5912 GtkRequisition child_requisition;
5914 /* FIXME: This really isn't right. It gets the min size wrong and forces
5915 * callers to do horrible hacks like set a huge usize on the child requisition
5916 * to get the base size right. We really want to find the answers to:
5918 * - If the geometry widget was infinitely big, how much extra space
5919 * would be needed for the stuff around it.
5921 * - If the geometry widget was infinitely small, how big would the
5922 * window still have to be.
5924 * Finding these answers would be a bit of a mess here. (Bug #68668)
5926 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5928 extra_width = widget->requisition.width - child_requisition.width;
5929 extra_height = widget->requisition.height - child_requisition.height;
5932 /* We don't want to set GDK_HINT_POS in here, we just set it
5933 * in gtk_window_move_resize() when we want the position
5937 if (*new_flags & GDK_HINT_BASE_SIZE)
5939 new_geometry->base_width += extra_width;
5940 new_geometry->base_height += extra_height;
5942 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5943 (*new_flags & GDK_HINT_RESIZE_INC) &&
5944 ((extra_width != 0) || (extra_height != 0)))
5946 *new_flags |= GDK_HINT_BASE_SIZE;
5948 new_geometry->base_width = extra_width;
5949 new_geometry->base_height = extra_height;
5952 if (*new_flags & GDK_HINT_MIN_SIZE)
5954 if (new_geometry->min_width < 0)
5955 new_geometry->min_width = requisition.width;
5957 new_geometry->min_width += extra_width;
5959 if (new_geometry->min_height < 0)
5960 new_geometry->min_height = requisition.height;
5962 new_geometry->min_height += extra_height;
5964 else if (!window->allow_shrink)
5966 *new_flags |= GDK_HINT_MIN_SIZE;
5968 new_geometry->min_width = requisition.width;
5969 new_geometry->min_height = requisition.height;
5972 if (*new_flags & GDK_HINT_MAX_SIZE)
5974 if (new_geometry->max_width < 0)
5975 new_geometry->max_width = requisition.width;
5977 new_geometry->max_width += extra_width;
5979 if (new_geometry->max_height < 0)
5980 new_geometry->max_height = requisition.height;
5982 new_geometry->max_height += extra_height;
5984 else if (!window->allow_grow)
5986 *new_flags |= GDK_HINT_MAX_SIZE;
5988 new_geometry->max_width = requisition.width;
5989 new_geometry->max_height = requisition.height;
5992 *new_flags |= GDK_HINT_WIN_GRAVITY;
5993 new_geometry->win_gravity = window->gravity;
5996 /***********************
5997 * Redrawing functions *
5998 ***********************/
6001 gtk_window_paint (GtkWidget *widget,
6004 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
6005 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
6009 gtk_window_expose (GtkWidget *widget,
6010 GdkEventExpose *event)
6012 if (!GTK_WIDGET_APP_PAINTABLE (widget))
6013 gtk_window_paint (widget, &event->area);
6015 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
6016 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
6022 * gtk_window_set_has_frame:
6023 * @window: a #GtkWindow
6024 * @setting: a boolean
6026 * (Note: this is a special-purpose function for the framebuffer port,
6027 * that causes GTK+ to draw its own window border. For most applications,
6028 * you want gtk_window_set_decorated() instead, which tells the window
6029 * manager whether to draw the window border.)
6031 * If this function is called on a window with setting of %TRUE, before
6032 * it is realized or showed, it will have a "frame" window around
6033 * @window->window, accessible in @window->frame. Using the signal
6034 * frame_event you can receive all events targeted at the frame.
6036 * This function is used by the linux-fb port to implement managed
6037 * windows, but it could conceivably be used by X-programs that
6038 * want to do their own window decorations.
6042 gtk_window_set_has_frame (GtkWindow *window,
6045 g_return_if_fail (GTK_IS_WINDOW (window));
6046 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
6048 window->has_frame = setting != FALSE;
6052 * gtk_window_get_has_frame:
6053 * @window: a #GtkWindow
6055 * Accessor for whether the window has a frame window exterior to
6056 * @window->window. Gets the value set by gtk_window_set_has_frame ().
6058 * Return value: %TRUE if a frame has been added to the window
6059 * via gtk_window_set_has_frame().
6062 gtk_window_get_has_frame (GtkWindow *window)
6064 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6066 return window->has_frame;
6070 * gtk_window_set_frame_dimensions:
6071 * @window: a #GtkWindow that has a frame
6072 * @left: The width of the left border
6073 * @top: The height of the top border
6074 * @right: The width of the right border
6075 * @bottom: The height of the bottom border
6077 * (Note: this is a special-purpose function intended for the framebuffer
6078 * port; see gtk_window_set_has_frame(). It will have no effect on the
6079 * window border drawn by the window manager, which is the normal
6080 * case when using the X Window system.)
6082 * For windows with frames (see gtk_window_set_has_frame()) this function
6083 * can be used to change the size of the frame border.
6086 gtk_window_set_frame_dimensions (GtkWindow *window,
6094 g_return_if_fail (GTK_IS_WINDOW (window));
6096 widget = GTK_WIDGET (window);
6098 if (window->frame_left == left &&
6099 window->frame_top == top &&
6100 window->frame_right == right &&
6101 window->frame_bottom == bottom)
6104 window->frame_left = left;
6105 window->frame_top = top;
6106 window->frame_right = right;
6107 window->frame_bottom = bottom;
6109 if (GTK_WIDGET_REALIZED (widget) && window->frame)
6111 gint width = widget->allocation.width + left + right;
6112 gint height = widget->allocation.height + top + bottom;
6113 gdk_window_resize (window->frame, width, height);
6114 gtk_decorated_window_move_resize_window (window,
6116 widget->allocation.width,
6117 widget->allocation.height);
6122 * gtk_window_present:
6123 * @window: a #GtkWindow
6125 * Presents a window to the user. This may mean raising the window
6126 * in the stacking order, deiconifying it, moving it to the current
6127 * desktop, and/or giving it the keyboard focus, possibly dependent
6128 * on the user's platform, window manager, and preferences.
6130 * If @window is hidden, this function calls gtk_widget_show()
6133 * This function should be used when the user tries to open a window
6134 * that's already open. Say for example the preferences dialog is
6135 * currently open, and the user chooses Preferences from the menu
6136 * a second time; use gtk_window_present() to move the already-open dialog
6137 * where the user can see it.
6139 * If you are calling this function in response to a user interaction,
6140 * it is preferable to use gtk_window_present_with_time().
6144 gtk_window_present (GtkWindow *window)
6146 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6150 * gtk_window_present_with_time:
6151 * @window: a #GtkWindow
6152 * @timestamp: the timestamp of the user interaction (typically a
6153 * button or key press event) which triggered this call
6155 * Presents a window to the user in response to a user interaction.
6156 * If you need to present a window without a timestamp, use
6157 * gtk_window_present(). See gtk_window_present() for details.
6162 gtk_window_present_with_time (GtkWindow *window,
6167 g_return_if_fail (GTK_IS_WINDOW (window));
6169 widget = GTK_WIDGET (window);
6171 if (GTK_WIDGET_VISIBLE (window))
6173 g_assert (widget->window != NULL);
6175 gdk_window_show (widget->window);
6177 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
6178 if (timestamp == GDK_CURRENT_TIME)
6180 #ifdef GDK_WINDOWING_X11
6181 GdkDisplay *display;
6183 display = gtk_widget_get_display (GTK_WIDGET (window));
6184 timestamp = gdk_x11_display_get_user_time (display);
6186 timestamp = gtk_get_current_event_time ();
6190 gdk_window_focus (widget->window, timestamp);
6194 gtk_widget_show (widget);
6199 * gtk_window_iconify:
6200 * @window: a #GtkWindow
6202 * Asks to iconify (i.e. minimize) the specified @window. Note that
6203 * you shouldn't assume the window is definitely iconified afterward,
6204 * because other entities (e.g. the user or <link
6205 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
6206 * again, or there may not be a window manager in which case
6207 * iconification isn't possible, etc. But normally the window will end
6208 * up iconified. Just don't write code that crashes if not.
6210 * It's permitted to call this function before showing a window,
6211 * in which case the window will be iconified before it ever appears
6214 * You can track iconification via the "window_state_event" signal
6219 gtk_window_iconify (GtkWindow *window)
6222 GdkWindow *toplevel;
6224 g_return_if_fail (GTK_IS_WINDOW (window));
6226 widget = GTK_WIDGET (window);
6228 window->iconify_initially = TRUE;
6231 toplevel = window->frame;
6233 toplevel = widget->window;
6235 if (toplevel != NULL)
6236 gdk_window_iconify (toplevel);
6240 * gtk_window_deiconify:
6241 * @window: a #GtkWindow
6243 * Asks to deiconify (i.e. unminimize) the specified @window. Note
6244 * that you shouldn't assume the window is definitely deiconified
6245 * afterward, because other entities (e.g. the user or <link
6246 * linkend="gtk-X11-arch">window manager</link>) could iconify it
6247 * again before your code which assumes deiconification gets to run.
6249 * You can track iconification via the "window_state_event" signal
6253 gtk_window_deiconify (GtkWindow *window)
6256 GdkWindow *toplevel;
6258 g_return_if_fail (GTK_IS_WINDOW (window));
6260 widget = GTK_WIDGET (window);
6262 window->iconify_initially = FALSE;
6265 toplevel = window->frame;
6267 toplevel = widget->window;
6269 if (toplevel != NULL)
6270 gdk_window_deiconify (toplevel);
6275 * @window: a #GtkWindow
6277 * Asks to stick @window, which means that it will appear on all user
6278 * desktops. Note that you shouldn't assume the window is definitely
6279 * stuck afterward, because other entities (e.g. the user or <link
6280 * linkend="gtk-X11-arch">window manager</link>) could unstick it
6281 * again, and some window managers do not support sticking
6282 * windows. But normally the window will end up stuck. Just don't
6283 * write code that crashes if not.
6285 * It's permitted to call this function before showing a window.
6287 * You can track stickiness via the "window_state_event" signal
6292 gtk_window_stick (GtkWindow *window)
6295 GdkWindow *toplevel;
6297 g_return_if_fail (GTK_IS_WINDOW (window));
6299 widget = GTK_WIDGET (window);
6301 window->stick_initially = TRUE;
6304 toplevel = window->frame;
6306 toplevel = widget->window;
6308 if (toplevel != NULL)
6309 gdk_window_stick (toplevel);
6313 * gtk_window_unstick:
6314 * @window: a #GtkWindow
6316 * Asks to unstick @window, which means that it will appear on only
6317 * one of the user's desktops. Note that you shouldn't assume the
6318 * window is definitely unstuck afterward, because other entities
6319 * (e.g. the user or <link linkend="gtk-X11-arch">window
6320 * manager</link>) could stick it again. But normally the window will
6321 * end up stuck. Just don't write code that crashes if not.
6323 * You can track stickiness via the "window_state_event" signal
6328 gtk_window_unstick (GtkWindow *window)
6331 GdkWindow *toplevel;
6333 g_return_if_fail (GTK_IS_WINDOW (window));
6335 widget = GTK_WIDGET (window);
6337 window->stick_initially = FALSE;
6340 toplevel = window->frame;
6342 toplevel = widget->window;
6344 if (toplevel != NULL)
6345 gdk_window_unstick (toplevel);
6349 * gtk_window_maximize:
6350 * @window: a #GtkWindow
6352 * Asks to maximize @window, so that it becomes full-screen. Note that
6353 * you shouldn't assume the window is definitely maximized afterward,
6354 * because other entities (e.g. the user or <link
6355 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
6356 * again, and not all window managers support maximization. But
6357 * normally the window will end up maximized. Just don't write code
6358 * that crashes if not.
6360 * It's permitted to call this function before showing a window,
6361 * in which case the window will be maximized when it appears onscreen
6364 * You can track maximization via the "window_state_event" signal
6369 gtk_window_maximize (GtkWindow *window)
6372 GdkWindow *toplevel;
6374 g_return_if_fail (GTK_IS_WINDOW (window));
6376 widget = GTK_WIDGET (window);
6378 window->maximize_initially = TRUE;
6381 toplevel = window->frame;
6383 toplevel = widget->window;
6385 if (toplevel != NULL)
6386 gdk_window_maximize (toplevel);
6390 * gtk_window_unmaximize:
6391 * @window: a #GtkWindow
6393 * Asks to unmaximize @window. Note that you shouldn't assume the
6394 * window is definitely unmaximized afterward, because other entities
6395 * (e.g. the user or <link linkend="gtk-X11-arch">window
6396 * manager</link>) could maximize it again, and not all window
6397 * managers honor requests to unmaximize. But normally the window will
6398 * end up unmaximized. Just don't write code that crashes if not.
6400 * You can track maximization via the "window_state_event" signal
6405 gtk_window_unmaximize (GtkWindow *window)
6408 GdkWindow *toplevel;
6410 g_return_if_fail (GTK_IS_WINDOW (window));
6412 widget = GTK_WIDGET (window);
6414 window->maximize_initially = FALSE;
6417 toplevel = window->frame;
6419 toplevel = widget->window;
6421 if (toplevel != NULL)
6422 gdk_window_unmaximize (toplevel);
6426 * gtk_window_fullscreen:
6427 * @window: a #GtkWindow
6429 * Asks to place @window in the fullscreen state. Note that you
6430 * shouldn't assume the window is definitely full screen afterward,
6431 * because other entities (e.g. the user or <link
6432 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
6433 * again, and not all window managers honor requests to fullscreen
6434 * windows. But normally the window will end up fullscreen. Just
6435 * don't write code that crashes if not.
6437 * You can track the fullscreen state via the "window_state_event" signal
6443 gtk_window_fullscreen (GtkWindow *window)
6446 GdkWindow *toplevel;
6447 GtkWindowPrivate *priv;
6449 g_return_if_fail (GTK_IS_WINDOW (window));
6451 widget = GTK_WIDGET (window);
6452 priv = GTK_WINDOW_GET_PRIVATE (window);
6454 priv->fullscreen_initially = TRUE;
6457 toplevel = window->frame;
6459 toplevel = widget->window;
6461 if (toplevel != NULL)
6462 gdk_window_fullscreen (toplevel);
6466 * gtk_window_unfullscreen:
6467 * @window: a #GtkWindow
6469 * Asks to toggle off the fullscreen state for @window. Note that you
6470 * shouldn't assume the window is definitely not full screen
6471 * afterward, because other entities (e.g. the user or <link
6472 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
6473 * again, and not all window managers honor requests to unfullscreen
6474 * windows. But normally the window will end up restored to its normal
6475 * state. Just don't write code that crashes if not.
6477 * You can track the fullscreen state via the "window_state_event" signal
6483 gtk_window_unfullscreen (GtkWindow *window)
6486 GdkWindow *toplevel;
6487 GtkWindowPrivate *priv;
6489 g_return_if_fail (GTK_IS_WINDOW (window));
6491 widget = GTK_WIDGET (window);
6492 priv = GTK_WINDOW_GET_PRIVATE (window);
6494 priv->fullscreen_initially = FALSE;
6497 toplevel = window->frame;
6499 toplevel = widget->window;
6501 if (toplevel != NULL)
6502 gdk_window_unfullscreen (toplevel);
6506 * gtk_window_set_keep_above:
6507 * @window: a #GtkWindow
6508 * @setting: whether to keep @window above other windows
6510 * Asks to keep @window above, so that it stays on top. Note that
6511 * you shouldn't assume the window is definitely above afterward,
6512 * because other entities (e.g. the user or <link
6513 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
6514 * and not all window managers support keeping windows above. But
6515 * normally the window will end kept above. Just don't write code
6516 * that crashes if not.
6518 * It's permitted to call this function before showing a window,
6519 * in which case the window will be kept above when it appears onscreen
6522 * You can track the above state via the "window_state_event" signal
6525 * Note that, according to the <ulink
6526 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
6527 * Manager Hints</ulink> specification, the above state is mainly meant
6528 * for user preferences and should not be used by applications e.g. for
6529 * drawing attention to their dialogs.
6534 gtk_window_set_keep_above (GtkWindow *window,
6538 GtkWindowPrivate *priv;
6539 GdkWindow *toplevel;
6541 g_return_if_fail (GTK_IS_WINDOW (window));
6543 widget = GTK_WIDGET (window);
6544 priv = GTK_WINDOW_GET_PRIVATE (window);
6546 priv->above_initially = setting;
6548 priv->below_initially = FALSE;
6551 toplevel = window->frame;
6553 toplevel = widget->window;
6555 if (toplevel != NULL)
6556 gdk_window_set_keep_above (toplevel, setting);
6560 * gtk_window_set_keep_below:
6561 * @window: a #GtkWindow
6562 * @setting: whether to keep @window below other windows
6564 * Asks to keep @window below, so that it stays in bottom. Note that
6565 * you shouldn't assume the window is definitely below afterward,
6566 * because other entities (e.g. the user or <link
6567 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
6568 * and not all window managers support putting windows below. But
6569 * normally the window will be kept below. Just don't write code
6570 * that crashes if not.
6572 * It's permitted to call this function before showing a window,
6573 * in which case the window will be kept below when it appears onscreen
6576 * You can track the below state via the "window_state_event" signal
6579 * Note that, according to the <ulink
6580 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
6581 * Manager Hints</ulink> specification, the above state is mainly meant
6582 * for user preferences and should not be used by applications e.g. for
6583 * drawing attention to their dialogs.
6588 gtk_window_set_keep_below (GtkWindow *window,
6592 GtkWindowPrivate *priv;
6593 GdkWindow *toplevel;
6595 g_return_if_fail (GTK_IS_WINDOW (window));
6597 widget = GTK_WIDGET (window);
6598 priv = GTK_WINDOW_GET_PRIVATE (window);
6600 priv->below_initially = setting;
6602 priv->above_initially = FALSE;
6605 toplevel = window->frame;
6607 toplevel = widget->window;
6609 if (toplevel != NULL)
6610 gdk_window_set_keep_below (toplevel, setting);
6614 * gtk_window_set_resizable:
6615 * @window: a #GtkWindow
6616 * @resizable: %TRUE if the user can resize this window
6618 * Sets whether the user can resize a window. Windows are user resizable
6622 gtk_window_set_resizable (GtkWindow *window,
6625 g_return_if_fail (GTK_IS_WINDOW (window));
6627 gtk_window_set_policy (window, FALSE, resizable, FALSE);
6631 * gtk_window_get_resizable:
6632 * @window: a #GtkWindow
6634 * Gets the value set by gtk_window_set_resizable().
6636 * Return value: %TRUE if the user can resize the window
6639 gtk_window_get_resizable (GtkWindow *window)
6641 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6643 /* allow_grow is most likely to indicate the semantic concept we
6644 * mean by "resizable" (and will be a reliable indicator if
6645 * set_policy() hasn't been called)
6647 return window->allow_grow;
6651 * gtk_window_set_gravity:
6652 * @window: a #GtkWindow
6653 * @gravity: window gravity
6655 * Window gravity defines the meaning of coordinates passed to
6656 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
6659 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
6660 * typically "do what you mean."
6664 gtk_window_set_gravity (GtkWindow *window,
6667 g_return_if_fail (GTK_IS_WINDOW (window));
6669 if (gravity != window->gravity)
6671 window->gravity = gravity;
6673 /* gtk_window_move_resize() will adapt gravity
6675 gtk_widget_queue_resize (GTK_WIDGET (window));
6677 g_object_notify (G_OBJECT (window), "gravity");
6682 * gtk_window_get_gravity:
6683 * @window: a #GtkWindow
6685 * Gets the value set by gtk_window_set_gravity().
6687 * Return value: window gravity
6690 gtk_window_get_gravity (GtkWindow *window)
6692 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
6694 return window->gravity;
6698 * gtk_window_begin_resize_drag:
6699 * @window: a #GtkWindow
6700 * @button: mouse button that initiated the drag
6701 * @edge: position of the resize control
6702 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6703 * @root_y: Y position where the user clicked to initiate the drag
6704 * @timestamp: timestamp from the click event that initiated the drag
6706 * Starts resizing a window. This function is used if an application
6707 * has window resizing controls. When GDK can support it, the resize
6708 * will be done using the standard mechanism for the <link
6709 * linkend="gtk-X11-arch">window manager</link> or windowing
6710 * system. Otherwise, GDK will try to emulate window resizing,
6711 * potentially not all that well, depending on the windowing system.
6715 gtk_window_begin_resize_drag (GtkWindow *window,
6723 GdkWindow *toplevel;
6725 g_return_if_fail (GTK_IS_WINDOW (window));
6726 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6728 widget = GTK_WIDGET (window);
6731 toplevel = window->frame;
6733 toplevel = widget->window;
6735 gdk_window_begin_resize_drag (toplevel,
6742 * gtk_window_get_frame_dimensions:
6743 * @window: a #GtkWindow
6744 * @left: location to store the width of the frame at the left, or %NULL
6745 * @top: location to store the height of the frame at the top, or %NULL
6746 * @right: location to store the width of the frame at the returns, or %NULL
6747 * @bottom: location to store the height of the frame at the bottom, or %NULL
6749 * (Note: this is a special-purpose function intended for the
6750 * framebuffer port; see gtk_window_set_has_frame(). It will not
6751 * return the size of the window border drawn by the <link
6752 * linkend="gtk-X11-arch">window manager</link>, which is the normal
6753 * case when using a windowing system. See
6754 * gdk_window_get_frame_extents() to get the standard window border
6757 * Retrieves the dimensions of the frame window for this toplevel.
6758 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
6761 gtk_window_get_frame_dimensions (GtkWindow *window,
6767 g_return_if_fail (GTK_IS_WINDOW (window));
6770 *left = window->frame_left;
6772 *top = window->frame_top;
6774 *right = window->frame_right;
6776 *bottom = window->frame_bottom;
6780 * gtk_window_begin_move_drag:
6781 * @window: a #GtkWindow
6782 * @button: mouse button that initiated the drag
6783 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6784 * @root_y: Y position where the user clicked to initiate the drag
6785 * @timestamp: timestamp from the click event that initiated the drag
6787 * Starts moving a window. This function is used if an application has
6788 * window movement grips. When GDK can support it, the window movement
6789 * will be done using the standard mechanism for the <link
6790 * linkend="gtk-X11-arch">window manager</link> or windowing
6791 * system. Otherwise, GDK will try to emulate window movement,
6792 * potentially not all that well, depending on the windowing system.
6796 gtk_window_begin_move_drag (GtkWindow *window,
6803 GdkWindow *toplevel;
6805 g_return_if_fail (GTK_IS_WINDOW (window));
6806 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6808 widget = GTK_WIDGET (window);
6811 toplevel = window->frame;
6813 toplevel = widget->window;
6815 gdk_window_begin_move_drag (toplevel,
6822 * gtk_window_set_screen:
6823 * @window: a #GtkWindow.
6824 * @screen: a #GdkScreen.
6826 * Sets the #GdkScreen where the @window is displayed; if
6827 * the window is already mapped, it will be unmapped, and
6828 * then remapped on the new screen.
6833 gtk_window_set_screen (GtkWindow *window,
6837 GdkScreen *previous_screen;
6838 gboolean was_mapped;
6840 g_return_if_fail (GTK_IS_WINDOW (window));
6841 g_return_if_fail (GDK_IS_SCREEN (screen));
6843 if (screen == window->screen)
6846 widget = GTK_WIDGET (window);
6848 previous_screen = window->screen;
6849 was_mapped = GTK_WIDGET_MAPPED (widget);
6852 gtk_widget_unmap (widget);
6853 if (GTK_WIDGET_REALIZED (widget))
6854 gtk_widget_unrealize (widget);
6856 gtk_window_free_key_hash (window);
6857 window->screen = screen;
6858 gtk_widget_reset_rc_styles (widget);
6859 if (screen != previous_screen)
6860 _gtk_widget_propagate_screen_changed (widget, previous_screen);
6861 g_object_notify (G_OBJECT (window), "screen");
6864 gtk_widget_map (widget);
6868 gtk_window_check_screen (GtkWindow *window)
6871 return window->screen;
6874 g_warning ("Screen for GtkWindow not set; you must always set\n"
6875 "a screen for a GtkWindow before using the window");
6881 * gtk_window_get_screen:
6882 * @window: a #GtkWindow.
6884 * Returns the #GdkScreen associated with @window.
6886 * Return value: a #GdkScreen.
6891 gtk_window_get_screen (GtkWindow *window)
6893 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6895 return window->screen;
6899 * gtk_window_is_active:
6900 * @window: a #GtkWindow
6902 * Returns whether the window is part of the current active toplevel.
6903 * (That is, the toplevel window receiving keystrokes.)
6904 * The return value is %TRUE if the window is active toplevel
6905 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
6906 * You might use this function if you wanted to draw a widget
6907 * differently in an active window from a widget in an inactive window.
6908 * See gtk_window_has_toplevel_focus()
6910 * Return value: %TRUE if the window part of the current active window.
6915 gtk_window_is_active (GtkWindow *window)
6917 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6919 return window->is_active;
6923 * gtk_window_has_toplevel_focus:
6924 * @window: a #GtkWindow
6926 * Returns whether the input focus is within this GtkWindow.
6927 * For real toplevel windows, this is identical to gtk_window_is_active(),
6928 * but for embedded windows, like #GtkPlug, the results will differ.
6930 * Return value: %TRUE if the input focus is within this GtkWindow
6935 gtk_window_has_toplevel_focus (GtkWindow *window)
6937 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6939 return window->has_toplevel_focus;
6943 gtk_window_group_class_init (GtkWindowGroupClass *klass)
6948 gtk_window_group_get_type (void)
6950 static GType window_group_type = 0;
6952 if (!window_group_type)
6954 static const GTypeInfo window_group_info =
6956 sizeof (GtkWindowGroupClass),
6957 NULL, /* base_init */
6958 NULL, /* base_finalize */
6959 (GClassInitFunc) gtk_window_group_class_init,
6960 NULL, /* class_finalize */
6961 NULL, /* class_data */
6962 sizeof (GtkWindowGroup),
6963 0, /* n_preallocs */
6964 (GInstanceInitFunc) NULL,
6967 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
6968 &window_group_info, 0);
6971 return window_group_type;
6975 * gtk_window_group_new:
6977 * Creates a new #GtkWindowGroup object. Grabs added with
6978 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
6980 * Return value: a new #GtkWindowGroup.
6983 gtk_window_group_new (void)
6985 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
6989 window_group_cleanup_grabs (GtkWindowGroup *group,
6993 GSList *to_remove = NULL;
6995 tmp_list = group->grabs;
6998 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
6999 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
7000 tmp_list = tmp_list->next;
7005 gtk_grab_remove (to_remove->data);
7006 g_object_unref (to_remove->data);
7007 to_remove = g_slist_delete_link (to_remove, to_remove);
7012 * gtk_window_group_add_window:
7013 * @window_group: a #GtkWindowGroup
7014 * @window: the #GtkWindow to add
7016 * Adds a window to a #GtkWindowGroup.
7019 gtk_window_group_add_window (GtkWindowGroup *window_group,
7022 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7023 g_return_if_fail (GTK_IS_WINDOW (window));
7025 if (window->group != window_group)
7027 g_object_ref (window);
7028 g_object_ref (window_group);
7031 gtk_window_group_remove_window (window->group, window);
7033 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
7035 window->group = window_group;
7037 g_object_unref (window);
7042 * gtk_window_group_remove_window:
7043 * @window_group: a #GtkWindowGroup
7044 * @window: the #GtkWindow to remove
7046 * Removes a window from a #GtkWindowGroup.
7049 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7052 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7053 g_return_if_fail (GTK_IS_WIDGET (window));
7054 g_return_if_fail (window->group == window_group);
7056 g_object_ref (window);
7058 window_group_cleanup_grabs (window_group, window);
7059 window->group = NULL;
7061 g_object_unref (window_group);
7062 g_object_unref (window);
7065 /* Return the group for the window or the default group
7068 _gtk_window_get_group (GtkWindow *window)
7070 if (window && window->group)
7071 return window->group;
7074 static GtkWindowGroup *default_group = NULL;
7077 default_group = gtk_window_group_new ();
7079 return default_group;
7083 /* Return the current grab widget of the given group
7086 _gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
7088 if (window_group->grabs)
7089 return GTK_WIDGET (window_group->grabs->data);
7094 Derived from XParseGeometry() in XFree86
7096 Copyright 1985, 1986, 1987,1998 The Open Group
7098 All Rights Reserved.
7100 The above copyright notice and this permission notice shall be included
7101 in all copies or substantial portions of the Software.
7103 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
7104 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7105 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7106 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
7107 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7108 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
7109 OTHER DEALINGS IN THE SOFTWARE.
7111 Except as contained in this notice, the name of The Open Group shall
7112 not be used in advertising or otherwise to promote the sale, use or
7113 other dealings in this Software without prior written authorization
7114 from The Open Group.
7119 * XParseGeometry parses strings of the form
7120 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
7121 * width, height, xoffset, and yoffset are unsigned integers.
7122 * Example: "=80x24+300-49"
7123 * The equal sign is optional.
7124 * It returns a bitmask that indicates which of the four values
7125 * were actually found in the string. For each value found,
7126 * the corresponding argument is updated; for each value
7127 * not found, the corresponding argument is left unchanged.
7130 /* The following code is from Xlib, and is minimally modified, so we
7131 * can track any upstream changes if required. Don't change this
7132 * code. Or if you do, put in a huge comment marking which thing
7137 read_int (gchar *string,
7145 else if (*string == '-')
7151 for (; (*string >= '0') && (*string <= '9'); string++)
7153 result = (result * 10) + (*string - '0');
7165 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
7166 * value (x, y, width, height) was found in the parsed string.
7168 #define NoValue 0x0000
7169 #define XValue 0x0001
7170 #define YValue 0x0002
7171 #define WidthValue 0x0004
7172 #define HeightValue 0x0008
7173 #define AllValues 0x000F
7174 #define XNegative 0x0010
7175 #define YNegative 0x0020
7177 /* Try not to reformat/modify, so we can compare/sync with X sources */
7179 gtk_XParseGeometry (const char *string,
7182 unsigned int *width,
7183 unsigned int *height)
7187 unsigned int tempWidth, tempHeight;
7189 char *nextCharacter;
7191 /* These initializations are just to silence gcc */
7197 if ( (string == NULL) || (*string == '\0')) return(mask);
7199 string++; /* ignore possible '=' at beg of geometry spec */
7201 strind = (char *)string;
7202 if (*strind != '+' && *strind != '-' && *strind != 'x') {
7203 tempWidth = read_int(strind, &nextCharacter);
7204 if (strind == nextCharacter)
7206 strind = nextCharacter;
7210 if (*strind == 'x' || *strind == 'X') {
7212 tempHeight = read_int(strind, &nextCharacter);
7213 if (strind == nextCharacter)
7215 strind = nextCharacter;
7216 mask |= HeightValue;
7219 if ((*strind == '+') || (*strind == '-')) {
7220 if (*strind == '-') {
7222 tempX = -read_int(strind, &nextCharacter);
7223 if (strind == nextCharacter)
7225 strind = nextCharacter;
7231 tempX = read_int(strind, &nextCharacter);
7232 if (strind == nextCharacter)
7234 strind = nextCharacter;
7237 if ((*strind == '+') || (*strind == '-')) {
7238 if (*strind == '-') {
7240 tempY = -read_int(strind, &nextCharacter);
7241 if (strind == nextCharacter)
7243 strind = nextCharacter;
7250 tempY = read_int(strind, &nextCharacter);
7251 if (strind == nextCharacter)
7253 strind = nextCharacter;
7259 /* If strind isn't at the end of the string the it's an invalid
7260 geometry specification. */
7262 if (*strind != '\0') return (0);
7268 if (mask & WidthValue)
7270 if (mask & HeightValue)
7271 *height = tempHeight;
7276 * gtk_window_parse_geometry:
7277 * @window: a #GtkWindow
7278 * @geometry: geometry string
7280 * Parses a standard X Window System geometry string - see the
7281 * manual page for X (type 'man X') for details on this.
7282 * gtk_window_parse_geometry() does work on all GTK+ ports
7283 * including Win32 but is primarily intended for an X environment.
7285 * If either a size or a position can be extracted from the
7286 * geometry string, gtk_window_parse_geometry() returns %TRUE
7287 * and calls gtk_window_set_default_size() and/or gtk_window_move()
7288 * to resize/move the window.
7290 * If gtk_window_parse_geometry() returns %TRUE, it will also
7291 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
7292 * indicating to the window manager that the size/position of
7293 * the window was user-specified. This causes most window
7294 * managers to honor the geometry.
7296 * Note that for gtk_window_parse_geometry() to work as expected, it has
7297 * to be called when the window has its "final" size, i.e. after calling
7298 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
7301 * <informalexample><programlisting>
7302 * #include <gtk/gtk.h>
7305 * fill_with_content (GtkWidget *vbox)
7307 * /<!-- -->* fill with content... *<!-- -->/
7311 * main (int argc, char *argv[])
7313 * GtkWidget *window, *vbox;
7314 * GdkGeometry size_hints = {
7315 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
7318 * gtk_init (&argc, &argv);
7320 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7321 * vbox = gtk_vbox_new (FALSE, 0);
7323 * gtk_container_add (GTK_CONTAINER (window), vbox);
7324 * fill_with_content (vbox);
7325 * gtk_widget_show_all (vbox);
7327 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
7330 * GDK_HINT_MIN_SIZE |
7331 * GDK_HINT_BASE_SIZE |
7332 * GDK_HINT_RESIZE_INC);
7336 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
7337 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
7340 * gtk_widget_show_all (window);
7345 * </programlisting></informalexample>
7347 * Return value: %TRUE if string was parsed successfully
7350 gtk_window_parse_geometry (GtkWindow *window,
7351 const gchar *geometry)
7353 gint result, x = 0, y = 0;
7356 gboolean size_set, pos_set;
7359 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7360 g_return_val_if_fail (geometry != NULL, FALSE);
7362 screen = gtk_window_check_screen (window);
7364 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
7367 if ((result & WidthValue) || (result & HeightValue))
7369 gtk_window_set_default_size_internal (window,
7370 TRUE, result & WidthValue ? w : -1,
7371 TRUE, result & HeightValue ? h : -1,
7376 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
7378 grav = GDK_GRAVITY_NORTH_WEST;
7380 if ((result & XNegative) && (result & YNegative))
7381 grav = GDK_GRAVITY_SOUTH_EAST;
7382 else if (result & XNegative)
7383 grav = GDK_GRAVITY_NORTH_EAST;
7384 else if (result & YNegative)
7385 grav = GDK_GRAVITY_SOUTH_WEST;
7387 if ((result & XValue) == 0)
7390 if ((result & YValue) == 0)
7393 if (grav == GDK_GRAVITY_SOUTH_WEST ||
7394 grav == GDK_GRAVITY_SOUTH_EAST)
7395 y = gdk_screen_get_height (screen) - h + y;
7397 if (grav == GDK_GRAVITY_SOUTH_EAST ||
7398 grav == GDK_GRAVITY_NORTH_EAST)
7399 x = gdk_screen_get_width (screen) - w + x;
7401 /* we don't let you put a window offscreen; maybe some people would
7402 * prefer to be able to, but it's kind of a bogus thing to do.
7411 if ((result & XValue) || (result & YValue))
7413 gtk_window_set_gravity (window, grav);
7414 gtk_window_move (window, x, y);
7418 if (size_set || pos_set)
7420 /* Set USSize, USPosition hints */
7421 GtkWindowGeometryInfo *info;
7423 info = gtk_window_get_geometry_info (window, TRUE);
7426 info->mask |= GDK_HINT_USER_POS;
7428 info->mask |= GDK_HINT_USER_SIZE;
7435 gtk_window_mnemonic_hash_foreach (guint keyval,
7441 GtkWindowKeysForeachFunc func;
7445 (*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
7449 _gtk_window_keys_foreach (GtkWindow *window,
7450 GtkWindowKeysForeachFunc func,
7454 GtkMnemonicHash *mnemonic_hash;
7458 GtkWindowKeysForeachFunc func;
7462 info.window = window;
7464 info.func_data = func_data;
7466 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
7468 _gtk_mnemonic_hash_foreach (mnemonic_hash,
7469 gtk_window_mnemonic_hash_foreach, &info);
7471 groups = gtk_accel_groups_from_object (G_OBJECT (window));
7474 GtkAccelGroup *group = groups->data;
7477 for (i = 0; i < group->n_accels; i++)
7479 GtkAccelKey *key = &group->priv_accels[i].key;
7482 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
7485 groups = groups->next;
7490 gtk_window_keys_changed (GtkWindow *window)
7492 gtk_window_free_key_hash (window);
7493 gtk_window_get_key_hash (window);
7496 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
7498 struct _GtkWindowKeyEntry
7502 guint is_mnemonic : 1;
7506 window_key_entry_destroy (gpointer data)
7508 g_slice_free (GtkWindowKeyEntry, data);
7512 add_to_key_hash (GtkWindow *window,
7514 GdkModifierType modifiers,
7515 gboolean is_mnemonic,
7518 GtkKeyHash *key_hash = data;
7520 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
7522 entry->keyval = keyval;
7523 entry->modifiers = modifiers;
7524 entry->is_mnemonic = is_mnemonic;
7526 /* GtkAccelGroup stores lowercased accelerators. To deal
7527 * with this, if <Shift> was specified, uppercase.
7529 if (modifiers & GDK_SHIFT_MASK)
7531 if (keyval == GDK_Tab)
7532 keyval = GDK_ISO_Left_Tab;
7534 keyval = gdk_keyval_to_upper (keyval);
7537 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
7541 gtk_window_get_key_hash (GtkWindow *window)
7543 GdkScreen *screen = gtk_window_check_screen (window);
7544 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7549 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
7550 (GDestroyNotify)window_key_entry_destroy);
7551 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
7552 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
7558 gtk_window_free_key_hash (GtkWindow *window)
7560 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7563 _gtk_key_hash_free (key_hash);
7564 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
7569 * gtk_window_activate_key:
7570 * @window: a #GtkWindow
7571 * @event: a #GdkEventKey
7573 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
7574 * called by the default ::key_press_event handler for toplevel windows,
7575 * however in some cases it may be useful to call this directly when
7576 * overriding the standard key handling for a toplevel window.
7578 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
7581 gtk_window_activate_key (GtkWindow *window,
7584 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7585 GtkWindowKeyEntry *found_entry = NULL;
7589 gtk_window_keys_changed (window);
7590 key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7595 GSList *entries = _gtk_key_hash_lookup (key_hash,
7596 event->hardware_keycode,
7598 gtk_accelerator_get_default_mod_mask (),
7602 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
7604 GtkWindowKeyEntry *entry = tmp_list->data;
7605 if (entry->is_mnemonic)
7607 found_entry = entry;
7612 if (!found_entry && entries)
7613 found_entry = entries->data;
7615 g_slist_free (entries);
7620 if (found_entry->is_mnemonic)
7621 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
7623 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
7630 window_update_has_focus (GtkWindow *window)
7632 GtkWidget *widget = GTK_WIDGET (window);
7633 gboolean has_focus = window->has_toplevel_focus && window->is_active;
7635 if (has_focus != window->has_focus)
7637 window->has_focus = has_focus;
7641 if (window->focus_widget &&
7642 window->focus_widget != widget &&
7643 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7644 do_focus_change (window->focus_widget, TRUE);
7648 if (window->focus_widget &&
7649 window->focus_widget != widget &&
7650 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7651 do_focus_change (window->focus_widget, FALSE);
7657 * _gtk_window_set_is_active:
7658 * @window: a #GtkWindow
7659 * @is_active: %TRUE if the window is in the currently active toplevel
7661 * Internal function that sets whether the #GtkWindow is part
7662 * of the currently active toplevel window (taking into account inter-process
7666 _gtk_window_set_is_active (GtkWindow *window,
7669 g_return_if_fail (GTK_IS_WINDOW (window));
7671 is_active = is_active != FALSE;
7673 if (is_active != window->is_active)
7675 window->is_active = is_active;
7676 window_update_has_focus (window);
7678 g_object_notify (G_OBJECT (window), "is-active");
7683 * _gtk_window_set_has_toplevel_focus:
7684 * @window: a #GtkWindow
7685 * @has_toplevel_focus: %TRUE if the in
7687 * Internal function that sets whether the keyboard focus for the
7688 * toplevel window (taking into account inter-process embedding.)
7691 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
7692 gboolean has_toplevel_focus)
7694 g_return_if_fail (GTK_IS_WINDOW (window));
7696 has_toplevel_focus = has_toplevel_focus != FALSE;
7698 if (has_toplevel_focus != window->has_toplevel_focus)
7700 window->has_toplevel_focus = has_toplevel_focus;
7701 window_update_has_focus (window);
7703 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
7708 * gtk_window_set_auto_startup_notification:
7709 * @setting: %TRUE to automatically do startup notification
7711 * By default, after showing the first #GtkWindow, GTK+ calls
7712 * gdk_notify_startup_complete(). Call this function to disable
7713 * the automatic startup notification. You might do this if your
7714 * first window is a splash screen, and you want to delay notification
7715 * until after your real main window has been shown, for example.
7717 * In that example, you would disable startup notification
7718 * temporarily, show your splash screen, then re-enable it so that
7719 * showing the main window would automatically result in notification.
7724 gtk_window_set_auto_startup_notification (gboolean setting)
7726 disable_startup_notification = !setting;
7731 #undef gtk_window_set_icon_from_file
7734 gtk_window_set_icon_from_file (GtkWindow *window,
7735 const gchar *filename,
7738 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
7741 if (utf8_filename == NULL)
7744 retval = gtk_window_set_icon_from_file_utf8 (window, utf8_filename, err);
7746 g_free (utf8_filename);
7751 #undef gtk_window_set_default_icon_from_file
7754 gtk_window_set_default_icon_from_file (const gchar *filename,
7757 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
7760 if (utf8_filename == NULL)
7763 retval = gtk_window_set_default_icon_from_file_utf8 (utf8_filename, err);
7765 g_free (utf8_filename);
7772 #define __GTK_WINDOW_C__
7773 #include "gtkaliasdef.c"