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 void gtk_window_set_property (GObject *object,
296 static void gtk_window_get_property (GObject *object,
303 gtk_window_get_type (void)
305 static GType window_type = 0;
309 static const GTypeInfo window_info =
311 sizeof (GtkWindowClass),
312 NULL, /* base_init */
313 NULL, /* base_finalize */
314 (GClassInitFunc) gtk_window_class_init,
315 NULL, /* class_finalize */
316 NULL, /* class_data */
319 (GInstanceInitFunc) gtk_window_init,
322 window_type = g_type_register_static (GTK_TYPE_BIN, I_("GtkWindow"),
330 add_tab_bindings (GtkBindingSet *binding_set,
331 GdkModifierType modifiers,
332 GtkDirectionType direction)
334 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
336 GTK_TYPE_DIRECTION_TYPE, direction);
337 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
339 GTK_TYPE_DIRECTION_TYPE, direction);
343 add_arrow_bindings (GtkBindingSet *binding_set,
345 GtkDirectionType direction)
347 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
349 gtk_binding_entry_add_signal (binding_set, keysym, 0,
351 GTK_TYPE_DIRECTION_TYPE, direction);
352 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
354 GTK_TYPE_DIRECTION_TYPE, direction);
355 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
357 GTK_TYPE_DIRECTION_TYPE, direction);
358 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
360 GTK_TYPE_DIRECTION_TYPE, direction);
365 gtk_window_class_init (GtkWindowClass *klass)
367 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
368 GtkObjectClass *object_class;
369 GtkWidgetClass *widget_class;
370 GtkContainerClass *container_class;
371 GtkBindingSet *binding_set;
373 object_class = (GtkObjectClass*) klass;
374 widget_class = (GtkWidgetClass*) klass;
375 container_class = (GtkContainerClass*) klass;
377 parent_class = g_type_class_peek_parent (klass);
379 gobject_class->dispose = gtk_window_dispose;
380 gobject_class->finalize = gtk_window_finalize;
382 gobject_class->set_property = gtk_window_set_property;
383 gobject_class->get_property = gtk_window_get_property;
385 object_class->destroy = gtk_window_destroy;
387 widget_class->show = gtk_window_show;
388 widget_class->hide = gtk_window_hide;
389 widget_class->map = gtk_window_map;
390 widget_class->map_event = gtk_window_map_event;
391 widget_class->unmap = gtk_window_unmap;
392 widget_class->realize = gtk_window_realize;
393 widget_class->unrealize = gtk_window_unrealize;
394 widget_class->size_request = gtk_window_size_request;
395 widget_class->size_allocate = gtk_window_size_allocate;
396 widget_class->configure_event = gtk_window_configure_event;
397 widget_class->key_press_event = gtk_window_key_press_event;
398 widget_class->key_release_event = gtk_window_key_release_event;
399 widget_class->enter_notify_event = gtk_window_enter_notify_event;
400 widget_class->leave_notify_event = gtk_window_leave_notify_event;
401 widget_class->focus_in_event = gtk_window_focus_in_event;
402 widget_class->focus_out_event = gtk_window_focus_out_event;
403 widget_class->client_event = gtk_window_client_event;
404 widget_class->focus = gtk_window_focus;
406 widget_class->expose_event = gtk_window_expose;
408 container_class->check_resize = gtk_window_check_resize;
410 klass->set_focus = gtk_window_real_set_focus;
411 klass->frame_event = gtk_window_frame_event;
413 klass->activate_default = gtk_window_real_activate_default;
414 klass->activate_focus = gtk_window_real_activate_focus;
415 klass->move_focus = gtk_window_move_focus;
416 klass->keys_changed = gtk_window_keys_changed;
418 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
421 g_object_class_install_property (gobject_class,
423 g_param_spec_enum ("type",
425 P_("The type of the window"),
426 GTK_TYPE_WINDOW_TYPE,
428 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
430 g_object_class_install_property (gobject_class,
432 g_param_spec_string ("title",
434 P_("The title of the window"),
436 GTK_PARAM_READWRITE));
438 g_object_class_install_property (gobject_class,
440 g_param_spec_string ("role",
442 P_("Unique identifier for the window to be used when restoring a session"),
444 GTK_PARAM_READWRITE));
446 g_object_class_install_property (gobject_class,
448 g_param_spec_boolean ("allow-shrink",
450 /* xgettext:no-c-format */
451 P_("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
453 GTK_PARAM_READWRITE));
455 g_object_class_install_property (gobject_class,
457 g_param_spec_boolean ("allow-grow",
459 P_("If TRUE, users can expand the window beyond its minimum size"),
461 GTK_PARAM_READWRITE));
463 g_object_class_install_property (gobject_class,
465 g_param_spec_boolean ("resizable",
467 P_("If TRUE, users can resize the window"),
469 GTK_PARAM_READWRITE));
471 g_object_class_install_property (gobject_class,
473 g_param_spec_boolean ("modal",
475 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
477 GTK_PARAM_READWRITE));
479 g_object_class_install_property (gobject_class,
481 g_param_spec_enum ("window-position",
482 P_("Window Position"),
483 P_("The initial position of the window"),
484 GTK_TYPE_WINDOW_POSITION,
486 GTK_PARAM_READWRITE));
488 g_object_class_install_property (gobject_class,
490 g_param_spec_int ("default-width",
492 P_("The default width of the window, used when initially showing the window"),
496 GTK_PARAM_READWRITE));
498 g_object_class_install_property (gobject_class,
500 g_param_spec_int ("default-height",
501 P_("Default Height"),
502 P_("The default height of the window, used when initially showing the window"),
506 GTK_PARAM_READWRITE));
508 g_object_class_install_property (gobject_class,
509 PROP_DESTROY_WITH_PARENT,
510 g_param_spec_boolean ("destroy-with-parent",
511 P_("Destroy with Parent"),
512 P_("If this window should be destroyed when the parent is destroyed"),
514 GTK_PARAM_READWRITE));
516 g_object_class_install_property (gobject_class,
518 g_param_spec_object ("icon",
520 P_("Icon for this window"),
522 GTK_PARAM_READWRITE));
525 * GtkWindow:icon-name:
527 * The :icon-name property specifies the name of the themed icon to
528 * use as the window icon. See #GtkIconTheme for more details.
532 g_object_class_install_property (gobject_class,
534 g_param_spec_string ("icon-name",
536 P_("Name of the themed icon for this window"),
538 GTK_PARAM_READWRITE));
540 g_object_class_install_property (gobject_class,
542 g_param_spec_object ("screen",
544 P_("The screen where this window will be displayed"),
546 GTK_PARAM_READWRITE));
548 g_object_class_install_property (gobject_class,
550 g_param_spec_boolean ("is-active",
552 P_("Whether the toplevel is the current active window"),
554 GTK_PARAM_READABLE));
556 g_object_class_install_property (gobject_class,
557 PROP_HAS_TOPLEVEL_FOCUS,
558 g_param_spec_boolean ("has-toplevel-focus",
559 P_("Focus in Toplevel"),
560 P_("Whether the input focus is within this GtkWindow"),
562 GTK_PARAM_READABLE));
564 g_object_class_install_property (gobject_class,
566 g_param_spec_enum ("type-hint",
568 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
569 GDK_TYPE_WINDOW_TYPE_HINT,
570 GDK_WINDOW_TYPE_HINT_NORMAL,
571 GTK_PARAM_READWRITE));
573 g_object_class_install_property (gobject_class,
574 PROP_SKIP_TASKBAR_HINT,
575 g_param_spec_boolean ("skip-taskbar-hint",
577 P_("TRUE if the window should not be in the task bar."),
579 GTK_PARAM_READWRITE));
581 g_object_class_install_property (gobject_class,
582 PROP_SKIP_PAGER_HINT,
583 g_param_spec_boolean ("skip-pager-hint",
585 P_("TRUE if the window should not be in the pager."),
587 GTK_PARAM_READWRITE));
589 g_object_class_install_property (gobject_class,
591 g_param_spec_boolean ("urgency-hint",
593 P_("TRUE if the window should be brought to the user's attention."),
595 GTK_PARAM_READWRITE));
598 * GtkWindow:accept-focus-hint:
600 * Whether the window should receive the input focus.
604 g_object_class_install_property (gobject_class,
606 g_param_spec_boolean ("accept-focus",
608 P_("TRUE if the window should receive the input focus."),
610 GTK_PARAM_READWRITE));
613 * GtkWindow:focus-on-map-hint:
615 * Whether the window should receive the input focus when mapped.
619 g_object_class_install_property (gobject_class,
621 g_param_spec_boolean ("focus-on-map",
623 P_("TRUE if the window should receive the input focus when mapped."),
625 GTK_PARAM_READWRITE));
628 * GtkWindow:decorated:
630 * Whether the window should be decorated by the window manager.
634 g_object_class_install_property (gobject_class,
636 g_param_spec_boolean ("decorated",
638 P_("Whether the window should be decorated by the window manager"),
640 GTK_PARAM_READWRITE));
643 * GtkWindow:deletable:
645 * Whether the window frame should have a close button.
649 g_object_class_install_property (gobject_class,
651 g_param_spec_boolean ("deletable",
653 P_("Whether the window frame should have a close button"),
655 GTK_PARAM_READWRITE));
661 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
662 * more details about window gravity.
666 g_object_class_install_property (gobject_class,
668 g_param_spec_enum ("gravity",
670 P_("The window gravity of the window"),
672 GDK_GRAVITY_NORTH_WEST,
673 GTK_PARAM_READWRITE));
675 window_signals[SET_FOCUS] =
676 g_signal_new (I_("set_focus"),
677 G_TYPE_FROM_CLASS (gobject_class),
679 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
681 _gtk_marshal_VOID__OBJECT,
685 window_signals[FRAME_EVENT] =
686 g_signal_new (I_("frame_event"),
687 G_TYPE_FROM_CLASS (gobject_class),
689 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
690 _gtk_boolean_handled_accumulator, NULL,
691 _gtk_marshal_BOOLEAN__BOXED,
695 window_signals[ACTIVATE_FOCUS] =
696 g_signal_new (I_("activate_focus"),
697 G_TYPE_FROM_CLASS (gobject_class),
698 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
699 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
701 _gtk_marshal_VOID__VOID,
705 window_signals[ACTIVATE_DEFAULT] =
706 g_signal_new (I_("activate_default"),
707 G_TYPE_FROM_CLASS (gobject_class),
708 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
709 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
711 _gtk_marshal_VOID__VOID,
715 window_signals[MOVE_FOCUS] =
716 g_signal_new (I_("move_focus"),
717 G_TYPE_FROM_CLASS (gobject_class),
718 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
719 G_STRUCT_OFFSET (GtkWindowClass, move_focus),
721 _gtk_marshal_VOID__ENUM,
724 GTK_TYPE_DIRECTION_TYPE);
726 window_signals[KEYS_CHANGED] =
727 g_signal_new (I_("keys_changed"),
728 G_TYPE_FROM_CLASS (gobject_class),
730 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
732 _gtk_marshal_VOID__VOID,
740 binding_set = gtk_binding_set_by_class (klass);
742 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
743 "activate_focus", 0);
744 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
745 "activate_focus", 0);
747 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
748 "activate_default", 0);
750 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
751 "activate_default", 0);
753 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
754 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
755 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
756 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
758 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
759 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
760 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
761 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
765 gtk_window_init (GtkWindow *window)
767 GdkColormap *colormap;
768 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
770 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
771 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
773 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
775 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
777 window->title = NULL;
778 window->wmclass_name = g_strdup (g_get_prgname ());
779 window->wmclass_class = g_strdup (gdk_get_program_class ());
780 window->wm_role = NULL;
781 window->geometry_info = NULL;
782 window->type = GTK_WINDOW_TOPLEVEL;
783 window->focus_widget = NULL;
784 window->default_widget = NULL;
785 window->configure_request_count = 0;
786 window->allow_shrink = FALSE;
787 window->allow_grow = TRUE;
788 window->configure_notify_received = FALSE;
789 window->position = GTK_WIN_POS_NONE;
790 window->need_default_size = TRUE;
791 window->need_default_position = TRUE;
792 window->modal = FALSE;
793 window->frame = NULL;
794 window->has_frame = FALSE;
795 window->frame_left = 0;
796 window->frame_right = 0;
797 window->frame_top = 0;
798 window->frame_bottom = 0;
799 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
800 window->gravity = GDK_GRAVITY_NORTH_WEST;
801 window->decorated = TRUE;
802 window->mnemonic_modifier = GDK_MOD1_MASK;
803 window->screen = gdk_screen_get_default ();
805 priv->accept_focus = TRUE;
806 priv->focus_on_map = TRUE;
807 priv->deletable = TRUE;
809 colormap = _gtk_widget_peek_colormap ();
811 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
813 g_object_ref_sink (window);
814 window->has_user_ref_count = TRUE;
815 toplevel_list = g_slist_prepend (toplevel_list, window);
817 gtk_decorated_window_init (window);
819 g_signal_connect (window,
821 G_CALLBACK (gtk_window_event),
826 gtk_window_set_property (GObject *object,
833 window = GTK_WINDOW (object);
838 window->type = g_value_get_enum (value);
841 gtk_window_set_title (window, g_value_get_string (value));
844 gtk_window_set_role (window, g_value_get_string (value));
846 case PROP_ALLOW_SHRINK:
847 window->allow_shrink = g_value_get_boolean (value);
848 gtk_widget_queue_resize (GTK_WIDGET (window));
850 case PROP_ALLOW_GROW:
851 window->allow_grow = g_value_get_boolean (value);
852 gtk_widget_queue_resize (GTK_WIDGET (window));
853 g_object_notify (G_OBJECT (window), "resizable");
856 window->allow_grow = g_value_get_boolean (value);
857 gtk_widget_queue_resize (GTK_WIDGET (window));
858 g_object_notify (G_OBJECT (window), "allow-grow");
861 gtk_window_set_modal (window, g_value_get_boolean (value));
864 gtk_window_set_position (window, g_value_get_enum (value));
866 case PROP_DEFAULT_WIDTH:
867 gtk_window_set_default_size_internal (window,
868 TRUE, g_value_get_int (value),
871 case PROP_DEFAULT_HEIGHT:
872 gtk_window_set_default_size_internal (window,
874 TRUE, g_value_get_int (value), FALSE);
876 case PROP_DESTROY_WITH_PARENT:
877 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
880 gtk_window_set_icon (window,
881 g_value_get_object (value));
884 gtk_window_set_icon_name (window, g_value_get_string (value));
887 gtk_window_set_screen (window, g_value_get_object (value));
890 gtk_window_set_type_hint (window,
891 g_value_get_enum (value));
893 case PROP_SKIP_TASKBAR_HINT:
894 gtk_window_set_skip_taskbar_hint (window,
895 g_value_get_boolean (value));
897 case PROP_SKIP_PAGER_HINT:
898 gtk_window_set_skip_pager_hint (window,
899 g_value_get_boolean (value));
901 case PROP_URGENCY_HINT:
902 gtk_window_set_urgency_hint (window,
903 g_value_get_boolean (value));
905 case PROP_ACCEPT_FOCUS:
906 gtk_window_set_accept_focus (window,
907 g_value_get_boolean (value));
909 case PROP_FOCUS_ON_MAP:
910 gtk_window_set_focus_on_map (window,
911 g_value_get_boolean (value));
914 gtk_window_set_decorated (window, g_value_get_boolean (value));
917 gtk_window_set_deletable (window, g_value_get_boolean (value));
920 gtk_window_set_gravity (window, g_value_get_enum (value));
928 gtk_window_get_property (GObject *object,
935 window = GTK_WINDOW (object);
939 GtkWindowGeometryInfo *info;
941 g_value_set_enum (value, window->type);
944 g_value_set_string (value, window->wm_role);
947 g_value_set_string (value, window->title);
949 case PROP_ALLOW_SHRINK:
950 g_value_set_boolean (value, window->allow_shrink);
952 case PROP_ALLOW_GROW:
953 g_value_set_boolean (value, window->allow_grow);
956 g_value_set_boolean (value, window->allow_grow);
959 g_value_set_boolean (value, window->modal);
962 g_value_set_enum (value, window->position);
964 case PROP_DEFAULT_WIDTH:
965 info = gtk_window_get_geometry_info (window, FALSE);
967 g_value_set_int (value, -1);
969 g_value_set_int (value, info->default_width);
971 case PROP_DEFAULT_HEIGHT:
972 info = gtk_window_get_geometry_info (window, FALSE);
974 g_value_set_int (value, -1);
976 g_value_set_int (value, info->default_height);
978 case PROP_DESTROY_WITH_PARENT:
979 g_value_set_boolean (value, window->destroy_with_parent);
982 g_value_set_object (value, gtk_window_get_icon (window));
985 g_value_set_string (value, gtk_window_get_icon_name (window));
988 g_value_set_object (value, window->screen);
991 g_value_set_boolean (value, window->is_active);
993 case PROP_HAS_TOPLEVEL_FOCUS:
994 g_value_set_boolean (value, window->has_toplevel_focus);
997 g_value_set_enum (value,
1000 case PROP_SKIP_TASKBAR_HINT:
1001 g_value_set_boolean (value,
1002 gtk_window_get_skip_taskbar_hint (window));
1004 case PROP_SKIP_PAGER_HINT:
1005 g_value_set_boolean (value,
1006 gtk_window_get_skip_pager_hint (window));
1008 case PROP_URGENCY_HINT:
1009 g_value_set_boolean (value,
1010 gtk_window_get_urgency_hint (window));
1012 case PROP_ACCEPT_FOCUS:
1013 g_value_set_boolean (value,
1014 gtk_window_get_accept_focus (window));
1016 case PROP_FOCUS_ON_MAP:
1017 g_value_set_boolean (value,
1018 gtk_window_get_focus_on_map (window));
1020 case PROP_DECORATED:
1021 g_value_set_boolean (value, gtk_window_get_decorated (window));
1023 case PROP_DELETABLE:
1024 g_value_set_boolean (value, gtk_window_get_deletable (window));
1027 g_value_set_enum (value, gtk_window_get_gravity (window));
1030 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1037 * @type: type of window
1039 * Creates a new #GtkWindow, which is a toplevel window that can
1040 * contain other widgets. Nearly always, the type of the window should
1041 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1042 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1043 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1044 * dialogs, though in some other toolkits dialogs are called "popups".
1045 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1046 * On X11, popup windows are not controlled by the <link
1047 * linkend="gtk-X11-arch">window manager</link>.
1049 * If you simply want an undecorated window (no window borders), use
1050 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1052 * Return value: a new #GtkWindow.
1055 gtk_window_new (GtkWindowType type)
1059 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1061 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1063 window->type = type;
1065 return GTK_WIDGET (window);
1069 * gtk_window_set_title:
1070 * @window: a #GtkWindow
1071 * @title: title of the window
1073 * Sets the title of the #GtkWindow. The title of a window will be
1074 * displayed in its title bar; on the X Window System, the title bar
1075 * is rendered by the <link linkend="gtk-X11-arch">window
1076 * manager</link>, so exactly how the title appears to users may vary
1077 * according to a user's exact configuration. The title should help a
1078 * user distinguish this window from other windows they may have
1079 * open. A good title might include the application name and current
1080 * document filename, for example.
1084 gtk_window_set_title (GtkWindow *window,
1089 g_return_if_fail (GTK_IS_WINDOW (window));
1091 new_title = g_strdup (title);
1092 g_free (window->title);
1093 window->title = new_title;
1095 if (GTK_WIDGET_REALIZED (window))
1097 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
1099 gtk_decorated_window_set_title (window, title);
1102 g_object_notify (G_OBJECT (window), "title");
1106 * gtk_window_get_title:
1107 * @window: a #GtkWindow
1109 * Retrieves the title of the window. See gtk_window_set_title().
1111 * Return value: the title of the window, or %NULL if none has
1112 * been set explicitely. The returned string is owned by the widget
1113 * and must not be modified or freed.
1115 G_CONST_RETURN gchar *
1116 gtk_window_get_title (GtkWindow *window)
1118 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1120 return window->title;
1124 * gtk_window_set_wmclass:
1125 * @window: a #GtkWindow
1126 * @wmclass_name: window name hint
1127 * @wmclass_class: window class hint
1129 * Don't use this function. It sets the X Window System "class" and
1130 * "name" hints for a window. According to the ICCCM, you should
1131 * always set these to the same value for all windows in an
1132 * application, and GTK+ sets them to that value by default, so calling
1133 * this function is sort of pointless. However, you may want to call
1134 * gtk_window_set_role() on each window in your application, for the
1135 * benefit of the session manager. Setting the role allows the window
1136 * manager to restore window positions when loading a saved session.
1140 gtk_window_set_wmclass (GtkWindow *window,
1141 const gchar *wmclass_name,
1142 const gchar *wmclass_class)
1144 g_return_if_fail (GTK_IS_WINDOW (window));
1146 g_free (window->wmclass_name);
1147 window->wmclass_name = g_strdup (wmclass_name);
1149 g_free (window->wmclass_class);
1150 window->wmclass_class = g_strdup (wmclass_class);
1152 if (GTK_WIDGET_REALIZED (window))
1153 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1157 * gtk_window_set_role:
1158 * @window: a #GtkWindow
1159 * @role: unique identifier for the window to be used when restoring a session
1161 * This function is only useful on X11, not with other GTK+ targets.
1163 * In combination with the window title, the window role allows a
1164 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1165 * same" window when an application is restarted. So for example you
1166 * might set the "toolbox" role on your app's toolbox window, so that
1167 * when the user restarts their session, the window manager can put
1168 * the toolbox back in the same place.
1170 * If a window already has a unique title, you don't need to set the
1171 * role, since the WM can use the title to identify the window when
1172 * restoring the session.
1176 gtk_window_set_role (GtkWindow *window,
1181 g_return_if_fail (GTK_IS_WINDOW (window));
1183 new_role = g_strdup (role);
1184 g_free (window->wm_role);
1185 window->wm_role = new_role;
1187 if (GTK_WIDGET_REALIZED (window))
1188 gdk_window_set_role (GTK_WIDGET (window)->window, window->wm_role);
1190 g_object_notify (G_OBJECT (window), "role");
1194 * gtk_window_get_role:
1195 * @window: a #GtkWindow
1197 * Returns the role of the window. See gtk_window_set_role() for
1198 * further explanation.
1200 * Return value: the role of the window if set, or %NULL. The
1201 * returned is owned by the widget and must not be modified
1204 G_CONST_RETURN gchar *
1205 gtk_window_get_role (GtkWindow *window)
1207 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1209 return window->wm_role;
1213 * gtk_window_set_focus:
1214 * @window: a #GtkWindow
1215 * @focus: widget to be the new focus widget, or %NULL to unset
1216 * any focus widget for the toplevel window.
1218 * If @focus is not the current focus widget, and is focusable, sets
1219 * it as the focus widget for the window. If @focus is %NULL, unsets
1220 * the focus widget for this window. To set the focus to a particular
1221 * widget in the toplevel, it is usually more convenient to use
1222 * gtk_widget_grab_focus() instead of this function.
1225 gtk_window_set_focus (GtkWindow *window,
1228 g_return_if_fail (GTK_IS_WINDOW (window));
1231 g_return_if_fail (GTK_IS_WIDGET (focus));
1232 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1236 gtk_widget_grab_focus (focus);
1239 /* Clear the existing focus chain, so that when we focus into
1240 * the window again, we start at the beginnning.
1242 GtkWidget *widget = window->focus_widget;
1245 while (widget->parent)
1247 widget = widget->parent;
1248 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1252 _gtk_window_internal_set_focus (window, NULL);
1257 _gtk_window_internal_set_focus (GtkWindow *window,
1260 g_return_if_fail (GTK_IS_WINDOW (window));
1262 if ((window->focus_widget != focus) ||
1263 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1264 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1268 * gtk_window_set_default:
1269 * @window: a #GtkWindow
1270 * @default_widget: widget to be the default, or %NULL to unset the
1271 * default widget for the toplevel.
1273 * The default widget is the widget that's activated when the user
1274 * presses Enter in a dialog (for example). This function sets or
1275 * unsets the default widget for a #GtkWindow about. When setting
1276 * (rather than unsetting) the default widget it's generally easier to
1277 * call gtk_widget_grab_focus() on the widget. Before making a widget
1278 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1279 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1282 gtk_window_set_default (GtkWindow *window,
1283 GtkWidget *default_widget)
1285 g_return_if_fail (GTK_IS_WINDOW (window));
1288 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1290 if (window->default_widget != default_widget)
1292 GtkWidget *old_default_widget = NULL;
1295 g_object_ref (default_widget);
1297 if (window->default_widget)
1299 old_default_widget = window->default_widget;
1301 if (window->focus_widget != window->default_widget ||
1302 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1303 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1304 gtk_widget_queue_draw (window->default_widget);
1307 window->default_widget = default_widget;
1309 if (window->default_widget)
1311 if (window->focus_widget == NULL ||
1312 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1313 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1314 gtk_widget_queue_draw (window->default_widget);
1317 if (old_default_widget)
1318 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1322 g_object_notify (G_OBJECT (default_widget), "has-default");
1323 g_object_unref (default_widget);
1329 gtk_window_set_policy (GtkWindow *window,
1330 gboolean allow_shrink,
1331 gboolean allow_grow,
1332 gboolean auto_shrink)
1334 g_return_if_fail (GTK_IS_WINDOW (window));
1336 window->allow_shrink = (allow_shrink != FALSE);
1337 window->allow_grow = (allow_grow != FALSE);
1339 g_object_freeze_notify (G_OBJECT (window));
1340 g_object_notify (G_OBJECT (window), "allow-shrink");
1341 g_object_notify (G_OBJECT (window), "allow-grow");
1342 g_object_notify (G_OBJECT (window), "resizable");
1343 g_object_thaw_notify (G_OBJECT (window));
1345 gtk_widget_queue_resize (GTK_WIDGET (window));
1349 handle_keys_changed (gpointer data)
1353 GDK_THREADS_ENTER ();
1354 window = GTK_WINDOW (data);
1356 if (window->keys_changed_handler)
1358 g_source_remove (window->keys_changed_handler);
1359 window->keys_changed_handler = 0;
1362 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1363 GDK_THREADS_LEAVE ();
1369 gtk_window_notify_keys_changed (GtkWindow *window)
1371 if (!window->keys_changed_handler)
1372 window->keys_changed_handler = g_idle_add (handle_keys_changed, window);
1376 * gtk_window_add_accel_group:
1377 * @window: window to attach accelerator group to
1378 * @accel_group: a #GtkAccelGroup
1380 * Associate @accel_group with @window, such that calling
1381 * gtk_accel_groups_activate() on @window will activate accelerators
1385 gtk_window_add_accel_group (GtkWindow *window,
1386 GtkAccelGroup *accel_group)
1388 g_return_if_fail (GTK_IS_WINDOW (window));
1389 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1391 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1392 g_signal_connect_object (accel_group, "accel_changed",
1393 G_CALLBACK (gtk_window_notify_keys_changed),
1394 window, G_CONNECT_SWAPPED);
1398 * gtk_window_remove_accel_group:
1399 * @window: a #GtkWindow
1400 * @accel_group: a #GtkAccelGroup
1402 * Reverses the effects of gtk_window_add_accel_group().
1405 gtk_window_remove_accel_group (GtkWindow *window,
1406 GtkAccelGroup *accel_group)
1408 g_return_if_fail (GTK_IS_WINDOW (window));
1409 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1411 g_signal_handlers_disconnect_by_func (accel_group,
1412 gtk_window_notify_keys_changed,
1414 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1417 static GtkMnemonicHash *
1418 gtk_window_get_mnemonic_hash (GtkWindow *window,
1421 GtkWindowPrivate *private = GTK_WINDOW_GET_PRIVATE (window);
1422 if (!private->mnemonic_hash && create)
1423 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1425 return private->mnemonic_hash;
1429 * gtk_window_add_mnemonic:
1430 * @window: a #GtkWindow
1431 * @keyval: the mnemonic
1432 * @target: the widget that gets activated by the mnemonic
1434 * Adds a mnemonic to this window.
1437 gtk_window_add_mnemonic (GtkWindow *window,
1441 g_return_if_fail (GTK_IS_WINDOW (window));
1442 g_return_if_fail (GTK_IS_WIDGET (target));
1444 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1446 gtk_window_notify_keys_changed (window);
1450 * gtk_window_remove_mnemonic:
1451 * @window: a #GtkWindow
1452 * @keyval: the mnemonic
1453 * @target: the widget that gets activated by the mnemonic
1455 * Removes a mnemonic from this window.
1458 gtk_window_remove_mnemonic (GtkWindow *window,
1462 g_return_if_fail (GTK_IS_WINDOW (window));
1463 g_return_if_fail (GTK_IS_WIDGET (target));
1465 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
1467 gtk_window_notify_keys_changed (window);
1471 * gtk_window_mnemonic_activate:
1472 * @window: a #GtkWindow
1473 * @keyval: the mnemonic
1474 * @modifier: the modifiers
1475 * @returns: %TRUE if the activation is done.
1477 * Activates the targets associated with the mnemonic.
1480 gtk_window_mnemonic_activate (GtkWindow *window,
1482 GdkModifierType modifier)
1484 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1486 if (window->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
1488 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
1490 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
1497 * gtk_window_set_mnemonic_modifier:
1498 * @window: a #GtkWindow
1499 * @modifier: the modifier mask used to activate
1500 * mnemonics on this window.
1502 * Sets the mnemonic modifier for this window.
1505 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1506 GdkModifierType modifier)
1508 g_return_if_fail (GTK_IS_WINDOW (window));
1509 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1511 window->mnemonic_modifier = modifier;
1512 gtk_window_notify_keys_changed (window);
1516 * gtk_window_get_mnemonic_modifier:
1517 * @window: a #GtkWindow
1519 * Returns the mnemonic modifier for this window. See
1520 * gtk_window_set_mnemonic_modifier().
1522 * Return value: the modifier mask used to activate
1523 * mnemonics on this window.
1526 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1528 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1530 return window->mnemonic_modifier;
1534 * gtk_window_set_position:
1535 * @window: a #GtkWindow.
1536 * @position: a position constraint.
1538 * Sets a position constraint for this window. If the old or new
1539 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1540 * the window to be repositioned to satisfy the new constraint.
1543 gtk_window_set_position (GtkWindow *window,
1544 GtkWindowPosition position)
1546 g_return_if_fail (GTK_IS_WINDOW (window));
1548 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1549 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1551 GtkWindowGeometryInfo *info;
1553 info = gtk_window_get_geometry_info (window, TRUE);
1555 /* this flag causes us to re-request the CENTER_ALWAYS
1556 * constraint in gtk_window_move_resize(), see
1557 * comment in that function.
1559 info->position_constraints_changed = TRUE;
1561 gtk_widget_queue_resize (GTK_WIDGET (window));
1564 window->position = position;
1566 g_object_notify (G_OBJECT (window), "window-position");
1570 * gtk_window_activate_focus:
1571 * @window: a #GtkWindow
1573 * Activates the current focused widget within the window.
1575 * Return value: %TRUE if a widget got activated.
1578 gtk_window_activate_focus (GtkWindow *window)
1580 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1582 if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1583 return gtk_widget_activate (window->focus_widget);
1589 * gtk_window_get_focus:
1590 * @window: a #GtkWindow
1592 * Retrieves the current focused widget within the window.
1593 * Note that this is the widget that would have the focus
1594 * if the toplevel window focused; if the toplevel window
1595 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1596 * not be %TRUE for the widget.
1598 * Return value: the currently focused widget, or %NULL if there is none.
1601 gtk_window_get_focus (GtkWindow *window)
1603 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1605 return window->focus_widget;
1609 * gtk_window_activate_default:
1610 * @window: a #GtkWindow
1612 * Activates the default widget for the window, unless the current
1613 * focused widget has been configured to receive the default action
1614 * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
1615 * focused widget is activated.
1617 * Return value: %TRUE if a widget got activated.
1620 gtk_window_activate_default (GtkWindow *window)
1622 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1624 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1625 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1626 return gtk_widget_activate (window->default_widget);
1627 else if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1628 return gtk_widget_activate (window->focus_widget);
1634 * gtk_window_set_modal:
1635 * @window: a #GtkWindow
1636 * @modal: whether the window is modal
1638 * Sets a window modal or non-modal. Modal windows prevent interaction
1639 * with other windows in the same application. To keep modal dialogs
1640 * on top of main application windows, use
1641 * gtk_window_set_transient_for() to make the dialog transient for the
1642 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1643 * will then disallow lowering the dialog below the parent.
1648 gtk_window_set_modal (GtkWindow *window,
1651 g_return_if_fail (GTK_IS_WINDOW (window));
1653 modal = modal != FALSE;
1654 if (window->modal == modal)
1657 window->modal = modal;
1659 /* adjust desired modality state */
1660 if (GTK_WIDGET_REALIZED (window))
1662 GtkWidget *widget = GTK_WIDGET (window);
1665 gdk_window_set_modal_hint (widget->window, TRUE);
1667 gdk_window_set_modal_hint (widget->window, FALSE);
1670 if (GTK_WIDGET_VISIBLE (window))
1673 gtk_grab_add (GTK_WIDGET (window));
1675 gtk_grab_remove (GTK_WIDGET (window));
1678 g_object_notify (G_OBJECT (window), "modal");
1682 * gtk_window_get_modal:
1683 * @window: a #GtkWindow
1685 * Returns whether the window is modal. See gtk_window_set_modal().
1687 * Return value: %TRUE if the window is set to be modal and
1688 * establishes a grab when shown
1691 gtk_window_get_modal (GtkWindow *window)
1693 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1695 return window->modal;
1699 * gtk_window_list_toplevels:
1701 * Returns a list of all existing toplevel windows. The widgets
1702 * in the list are not individually referenced. If you want
1703 * to iterate through the list and perform actions involving
1704 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1705 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1706 * then unref all the widgets afterwards.
1708 * Return value: list of toplevel widgets
1711 gtk_window_list_toplevels (void)
1716 for (slist = toplevel_list; slist; slist = slist->next)
1717 list = g_list_prepend (list, slist->data);
1723 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1725 GList *embedded_windows;
1727 g_return_if_fail (GTK_IS_WINDOW (window));
1729 embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1730 if (embedded_windows)
1731 g_object_steal_qdata (G_OBJECT (window),
1732 g_quark_from_static_string ("gtk-embedded"));
1733 embedded_windows = g_list_prepend (embedded_windows,
1734 GUINT_TO_POINTER (xid));
1736 g_object_set_data_full (G_OBJECT (window), I_("gtk-embedded"),
1739 (GDestroyNotify) g_list_free : NULL);
1743 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1745 GList *embedded_windows;
1748 g_return_if_fail (GTK_IS_WINDOW (window));
1750 embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1751 if (embedded_windows)
1752 g_object_steal_qdata (G_OBJECT (window),
1753 g_quark_from_static_string ("gtk-embedded"));
1755 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1758 embedded_windows = g_list_remove_link (embedded_windows, node);
1759 g_list_free_1 (node);
1762 g_object_set_data_full (G_OBJECT (window), I_("gtk-embedded"),
1765 (GDestroyNotify) g_list_free : NULL);
1769 _gtk_window_reposition (GtkWindow *window,
1773 g_return_if_fail (GTK_IS_WINDOW (window));
1775 gtk_window_move (window, x, y);
1779 gtk_window_dispose (GObject *object)
1781 GtkWindow *window = GTK_WINDOW (object);
1783 gtk_window_set_focus (window, NULL);
1784 gtk_window_set_default (window, NULL);
1786 G_OBJECT_CLASS (parent_class)->dispose (object);
1790 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1792 gtk_widget_destroy (GTK_WIDGET (child));
1796 connect_parent_destroyed (GtkWindow *window)
1798 if (window->transient_parent)
1800 g_signal_connect (window->transient_parent,
1802 G_CALLBACK (parent_destroyed_callback),
1808 disconnect_parent_destroyed (GtkWindow *window)
1810 if (window->transient_parent)
1812 g_signal_handlers_disconnect_by_func (window->transient_parent,
1813 parent_destroyed_callback,
1819 gtk_window_transient_parent_realized (GtkWidget *parent,
1822 if (GTK_WIDGET_REALIZED (window))
1823 gdk_window_set_transient_for (window->window, parent->window);
1827 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1830 if (GTK_WIDGET_REALIZED (window))
1831 gdk_property_delete (window->window,
1832 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
1836 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
1840 gtk_window_set_screen (window, parent->screen);
1844 gtk_window_unset_transient_for (GtkWindow *window)
1846 if (window->transient_parent)
1848 if (window->transient_parent->group)
1849 gtk_window_group_remove_window (window->transient_parent->group,
1852 g_signal_handlers_disconnect_by_func (window->transient_parent,
1853 gtk_window_transient_parent_realized,
1855 g_signal_handlers_disconnect_by_func (window->transient_parent,
1856 gtk_window_transient_parent_unrealized,
1858 g_signal_handlers_disconnect_by_func (window->transient_parent,
1859 gtk_window_transient_parent_screen_changed,
1861 g_signal_handlers_disconnect_by_func (window->transient_parent,
1862 gtk_widget_destroyed,
1863 &window->transient_parent);
1865 if (window->destroy_with_parent)
1866 disconnect_parent_destroyed (window);
1868 window->transient_parent = NULL;
1873 * gtk_window_set_transient_for:
1874 * @window: a #GtkWindow
1875 * @parent: parent window
1877 * Dialog windows should be set transient for the main application
1878 * window they were spawned from. This allows <link
1879 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1880 * dialog on top of the main window, or center the dialog over the
1881 * main window. gtk_dialog_new_with_buttons() and other convenience
1882 * functions in GTK+ will sometimes call
1883 * gtk_window_set_transient_for() on your behalf.
1885 * On Windows, this function will and put the child window
1886 * on top of the parent, much as the window manager would have
1891 gtk_window_set_transient_for (GtkWindow *window,
1894 g_return_if_fail (GTK_IS_WINDOW (window));
1895 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1896 g_return_if_fail (window != parent);
1899 if (window->transient_parent)
1901 if (GTK_WIDGET_REALIZED (window) &&
1902 GTK_WIDGET_REALIZED (window->transient_parent) &&
1903 (!parent || !GTK_WIDGET_REALIZED (parent)))
1904 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1905 GTK_WIDGET (window));
1907 gtk_window_unset_transient_for (window);
1910 window->transient_parent = parent;
1914 g_signal_connect (parent, "destroy",
1915 G_CALLBACK (gtk_widget_destroyed),
1916 &window->transient_parent);
1917 g_signal_connect (parent, "realize",
1918 G_CALLBACK (gtk_window_transient_parent_realized),
1920 g_signal_connect (parent, "unrealize",
1921 G_CALLBACK (gtk_window_transient_parent_unrealized),
1923 g_signal_connect (parent, "notify::screen",
1924 G_CALLBACK (gtk_window_transient_parent_screen_changed),
1927 gtk_window_set_screen (window, parent->screen);
1929 if (window->destroy_with_parent)
1930 connect_parent_destroyed (window);
1932 if (GTK_WIDGET_REALIZED (window) &&
1933 GTK_WIDGET_REALIZED (parent))
1934 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1935 GTK_WIDGET (window));
1938 gtk_window_group_add_window (parent->group, window);
1943 * gtk_window_get_transient_for:
1944 * @window: a #GtkWindow
1946 * Fetches the transient parent for this window. See
1947 * gtk_window_set_transient_for().
1949 * Return value: the transient parent for this window, or %NULL
1950 * if no transient parent has been set.
1953 gtk_window_get_transient_for (GtkWindow *window)
1955 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1957 return window->transient_parent;
1961 * gtk_window_set_type_hint:
1962 * @window: a #GtkWindow
1963 * @hint: the window type
1965 * By setting the type hint for the window, you allow the window
1966 * manager to decorate and handle the window in a way which is
1967 * suitable to the function of the window in your application.
1969 * This function should be called before the window becomes visible.
1971 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1972 * will sometimes call gtk_window_set_type_hint() on your behalf.
1976 gtk_window_set_type_hint (GtkWindow *window,
1977 GdkWindowTypeHint hint)
1979 g_return_if_fail (GTK_IS_WINDOW (window));
1980 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1981 window->type_hint = hint;
1985 * gtk_window_get_type_hint:
1986 * @window: a #GtkWindow
1988 * Gets the type hint for this window. See gtk_window_set_type_hint().
1990 * Return value: the type hint for @window.
1993 gtk_window_get_type_hint (GtkWindow *window)
1995 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1997 return window->type_hint;
2001 * gtk_window_set_skip_taskbar_hint:
2002 * @window: a #GtkWindow
2003 * @setting: %TRUE to keep this window from appearing in the task bar
2005 * Windows may set a hint asking the desktop environment not to display
2006 * the window in the task bar. This function sets this hint.
2011 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2014 GtkWindowPrivate *priv;
2016 g_return_if_fail (GTK_IS_WINDOW (window));
2018 priv = GTK_WINDOW_GET_PRIVATE (window);
2020 setting = setting != FALSE;
2022 if (priv->skips_taskbar != setting)
2024 priv->skips_taskbar = setting;
2025 if (GTK_WIDGET_REALIZED (window))
2026 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
2027 priv->skips_taskbar);
2028 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2033 * gtk_window_get_skip_taskbar_hint:
2034 * @window: a #GtkWindow
2036 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2038 * Return value: %TRUE if window shouldn't be in taskbar
2043 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2045 GtkWindowPrivate *priv;
2047 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2049 priv = GTK_WINDOW_GET_PRIVATE (window);
2051 return priv->skips_taskbar;
2055 * gtk_window_set_skip_pager_hint:
2056 * @window: a #GtkWindow
2057 * @setting: %TRUE to keep this window from appearing in the pager
2059 * Windows may set a hint asking the desktop environment not to display
2060 * the window in the pager. This function sets this hint.
2061 * (A "pager" is any desktop navigation tool such as a workspace
2062 * switcher that displays a thumbnail representation of the windows
2068 gtk_window_set_skip_pager_hint (GtkWindow *window,
2071 GtkWindowPrivate *priv;
2073 g_return_if_fail (GTK_IS_WINDOW (window));
2075 priv = GTK_WINDOW_GET_PRIVATE (window);
2077 setting = setting != FALSE;
2079 if (priv->skips_pager != setting)
2081 priv->skips_pager = setting;
2082 if (GTK_WIDGET_REALIZED (window))
2083 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2085 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2090 * gtk_window_get_skip_pager_hint:
2091 * @window: a #GtkWindow
2093 * Gets the value set by gtk_window_set_skip_pager_hint().
2095 * Return value: %TRUE if window shouldn't be in pager
2100 gtk_window_get_skip_pager_hint (GtkWindow *window)
2102 GtkWindowPrivate *priv;
2104 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2106 priv = GTK_WINDOW_GET_PRIVATE (window);
2108 return priv->skips_pager;
2112 * gtk_window_set_urgency_hint:
2113 * @window: a #GtkWindow
2114 * @setting: %TRUE to mark this window as urgent
2116 * Windows may set a hint asking the desktop environment to draw
2117 * the users attention to the window. This function sets this hint.
2122 gtk_window_set_urgency_hint (GtkWindow *window,
2125 GtkWindowPrivate *priv;
2127 g_return_if_fail (GTK_IS_WINDOW (window));
2129 priv = GTK_WINDOW_GET_PRIVATE (window);
2131 setting = setting != FALSE;
2133 if (priv->urgent != setting)
2135 priv->urgent = setting;
2136 if (GTK_WIDGET_REALIZED (window))
2137 gdk_window_set_urgency_hint (GTK_WIDGET (window)->window,
2139 g_object_notify (G_OBJECT (window), "urgency-hint");
2144 * gtk_window_get_urgency_hint:
2145 * @window: a #GtkWindow
2147 * Gets the value set by gtk_window_set_urgency_hint()
2149 * Return value: %TRUE if window is urgent
2154 gtk_window_get_urgency_hint (GtkWindow *window)
2156 GtkWindowPrivate *priv;
2158 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2160 priv = GTK_WINDOW_GET_PRIVATE (window);
2162 return priv->urgent;
2166 * gtk_window_set_accept_focus:
2167 * @window: a #GtkWindow
2168 * @setting: %TRUE to let this window receive input focus
2170 * Windows may set a hint asking the desktop environment not to receive
2171 * the input focus. This function sets this hint.
2176 gtk_window_set_accept_focus (GtkWindow *window,
2179 GtkWindowPrivate *priv;
2181 g_return_if_fail (GTK_IS_WINDOW (window));
2183 priv = GTK_WINDOW_GET_PRIVATE (window);
2185 setting = setting != FALSE;
2187 if (priv->accept_focus != setting)
2189 priv->accept_focus = setting;
2190 if (GTK_WIDGET_REALIZED (window))
2191 gdk_window_set_accept_focus (GTK_WIDGET (window)->window,
2192 priv->accept_focus);
2193 g_object_notify (G_OBJECT (window), "accept-focus");
2198 * gtk_window_get_accept_focus:
2199 * @window: a #GtkWindow
2201 * Gets the value set by gtk_window_set_accept_focus().
2203 * Return value: %TRUE if window should receive the input focus
2208 gtk_window_get_accept_focus (GtkWindow *window)
2210 GtkWindowPrivate *priv;
2212 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2214 priv = GTK_WINDOW_GET_PRIVATE (window);
2216 return priv->accept_focus;
2220 * gtk_window_set_focus_on_map:
2221 * @window: a #GtkWindow
2222 * @setting: %TRUE to let this window receive input focus on map
2224 * Windows may set a hint asking the desktop environment not to receive
2225 * the input focus when the window is mapped. This function sets this
2231 gtk_window_set_focus_on_map (GtkWindow *window,
2234 GtkWindowPrivate *priv;
2236 g_return_if_fail (GTK_IS_WINDOW (window));
2238 priv = GTK_WINDOW_GET_PRIVATE (window);
2240 setting = setting != FALSE;
2242 if (priv->focus_on_map != setting)
2244 priv->focus_on_map = setting;
2245 if (GTK_WIDGET_REALIZED (window))
2246 gdk_window_set_focus_on_map (GTK_WIDGET (window)->window,
2247 priv->focus_on_map);
2248 g_object_notify (G_OBJECT (window), "focus-on-map");
2253 * gtk_window_get_focus_on_map:
2254 * @window: a #GtkWindow
2256 * Gets the value set by gtk_window_set_focus_on_map().
2258 * Return value: %TRUE if window should receive the input focus when
2264 gtk_window_get_focus_on_map (GtkWindow *window)
2266 GtkWindowPrivate *priv;
2268 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2270 priv = GTK_WINDOW_GET_PRIVATE (window);
2272 return priv->focus_on_map;
2276 * gtk_window_set_destroy_with_parent:
2277 * @window: a #GtkWindow
2278 * @setting: whether to destroy @window with its transient parent
2280 * If @setting is %TRUE, then destroying the transient parent of @window
2281 * will also destroy @window itself. This is useful for dialogs that
2282 * shouldn't persist beyond the lifetime of the main window they're
2283 * associated with, for example.
2286 gtk_window_set_destroy_with_parent (GtkWindow *window,
2289 g_return_if_fail (GTK_IS_WINDOW (window));
2291 if (window->destroy_with_parent == (setting != FALSE))
2294 if (window->destroy_with_parent)
2296 disconnect_parent_destroyed (window);
2300 connect_parent_destroyed (window);
2303 window->destroy_with_parent = setting;
2305 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2309 * gtk_window_get_destroy_with_parent:
2310 * @window: a #GtkWindow
2312 * Returns whether the window will be destroyed with its transient parent. See
2313 * gtk_window_set_destroy_with_parent ().
2315 * Return value: %TRUE if the window will be destroyed with its transient parent.
2318 gtk_window_get_destroy_with_parent (GtkWindow *window)
2320 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2322 return window->destroy_with_parent;
2325 static GtkWindowGeometryInfo*
2326 gtk_window_get_geometry_info (GtkWindow *window,
2329 GtkWindowGeometryInfo *info;
2331 info = window->geometry_info;
2332 if (!info && create)
2334 info = g_new0 (GtkWindowGeometryInfo, 1);
2336 info->default_width = -1;
2337 info->default_height = -1;
2338 info->resize_width = -1;
2339 info->resize_height = -1;
2340 info->initial_x = 0;
2341 info->initial_y = 0;
2342 info->initial_pos_set = FALSE;
2343 info->default_is_geometry = FALSE;
2344 info->position_constraints_changed = FALSE;
2345 info->last.configure_request.x = 0;
2346 info->last.configure_request.y = 0;
2347 info->last.configure_request.width = -1;
2348 info->last.configure_request.height = -1;
2349 info->widget = NULL;
2351 window->geometry_info = info;
2358 * gtk_window_set_geometry_hints:
2359 * @window: a #GtkWindow
2360 * @geometry_widget: widget the geometry hints will be applied to
2361 * @geometry: struct containing geometry information
2362 * @geom_mask: mask indicating which struct fields should be paid attention to
2364 * This function sets up hints about how a window can be resized by
2365 * the user. You can set a minimum and maximum size; allowed resize
2366 * increments (e.g. for xterm, you can only resize by the size of a
2367 * character); aspect ratios; and more. See the #GdkGeometry struct.
2371 gtk_window_set_geometry_hints (GtkWindow *window,
2372 GtkWidget *geometry_widget,
2373 GdkGeometry *geometry,
2374 GdkWindowHints geom_mask)
2376 GtkWindowGeometryInfo *info;
2378 g_return_if_fail (GTK_IS_WINDOW (window));
2379 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2381 info = gtk_window_get_geometry_info (window, TRUE);
2384 g_signal_handlers_disconnect_by_func (info->widget,
2385 gtk_widget_destroyed,
2388 info->widget = geometry_widget;
2390 g_signal_connect (geometry_widget, "destroy",
2391 G_CALLBACK (gtk_widget_destroyed),
2395 info->geometry = *geometry;
2397 /* We store gravity in window->gravity not in the hints. */
2398 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2400 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2402 gtk_window_set_gravity (window, geometry->win_gravity);
2405 gtk_widget_queue_resize (GTK_WIDGET (window));
2409 * gtk_window_set_decorated:
2410 * @window: a #GtkWindow
2411 * @setting: %TRUE to decorate the window
2413 * By default, windows are decorated with a title bar, resize
2414 * controls, etc. Some <link linkend="gtk-X11-arch">window
2415 * managers</link> allow GTK+ to disable these decorations, creating a
2416 * borderless window. If you set the decorated property to %FALSE
2417 * using this function, GTK+ will do its best to convince the window
2418 * manager not to decorate the window. Depending on the system, this
2419 * function may not have any effect when called on a window that is
2420 * already visible, so you should call it before calling gtk_window_show().
2422 * On Windows, this function always works, since there's no window manager
2427 gtk_window_set_decorated (GtkWindow *window,
2430 g_return_if_fail (GTK_IS_WINDOW (window));
2432 setting = setting != FALSE;
2434 if (setting == window->decorated)
2437 window->decorated = setting;
2439 if (GTK_WIDGET (window)->window)
2441 if (window->decorated)
2442 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2445 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2449 g_object_notify (G_OBJECT (window), "decorated");
2453 * gtk_window_get_decorated:
2454 * @window: a #GtkWindow
2456 * Returns whether the window has been set to have decorations
2457 * such as a title bar via gtk_window_set_decorated().
2459 * Return value: %TRUE if the window has been set to have decorations
2462 gtk_window_get_decorated (GtkWindow *window)
2464 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2466 return window->decorated;
2470 * @window: a #GtkWindow
2471 * @setting: %TRUE to decorate the window as deletable
2473 * By default, windows have a close button in the window frame. Some
2474 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
2475 * disable this button. If you set the deletable property to %FALSE
2476 * using this function, GTK+ will do its best to convince the window
2477 * manager not to show a close button. Depending on the system, this
2478 * function may not have any effect when called on a window that is
2479 * already visible, so you should call it before calling gtk_window_show().
2481 * On Windows, this function always works, since there's no window manager
2487 gtk_window_set_deletable (GtkWindow *window,
2490 GtkWindowPrivate *priv;
2492 g_return_if_fail (GTK_IS_WINDOW (window));
2494 priv = GTK_WINDOW_GET_PRIVATE (window);
2496 setting = setting != FALSE;
2498 if (setting == priv->deletable)
2501 priv->deletable = setting;
2503 if (GTK_WIDGET (window)->window)
2505 if (priv->deletable)
2506 gdk_window_set_functions (GTK_WIDGET (window)->window,
2509 gdk_window_set_functions (GTK_WIDGET (window)->window,
2510 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
2513 g_object_notify (G_OBJECT (window), "deletable");
2517 * gtk_window_get_deletable:
2518 * @window: a #GtkWindow
2520 * Returns whether the window has been set to have a close button
2521 * via gtk_window_set_deletable().
2523 * Return value: %TRUE if the window has been set to have a close button
2526 gtk_window_get_deletable (GtkWindow *window)
2528 GtkWindowPrivate *priv;
2530 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2532 priv = GTK_WINDOW_GET_PRIVATE (window);
2534 return priv->deletable;
2537 static GtkWindowIconInfo*
2538 get_icon_info (GtkWindow *window)
2540 return g_object_get_data (G_OBJECT (window),
2541 "gtk-window-icon-info");
2545 free_icon_info (GtkWindowIconInfo *info)
2547 g_free (info->icon_name);
2552 static GtkWindowIconInfo*
2553 ensure_icon_info (GtkWindow *window)
2555 GtkWindowIconInfo *info;
2557 info = get_icon_info (window);
2561 info = g_new0 (GtkWindowIconInfo, 1);
2562 g_object_set_data_full (G_OBJECT (window),
2563 I_("gtk-window-icon-info"),
2565 (GDestroyNotify)free_icon_info);
2577 static ScreenIconInfo *
2578 get_screen_icon_info (GdkScreen *screen)
2580 ScreenIconInfo *info = g_object_get_data (G_OBJECT (screen),
2581 "gtk-window-default-icon-pixmap");
2584 info = g_new0 (ScreenIconInfo, 1);
2585 g_object_set_data (G_OBJECT (screen), I_("gtk-window-default-icon-pixmap"), info);
2588 if (info->serial != default_icon_serial)
2592 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2593 info->pixmap = NULL;
2598 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2602 info->serial = default_icon_serial;
2609 get_pixmap_and_mask (GdkWindow *window,
2610 GtkWindowIconInfo *parent_info,
2611 gboolean is_default_list,
2613 GdkPixmap **pmap_return,
2614 GdkBitmap **mask_return)
2616 GdkScreen *screen = gdk_drawable_get_screen (window);
2617 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2618 GdkPixbuf *best_icon;
2622 *pmap_return = NULL;
2623 *mask_return = NULL;
2625 if (is_default_list &&
2626 default_icon_info->pixmap != NULL)
2628 /* Use shared icon pixmap for all windows on this screen.
2630 if (default_icon_info->pixmap)
2631 g_object_ref (default_icon_info->pixmap);
2632 if (default_icon_info->mask)
2633 g_object_ref (default_icon_info->mask);
2635 *pmap_return = default_icon_info->pixmap;
2636 *mask_return = default_icon_info->mask;
2638 else if (parent_info && parent_info->icon_pixmap)
2640 if (parent_info->icon_pixmap)
2641 g_object_ref (parent_info->icon_pixmap);
2642 if (parent_info->icon_mask)
2643 g_object_ref (parent_info->icon_mask);
2645 *pmap_return = parent_info->icon_pixmap;
2646 *mask_return = parent_info->icon_mask;
2650 #define IDEAL_SIZE 48
2652 best_size = G_MAXINT;
2654 tmp_list = icon_list;
2655 while (tmp_list != NULL)
2657 GdkPixbuf *pixbuf = tmp_list->data;
2660 /* average width and height - if someone passes in a rectangular
2661 * icon they deserve what they get.
2663 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2666 if (best_icon == NULL)
2673 /* icon is better if it's 32 pixels or larger, and closer to
2674 * the ideal size than the current best.
2677 (ABS (best_size - IDEAL_SIZE) <
2678 ABS (this - IDEAL_SIZE)))
2685 tmp_list = tmp_list->next;
2689 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2690 gdk_screen_get_system_colormap (screen),
2695 /* Save pmap/mask for others to use if appropriate */
2698 parent_info->icon_pixmap = *pmap_return;
2699 parent_info->icon_mask = *mask_return;
2701 if (parent_info->icon_pixmap)
2702 g_object_ref (parent_info->icon_pixmap);
2703 if (parent_info->icon_mask)
2704 g_object_ref (parent_info->icon_mask);
2706 else if (is_default_list)
2708 default_icon_info->pixmap = *pmap_return;
2709 default_icon_info->mask = *mask_return;
2711 if (default_icon_info->pixmap)
2712 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2713 (gpointer*)&default_icon_info->pixmap);
2714 if (default_icon_info->mask)
2715 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2716 (gpointer*)&default_icon_info->mask);
2722 icon_list_from_theme (GtkWidget *widget,
2727 GtkIconTheme *icon_theme;
2732 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
2734 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
2737 for (i = 0; sizes[i]; i++)
2740 * We need an EWMH extension to handle scalable icons
2741 * by passing their name to the WM. For now just use a
2745 icon = gtk_icon_theme_load_icon (icon_theme, name,
2748 icon = gtk_icon_theme_load_icon (icon_theme, name,
2751 list = g_list_append (list, icon);
2761 gtk_window_realize_icon (GtkWindow *window)
2764 GtkWindowIconInfo *info;
2767 widget = GTK_WIDGET (window);
2769 g_return_if_fail (widget->window != NULL);
2771 /* no point setting an icon on override-redirect */
2772 if (window->type == GTK_WINDOW_POPUP)
2777 info = ensure_icon_info (window);
2782 g_return_if_fail (info->icon_pixmap == NULL);
2783 g_return_if_fail (info->icon_mask == NULL);
2785 info->using_default_icon = FALSE;
2786 info->using_parent_icon = FALSE;
2787 info->using_themed_icon = FALSE;
2789 icon_list = info->icon_list;
2791 /* Look up themed icon */
2792 if (icon_list == NULL && info->icon_name)
2794 icon_list = icon_list_from_theme (widget, info->icon_name);
2796 info->using_themed_icon = TRUE;
2799 /* Inherit from transient parent */
2800 if (icon_list == NULL && window->transient_parent)
2802 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2804 info->using_parent_icon = TRUE;
2807 /* Inherit from default */
2808 if (icon_list == NULL)
2810 icon_list = default_icon_list;
2812 info->using_default_icon = TRUE;
2815 /* Look up themed icon */
2816 if (icon_list == NULL && default_icon_name)
2818 icon_list = icon_list_from_theme (widget, default_icon_name);
2819 info->using_default_icon = TRUE;
2820 info->using_themed_icon = TRUE;
2823 gdk_window_set_icon_list (widget->window, icon_list);
2825 get_pixmap_and_mask (widget->window,
2826 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2827 info->using_default_icon,
2832 /* This is a slight ICCCM violation since it's a color pixmap not
2833 * a bitmap, but everyone does it.
2835 gdk_window_set_icon (widget->window,
2840 info->realized = TRUE;
2842 if (info->using_themed_icon)
2844 GtkIconTheme *icon_theme;
2846 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
2847 g_list_free (icon_list);
2849 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2850 g_signal_connect (icon_theme, "changed",
2851 G_CALLBACK (update_themed_icon), window);
2856 gtk_window_unrealize_icon (GtkWindow *window)
2858 GtkWindowIconInfo *info;
2860 info = get_icon_info (window);
2865 if (info->icon_pixmap)
2866 g_object_unref (info->icon_pixmap);
2868 if (info->icon_mask)
2869 g_object_unref (info->icon_mask);
2871 info->icon_pixmap = NULL;
2872 info->icon_mask = NULL;
2874 if (info->using_themed_icon)
2876 GtkIconTheme *icon_theme;
2878 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2880 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
2883 /* We don't clear the properties on the window, just figure the
2884 * window is going away.
2887 info->realized = FALSE;
2892 * gtk_window_set_icon_list:
2893 * @window: a #GtkWindow
2894 * @list: list of #GdkPixbuf
2896 * Sets up the icon representing a #GtkWindow. The icon is used when
2897 * the window is minimized (also known as iconified). Some window
2898 * managers or desktop environments may also place it in the window
2899 * frame, or display it in other contexts.
2901 * gtk_window_set_icon_list() allows you to pass in the same icon in
2902 * several hand-drawn sizes. The list should contain the natural sizes
2903 * your icon is available in; that is, don't scale the image before
2904 * passing it to GTK+. Scaling is postponed until the last minute,
2905 * when the desired final size is known, to allow best quality.
2907 * By passing several sizes, you may improve the final image quality
2908 * of the icon, by reducing or eliminating automatic image scaling.
2910 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2911 * larger images (64x64, 128x128) if you have them.
2913 * See also gtk_window_set_default_icon_list() to set the icon
2914 * for all windows in your application in one go.
2916 * Note that transient windows (those who have been set transient for another
2917 * window using gtk_window_set_transient_for()) will inherit their
2918 * icon from their transient parent. So there's no need to explicitly
2919 * set the icon on transient windows.
2922 gtk_window_set_icon_list (GtkWindow *window,
2925 GtkWindowIconInfo *info;
2927 g_return_if_fail (GTK_IS_WINDOW (window));
2929 info = ensure_icon_info (window);
2931 if (info->icon_list == list) /* check for NULL mostly */
2934 g_list_foreach (list,
2935 (GFunc) g_object_ref, NULL);
2937 g_list_foreach (info->icon_list,
2938 (GFunc) g_object_unref, NULL);
2940 g_list_free (info->icon_list);
2942 info->icon_list = g_list_copy (list);
2944 g_object_notify (G_OBJECT (window), "icon");
2946 gtk_window_unrealize_icon (window);
2948 if (GTK_WIDGET_REALIZED (window))
2949 gtk_window_realize_icon (window);
2951 /* We could try to update our transient children, but I don't think
2952 * it's really worth it. If we did it, the best way would probably
2953 * be to have children connect to notify::icon-list
2958 * gtk_window_get_icon_list:
2959 * @window: a #GtkWindow
2961 * Retrieves the list of icons set by gtk_window_set_icon_list().
2962 * The list is copied, but the reference count on each
2963 * member won't be incremented.
2965 * Return value: copy of window's icon list
2968 gtk_window_get_icon_list (GtkWindow *window)
2970 GtkWindowIconInfo *info;
2972 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2974 info = get_icon_info (window);
2977 return g_list_copy (info->icon_list);
2983 * gtk_window_set_icon:
2984 * @window: a #GtkWindow
2985 * @icon: icon image, or %NULL
2987 * Sets up the icon representing a #GtkWindow. This icon is used when
2988 * the window is minimized (also known as iconified). Some window
2989 * managers or desktop environments may also place it in the window
2990 * frame, or display it in other contexts.
2992 * The icon should be provided in whatever size it was naturally
2993 * drawn; that is, don't scale the image before passing it to
2994 * GTK+. Scaling is postponed until the last minute, when the desired
2995 * final size is known, to allow best quality.
2997 * If you have your icon hand-drawn in multiple sizes, use
2998 * gtk_window_set_icon_list(). Then the best size will be used.
3000 * This function is equivalent to calling gtk_window_set_icon_list()
3001 * with a 1-element list.
3003 * See also gtk_window_set_default_icon_list() to set the icon
3004 * for all windows in your application in one go.
3007 gtk_window_set_icon (GtkWindow *window,
3012 g_return_if_fail (GTK_IS_WINDOW (window));
3013 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3018 list = g_list_append (list, icon);
3020 gtk_window_set_icon_list (window, list);
3026 update_themed_icon (GtkIconTheme *icon_theme,
3029 g_object_notify (G_OBJECT (window), "icon");
3031 gtk_window_unrealize_icon (window);
3033 if (GTK_WIDGET_REALIZED (window))
3034 gtk_window_realize_icon (window);
3038 * gtk_window_set_icon_name:
3039 * @window: a #GtkWindow
3040 * @name: the name of the themed icon
3042 * Sets the icon for the window from a named themed icon. See
3043 * the docs for #GtkIconTheme for more details.
3045 * Note that this has nothing to do with the WM_ICON_NAME
3046 * property which is mentioned in the ICCCM.
3051 gtk_window_set_icon_name (GtkWindow *window,
3054 GtkWindowIconInfo *info;
3057 g_return_if_fail (GTK_IS_WINDOW (window));
3059 info = ensure_icon_info (window);
3061 tmp = info->icon_name;
3062 info->icon_name = g_strdup (name);
3065 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3066 g_list_free (info->icon_list);
3067 info->icon_list = NULL;
3069 update_themed_icon (NULL, window);
3071 g_object_notify (G_OBJECT (window), "icon-name");
3075 * gtk_window_get_icon_name:
3076 * @window: a #GtkWindow
3078 * Returns the name of the themed icon for the window,
3079 * see gtk_window_set_icon_name().
3081 * Returns: the icon name or %NULL if the window has
3086 G_CONST_RETURN gchar *
3087 gtk_window_get_icon_name (GtkWindow *window)
3089 GtkWindowIconInfo *info;
3091 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3093 info = ensure_icon_info (window);
3095 return info->icon_name;
3099 * gtk_window_get_icon:
3100 * @window: a #GtkWindow
3102 * Gets the value set by gtk_window_set_icon() (or if you've
3103 * called gtk_window_set_icon_list(), gets the first icon in
3106 * Return value: icon for window
3109 gtk_window_get_icon (GtkWindow *window)
3111 GtkWindowIconInfo *info;
3113 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3115 info = get_icon_info (window);
3116 if (info && info->icon_list)
3117 return GDK_PIXBUF (info->icon_list->data);
3122 /* Load pixbuf, printing warning on failure if error == NULL
3125 load_pixbuf_verbosely (const char *filename,
3128 GError *local_err = NULL;
3131 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3139 g_warning ("Error loading icon from file '%s':\n\t%s",
3140 filename, local_err->message);
3141 g_error_free (local_err);
3149 * gtk_window_set_icon_from_file:
3150 * @window: a #GtkWindow
3151 * @filename: location of icon file
3152 * @err: location to store error, or %NULL.
3154 * Sets the icon for @window.
3155 * Warns on failure if @err is %NULL.
3157 * This function is equivalent to calling gtk_window_set_icon()
3158 * with a pixbuf created by loading the image from @filename.
3160 * Returns: %TRUE if setting the icon succeeded.
3165 gtk_window_set_icon_from_file (GtkWindow *window,
3166 const gchar *filename,
3169 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3173 gtk_window_set_icon (window, pixbuf);
3174 g_object_unref (pixbuf);
3183 * gtk_window_set_default_icon_list:
3184 * @list: a list of #GdkPixbuf
3186 * Sets an icon list to be used as fallback for windows that haven't
3187 * had gtk_window_set_icon_list() called on them to set up a
3188 * window-specific icon list. This function allows you to set up the
3189 * icon for all windows in your app at once.
3191 * See gtk_window_set_icon_list() for more details.
3195 gtk_window_set_default_icon_list (GList *list)
3199 if (list == default_icon_list)
3202 /* Update serial so we don't used cached pixmaps/masks
3204 default_icon_serial++;
3206 g_list_foreach (list,
3207 (GFunc) g_object_ref, NULL);
3209 g_list_foreach (default_icon_list,
3210 (GFunc) g_object_unref, NULL);
3212 g_list_free (default_icon_list);
3214 default_icon_list = g_list_copy (list);
3216 /* Update all toplevels */
3217 toplevels = gtk_window_list_toplevels ();
3218 tmp_list = toplevels;
3219 while (tmp_list != NULL)
3221 GtkWindowIconInfo *info;
3222 GtkWindow *w = tmp_list->data;
3224 info = get_icon_info (w);
3225 if (info && info->using_default_icon)
3227 gtk_window_unrealize_icon (w);
3228 if (GTK_WIDGET_REALIZED (w))
3229 gtk_window_realize_icon (w);
3232 tmp_list = tmp_list->next;
3234 g_list_free (toplevels);
3238 * gtk_window_set_default_icon:
3241 * Sets an icon to be used as fallback for windows that haven't
3242 * had gtk_window_set_icon() called on them from a pixbuf.
3247 gtk_window_set_default_icon (GdkPixbuf *icon)
3251 g_return_if_fail (GDK_IS_PIXBUF (icon));
3253 list = g_list_prepend (NULL, icon);
3254 gtk_window_set_default_icon_list (list);
3259 * gtk_window_set_default_icon_name:
3260 * @name: the name of the themed icon
3262 * Sets an icon to be used as fallback for windows that haven't
3263 * had gtk_window_set_icon_list() called on them from a named
3264 * themed icon, see gtk_window_set_icon_name().
3269 gtk_window_set_default_icon_name (const gchar *name)
3274 /* Update serial so we don't used cached pixmaps/masks
3276 default_icon_serial++;
3278 g_free (default_icon_name);
3279 default_icon_name = g_strdup (name);
3281 g_list_foreach (default_icon_list,
3282 (GFunc) g_object_unref, NULL);
3284 g_list_free (default_icon_list);
3285 default_icon_list = NULL;
3287 /* Update all toplevels */
3288 toplevels = gtk_window_list_toplevels ();
3289 tmp_list = toplevels;
3290 while (tmp_list != NULL)
3292 GtkWindowIconInfo *info;
3293 GtkWindow *w = tmp_list->data;
3295 info = get_icon_info (w);
3296 if (info && info->using_default_icon && info->using_themed_icon)
3298 gtk_window_unrealize_icon (w);
3299 if (GTK_WIDGET_REALIZED (w))
3300 gtk_window_realize_icon (w);
3303 tmp_list = tmp_list->next;
3305 g_list_free (toplevels);
3309 * gtk_window_set_default_icon_from_file:
3310 * @filename: location of icon file
3311 * @err: location to store error, or %NULL.
3313 * Sets an icon to be used as fallback for windows that haven't
3314 * had gtk_window_set_icon_list() called on them from a file
3315 * on disk. Warns on failure if @err is %NULL.
3317 * Returns: %TRUE if setting the icon succeeded.
3322 gtk_window_set_default_icon_from_file (const gchar *filename,
3325 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3329 gtk_window_set_default_icon (pixbuf);
3330 g_object_unref (pixbuf);
3339 * gtk_window_get_default_icon_list:
3341 * Gets the value set by gtk_window_set_default_icon_list().
3342 * The list is a copy and should be freed with g_list_free(),
3343 * but the pixbufs in the list have not had their reference count
3346 * Return value: copy of default icon list
3349 gtk_window_get_default_icon_list (void)
3351 return g_list_copy (default_icon_list);
3355 gtk_window_set_default_size_internal (GtkWindow *window,
3356 gboolean change_width,
3358 gboolean change_height,
3360 gboolean is_geometry)
3362 GtkWindowGeometryInfo *info;
3364 g_return_if_fail (change_width == FALSE || width >= -1);
3365 g_return_if_fail (change_height == FALSE || height >= -1);
3367 info = gtk_window_get_geometry_info (window, TRUE);
3369 g_object_freeze_notify (G_OBJECT (window));
3371 info->default_is_geometry = is_geometry != FALSE;
3381 info->default_width = width;
3383 g_object_notify (G_OBJECT (window), "default-width");
3394 info->default_height = height;
3396 g_object_notify (G_OBJECT (window), "default-height");
3399 g_object_thaw_notify (G_OBJECT (window));
3401 gtk_widget_queue_resize (GTK_WIDGET (window));
3405 * gtk_window_set_default_size:
3406 * @window: a #GtkWindow
3407 * @width: width in pixels, or -1 to unset the default width
3408 * @height: height in pixels, or -1 to unset the default height
3410 * Sets the default size of a window. If the window's "natural" size
3411 * (its size request) is larger than the default, the default will be
3412 * ignored. More generally, if the default size does not obey the
3413 * geometry hints for the window (gtk_window_set_geometry_hints() can
3414 * be used to set these explicitly), the default size will be clamped
3415 * to the nearest permitted size.
3417 * Unlike gtk_widget_set_size_request(), which sets a size request for
3418 * a widget and thus would keep users from shrinking the window, this
3419 * function only sets the initial size, just as if the user had
3420 * resized the window themselves. Users can still shrink the window
3421 * again as they normally would. Setting a default size of -1 means to
3422 * use the "natural" default size (the size request of the window).
3424 * For more control over a window's initial size and how resizing works,
3425 * investigate gtk_window_set_geometry_hints().
3427 * For some uses, gtk_window_resize() is a more appropriate function.
3428 * gtk_window_resize() changes the current size of the window, rather
3429 * than the size to be used on initial display. gtk_window_resize() always
3430 * affects the window itself, not the geometry widget.
3432 * The default size of a window only affects the first time a window is
3433 * shown; if a window is hidden and re-shown, it will remember the size
3434 * it had prior to hiding, rather than using the default size.
3436 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3437 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3440 gtk_window_set_default_size (GtkWindow *window,
3444 g_return_if_fail (GTK_IS_WINDOW (window));
3445 g_return_if_fail (width >= -1);
3446 g_return_if_fail (height >= -1);
3448 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3452 * gtk_window_get_default_size:
3453 * @window: a #GtkWindow
3454 * @width: location to store the default width, or %NULL
3455 * @height: location to store the default height, or %NULL
3457 * Gets the default size of the window. A value of -1 for the width or
3458 * height indicates that a default size has not been explicitly set
3459 * for that dimension, so the "natural" size of the window will be
3464 gtk_window_get_default_size (GtkWindow *window,
3468 GtkWindowGeometryInfo *info;
3470 g_return_if_fail (GTK_IS_WINDOW (window));
3472 info = gtk_window_get_geometry_info (window, FALSE);
3475 *width = info ? info->default_width : -1;
3478 *height = info ? info->default_height : -1;
3482 * gtk_window_resize:
3483 * @window: a #GtkWindow
3484 * @width: width in pixels to resize the window to
3485 * @height: height in pixels to resize the window to
3487 * Resizes the window as if the user had done so, obeying geometry
3488 * constraints. The default geometry constraint is that windows may
3489 * not be smaller than their size request; to override this
3490 * constraint, call gtk_widget_set_size_request() to set the window's
3491 * request to a smaller value.
3493 * If gtk_window_resize() is called before showing a window for the
3494 * first time, it overrides any default size set with
3495 * gtk_window_set_default_size().
3497 * Windows may not be resized smaller than 1 by 1 pixels.
3501 gtk_window_resize (GtkWindow *window,
3505 GtkWindowGeometryInfo *info;
3507 g_return_if_fail (GTK_IS_WINDOW (window));
3508 g_return_if_fail (width > 0);
3509 g_return_if_fail (height > 0);
3511 info = gtk_window_get_geometry_info (window, TRUE);
3513 info->resize_width = width;
3514 info->resize_height = height;
3516 gtk_widget_queue_resize (GTK_WIDGET (window));
3520 * gtk_window_get_size:
3521 * @window: a #GtkWindow
3522 * @width: return location for width, or %NULL
3523 * @height: return location for height, or %NULL
3525 * Obtains the current size of @window. If @window is not onscreen,
3526 * it returns the size GTK+ will suggest to the <link
3527 * linkend="gtk-X11-arch">window manager</link> for the initial window
3528 * size (but this is not reliably the same as the size the window
3529 * manager will actually select). The size obtained by
3530 * gtk_window_get_size() is the last size received in a
3531 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
3532 * rather than querying the X server for the size. As a result, if you
3533 * call gtk_window_resize() then immediately call
3534 * gtk_window_get_size(), the size won't have taken effect yet. After
3535 * the window manager processes the resize request, GTK+ receives
3536 * notification that the size has changed via a configure event, and
3537 * the size of the window gets updated.
3539 * Note 1: Nearly any use of this function creates a race condition,
3540 * because the size of the window may change between the time that you
3541 * get the size and the time that you perform some action assuming
3542 * that size is the current size. To avoid race conditions, connect to
3543 * "configure_event" on the window and adjust your size-dependent
3544 * state to match the size delivered in the #GdkEventConfigure.
3546 * Note 2: The returned size does <emphasis>not</emphasis> include the
3547 * size of the window manager decorations (aka the window frame or
3548 * border). Those are not drawn by GTK+ and GTK+ has no reliable
3549 * method of determining their size.
3551 * Note 3: If you are getting a window size in order to position
3552 * the window onscreen, there may be a better way. The preferred
3553 * way is to simply set the window's semantic type with
3554 * gtk_window_set_type_hint(), which allows the window manager to
3555 * e.g. center dialogs. Also, if you set the transient parent of
3556 * dialogs with gtk_window_set_transient_for() window managers
3557 * will often center the dialog over its parent window. It's
3558 * much preferred to let the window manager handle these
3559 * things rather than doing it yourself, because all apps will
3560 * behave consistently and according to user prefs if the window
3561 * manager handles it. Also, the window manager can take the size
3562 * of the window decorations/border into account, while your
3563 * application cannot.
3565 * In any case, if you insist on application-specified window
3566 * positioning, there's <emphasis>still</emphasis> a better way than
3567 * doing it yourself - gtk_window_set_position() will frequently
3568 * handle the details for you.
3572 gtk_window_get_size (GtkWindow *window,
3578 g_return_if_fail (GTK_IS_WINDOW (window));
3580 if (width == NULL && height == NULL)
3583 if (GTK_WIDGET_MAPPED (window))
3585 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3590 GdkRectangle configure_request;
3592 gtk_window_compute_configure_request (window,
3596 w = configure_request.width;
3597 h = configure_request.height;
3608 * @window: a #GtkWindow
3609 * @x: X coordinate to move window to
3610 * @y: Y coordinate to move window to
3612 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3613 * @window to the given position. Window managers are free to ignore
3614 * this; most window managers ignore requests for initial window
3615 * positions (instead using a user-defined placement algorithm) and
3616 * honor requests after the window has already been shown.
3618 * Note: the position is the position of the gravity-determined
3619 * reference point for the window. The gravity determines two things:
3620 * first, the location of the reference point in root window
3621 * coordinates; and second, which point on the window is positioned at
3622 * the reference point.
3624 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3625 * point is simply the @x, @y supplied to gtk_window_move(). The
3626 * top-left corner of the window decorations (aka window frame or
3627 * border) will be placed at @x, @y. Therefore, to position a window
3628 * at the top left of the screen, you want to use the default gravity
3629 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3631 * To position a window at the bottom right corner of the screen, you
3632 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3633 * point is at @x + the window width and @y + the window height, and
3634 * the bottom-right corner of the window border will be placed at that
3635 * reference point. So, to place a window in the bottom right corner
3636 * you would first set gravity to south east, then write:
3637 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3638 * gdk_screen_height () - window_height)</literal>.
3640 * The Extended Window Manager Hints specification at <ulink
3641 * url="http://www.freedesktop.org/Standards/wm-spec">
3642 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
3643 * nice table of gravities in the "implementation notes" section.
3645 * The gtk_window_get_position() documentation may also be relevant.
3649 gtk_window_move (GtkWindow *window,
3653 GtkWindowGeometryInfo *info;
3656 g_return_if_fail (GTK_IS_WINDOW (window));
3658 widget = GTK_WIDGET (window);
3660 info = gtk_window_get_geometry_info (window, TRUE);
3662 if (GTK_WIDGET_MAPPED (window))
3664 /* we have now sent a request with this position
3665 * with currently-active constraints, so toggle flag.
3667 info->position_constraints_changed = FALSE;
3669 /* we only constrain if mapped - if not mapped,
3670 * then gtk_window_compute_configure_request()
3671 * will apply the constraints later, and we
3672 * don't want to lose information about
3673 * what position the user set before then.
3674 * i.e. if you do a move() then turn off POS_CENTER
3675 * then show the window, your move() will work.
3677 gtk_window_constrain_position (window,
3678 widget->allocation.width,
3679 widget->allocation.height,
3682 /* Note that this request doesn't go through our standard request
3683 * framework, e.g. doesn't increment configure_request_count,
3684 * doesn't set info->last, etc.; that's because
3685 * we don't save the info needed to arrive at this same request
3688 * To gtk_window_move_resize(), this will end up looking exactly
3689 * the same as the position being changed by the window
3693 /* FIXME are we handling gravity properly for framed windows? */
3695 gdk_window_move (window->frame,
3696 x - window->frame_left,
3697 y - window->frame_top);
3699 gdk_window_move (GTK_WIDGET (window)->window,
3704 /* Save this position to apply on mapping */
3705 info->initial_x = x;
3706 info->initial_y = y;
3707 info->initial_pos_set = TRUE;
3712 * gtk_window_get_position:
3713 * @window: a #GtkWindow
3714 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3715 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3717 * This function returns the position you need to pass to
3718 * gtk_window_move() to keep @window in its current position. This
3719 * means that the meaning of the returned value varies with window
3720 * gravity. See gtk_window_move() for more details.
3722 * If you haven't changed the window gravity, its gravity will be
3723 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3724 * gets the position of the top-left corner of the window manager
3725 * frame for the window. gtk_window_move() sets the position of this
3726 * same top-left corner.
3728 * gtk_window_get_position() is not 100% reliable because the X Window System
3729 * does not specify a way to obtain the geometry of the
3730 * decorations placed on a window by the window manager.
3731 * Thus GTK+ is using a "best guess" that works with most
3734 * Moreover, nearly all window managers are historically broken with
3735 * respect to their handling of window gravity. So moving a window to
3736 * its current position as returned by gtk_window_get_position() tends
3737 * to result in moving the window slightly. Window managers are
3738 * slowly getting better over time.
3740 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3741 * frame is not relevant, and thus gtk_window_get_position() will
3742 * always produce accurate results. However you can't use static
3743 * gravity to do things like place a window in a corner of the screen,
3744 * because static gravity ignores the window manager decorations.
3746 * If you are saving and restoring your application's window
3747 * positions, you should know that it's impossible for applications to
3748 * do this without getting it somewhat wrong because applications do
3749 * not have sufficient knowledge of window manager state. The Correct
3750 * Mechanism is to support the session management protocol (see the
3751 * "GnomeClient" object in the GNOME libraries for example) and allow
3752 * the window manager to save your window sizes and positions.
3757 gtk_window_get_position (GtkWindow *window,
3763 g_return_if_fail (GTK_IS_WINDOW (window));
3765 widget = GTK_WIDGET (window);
3767 if (window->gravity == GDK_GRAVITY_STATIC)
3769 if (GTK_WIDGET_MAPPED (widget))
3771 /* This does a server round-trip, which is sort of wrong;
3772 * but a server round-trip is inevitable for
3773 * gdk_window_get_frame_extents() in the usual
3774 * NorthWestGravity case below, so not sure what else to
3775 * do. We should likely be consistent about whether we get
3776 * the client-side info or the server-side info.
3778 gdk_window_get_origin (widget->window, root_x, root_y);
3782 GdkRectangle configure_request;
3784 gtk_window_compute_configure_request (window,
3788 *root_x = configure_request.x;
3789 *root_y = configure_request.y;
3794 GdkRectangle frame_extents;
3799 if (GTK_WIDGET_MAPPED (widget))
3802 gdk_window_get_frame_extents (window->frame, &frame_extents);
3804 gdk_window_get_frame_extents (widget->window, &frame_extents);
3805 x = frame_extents.x;
3806 y = frame_extents.y;
3807 gtk_window_get_size (window, &w, &h);
3811 /* We just say the frame has 0 size on all sides.
3812 * Not sure what else to do.
3814 gtk_window_compute_configure_request (window,
3817 x = frame_extents.x;
3818 y = frame_extents.y;
3819 w = frame_extents.width;
3820 h = frame_extents.height;
3823 switch (window->gravity)
3825 case GDK_GRAVITY_NORTH:
3826 case GDK_GRAVITY_CENTER:
3827 case GDK_GRAVITY_SOUTH:
3828 /* Find center of frame. */
3829 x += frame_extents.width / 2;
3830 /* Center client window on that point. */
3834 case GDK_GRAVITY_SOUTH_EAST:
3835 case GDK_GRAVITY_EAST:
3836 case GDK_GRAVITY_NORTH_EAST:
3837 /* Find right edge of frame */
3838 x += frame_extents.width;
3839 /* Align left edge of client at that point. */
3846 switch (window->gravity)
3848 case GDK_GRAVITY_WEST:
3849 case GDK_GRAVITY_CENTER:
3850 case GDK_GRAVITY_EAST:
3851 /* Find center of frame. */
3852 y += frame_extents.height / 2;
3853 /* Center client window there. */
3856 case GDK_GRAVITY_SOUTH_WEST:
3857 case GDK_GRAVITY_SOUTH:
3858 case GDK_GRAVITY_SOUTH_EAST:
3859 /* Find south edge of frame */
3860 y += frame_extents.height;
3861 /* Place bottom edge of client there */
3876 * gtk_window_reshow_with_initial_size:
3877 * @window: a #GtkWindow
3879 * Hides @window, then reshows it, resetting the
3880 * default size and position of the window. Used
3881 * by GUI builders only.
3884 gtk_window_reshow_with_initial_size (GtkWindow *window)
3888 g_return_if_fail (GTK_IS_WINDOW (window));
3890 widget = GTK_WIDGET (window);
3892 gtk_widget_hide (widget);
3893 gtk_widget_unrealize (widget);
3894 gtk_widget_show (widget);
3898 gtk_window_destroy (GtkObject *object)
3900 GtkWindow *window = GTK_WINDOW (object);
3902 toplevel_list = g_slist_remove (toplevel_list, window);
3904 if (window->transient_parent)
3905 gtk_window_set_transient_for (window, NULL);
3907 /* frees the icons */
3908 gtk_window_set_icon_list (window, NULL);
3910 if (window->has_user_ref_count)
3912 window->has_user_ref_count = FALSE;
3913 g_object_unref (window);
3917 gtk_window_group_remove_window (window->group, window);
3919 gtk_window_free_key_hash (window);
3921 GTK_OBJECT_CLASS (parent_class)->destroy (object);
3925 gtk_window_finalize (GObject *object)
3927 GtkWindow *window = GTK_WINDOW (object);
3928 GtkMnemonicHash *mnemonic_hash;
3930 g_free (window->title);
3931 g_free (window->wmclass_name);
3932 g_free (window->wmclass_class);
3933 g_free (window->wm_role);
3935 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
3937 _gtk_mnemonic_hash_free (mnemonic_hash);
3939 if (window->geometry_info)
3941 if (window->geometry_info->widget)
3942 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3943 gtk_widget_destroyed,
3944 &window->geometry_info->widget);
3945 g_free (window->geometry_info);
3948 if (window->keys_changed_handler)
3950 g_source_remove (window->keys_changed_handler);
3951 window->keys_changed_handler = 0;
3954 G_OBJECT_CLASS (parent_class)->finalize (object);
3958 gtk_window_show (GtkWidget *widget)
3960 GtkWindow *window = GTK_WINDOW (widget);
3961 GtkContainer *container = GTK_CONTAINER (window);
3962 gboolean need_resize;
3964 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3966 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3967 container->need_resize = FALSE;
3971 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3972 GtkAllocation allocation = { 0, 0 };
3973 GdkRectangle configure_request;
3974 GdkGeometry new_geometry;
3976 gboolean was_realized;
3978 /* We are going to go ahead and perform this configure request
3979 * and then emulate a configure notify by going ahead and
3980 * doing a size allocate. Sort of a synchronous
3981 * mini-copy of gtk_window_move_resize() here.
3983 gtk_window_compute_configure_request (window,
3988 /* We update this because we are going to go ahead
3989 * and gdk_window_resize() below, rather than
3992 info->last.configure_request.width = configure_request.width;
3993 info->last.configure_request.height = configure_request.height;
3995 /* and allocate the window - this is normally done
3996 * in move_resize in response to configure notify
3998 allocation.width = configure_request.width;
3999 allocation.height = configure_request.height;
4000 gtk_widget_size_allocate (widget, &allocation);
4002 /* Then we guarantee we have a realize */
4003 was_realized = FALSE;
4004 if (!GTK_WIDGET_REALIZED (widget))
4006 gtk_widget_realize (widget);
4007 was_realized = TRUE;
4010 /* Must be done after the windows are realized,
4011 * so that the decorations can be read
4013 gtk_decorated_window_calculate_frame_size (window);
4015 /* We only send configure request if we didn't just finish
4016 * creating the window; if we just created the window
4017 * then we created it with widget->allocation anyhow.
4020 gdk_window_move_resize (widget->window,
4021 configure_request.x,
4022 configure_request.y,
4023 configure_request.width,
4024 configure_request.height);
4027 gtk_container_check_resize (container);
4029 gtk_widget_map (widget);
4031 /* Try to make sure that we have some focused widget
4033 if (!window->focus_widget && !GTK_IS_PLUG (window))
4034 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4037 gtk_grab_add (widget);
4041 gtk_window_hide (GtkWidget *widget)
4043 GtkWindow *window = GTK_WINDOW (widget);
4045 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4046 gtk_widget_unmap (widget);
4049 gtk_grab_remove (widget);
4053 gtk_window_map (GtkWidget *widget)
4055 GtkWindow *window = GTK_WINDOW (widget);
4056 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4057 GdkWindow *toplevel;
4059 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4061 if (window->bin.child &&
4062 GTK_WIDGET_VISIBLE (window->bin.child) &&
4063 !GTK_WIDGET_MAPPED (window->bin.child))
4064 gtk_widget_map (window->bin.child);
4067 toplevel = window->frame;
4069 toplevel = widget->window;
4071 if (window->maximize_initially)
4072 gdk_window_maximize (toplevel);
4074 gdk_window_unmaximize (toplevel);
4076 if (window->stick_initially)
4077 gdk_window_stick (toplevel);
4079 gdk_window_unstick (toplevel);
4081 if (window->iconify_initially)
4082 gdk_window_iconify (toplevel);
4084 gdk_window_deiconify (toplevel);
4086 if (priv->fullscreen_initially)
4087 gdk_window_fullscreen (toplevel);
4089 gdk_window_unfullscreen (toplevel);
4091 gdk_window_set_keep_above (toplevel, priv->above_initially);
4093 gdk_window_set_keep_below (toplevel, priv->below_initially);
4095 /* No longer use the default settings */
4096 window->need_default_size = FALSE;
4097 window->need_default_position = FALSE;
4099 gdk_window_show (widget->window);
4102 gdk_window_show (window->frame);
4104 if (!disable_startup_notification &&
4105 !sent_startup_notification)
4107 sent_startup_notification = TRUE;
4108 gdk_notify_startup_complete ();
4113 gtk_window_map_event (GtkWidget *widget,
4116 if (!GTK_WIDGET_MAPPED (widget))
4118 /* we should be be unmapped, but are getting a MapEvent, this may happen
4119 * to toplevel XWindows if mapping was intercepted by a window manager
4120 * and an unmap request occoured while the MapRequestEvent was still
4121 * being handled. we work around this situaiton here by re-requesting
4122 * the window being unmapped. more details can be found in:
4123 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4125 gdk_window_hide (widget->window);
4131 gtk_window_unmap (GtkWidget *widget)
4133 GtkWindow *window = GTK_WINDOW (widget);
4134 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
4135 GtkWindowGeometryInfo *info;
4136 GdkWindowState state;
4138 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4140 gdk_window_withdraw (window->frame);
4142 gdk_window_withdraw (widget->window);
4144 window->configure_request_count = 0;
4145 window->configure_notify_received = FALSE;
4147 /* on unmap, we reset the default positioning of the window,
4148 * so it's placed again, but we don't reset the default
4149 * size of the window, so it's remembered.
4151 window->need_default_position = TRUE;
4153 info = gtk_window_get_geometry_info (window, FALSE);
4156 info->initial_pos_set = FALSE;
4157 info->position_constraints_changed = FALSE;
4160 state = gdk_window_get_state (widget->window);
4161 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
4162 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
4163 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
4164 priv->above_initially = state & GDK_WINDOW_STATE_ABOVE;
4165 priv->below_initially = state & GDK_WINDOW_STATE_BELOW;
4169 gtk_window_realize (GtkWidget *widget)
4172 GdkWindow *parent_window;
4173 GdkWindowAttr attributes;
4174 gint attributes_mask;
4175 GtkWindowPrivate *priv;
4177 window = GTK_WINDOW (widget);
4179 priv = GTK_WINDOW_GET_PRIVATE (window);
4181 /* ensure widget tree is properly size allocated */
4182 if (widget->allocation.x == -1 &&
4183 widget->allocation.y == -1 &&
4184 widget->allocation.width == 1 &&
4185 widget->allocation.height == 1)
4187 GtkRequisition requisition;
4188 GtkAllocation allocation = { 0, 0, 200, 200 };
4190 gtk_widget_size_request (widget, &requisition);
4191 if (requisition.width || requisition.height)
4193 /* non-empty window */
4194 allocation.width = requisition.width;
4195 allocation.height = requisition.height;
4197 gtk_widget_size_allocate (widget, &allocation);
4199 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4201 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
4204 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4206 switch (window->type)
4208 case GTK_WINDOW_TOPLEVEL:
4209 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4211 case GTK_WINDOW_POPUP:
4212 attributes.window_type = GDK_WINDOW_TEMP;
4215 g_warning (G_STRLOC": Unknown window type %d!", window->type);
4219 attributes.title = window->title;
4220 attributes.wmclass_name = window->wmclass_name;
4221 attributes.wmclass_class = window->wmclass_class;
4222 attributes.wclass = GDK_INPUT_OUTPUT;
4223 attributes.visual = gtk_widget_get_visual (widget);
4224 attributes.colormap = gtk_widget_get_colormap (widget);
4226 if (window->has_frame)
4228 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
4229 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
4230 attributes.event_mask = (GDK_EXPOSURE_MASK |
4231 GDK_KEY_PRESS_MASK |
4232 GDK_ENTER_NOTIFY_MASK |
4233 GDK_LEAVE_NOTIFY_MASK |
4234 GDK_FOCUS_CHANGE_MASK |
4235 GDK_STRUCTURE_MASK |
4236 GDK_BUTTON_MOTION_MASK |
4237 GDK_POINTER_MOTION_HINT_MASK |
4238 GDK_BUTTON_PRESS_MASK |
4239 GDK_BUTTON_RELEASE_MASK);
4241 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4243 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4244 &attributes, attributes_mask);
4246 gdk_window_set_user_data (window->frame, widget);
4248 attributes.window_type = GDK_WINDOW_CHILD;
4249 attributes.x = window->frame_left;
4250 attributes.y = window->frame_top;
4252 attributes_mask = GDK_WA_X | GDK_WA_Y;
4254 parent_window = window->frame;
4258 attributes_mask = 0;
4259 parent_window = gtk_widget_get_root_window (widget);
4262 attributes.width = widget->allocation.width;
4263 attributes.height = widget->allocation.height;
4264 attributes.event_mask = gtk_widget_get_events (widget);
4265 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4266 GDK_KEY_PRESS_MASK |
4267 GDK_KEY_RELEASE_MASK |
4268 GDK_ENTER_NOTIFY_MASK |
4269 GDK_LEAVE_NOTIFY_MASK |
4270 GDK_FOCUS_CHANGE_MASK |
4271 GDK_STRUCTURE_MASK);
4273 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
4274 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
4275 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
4277 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
4279 gdk_window_enable_synchronized_configure (widget->window);
4281 gdk_window_set_user_data (widget->window, window);
4283 widget->style = gtk_style_attach (widget->style, widget->window);
4284 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4286 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
4288 /* This is a bad hack to set the window background. */
4289 gtk_window_paint (widget, NULL);
4291 if (window->transient_parent &&
4292 GTK_WIDGET_REALIZED (window->transient_parent))
4293 gdk_window_set_transient_for (widget->window,
4294 GTK_WIDGET (window->transient_parent)->window);
4296 if (window->wm_role)
4297 gdk_window_set_role (widget->window, window->wm_role);
4299 if (!window->decorated)
4300 gdk_window_set_decorations (widget->window, 0);
4302 if (!priv->deletable)
4303 gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4305 gdk_window_set_type_hint (widget->window, window->type_hint);
4307 if (gtk_window_get_skip_pager_hint (window))
4308 gdk_window_set_skip_pager_hint (widget->window, TRUE);
4310 if (gtk_window_get_skip_taskbar_hint (window))
4311 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
4313 if (gtk_window_get_accept_focus (window))
4314 gdk_window_set_accept_focus (widget->window, TRUE);
4316 gdk_window_set_accept_focus (widget->window, FALSE);
4318 if (gtk_window_get_focus_on_map (window))
4319 gdk_window_set_focus_on_map (widget->window, TRUE);
4321 gdk_window_set_focus_on_map (widget->window, FALSE);
4324 gdk_window_set_modal_hint (widget->window, TRUE);
4326 gdk_window_set_modal_hint (widget->window, FALSE);
4329 gtk_window_realize_icon (window);
4333 gtk_window_unrealize (GtkWidget *widget)
4336 GtkWindowGeometryInfo *info;
4338 window = GTK_WINDOW (widget);
4340 /* On unrealize, we reset the size of the window such
4341 * that we will re-apply the default sizing stuff
4342 * next time we show the window.
4344 * Default positioning is reset on unmap, instead of unrealize.
4346 window->need_default_size = TRUE;
4347 info = gtk_window_get_geometry_info (window, FALSE);
4350 info->resize_width = -1;
4351 info->resize_height = -1;
4352 info->last.configure_request.x = 0;
4353 info->last.configure_request.y = 0;
4354 info->last.configure_request.width = -1;
4355 info->last.configure_request.height = -1;
4356 /* be sure we reset geom hints on re-realize */
4357 info->last.flags = 0;
4362 gdk_window_set_user_data (window->frame, NULL);
4363 gdk_window_destroy (window->frame);
4364 window->frame = NULL;
4368 gtk_window_unrealize_icon (window);
4370 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
4374 gtk_window_size_request (GtkWidget *widget,
4375 GtkRequisition *requisition)
4380 window = GTK_WINDOW (widget);
4381 bin = GTK_BIN (window);
4383 requisition->width = GTK_CONTAINER (window)->border_width * 2;
4384 requisition->height = GTK_CONTAINER (window)->border_width * 2;
4386 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
4388 GtkRequisition child_requisition;
4390 gtk_widget_size_request (bin->child, &child_requisition);
4392 requisition->width += child_requisition.width;
4393 requisition->height += child_requisition.height;
4398 gtk_window_size_allocate (GtkWidget *widget,
4399 GtkAllocation *allocation)
4402 GtkAllocation child_allocation;
4404 window = GTK_WINDOW (widget);
4405 widget->allocation = *allocation;
4407 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
4409 child_allocation.x = GTK_CONTAINER (window)->border_width;
4410 child_allocation.y = GTK_CONTAINER (window)->border_width;
4411 child_allocation.width =
4412 MAX (1, (gint)allocation->width - child_allocation.x * 2);
4413 child_allocation.height =
4414 MAX (1, (gint)allocation->height - child_allocation.y * 2);
4416 gtk_widget_size_allocate (window->bin.child, &child_allocation);
4419 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4421 gdk_window_resize (window->frame,
4422 allocation->width + window->frame_left + window->frame_right,
4423 allocation->height + window->frame_top + window->frame_bottom);
4428 gtk_window_event (GtkWidget *widget, GdkEvent *event)
4431 gboolean return_val;
4433 window = GTK_WINDOW (widget);
4435 if (window->frame && (event->any.window == window->frame))
4437 if ((event->type != GDK_KEY_PRESS) &&
4438 (event->type != GDK_KEY_RELEASE) &&
4439 (event->type != GDK_FOCUS_CHANGE))
4441 g_signal_stop_emission_by_name (widget, "event");
4443 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
4448 g_object_unref (event->any.window);
4449 event->any.window = g_object_ref (widget->window);
4457 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
4459 GdkEventConfigure *configure_event;
4462 switch (event->type)
4465 configure_event = (GdkEventConfigure *)event;
4467 /* Invalidate the decorations */
4470 rect.width = configure_event->width;
4471 rect.height = configure_event->height;
4473 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
4475 /* Pass on the (modified) configure event */
4476 configure_event->width -= window->frame_left + window->frame_right;
4477 configure_event->height -= window->frame_top + window->frame_bottom;
4478 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
4487 gtk_window_configure_event (GtkWidget *widget,
4488 GdkEventConfigure *event)
4490 GtkWindow *window = GTK_WINDOW (widget);
4491 gboolean expected_reply = window->configure_request_count > 0;
4493 /* window->configure_request_count incremented for each
4494 * configure request, and decremented to a min of 0 for
4495 * each configure notify.
4497 * All it means is that we know we will get at least
4498 * window->configure_request_count more configure notifies.
4499 * We could get more configure notifies than that; some
4500 * of the configure notifies we get may be unrelated to
4501 * the configure requests. But we will get at least
4502 * window->configure_request_count notifies.
4505 if (window->configure_request_count > 0)
4506 window->configure_request_count -= 1;
4508 /* As an optimization, we avoid a resize when possible.
4510 * The only times we can avoid a resize are:
4511 * - we know only the position changed, not the size
4512 * - we know we have made more requests and so will get more
4513 * notifies and can wait to resize when we get them
4516 if (!expected_reply &&
4517 (widget->allocation.width == event->width &&
4518 widget->allocation.height == event->height))
4520 gdk_window_configure_finished (widget->window);
4525 * If we do need to resize, we do that by:
4526 * - filling in widget->allocation with the new size
4527 * - setting configure_notify_received to TRUE
4528 * for use in gtk_window_move_resize()
4529 * - queueing a resize, leading to invocation of
4530 * gtk_window_move_resize() in an idle handler
4534 window->configure_notify_received = TRUE;
4536 widget->allocation.width = event->width;
4537 widget->allocation.height = event->height;
4539 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4544 /* the accel_key and accel_mods fields of the key have to be setup
4545 * upon calling this function. it'll then return whether that key
4546 * is at all used as accelerator, and if so will OR in the
4547 * accel_flags member of the key.
4550 _gtk_window_query_nonaccels (GtkWindow *window,
4552 GdkModifierType accel_mods)
4554 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4556 /* movement keys are considered locked accels */
4559 static const guint bindings[] = {
4560 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
4561 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
4565 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
4566 if (bindings[i] == accel_key)
4570 /* mnemonics are considered locked accels */
4571 if (accel_mods == window->mnemonic_modifier)
4573 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4574 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
4582 * gtk_window_propagate_key_event:
4583 * @window: a #GtkWindow
4584 * @event: a #GdkEventKey
4586 * Propagate a key press or release event to the focus widget and
4587 * up the focus container chain until a widget handles @event.
4588 * This is normally called by the default ::key_press_event and
4589 * ::key_release_event handlers for toplevel windows,
4590 * however in some cases it may be useful to call this directly when
4591 * overriding the standard key handling for a toplevel window.
4593 * Return value: %TRUE if a widget in the focus chain handled the event.
4596 gtk_window_propagate_key_event (GtkWindow *window,
4599 gboolean handled = FALSE;
4600 GtkWidget *widget, *focus;
4602 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4604 widget = GTK_WIDGET (window);
4605 focus = window->focus_widget;
4607 g_object_ref (focus);
4610 focus && focus != widget &&
4611 gtk_widget_get_toplevel (focus) == widget)
4615 if (GTK_WIDGET_IS_SENSITIVE (focus))
4616 handled = gtk_widget_event (focus, (GdkEvent*) event);
4618 parent = focus->parent;
4620 g_object_ref (parent);
4622 g_object_unref (focus);
4628 g_object_unref (focus);
4634 gtk_window_key_press_event (GtkWidget *widget,
4637 GtkWindow *window = GTK_WINDOW (widget);
4638 gboolean handled = FALSE;
4640 /* handle mnemonics and accelerators */
4642 handled = gtk_window_activate_key (window, event);
4644 /* handle focus widget key events */
4646 handled = gtk_window_propagate_key_event (window, event);
4648 /* Chain up, invokes binding set */
4650 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4656 gtk_window_key_release_event (GtkWidget *widget,
4659 GtkWindow *window = GTK_WINDOW (widget);
4660 gboolean handled = FALSE;
4662 /* handle focus widget key events */
4664 handled = gtk_window_propagate_key_event (window, event);
4666 /* Chain up, invokes binding set */
4668 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4674 gtk_window_real_activate_default (GtkWindow *window)
4676 gtk_window_activate_default (window);
4680 gtk_window_real_activate_focus (GtkWindow *window)
4682 gtk_window_activate_focus (window);
4686 gtk_window_move_focus (GtkWindow *window,
4687 GtkDirectionType dir)
4689 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4691 if (!GTK_CONTAINER (window)->focus_child)
4692 gtk_window_set_focus (window, NULL);
4696 gtk_window_enter_notify_event (GtkWidget *widget,
4697 GdkEventCrossing *event)
4703 gtk_window_leave_notify_event (GtkWidget *widget,
4704 GdkEventCrossing *event)
4710 do_focus_change (GtkWidget *widget,
4713 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4715 g_object_ref (widget);
4718 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4720 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4722 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4723 fevent->focus_change.window = widget->window;
4725 g_object_ref (widget->window);
4726 fevent->focus_change.in = in;
4728 gtk_widget_event (widget, fevent);
4730 g_object_notify (G_OBJECT (widget), "has-focus");
4732 g_object_unref (widget);
4733 gdk_event_free (fevent);
4737 gtk_window_focus_in_event (GtkWidget *widget,
4738 GdkEventFocus *event)
4740 GtkWindow *window = GTK_WINDOW (widget);
4742 /* It appears spurious focus in events can occur when
4743 * the window is hidden. So we'll just check to see if
4744 * the window is visible before actually handling the
4747 if (GTK_WIDGET_VISIBLE (widget))
4749 _gtk_window_set_has_toplevel_focus (window, TRUE);
4750 _gtk_window_set_is_active (window, TRUE);
4757 gtk_window_focus_out_event (GtkWidget *widget,
4758 GdkEventFocus *event)
4760 GtkWindow *window = GTK_WINDOW (widget);
4762 _gtk_window_set_has_toplevel_focus (window, FALSE);
4763 _gtk_window_set_is_active (window, FALSE);
4768 static GdkAtom atom_rcfiles = GDK_NONE;
4769 static GdkAtom atom_iconthemes = GDK_NONE;
4772 send_client_message_to_embedded_windows (GtkWidget *widget,
4773 GdkAtom message_type)
4775 GList *embedded_windows;
4777 embedded_windows = g_object_get_data (G_OBJECT (widget), "gtk-embedded");
4778 if (embedded_windows)
4780 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4783 for (i = 0; i < 5; i++)
4784 send_event->client.data.l[i] = 0;
4785 send_event->client.data_format = 32;
4786 send_event->client.message_type = message_type;
4788 while (embedded_windows)
4790 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4791 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4792 embedded_windows = embedded_windows->next;
4795 gdk_event_free (send_event);
4800 gtk_window_client_event (GtkWidget *widget,
4801 GdkEventClient *event)
4805 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
4806 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
4809 if (event->message_type == atom_rcfiles)
4811 send_client_message_to_embedded_windows (widget, atom_rcfiles);
4812 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4815 if (event->message_type == atom_iconthemes)
4817 send_client_message_to_embedded_windows (widget, atom_iconthemes);
4818 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
4825 gtk_window_check_resize (GtkContainer *container)
4827 GtkWindow *window = GTK_WINDOW (container);
4829 if (GTK_WIDGET_VISIBLE (container))
4830 gtk_window_move_resize (window);
4834 gtk_window_focus (GtkWidget *widget,
4835 GtkDirectionType direction)
4839 GtkContainer *container;
4840 GtkWidget *old_focus_child;
4843 container = GTK_CONTAINER (widget);
4844 window = GTK_WINDOW (widget);
4845 bin = GTK_BIN (widget);
4847 old_focus_child = container->focus_child;
4849 /* We need a special implementation here to deal properly with wrapping
4850 * around in the tab chain without the danger of going into an
4853 if (old_focus_child)
4855 if (gtk_widget_child_focus (old_focus_child, direction))
4859 if (window->focus_widget)
4861 if (direction == GTK_DIR_LEFT ||
4862 direction == GTK_DIR_RIGHT ||
4863 direction == GTK_DIR_UP ||
4864 direction == GTK_DIR_DOWN)
4869 /* Wrapped off the end, clear the focus setting for the toplpevel */
4870 parent = window->focus_widget->parent;
4873 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4874 parent = GTK_WIDGET (parent)->parent;
4877 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4880 /* Now try to focus the first widget in the window */
4883 if (gtk_widget_child_focus (bin->child, direction))
4891 gtk_window_real_set_focus (GtkWindow *window,
4894 GtkWidget *old_focus = window->focus_widget;
4895 gboolean had_default = FALSE;
4896 gboolean focus_had_default = FALSE;
4897 gboolean old_focus_had_default = FALSE;
4901 g_object_ref (old_focus);
4902 g_object_freeze_notify (G_OBJECT (old_focus));
4903 old_focus_had_default = GTK_WIDGET_HAS_DEFAULT (old_focus);
4907 g_object_ref (focus);
4908 g_object_freeze_notify (G_OBJECT (focus));
4909 focus_had_default = GTK_WIDGET_HAS_DEFAULT (focus);
4912 if (window->default_widget)
4913 had_default = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4915 if (window->focus_widget)
4917 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4918 (window->focus_widget != window->default_widget))
4920 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4921 gtk_widget_queue_draw (window->focus_widget);
4923 if (window->default_widget)
4924 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4927 window->focus_widget = NULL;
4929 if (window->has_focus)
4930 do_focus_change (old_focus, FALSE);
4932 g_object_notify (G_OBJECT (old_focus), "is-focus");
4935 /* The above notifications may have set a new focus widget,
4936 * if so, we don't want to override it.
4938 if (focus && !window->focus_widget)
4940 window->focus_widget = focus;
4942 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4943 (window->focus_widget != window->default_widget))
4945 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4946 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4948 if (window->default_widget)
4949 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4952 if (window->has_focus)
4953 do_focus_change (window->focus_widget, TRUE);
4955 g_object_notify (G_OBJECT (window->focus_widget), "is-focus");
4958 /* If the default widget changed, a redraw will have been queued
4959 * on the old and new default widgets by gtk_window_set_default(), so
4960 * we only have to worry about the case where it didn't change.
4961 * We'll sometimes queue a draw twice on the new widget but that
4964 if (window->default_widget &&
4965 (had_default != GTK_WIDGET_HAS_DEFAULT (window->default_widget)))
4966 gtk_widget_queue_draw (window->default_widget);
4970 if (old_focus_had_default != GTK_WIDGET_HAS_DEFAULT (old_focus))
4971 gtk_widget_queue_draw (old_focus);
4973 g_object_thaw_notify (G_OBJECT (old_focus));
4974 g_object_unref (old_focus);
4978 if (focus_had_default != GTK_WIDGET_HAS_DEFAULT (focus))
4979 gtk_widget_queue_draw (focus);
4981 g_object_thaw_notify (G_OBJECT (focus));
4982 g_object_unref (focus);
4987 * _gtk_window_unset_focus_and_default:
4988 * @window: a #GtkWindow
4989 * @widget: a widget inside of @window
4991 * Checks whether the focus and default widgets of @window are
4992 * @widget or a descendent of @widget, and if so, unset them.
4995 _gtk_window_unset_focus_and_default (GtkWindow *window,
5001 g_object_ref (window);
5002 g_object_ref (widget);
5004 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
5006 child = window->focus_widget;
5008 while (child && child != widget)
5009 child = child->parent;
5011 if (child == widget)
5012 gtk_window_set_focus (GTK_WINDOW (window), NULL);
5015 child = window->default_widget;
5017 while (child && child != widget)
5018 child = child->parent;
5020 if (child == widget)
5021 gtk_window_set_default (window, NULL);
5023 g_object_unref (widget);
5024 g_object_unref (window);
5027 /*********************************
5028 * Functions related to resizing *
5029 *********************************/
5031 /* This function doesn't constrain to geometry hints */
5033 gtk_window_compute_configure_request_size (GtkWindow *window,
5037 GtkRequisition requisition;
5038 GtkWindowGeometryInfo *info;
5042 * - we've done a size request
5045 widget = GTK_WIDGET (window);
5047 info = gtk_window_get_geometry_info (window, FALSE);
5049 if (window->need_default_size)
5051 gtk_widget_get_child_requisition (widget, &requisition);
5053 /* Default to requisition */
5054 *width = requisition.width;
5055 *height = requisition.height;
5057 /* If window is empty so requests 0, default to random nonzero size */
5058 if (*width == 0 && *height == 0)
5064 /* Override requisition with default size */
5068 gint base_width = 0;
5069 gint base_height = 0;
5071 gint height_inc = 1;
5073 if (info->default_is_geometry &&
5074 (info->default_width > 0 || info->default_height > 0))
5076 GdkGeometry geometry;
5079 gtk_window_compute_hints (window, &geometry, &flags);
5081 if (flags & GDK_HINT_BASE_SIZE)
5083 base_width = geometry.base_width;
5084 base_height = geometry.base_height;
5086 else if (flags & GDK_HINT_MIN_SIZE)
5088 base_width = geometry.min_width;
5089 base_height = geometry.min_height;
5091 if (flags & GDK_HINT_RESIZE_INC)
5093 width_inc = geometry.width_inc;
5094 height_inc = geometry.height_inc;
5098 if (info->default_width > 0)
5099 *width = info->default_width * width_inc + base_width;
5101 if (info->default_height > 0)
5102 *height = info->default_height * height_inc + base_height;
5107 /* Default to keeping current size */
5108 *width = widget->allocation.width;
5109 *height = widget->allocation.height;
5112 /* Override any size with gtk_window_resize() values */
5115 if (info->resize_width > 0)
5116 *width = info->resize_width;
5118 if (info->resize_height > 0)
5119 *height = info->resize_height;
5123 static GtkWindowPosition
5124 get_effective_position (GtkWindow *window)
5126 GtkWindowPosition pos = window->position;
5127 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5128 (window->transient_parent == NULL ||
5129 !GTK_WIDGET_MAPPED (window->transient_parent)))
5130 pos = GTK_WIN_POS_NONE;
5136 get_center_monitor_of_window (GtkWindow *window)
5138 /* We could try to sort out the relative positions of the monitors and
5139 * stuff, or we could just be losers and assume you have a row
5140 * or column of monitors.
5142 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5146 get_monitor_containing_pointer (GtkWindow *window)
5150 GdkScreen *window_screen;
5151 GdkScreen *pointer_screen;
5153 window_screen = gtk_window_check_screen (window);
5154 gdk_display_get_pointer (gdk_screen_get_display (window_screen),
5158 if (pointer_screen == window_screen)
5159 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5167 center_window_on_monitor (GtkWindow *window,
5173 GdkRectangle monitor;
5176 monitor_num = get_monitor_containing_pointer (window);
5178 if (monitor_num == -1)
5179 monitor_num = get_center_monitor_of_window (window);
5181 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5182 monitor_num, &monitor);
5184 *x = (monitor.width - w) / 2 + monitor.x;
5185 *y = (monitor.height - h) / 2 + monitor.y;
5187 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5188 * and WM decorations.
5197 clamp_window_to_rectangle (gint *x,
5201 const GdkRectangle *rect)
5203 gint outside_w, outside_h;
5205 outside_w = (*x + w) - (rect->x + rect->width);
5209 outside_h = (*y + h) - (rect->y + rect->height);
5213 /* if larger than the screen, center on the screen. */
5215 *x += (rect->x - *x) / 2;
5217 *y += (rect->y - *y) / 2;
5222 gtk_window_compute_configure_request (GtkWindow *window,
5223 GdkRectangle *request,
5224 GdkGeometry *geometry,
5227 GdkGeometry new_geometry;
5231 GtkWindowPosition pos;
5232 GtkWidget *parent_widget;
5233 GtkWindowGeometryInfo *info;
5237 widget = GTK_WIDGET (window);
5239 screen = gtk_window_check_screen (window);
5241 gtk_widget_size_request (widget, NULL);
5242 gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
5244 gtk_window_compute_hints (window, &new_geometry, &new_flags);
5245 gtk_window_constrain_size (window,
5246 &new_geometry, new_flags,
5250 parent_widget = (GtkWidget*) window->transient_parent;
5252 pos = get_effective_position (window);
5253 info = gtk_window_get_geometry_info (window, TRUE);
5255 /* by default, don't change position requested */
5256 x = info->last.configure_request.x;
5257 y = info->last.configure_request.y;
5259 if (window->need_default_position)
5262 /* FIXME this all interrelates with window gravity.
5263 * For most of them I think we want to set GRAVITY_CENTER.
5265 * Not sure how to go about that.
5270 /* here we are only handling CENTER_ALWAYS
5271 * as it relates to default positioning,
5272 * where it's equivalent to simply CENTER
5274 case GTK_WIN_POS_CENTER_ALWAYS:
5275 case GTK_WIN_POS_CENTER:
5276 center_window_on_monitor (window, w, h, &x, &y);
5279 case GTK_WIN_POS_CENTER_ON_PARENT:
5282 GdkRectangle monitor;
5285 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
5287 if (parent_widget->window != NULL)
5288 monitor_num = gdk_screen_get_monitor_at_window (screen,
5289 parent_widget->window);
5293 gdk_window_get_origin (parent_widget->window,
5296 x = ox + (parent_widget->allocation.width - w) / 2;
5297 y = oy + (parent_widget->allocation.height - h) / 2;
5299 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5300 * WM decorations. If parent wasn't on a monitor, just
5303 if (monitor_num >= 0)
5305 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5306 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5311 case GTK_WIN_POS_MOUSE:
5313 gint screen_width = gdk_screen_get_width (screen);
5314 gint screen_height = gdk_screen_get_height (screen);
5316 GdkRectangle monitor;
5317 GdkScreen *pointer_screen;
5320 gdk_display_get_pointer (gdk_screen_get_display (screen),
5324 if (pointer_screen == screen)
5325 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
5331 x = CLAMP (x, 0, screen_width - w);
5332 y = CLAMP (y, 0, screen_height - h);
5334 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5335 * WM decorations. Don't try to figure out what's going
5336 * on if the mouse wasn't inside a monitor.
5338 if (monitor_num >= 0)
5340 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5341 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5349 } /* if (window->need_default_position) */
5351 if (window->need_default_position &&
5352 info->initial_pos_set)
5354 x = info->initial_x;
5355 y = info->initial_y;
5356 gtk_window_constrain_position (window, w, h, &x, &y);
5362 request->height = h;
5365 *geometry = new_geometry;
5371 gtk_window_constrain_position (GtkWindow *window,
5377 /* See long comments in gtk_window_move_resize()
5378 * on when it's safe to call this function.
5380 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
5382 gint center_x, center_y;
5384 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
5392 gtk_window_move_resize (GtkWindow *window)
5396 * First we determine whether any information has changed that would
5397 * cause us to revise our last configure request. If we would send
5398 * a different configure request from last time, then
5399 * configure_request_size_changed = TRUE or
5400 * configure_request_pos_changed = TRUE. configure_request_size_changed
5401 * may be true due to new hints, a gtk_window_resize(), or whatever.
5402 * configure_request_pos_changed may be true due to gtk_window_set_position()
5403 * or gtk_window_move().
5405 * If the configure request has changed, we send off a new one. To
5406 * ensure GTK+ invariants are maintained (resize queue does what it
5407 * should), we go ahead and size_allocate the requested size in this
5410 * If the configure request has not changed, we don't ever resend
5411 * it, because it could mean fighting the user or window manager.
5414 * To prepare the configure request, we come up with a base size/pos:
5415 * - the one from gtk_window_move()/gtk_window_resize()
5416 * - else default_width, default_height if we haven't ever
5418 * - else the size request if we haven't ever been mapped,
5419 * as a substitute default size
5420 * - else the current size of the window, as received from
5421 * configure notifies (i.e. the current allocation)
5423 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
5424 * the position request to be centered.
5427 GtkContainer *container;
5428 GtkWindowGeometryInfo *info;
5429 GdkGeometry new_geometry;
5431 GdkRectangle new_request;
5432 gboolean configure_request_size_changed;
5433 gboolean configure_request_pos_changed;
5434 gboolean hints_changed; /* do we need to send these again */
5435 GtkWindowLastGeometryInfo saved_last_info;
5437 widget = GTK_WIDGET (window);
5438 container = GTK_CONTAINER (widget);
5439 info = gtk_window_get_geometry_info (window, TRUE);
5441 configure_request_size_changed = FALSE;
5442 configure_request_pos_changed = FALSE;
5444 gtk_window_compute_configure_request (window, &new_request,
5445 &new_geometry, &new_flags);
5447 /* This check implies the invariant that we never set info->last
5448 * without setting the hints and sending off a configure request.
5450 * If we change info->last without sending the request, we may
5453 if (info->last.configure_request.x != new_request.x ||
5454 info->last.configure_request.y != new_request.y)
5455 configure_request_pos_changed = TRUE;
5457 if ((info->last.configure_request.width != new_request.width ||
5458 info->last.configure_request.height != new_request.height))
5459 configure_request_size_changed = TRUE;
5461 hints_changed = FALSE;
5463 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
5464 &new_geometry, new_flags))
5466 hints_changed = TRUE;
5469 /* Position Constraints
5470 * ====================
5472 * POS_CENTER_ALWAYS is conceptually a constraint rather than
5473 * a default. The other POS_ values are used only when the
5474 * window is shown, not after that.
5476 * However, we can't implement a position constraint as
5477 * "anytime the window size changes, center the window"
5478 * because this may well end up fighting the WM or user. In
5479 * fact it gets in an infinite loop with at least one WM.
5481 * Basically, applications are in no way in a position to
5482 * constrain the position of a window, with one exception:
5483 * override redirect windows. (Really the intended purpose
5484 * of CENTER_ALWAYS anyhow, I would think.)
5486 * So the way we implement this "constraint" is to say that when WE
5487 * cause a move or resize, i.e. we make a configure request changing
5488 * window size, we recompute the CENTER_ALWAYS position to reflect
5489 * the new window size, and include it in our request. Also, if we
5490 * just turned on CENTER_ALWAYS we snap to center with a new
5491 * request. Otherwise, if we are just NOTIFIED of a move or resize
5492 * done by someone else e.g. the window manager, we do NOT send a
5493 * new configure request.
5495 * For override redirect windows, this works fine; all window
5496 * sizes are from our configure requests. For managed windows,
5497 * it is at least semi-sane, though who knows what the
5498 * app author is thinking.
5501 /* This condition should be kept in sync with the condition later on
5502 * that determines whether we send a configure request. i.e. we
5503 * should do this position constraining anytime we were going to
5504 * send a configure request anyhow, plus when constraints have
5507 if (configure_request_pos_changed ||
5508 configure_request_size_changed ||
5510 info->position_constraints_changed)
5512 /* We request the constrained position if:
5513 * - we were changing position, and need to clamp
5514 * the change to the constraint
5515 * - we're changing the size anyway
5516 * - set_position() was called to toggle CENTER_ALWAYS on
5519 gtk_window_constrain_position (window,
5525 /* Update whether we need to request a move */
5526 if (info->last.configure_request.x != new_request.x ||
5527 info->last.configure_request.y != new_request.y)
5528 configure_request_pos_changed = TRUE;
5530 configure_request_pos_changed = FALSE;
5534 if (window->type == GTK_WINDOW_TOPLEVEL)
5536 int notify_x, notify_y;
5538 /* this is the position from the last configure notify */
5539 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
5541 g_message ("--- %s ---\n"
5542 "last : %d,%d\t%d x %d\n"
5543 "this : %d,%d\t%d x %d\n"
5544 "alloc : %d,%d\t%d x %d\n"
5546 "resize: \t%d x %d\n"
5547 "size_changed: %d pos_changed: %d hints_changed: %d\n"
5548 "configure_notify_received: %d\n"
5549 "configure_request_count: %d\n"
5550 "position_constraints_changed: %d\n",
5551 window->title ? window->title : "(no title)",
5552 info->last.configure_request.x,
5553 info->last.configure_request.y,
5554 info->last.configure_request.width,
5555 info->last.configure_request.height,
5561 widget->allocation.width,
5562 widget->allocation.height,
5563 widget->requisition.width,
5564 widget->requisition.height,
5566 info->resize_height,
5567 configure_request_pos_changed,
5568 configure_request_size_changed,
5570 window->configure_notify_received,
5571 window->configure_request_count,
5572 info->position_constraints_changed);
5576 saved_last_info = info->last;
5577 info->last.geometry = new_geometry;
5578 info->last.flags = new_flags;
5579 info->last.configure_request = new_request;
5581 /* need to set PPosition so the WM will look at our position,
5582 * but we don't want to count PPosition coming and going as a hints
5583 * change for future iterations. So we saved info->last prior to
5587 /* Also, if the initial position was explicitly set, then we always
5588 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
5592 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
5593 * this is an initial map
5596 if ((configure_request_pos_changed ||
5597 info->initial_pos_set ||
5598 (window->need_default_position &&
5599 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
5600 (new_flags & GDK_HINT_POS) == 0)
5602 new_flags |= GDK_HINT_POS;
5603 hints_changed = TRUE;
5606 /* Set hints if necessary
5609 gdk_window_set_geometry_hints (widget->window,
5613 /* handle resizing/moving and widget tree allocation
5615 if (window->configure_notify_received)
5617 GtkAllocation allocation;
5619 /* If we have received a configure event since
5620 * the last time in this function, we need to
5621 * accept our new size and size_allocate child widgets.
5622 * (see gtk_window_configure_event() for more details).
5624 * 1 or more configure notifies may have been received.
5625 * Also, configure_notify_received will only be TRUE
5626 * if all expected configure notifies have been received
5627 * (one per configure request), as an optimization.
5630 window->configure_notify_received = FALSE;
5632 /* gtk_window_configure_event() filled in widget->allocation */
5633 allocation = widget->allocation;
5634 gtk_widget_size_allocate (widget, &allocation);
5636 gdk_window_process_all_updates ();
5638 gdk_window_configure_finished (widget->window);
5640 /* If the configure request changed, it means that
5642 * 1) coincidentally changed hints or widget properties
5643 * impacting the configure request before getting
5644 * a configure notify, or
5645 * 2) some broken widget is changing its size request
5646 * during size allocation, resulting in
5647 * a false appearance of changed configure request.
5649 * For 1), we could just go ahead and ask for the
5650 * new size right now, but doing that for 2)
5651 * might well be fighting the user (and can even
5652 * trigger a loop). Since we really don't want to
5653 * do that, we requeue a resize in hopes that
5654 * by the time it gets handled, the child has seen
5655 * the light and is willing to go along with the
5656 * new size. (this happens for the zvt widget, since
5657 * the size_allocate() above will have stored the
5658 * requisition corresponding to the new size in the
5661 * This doesn't buy us anything for 1), but it shouldn't
5662 * hurt us too badly, since it is what would have
5663 * happened if we had gotten the configure event before
5664 * the new size had been set.
5667 if (configure_request_size_changed ||
5668 configure_request_pos_changed)
5670 /* Don't change the recorded last info after all, because we
5671 * haven't actually updated to the new info yet - we decided
5672 * to postpone our configure request until later.
5674 info->last = saved_last_info;
5676 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
5679 return; /* Bail out, we didn't really process the move/resize */
5681 else if ((configure_request_size_changed || hints_changed) &&
5682 (widget->allocation.width != new_request.width ||
5683 widget->allocation.height != new_request.height))
5686 /* We are in one of the following situations:
5687 * A. configure_request_size_changed
5688 * our requisition has changed and we need a different window size,
5689 * so we request it from the window manager.
5690 * B. !configure_request_size_changed && hints_changed
5691 * the window manager rejects our size, but we have just changed the
5692 * window manager hints, so there's a chance our request will
5693 * be honoured this time, so we try again.
5695 * However, if the new requisition is the same as the current allocation,
5696 * we don't request it again, since we won't get a ConfigureNotify back from
5697 * the window manager unless it decides to change our requisition. If
5698 * we don't get the ConfigureNotify back, the resize queue will never be run.
5701 /* Now send the configure request */
5702 if (configure_request_pos_changed)
5706 gdk_window_move_resize (window->frame,
5707 new_request.x - window->frame_left,
5708 new_request.y - window->frame_top,
5709 new_request.width + window->frame_left + window->frame_right,
5710 new_request.height + window->frame_top + window->frame_bottom);
5711 gdk_window_resize (widget->window,
5712 new_request.width, new_request.height);
5715 gdk_window_move_resize (widget->window,
5716 new_request.x, new_request.y,
5717 new_request.width, new_request.height);
5719 else /* only size changed */
5722 gdk_window_resize (window->frame,
5723 new_request.width + window->frame_left + window->frame_right,
5724 new_request.height + window->frame_top + window->frame_bottom);
5725 gdk_window_resize (widget->window,
5726 new_request.width, new_request.height);
5729 /* Increment the number of have-not-yet-received-notify requests */
5730 window->configure_request_count += 1;
5732 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5733 * configure event in response to our resizing request.
5734 * the configure event will cause a new resize with
5735 * ->configure_notify_received=TRUE.
5736 * until then, we want to
5737 * - discard expose events
5738 * - coalesce resizes for our children
5739 * - defer any window resizes until the configure event arrived
5740 * to achieve this, we queue a resize for the window, but remove its
5741 * resizing handler, so resizing will not be handled from the next
5742 * idle handler but when the configure event arrives.
5744 * FIXME: we should also dequeue the pending redraws here, since
5745 * we handle those ourselves upon ->configure_notify_received==TRUE.
5747 if (container->resize_mode == GTK_RESIZE_QUEUE)
5749 gtk_widget_queue_resize (widget);
5750 _gtk_container_dequeue_resize_handler (container);
5755 /* Handle any position changes.
5757 if (configure_request_pos_changed)
5761 gdk_window_move (window->frame,
5762 new_request.x - window->frame_left,
5763 new_request.y - window->frame_top);
5766 gdk_window_move (widget->window,
5767 new_request.x, new_request.y);
5770 /* And run the resize queue.
5772 gtk_container_resize_children (container);
5775 /* We have now processed a move/resize since the last position
5776 * constraint change, setting of the initial position, or resize.
5777 * (Not resetting these flags here can lead to infinite loops for
5778 * GTK_RESIZE_IMMEDIATE containers)
5780 info->position_constraints_changed = FALSE;
5781 info->initial_pos_set = FALSE;
5782 info->resize_width = -1;
5783 info->resize_height = -1;
5786 /* Compare two sets of Geometry hints for equality.
5789 gtk_window_compare_hints (GdkGeometry *geometry_a,
5791 GdkGeometry *geometry_b,
5794 if (flags_a != flags_b)
5797 if ((flags_a & GDK_HINT_MIN_SIZE) &&
5798 (geometry_a->min_width != geometry_b->min_width ||
5799 geometry_a->min_height != geometry_b->min_height))
5802 if ((flags_a & GDK_HINT_MAX_SIZE) &&
5803 (geometry_a->max_width != geometry_b->max_width ||
5804 geometry_a->max_height != geometry_b->max_height))
5807 if ((flags_a & GDK_HINT_BASE_SIZE) &&
5808 (geometry_a->base_width != geometry_b->base_width ||
5809 geometry_a->base_height != geometry_b->base_height))
5812 if ((flags_a & GDK_HINT_ASPECT) &&
5813 (geometry_a->min_aspect != geometry_b->min_aspect ||
5814 geometry_a->max_aspect != geometry_b->max_aspect))
5817 if ((flags_a & GDK_HINT_RESIZE_INC) &&
5818 (geometry_a->width_inc != geometry_b->width_inc ||
5819 geometry_a->height_inc != geometry_b->height_inc))
5822 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5823 geometry_a->win_gravity != geometry_b->win_gravity)
5830 _gtk_window_constrain_size (GtkWindow *window,
5836 GtkWindowGeometryInfo *info;
5838 g_return_if_fail (GTK_IS_WINDOW (window));
5840 info = window->geometry_info;
5843 GdkWindowHints flags = info->last.flags;
5844 GdkGeometry *geometry = &info->last.geometry;
5846 gtk_window_constrain_size (window,
5857 gtk_window_constrain_size (GtkWindow *window,
5858 GdkGeometry *geometry,
5865 gdk_window_constrain_size (geometry, flags, width, height,
5866 new_width, new_height);
5869 /* Compute the set of geometry hints and flags for a window
5870 * based on the application set geometry, and requisiition
5871 * of the window. gtk_widget_size_request() must have been
5875 gtk_window_compute_hints (GtkWindow *window,
5876 GdkGeometry *new_geometry,
5880 gint extra_width = 0;
5881 gint extra_height = 0;
5882 GtkWindowGeometryInfo *geometry_info;
5883 GtkRequisition requisition;
5885 widget = GTK_WIDGET (window);
5887 gtk_widget_get_child_requisition (widget, &requisition);
5888 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5892 *new_flags = geometry_info->mask;
5893 *new_geometry = geometry_info->geometry;
5900 if (geometry_info && geometry_info->widget)
5902 GtkRequisition child_requisition;
5904 /* FIXME: This really isn't right. It gets the min size wrong and forces
5905 * callers to do horrible hacks like set a huge usize on the child requisition
5906 * to get the base size right. We really want to find the answers to:
5908 * - If the geometry widget was infinitely big, how much extra space
5909 * would be needed for the stuff around it.
5911 * - If the geometry widget was infinitely small, how big would the
5912 * window still have to be.
5914 * Finding these answers would be a bit of a mess here. (Bug #68668)
5916 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5918 extra_width = widget->requisition.width - child_requisition.width;
5919 extra_height = widget->requisition.height - child_requisition.height;
5922 /* We don't want to set GDK_HINT_POS in here, we just set it
5923 * in gtk_window_move_resize() when we want the position
5927 if (*new_flags & GDK_HINT_BASE_SIZE)
5929 new_geometry->base_width += extra_width;
5930 new_geometry->base_height += extra_height;
5932 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5933 (*new_flags & GDK_HINT_RESIZE_INC) &&
5934 ((extra_width != 0) || (extra_height != 0)))
5936 *new_flags |= GDK_HINT_BASE_SIZE;
5938 new_geometry->base_width = extra_width;
5939 new_geometry->base_height = extra_height;
5942 if (*new_flags & GDK_HINT_MIN_SIZE)
5944 if (new_geometry->min_width < 0)
5945 new_geometry->min_width = requisition.width;
5947 new_geometry->min_width += extra_width;
5949 if (new_geometry->min_height < 0)
5950 new_geometry->min_height = requisition.height;
5952 new_geometry->min_height += extra_height;
5954 else if (!window->allow_shrink)
5956 *new_flags |= GDK_HINT_MIN_SIZE;
5958 new_geometry->min_width = requisition.width;
5959 new_geometry->min_height = requisition.height;
5962 if (*new_flags & GDK_HINT_MAX_SIZE)
5964 if (new_geometry->max_width < 0)
5965 new_geometry->max_width = requisition.width;
5967 new_geometry->max_width += extra_width;
5969 if (new_geometry->max_height < 0)
5970 new_geometry->max_height = requisition.height;
5972 new_geometry->max_height += extra_height;
5974 else if (!window->allow_grow)
5976 *new_flags |= GDK_HINT_MAX_SIZE;
5978 new_geometry->max_width = requisition.width;
5979 new_geometry->max_height = requisition.height;
5982 *new_flags |= GDK_HINT_WIN_GRAVITY;
5983 new_geometry->win_gravity = window->gravity;
5986 /***********************
5987 * Redrawing functions *
5988 ***********************/
5991 gtk_window_paint (GtkWidget *widget,
5994 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
5995 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
5999 gtk_window_expose (GtkWidget *widget,
6000 GdkEventExpose *event)
6002 if (!GTK_WIDGET_APP_PAINTABLE (widget))
6003 gtk_window_paint (widget, &event->area);
6005 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
6006 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
6012 * gtk_window_set_has_frame:
6013 * @window: a #GtkWindow
6014 * @setting: a boolean
6016 * (Note: this is a special-purpose function for the framebuffer port,
6017 * that causes GTK+ to draw its own window border. For most applications,
6018 * you want gtk_window_set_decorated() instead, which tells the window
6019 * manager whether to draw the window border.)
6021 * If this function is called on a window with setting of %TRUE, before
6022 * it is realized or showed, it will have a "frame" window around
6023 * @window->window, accessible in @window->frame. Using the signal
6024 * frame_event you can receive all events targeted at the frame.
6026 * This function is used by the linux-fb port to implement managed
6027 * windows, but it could concievably be used by X-programs that
6028 * want to do their own window decorations.
6032 gtk_window_set_has_frame (GtkWindow *window,
6035 g_return_if_fail (GTK_IS_WINDOW (window));
6036 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
6038 window->has_frame = setting != FALSE;
6042 * gtk_window_get_has_frame:
6043 * @window: a #GtkWindow
6045 * Accessor for whether the window has a frame window exterior to
6046 * @window->window. Gets the value set by gtk_window_set_has_frame ().
6048 * Return value: %TRUE if a frame has been added to the window
6049 * via gtk_window_set_has_frame().
6052 gtk_window_get_has_frame (GtkWindow *window)
6054 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6056 return window->has_frame;
6060 * gtk_window_set_frame_dimensions:
6061 * @window: a #GtkWindow that has a frame
6062 * @left: The width of the left border
6063 * @top: The height of the top border
6064 * @right: The width of the right border
6065 * @bottom: The height of the bottom border
6067 * (Note: this is a special-purpose function intended for the framebuffer
6068 * port; see gtk_window_set_has_frame(). It will have no effect on the
6069 * window border drawn by the window manager, which is the normal
6070 * case when using the X Window system.)
6072 * For windows with frames (see gtk_window_set_has_frame()) this function
6073 * can be used to change the size of the frame border.
6076 gtk_window_set_frame_dimensions (GtkWindow *window,
6084 g_return_if_fail (GTK_IS_WINDOW (window));
6086 widget = GTK_WIDGET (window);
6088 if (window->frame_left == left &&
6089 window->frame_top == top &&
6090 window->frame_right == right &&
6091 window->frame_bottom == bottom)
6094 window->frame_left = left;
6095 window->frame_top = top;
6096 window->frame_right = right;
6097 window->frame_bottom = bottom;
6099 if (GTK_WIDGET_REALIZED (widget) && window->frame)
6101 gint width = widget->allocation.width + left + right;
6102 gint height = widget->allocation.height + top + bottom;
6103 gdk_window_resize (window->frame, width, height);
6104 gtk_decorated_window_move_resize_window (window,
6106 widget->allocation.width,
6107 widget->allocation.height);
6112 * gtk_window_present:
6113 * @window: a #GtkWindow
6115 * Presents a window to the user. This may mean raising the window
6116 * in the stacking order, deiconifying it, moving it to the current
6117 * desktop, and/or giving it the keyboard focus, possibly dependent
6118 * on the user's platform, window manager, and preferences.
6120 * If @window is hidden, this function calls gtk_widget_show()
6123 * This function should be used when the user tries to open a window
6124 * that's already open. Say for example the preferences dialog is
6125 * currently open, and the user chooses Preferences from the menu
6126 * a second time; use gtk_window_present() to move the already-open dialog
6127 * where the user can see it.
6129 * If you are calling this function in response to a user interaction,
6130 * it is preferable to use gdk_window_present_with_time().
6134 gtk_window_present (GtkWindow *window)
6136 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6140 * gtk_window_present_with_time:
6141 * @window: a #GtkWindow
6142 * @timestamp: the timestamp of the user interaction (typically a
6143 * button or key press event) which triggered this call
6145 * Presents a window to the user in response to a user interaction.
6146 * If you need to present a window without a timestamp, use
6147 * gtk_window_present(). See gtk_window_present() for details.
6152 gtk_window_present_with_time (GtkWindow *window,
6157 g_return_if_fail (GTK_IS_WINDOW (window));
6159 widget = GTK_WIDGET (window);
6161 if (GTK_WIDGET_VISIBLE (window))
6163 g_assert (widget->window != NULL);
6165 gdk_window_show (widget->window);
6167 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
6168 if (timestamp == GDK_CURRENT_TIME)
6170 #ifdef GDK_WINDOWING_X11
6171 GdkDisplay *display;
6173 display = gtk_widget_get_display (GTK_WIDGET (window));
6174 timestamp = gdk_x11_display_get_user_time (display);
6176 timestamp = gtk_get_current_event_time ();
6180 gdk_window_focus (widget->window, timestamp);
6184 gtk_widget_show (widget);
6189 * gtk_window_iconify:
6190 * @window: a #GtkWindow
6192 * Asks to iconify (i.e. minimize) the specified @window. Note that
6193 * you shouldn't assume the window is definitely iconified afterward,
6194 * because other entities (e.g. the user or <link
6195 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
6196 * again, or there may not be a window manager in which case
6197 * iconification isn't possible, etc. But normally the window will end
6198 * up iconified. Just don't write code that crashes if not.
6200 * It's permitted to call this function before showing a window,
6201 * in which case the window will be iconified before it ever appears
6204 * You can track iconification via the "window_state_event" signal
6209 gtk_window_iconify (GtkWindow *window)
6212 GdkWindow *toplevel;
6214 g_return_if_fail (GTK_IS_WINDOW (window));
6216 widget = GTK_WIDGET (window);
6218 window->iconify_initially = TRUE;
6221 toplevel = window->frame;
6223 toplevel = widget->window;
6225 if (toplevel != NULL)
6226 gdk_window_iconify (toplevel);
6230 * gtk_window_deiconify:
6231 * @window: a #GtkWindow
6233 * Asks to deiconify (i.e. unminimize) the specified @window. Note
6234 * that you shouldn't assume the window is definitely deiconified
6235 * afterward, because other entities (e.g. the user or <link
6236 * linkend="gtk-X11-arch">window manager</link>) could iconify it
6237 * again before your code which assumes deiconification gets to run.
6239 * You can track iconification via the "window_state_event" signal
6243 gtk_window_deiconify (GtkWindow *window)
6246 GdkWindow *toplevel;
6248 g_return_if_fail (GTK_IS_WINDOW (window));
6250 widget = GTK_WIDGET (window);
6252 window->iconify_initially = FALSE;
6255 toplevel = window->frame;
6257 toplevel = widget->window;
6259 if (toplevel != NULL)
6260 gdk_window_deiconify (toplevel);
6265 * @window: a #GtkWindow
6267 * Asks to stick @window, which means that it will appear on all user
6268 * desktops. Note that you shouldn't assume the window is definitely
6269 * stuck afterward, because other entities (e.g. the user or <link
6270 * linkend="gtk-X11-arch">window manager</link>) could unstick it
6271 * again, and some window managers do not support sticking
6272 * windows. But normally the window will end up stuck. Just don't
6273 * write code that crashes if not.
6275 * It's permitted to call this function before showing a window.
6277 * You can track stickiness via the "window_state_event" signal
6282 gtk_window_stick (GtkWindow *window)
6285 GdkWindow *toplevel;
6287 g_return_if_fail (GTK_IS_WINDOW (window));
6289 widget = GTK_WIDGET (window);
6291 window->stick_initially = TRUE;
6294 toplevel = window->frame;
6296 toplevel = widget->window;
6298 if (toplevel != NULL)
6299 gdk_window_stick (toplevel);
6303 * gtk_window_unstick:
6304 * @window: a #GtkWindow
6306 * Asks to unstick @window, which means that it will appear on only
6307 * one of the user's desktops. Note that you shouldn't assume the
6308 * window is definitely unstuck afterward, because other entities
6309 * (e.g. the user or <link linkend="gtk-X11-arch">window
6310 * manager</link>) could stick it again. But normally the window will
6311 * end up stuck. Just don't write code that crashes if not.
6313 * You can track stickiness via the "window_state_event" signal
6318 gtk_window_unstick (GtkWindow *window)
6321 GdkWindow *toplevel;
6323 g_return_if_fail (GTK_IS_WINDOW (window));
6325 widget = GTK_WIDGET (window);
6327 window->stick_initially = FALSE;
6330 toplevel = window->frame;
6332 toplevel = widget->window;
6334 if (toplevel != NULL)
6335 gdk_window_unstick (toplevel);
6339 * gtk_window_maximize:
6340 * @window: a #GtkWindow
6342 * Asks to maximize @window, so that it becomes full-screen. Note that
6343 * you shouldn't assume the window is definitely maximized afterward,
6344 * because other entities (e.g. the user or <link
6345 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
6346 * again, and not all window managers support maximization. But
6347 * normally the window will end up maximized. Just don't write code
6348 * that crashes if not.
6350 * It's permitted to call this function before showing a window,
6351 * in which case the window will be maximized when it appears onscreen
6354 * You can track maximization via the "window_state_event" signal
6359 gtk_window_maximize (GtkWindow *window)
6362 GdkWindow *toplevel;
6364 g_return_if_fail (GTK_IS_WINDOW (window));
6366 widget = GTK_WIDGET (window);
6368 window->maximize_initially = TRUE;
6371 toplevel = window->frame;
6373 toplevel = widget->window;
6375 if (toplevel != NULL)
6376 gdk_window_maximize (toplevel);
6380 * gtk_window_unmaximize:
6381 * @window: a #GtkWindow
6383 * Asks to unmaximize @window. Note that you shouldn't assume the
6384 * window is definitely unmaximized afterward, because other entities
6385 * (e.g. the user or <link linkend="gtk-X11-arch">window
6386 * manager</link>) could maximize it again, and not all window
6387 * managers honor requests to unmaximize. But normally the window will
6388 * end up unmaximized. Just don't write code that crashes if not.
6390 * You can track maximization via the "window_state_event" signal
6395 gtk_window_unmaximize (GtkWindow *window)
6398 GdkWindow *toplevel;
6400 g_return_if_fail (GTK_IS_WINDOW (window));
6402 widget = GTK_WIDGET (window);
6404 window->maximize_initially = FALSE;
6407 toplevel = window->frame;
6409 toplevel = widget->window;
6411 if (toplevel != NULL)
6412 gdk_window_unmaximize (toplevel);
6416 * gtk_window_fullscreen:
6417 * @window: a #GtkWindow
6419 * Asks to place @window in the fullscreen state. Note that you
6420 * shouldn't assume the window is definitely full screen afterward,
6421 * because other entities (e.g. the user or <link
6422 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
6423 * again, and not all window managers honor requests to fullscreen
6424 * windows. But normally the window will end up fullscreen. Just
6425 * don't write code that crashes if not.
6427 * You can track the fullscreen state via the "window_state_event" signal
6433 gtk_window_fullscreen (GtkWindow *window)
6436 GdkWindow *toplevel;
6437 GtkWindowPrivate *priv;
6439 g_return_if_fail (GTK_IS_WINDOW (window));
6441 widget = GTK_WIDGET (window);
6442 priv = GTK_WINDOW_GET_PRIVATE (window);
6444 priv->fullscreen_initially = TRUE;
6447 toplevel = window->frame;
6449 toplevel = widget->window;
6451 if (toplevel != NULL)
6452 gdk_window_fullscreen (toplevel);
6456 * gtk_window_unfullscreen:
6457 * @window: a #GtkWindow
6459 * Asks to toggle off the fullscreen state for @window. Note that you
6460 * shouldn't assume the window is definitely not full screen
6461 * afterward, because other entities (e.g. the user or <link
6462 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
6463 * again, and not all window managers honor requests to unfullscreen
6464 * windows. But normally the window will end up restored to its normal
6465 * state. Just don't write code that crashes if not.
6467 * You can track the fullscreen state via the "window_state_event" signal
6473 gtk_window_unfullscreen (GtkWindow *window)
6476 GdkWindow *toplevel;
6477 GtkWindowPrivate *priv;
6479 g_return_if_fail (GTK_IS_WINDOW (window));
6481 widget = GTK_WIDGET (window);
6482 priv = GTK_WINDOW_GET_PRIVATE (window);
6484 priv->fullscreen_initially = FALSE;
6487 toplevel = window->frame;
6489 toplevel = widget->window;
6491 if (toplevel != NULL)
6492 gdk_window_unfullscreen (toplevel);
6496 * gtk_window_set_keep_above:
6497 * @window: a #GtkWindow
6498 * @setting: whether to keep @window above other windows
6500 * Asks to keep @window above, so that it stays on top. Note that
6501 * you shouldn't assume the window is definitely above afterward,
6502 * because other entities (e.g. the user or <link
6503 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
6504 * and not all window managers support keeping windows above. But
6505 * normally the window will end kept above. Just don't write code
6506 * that crashes if not.
6508 * It's permitted to call this function before showing a window,
6509 * in which case the window will be kept above when it appears onscreen
6512 * You can track the above state via the "window_state_event" signal
6515 * Note that, according to the <ulink
6516 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
6517 * Manager Hints</ulink> specification, the above state is mainly meant
6518 * for user preferences and should not be used by applications e.g. for
6519 * drawing attention to their dialogs.
6524 gtk_window_set_keep_above (GtkWindow *window,
6528 GtkWindowPrivate *priv;
6529 GdkWindow *toplevel;
6531 g_return_if_fail (GTK_IS_WINDOW (window));
6533 widget = GTK_WIDGET (window);
6534 priv = GTK_WINDOW_GET_PRIVATE (window);
6536 priv->above_initially = setting;
6538 priv->below_initially = FALSE;
6541 toplevel = window->frame;
6543 toplevel = widget->window;
6545 if (toplevel != NULL)
6546 gdk_window_set_keep_above (toplevel, setting);
6550 * gtk_window_set_keep_below:
6551 * @window: a #GtkWindow
6552 * @setting: whether to keep @window below other windows
6554 * Asks to keep @window below, so that it stays in bottom. Note that
6555 * you shouldn't assume the window is definitely below afterward,
6556 * because other entities (e.g. the user or <link
6557 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
6558 * and not all window managers support putting windows below. But
6559 * normally the window will be kept below. Just don't write code
6560 * that crashes if not.
6562 * It's permitted to call this function before showing a window,
6563 * in which case the window will be kept below when it appears onscreen
6566 * You can track the below state via the "window_state_event" signal
6569 * Note that, according to the <ulink
6570 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
6571 * Manager Hints</ulink> specification, the above state is mainly meant
6572 * for user preferences and should not be used by applications e.g. for
6573 * drawing attention to their dialogs.
6578 gtk_window_set_keep_below (GtkWindow *window,
6582 GtkWindowPrivate *priv;
6583 GdkWindow *toplevel;
6585 g_return_if_fail (GTK_IS_WINDOW (window));
6587 widget = GTK_WIDGET (window);
6588 priv = GTK_WINDOW_GET_PRIVATE (window);
6590 priv->below_initially = setting;
6592 priv->above_initially = FALSE;
6595 toplevel = window->frame;
6597 toplevel = widget->window;
6599 if (toplevel != NULL)
6600 gdk_window_set_keep_below (toplevel, setting);
6604 * gtk_window_set_resizable:
6605 * @window: a #GtkWindow
6606 * @resizable: %TRUE if the user can resize this window
6608 * Sets whether the user can resize a window. Windows are user resizable
6612 gtk_window_set_resizable (GtkWindow *window,
6615 g_return_if_fail (GTK_IS_WINDOW (window));
6617 gtk_window_set_policy (window, FALSE, resizable, FALSE);
6621 * gtk_window_get_resizable:
6622 * @window: a #GtkWindow
6624 * Gets the value set by gtk_window_set_resizable().
6626 * Return value: %TRUE if the user can resize the window
6629 gtk_window_get_resizable (GtkWindow *window)
6631 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6633 /* allow_grow is most likely to indicate the semantic concept we
6634 * mean by "resizable" (and will be a reliable indicator if
6635 * set_policy() hasn't been called)
6637 return window->allow_grow;
6641 * gtk_window_set_gravity:
6642 * @window: a #GtkWindow
6643 * @gravity: window gravity
6645 * Window gravity defines the meaning of coordinates passed to
6646 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
6649 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
6650 * typically "do what you mean."
6654 gtk_window_set_gravity (GtkWindow *window,
6657 g_return_if_fail (GTK_IS_WINDOW (window));
6659 if (gravity != window->gravity)
6661 window->gravity = gravity;
6663 /* gtk_window_move_resize() will adapt gravity
6665 gtk_widget_queue_resize (GTK_WIDGET (window));
6667 g_object_notify (G_OBJECT (window), "gravity");
6672 * gtk_window_get_gravity:
6673 * @window: a #GtkWindow
6675 * Gets the value set by gtk_window_set_gravity().
6677 * Return value: window gravity
6680 gtk_window_get_gravity (GtkWindow *window)
6682 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
6684 return window->gravity;
6688 * gtk_window_begin_resize_drag:
6689 * @window: a #GtkWindow
6690 * @button: mouse button that initiated the drag
6691 * @edge: position of the resize control
6692 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6693 * @root_y: Y position where the user clicked to initiate the drag
6694 * @timestamp: timestamp from the click event that initiated the drag
6696 * Starts resizing a window. This function is used if an application
6697 * has window resizing controls. When GDK can support it, the resize
6698 * will be done using the standard mechanism for the <link
6699 * linkend="gtk-X11-arch">window manager</link> or windowing
6700 * system. Otherwise, GDK will try to emulate window resizing,
6701 * potentially not all that well, depending on the windowing system.
6705 gtk_window_begin_resize_drag (GtkWindow *window,
6713 GdkWindow *toplevel;
6715 g_return_if_fail (GTK_IS_WINDOW (window));
6716 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6718 widget = GTK_WIDGET (window);
6721 toplevel = window->frame;
6723 toplevel = widget->window;
6725 gdk_window_begin_resize_drag (toplevel,
6732 * gtk_window_get_frame_dimensions:
6733 * @window: a #GtkWindow
6734 * @left: location to store the width of the frame at the left, or %NULL
6735 * @top: location to store the height of the frame at the top, or %NULL
6736 * @right: location to store the width of the frame at the returns, or %NULL
6737 * @bottom: location to store the height of the frame at the bottom, or %NULL
6739 * (Note: this is a special-purpose function intended for the
6740 * framebuffer port; see gtk_window_set_has_frame(). It will not
6741 * return the size of the window border drawn by the <link
6742 * linkend="gtk-X11-arch">window manager</link>, which is the normal
6743 * case when using a windowing system. See
6744 * gdk_window_get_frame_extents() to get the standard window border
6747 * Retrieves the dimensions of the frame window for this toplevel.
6748 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
6751 gtk_window_get_frame_dimensions (GtkWindow *window,
6757 g_return_if_fail (GTK_IS_WINDOW (window));
6760 *left = window->frame_left;
6762 *top = window->frame_top;
6764 *right = window->frame_right;
6766 *bottom = window->frame_bottom;
6770 * gtk_window_begin_move_drag:
6771 * @window: a #GtkWindow
6772 * @button: mouse button that initiated the drag
6773 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6774 * @root_y: Y position where the user clicked to initiate the drag
6775 * @timestamp: timestamp from the click event that initiated the drag
6777 * Starts moving a window. This function is used if an application has
6778 * window movement grips. When GDK can support it, the window movement
6779 * will be done using the standard mechanism for the <link
6780 * linkend="gtk-X11-arch">window manager</link> or windowing
6781 * system. Otherwise, GDK will try to emulate window movement,
6782 * potentially not all that well, depending on the windowing system.
6786 gtk_window_begin_move_drag (GtkWindow *window,
6793 GdkWindow *toplevel;
6795 g_return_if_fail (GTK_IS_WINDOW (window));
6796 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6798 widget = GTK_WIDGET (window);
6801 toplevel = window->frame;
6803 toplevel = widget->window;
6805 gdk_window_begin_move_drag (toplevel,
6812 * gtk_window_set_screen:
6813 * @window: a #GtkWindow.
6814 * @screen: a #GdkScreen.
6816 * Sets the #GdkScreen where the @window is displayed; if
6817 * the window is already mapped, it will be unmapped, and
6818 * then remapped on the new screen.
6823 gtk_window_set_screen (GtkWindow *window,
6827 GdkScreen *previous_screen;
6828 gboolean was_mapped;
6830 g_return_if_fail (GTK_IS_WINDOW (window));
6831 g_return_if_fail (GDK_IS_SCREEN (screen));
6833 if (screen == window->screen)
6836 widget = GTK_WIDGET (window);
6838 previous_screen = window->screen;
6839 was_mapped = GTK_WIDGET_MAPPED (widget);
6842 gtk_widget_unmap (widget);
6843 if (GTK_WIDGET_REALIZED (widget))
6844 gtk_widget_unrealize (widget);
6846 gtk_window_free_key_hash (window);
6847 window->screen = screen;
6848 gtk_widget_reset_rc_styles (widget);
6849 if (screen != previous_screen)
6850 _gtk_widget_propagate_screen_changed (widget, previous_screen);
6851 g_object_notify (G_OBJECT (window), "screen");
6854 gtk_widget_map (widget);
6858 gtk_window_check_screen (GtkWindow *window)
6861 return window->screen;
6864 g_warning ("Screen for GtkWindow not set; you must always set\n"
6865 "a screen for a GtkWindow before using the window");
6871 * gtk_window_get_screen:
6872 * @window: a #GtkWindow.
6874 * Returns the #GdkScreen associated with @window.
6876 * Return value: a #GdkScreen.
6881 gtk_window_get_screen (GtkWindow *window)
6883 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6885 return window->screen;
6889 * gtk_window_is_active:
6890 * @window: a #GtkWindow
6892 * Returns whether the window is part of the current active toplevel.
6893 * (That is, the toplevel window receiving keystrokes.)
6894 * The return value is %TRUE if the window is active toplevel
6895 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
6896 * You might use this function if you wanted to draw a widget
6897 * differently in an active window from a widget in an inactive window.
6898 * See gtk_window_has_toplevel_focus()
6900 * Return value: %TRUE if the window part of the current active window.
6905 gtk_window_is_active (GtkWindow *window)
6907 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6909 return window->is_active;
6913 * gtk_window_has_toplevel_focus:
6914 * @window: a #GtkWindow
6916 * Returns whether the input focus is within this GtkWindow.
6917 * For real toplevel windows, this is identical to gtk_window_is_active(),
6918 * but for embedded windows, like #GtkPlug, the results will differ.
6920 * Return value: %TRUE if the input focus is within this GtkWindow
6925 gtk_window_has_toplevel_focus (GtkWindow *window)
6927 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6929 return window->has_toplevel_focus;
6933 gtk_window_group_class_init (GtkWindowGroupClass *klass)
6938 gtk_window_group_get_type (void)
6940 static GType window_group_type = 0;
6942 if (!window_group_type)
6944 static const GTypeInfo window_group_info =
6946 sizeof (GtkWindowGroupClass),
6947 NULL, /* base_init */
6948 NULL, /* base_finalize */
6949 (GClassInitFunc) gtk_window_group_class_init,
6950 NULL, /* class_finalize */
6951 NULL, /* class_data */
6952 sizeof (GtkWindowGroup),
6953 0, /* n_preallocs */
6954 (GInstanceInitFunc) NULL,
6957 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
6958 &window_group_info, 0);
6961 return window_group_type;
6965 * gtk_window_group_new:
6967 * Creates a new #GtkWindowGroup object. Grabs added with
6968 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
6970 * Return value: a new #GtkWindowGroup.
6973 gtk_window_group_new (void)
6975 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
6979 window_group_cleanup_grabs (GtkWindowGroup *group,
6983 GSList *to_remove = NULL;
6985 tmp_list = group->grabs;
6988 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
6989 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
6990 tmp_list = tmp_list->next;
6995 gtk_grab_remove (to_remove->data);
6996 g_object_unref (to_remove->data);
6997 to_remove = g_slist_delete_link (to_remove, to_remove);
7002 * gtk_window_group_add_window:
7003 * @window_group: a #GtkWindowGroup
7004 * @window: the #GtkWindow to add
7006 * Adds a window to a #GtkWindowGroup.
7009 gtk_window_group_add_window (GtkWindowGroup *window_group,
7012 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7013 g_return_if_fail (GTK_IS_WINDOW (window));
7015 if (window->group != window_group)
7017 g_object_ref (window);
7018 g_object_ref (window_group);
7021 gtk_window_group_remove_window (window->group, window);
7023 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
7025 window->group = window_group;
7027 g_object_unref (window);
7032 * gtk_window_group_remove_window:
7033 * @window_group: a #GtkWindowGroup
7034 * @window: the #GtkWindow to remove
7036 * Removes a window from a #GtkWindowGroup.
7039 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7042 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7043 g_return_if_fail (GTK_IS_WIDGET (window));
7044 g_return_if_fail (window->group == window_group);
7046 g_object_ref (window);
7048 window_group_cleanup_grabs (window_group, window);
7049 window->group = NULL;
7051 g_object_unref (window_group);
7052 g_object_unref (window);
7055 /* Return the group for the window or the default group
7058 _gtk_window_get_group (GtkWindow *window)
7060 if (window && window->group)
7061 return window->group;
7064 static GtkWindowGroup *default_group = NULL;
7067 default_group = gtk_window_group_new ();
7069 return default_group;
7073 /* Return the current grab widget of the given group
7076 _gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
7078 if (window_group->grabs)
7079 return GTK_WIDGET (window_group->grabs->data);
7084 Derived from XParseGeometry() in XFree86
7086 Copyright 1985, 1986, 1987,1998 The Open Group
7088 All Rights Reserved.
7090 The above copyright notice and this permission notice shall be included
7091 in all copies or substantial portions of the Software.
7093 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
7094 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7095 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7096 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
7097 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7098 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
7099 OTHER DEALINGS IN THE SOFTWARE.
7101 Except as contained in this notice, the name of The Open Group shall
7102 not be used in advertising or otherwise to promote the sale, use or
7103 other dealings in this Software without prior written authorization
7104 from The Open Group.
7109 * XParseGeometry parses strings of the form
7110 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
7111 * width, height, xoffset, and yoffset are unsigned integers.
7112 * Example: "=80x24+300-49"
7113 * The equal sign is optional.
7114 * It returns a bitmask that indicates which of the four values
7115 * were actually found in the string. For each value found,
7116 * the corresponding argument is updated; for each value
7117 * not found, the corresponding argument is left unchanged.
7120 /* The following code is from Xlib, and is minimally modified, so we
7121 * can track any upstream changes if required. Don't change this
7122 * code. Or if you do, put in a huge comment marking which thing
7127 read_int (gchar *string,
7135 else if (*string == '-')
7141 for (; (*string >= '0') && (*string <= '9'); string++)
7143 result = (result * 10) + (*string - '0');
7155 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
7156 * value (x, y, width, height) was found in the parsed string.
7158 #define NoValue 0x0000
7159 #define XValue 0x0001
7160 #define YValue 0x0002
7161 #define WidthValue 0x0004
7162 #define HeightValue 0x0008
7163 #define AllValues 0x000F
7164 #define XNegative 0x0010
7165 #define YNegative 0x0020
7167 /* Try not to reformat/modify, so we can compare/sync with X sources */
7169 gtk_XParseGeometry (const char *string,
7172 unsigned int *width,
7173 unsigned int *height)
7177 unsigned int tempWidth, tempHeight;
7179 char *nextCharacter;
7181 /* These initializations are just to silence gcc */
7187 if ( (string == NULL) || (*string == '\0')) return(mask);
7189 string++; /* ignore possible '=' at beg of geometry spec */
7191 strind = (char *)string;
7192 if (*strind != '+' && *strind != '-' && *strind != 'x') {
7193 tempWidth = read_int(strind, &nextCharacter);
7194 if (strind == nextCharacter)
7196 strind = nextCharacter;
7200 if (*strind == 'x' || *strind == 'X') {
7202 tempHeight = read_int(strind, &nextCharacter);
7203 if (strind == nextCharacter)
7205 strind = nextCharacter;
7206 mask |= HeightValue;
7209 if ((*strind == '+') || (*strind == '-')) {
7210 if (*strind == '-') {
7212 tempX = -read_int(strind, &nextCharacter);
7213 if (strind == nextCharacter)
7215 strind = nextCharacter;
7221 tempX = read_int(strind, &nextCharacter);
7222 if (strind == nextCharacter)
7224 strind = nextCharacter;
7227 if ((*strind == '+') || (*strind == '-')) {
7228 if (*strind == '-') {
7230 tempY = -read_int(strind, &nextCharacter);
7231 if (strind == nextCharacter)
7233 strind = nextCharacter;
7240 tempY = read_int(strind, &nextCharacter);
7241 if (strind == nextCharacter)
7243 strind = nextCharacter;
7249 /* If strind isn't at the end of the string the it's an invalid
7250 geometry specification. */
7252 if (*strind != '\0') return (0);
7258 if (mask & WidthValue)
7260 if (mask & HeightValue)
7261 *height = tempHeight;
7266 * gtk_window_parse_geometry:
7267 * @window: a #GtkWindow
7268 * @geometry: geometry string
7270 * Parses a standard X Window System geometry string - see the
7271 * manual page for X (type 'man X') for details on this.
7272 * gtk_window_parse_geometry() does work on all GTK+ ports
7273 * including Win32 but is primarily intended for an X environment.
7275 * If either a size or a position can be extracted from the
7276 * geometry string, gtk_window_parse_geometry() returns %TRUE
7277 * and calls gtk_window_set_default_size() and/or gtk_window_move()
7278 * to resize/move the window.
7280 * If gtk_window_parse_geometry() returns %TRUE, it will also
7281 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
7282 * indicating to the window manager that the size/position of
7283 * the window was user-specified. This causes most window
7284 * managers to honor the geometry.
7286 * Note that for gtk_window_parse_geometry() to work as expected, it has
7287 * to be called when the window has its "final" size, i.e. after calling
7288 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
7291 * <informalexample><programlisting>
7292 * #include <gtk/gtk.h>
7295 * fill_with_content (GtkWidget *vbox)
7297 * /<!-- -->* fill with content... *<!-- -->/
7301 * main (int argc, char *argv[])
7303 * GtkWidget *window, *vbox;
7304 * GdkGeometry size_hints = {
7305 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
7308 * gtk_init (&argc, &argv);
7310 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7311 * vbox = gtk_vbox_new (FALSE, 0);
7313 * gtk_container_add (GTK_CONTAINER (window), vbox);
7314 * fill_with_content (vbox);
7315 * gtk_widget_show_all (vbox);
7317 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
7320 * GDK_HINT_MIN_SIZE |
7321 * GDK_HINT_BASE_SIZE |
7322 * GDK_HINT_RESIZE_INC);
7326 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
7327 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
7330 * gtk_widget_show_all (window);
7335 * </programlisting></informalexample>
7337 * Return value: %TRUE if string was parsed successfully
7340 gtk_window_parse_geometry (GtkWindow *window,
7341 const gchar *geometry)
7343 gint result, x = 0, y = 0;
7346 gboolean size_set, pos_set;
7349 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7350 g_return_val_if_fail (geometry != NULL, FALSE);
7352 screen = gtk_window_check_screen (window);
7354 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
7357 if ((result & WidthValue) || (result & HeightValue))
7359 gtk_window_set_default_size_internal (window,
7360 TRUE, result & WidthValue ? w : -1,
7361 TRUE, result & HeightValue ? h : -1,
7366 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
7368 grav = GDK_GRAVITY_NORTH_WEST;
7370 if ((result & XNegative) && (result & YNegative))
7371 grav = GDK_GRAVITY_SOUTH_EAST;
7372 else if (result & XNegative)
7373 grav = GDK_GRAVITY_NORTH_EAST;
7374 else if (result & YNegative)
7375 grav = GDK_GRAVITY_SOUTH_WEST;
7377 if ((result & XValue) == 0)
7380 if ((result & YValue) == 0)
7383 if (grav == GDK_GRAVITY_SOUTH_WEST ||
7384 grav == GDK_GRAVITY_SOUTH_EAST)
7385 y = gdk_screen_get_height (screen) - h + y;
7387 if (grav == GDK_GRAVITY_SOUTH_EAST ||
7388 grav == GDK_GRAVITY_NORTH_EAST)
7389 x = gdk_screen_get_width (screen) - w + x;
7391 /* we don't let you put a window offscreen; maybe some people would
7392 * prefer to be able to, but it's kind of a bogus thing to do.
7401 if ((result & XValue) || (result & YValue))
7403 gtk_window_set_gravity (window, grav);
7404 gtk_window_move (window, x, y);
7408 if (size_set || pos_set)
7410 /* Set USSize, USPosition hints */
7411 GtkWindowGeometryInfo *info;
7413 info = gtk_window_get_geometry_info (window, TRUE);
7416 info->mask |= GDK_HINT_USER_POS;
7418 info->mask |= GDK_HINT_USER_SIZE;
7425 gtk_window_mnemonic_hash_foreach (guint keyval,
7431 GtkWindowKeysForeachFunc func;
7435 (*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
7439 _gtk_window_keys_foreach (GtkWindow *window,
7440 GtkWindowKeysForeachFunc func,
7444 GtkMnemonicHash *mnemonic_hash;
7448 GtkWindowKeysForeachFunc func;
7452 info.window = window;
7454 info.func_data = func_data;
7456 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
7458 _gtk_mnemonic_hash_foreach (mnemonic_hash,
7459 gtk_window_mnemonic_hash_foreach, &info);
7461 groups = gtk_accel_groups_from_object (G_OBJECT (window));
7464 GtkAccelGroup *group = groups->data;
7467 for (i = 0; i < group->n_accels; i++)
7469 GtkAccelKey *key = &group->priv_accels[i].key;
7472 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
7475 groups = groups->next;
7480 gtk_window_keys_changed (GtkWindow *window)
7482 gtk_window_free_key_hash (window);
7483 gtk_window_get_key_hash (window);
7486 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
7488 struct _GtkWindowKeyEntry
7492 gboolean is_mnemonic;
7496 add_to_key_hash (GtkWindow *window,
7498 GdkModifierType modifiers,
7499 gboolean is_mnemonic,
7502 GtkKeyHash *key_hash = data;
7504 GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
7506 entry->keyval = keyval;
7507 entry->modifiers = modifiers;
7508 entry->is_mnemonic = is_mnemonic;
7510 /* GtkAccelGroup stores lowercased accelerators. To deal
7511 * with this, if <Shift> was specified, uppercase.
7513 if (modifiers & GDK_SHIFT_MASK)
7515 if (keyval == GDK_Tab)
7516 keyval = GDK_ISO_Left_Tab;
7518 keyval = gdk_keyval_to_upper (keyval);
7521 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
7525 gtk_window_get_key_hash (GtkWindow *window)
7527 GdkScreen *screen = gtk_window_check_screen (window);
7528 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
7533 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
7534 (GDestroyNotify)g_free);
7535 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
7536 g_object_set_data (G_OBJECT (window), I_("gtk-window-key-hash"), key_hash);
7542 gtk_window_free_key_hash (GtkWindow *window)
7544 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
7547 _gtk_key_hash_free (key_hash);
7548 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
7553 * gtk_window_activate_key:
7554 * @window: a #GtkWindow
7555 * @event: a #GdkEventKey
7557 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
7558 * called by the default ::key_press_event handler for toplevel windows,
7559 * however in some cases it may be useful to call this directly when
7560 * overriding the standard key handling for a toplevel window.
7562 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
7565 gtk_window_activate_key (GtkWindow *window,
7568 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
7569 GtkWindowKeyEntry *found_entry = NULL;
7573 gtk_window_keys_changed (window);
7574 key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
7579 GSList *entries = _gtk_key_hash_lookup (key_hash,
7580 event->hardware_keycode,
7582 gtk_accelerator_get_default_mod_mask (),
7586 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
7588 GtkWindowKeyEntry *entry = tmp_list->data;
7589 if (entry->is_mnemonic)
7591 found_entry = entry;
7596 if (!found_entry && entries)
7597 found_entry = entries->data;
7599 g_slist_free (entries);
7604 if (found_entry->is_mnemonic)
7605 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
7607 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
7614 window_update_has_focus (GtkWindow *window)
7616 GtkWidget *widget = GTK_WIDGET (window);
7617 gboolean has_focus = window->has_toplevel_focus && window->is_active;
7619 if (has_focus != window->has_focus)
7621 window->has_focus = has_focus;
7625 if (window->focus_widget &&
7626 window->focus_widget != widget &&
7627 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7628 do_focus_change (window->focus_widget, TRUE);
7632 if (window->focus_widget &&
7633 window->focus_widget != widget &&
7634 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7635 do_focus_change (window->focus_widget, FALSE);
7641 * _gtk_window_set_is_active:
7642 * @window: a #GtkWindow
7643 * @is_active: %TRUE if the window is in the currently active toplevel
7645 * Internal function that sets whether the #GtkWindow is part
7646 * of the currently active toplevel window (taking into account inter-process
7650 _gtk_window_set_is_active (GtkWindow *window,
7653 g_return_if_fail (GTK_IS_WINDOW (window));
7655 is_active = is_active != FALSE;
7657 if (is_active != window->is_active)
7659 window->is_active = is_active;
7660 window_update_has_focus (window);
7662 g_object_notify (G_OBJECT (window), "is-active");
7667 * _gtk_window_set_has_toplevel_focus:
7668 * @window: a #GtkWindow
7669 * @has_toplevel_focus: %TRUE if the in
7671 * Internal function that sets whether the keyboard focus for the
7672 * toplevel window (taking into account inter-process embedding.)
7675 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
7676 gboolean has_toplevel_focus)
7678 g_return_if_fail (GTK_IS_WINDOW (window));
7680 has_toplevel_focus = has_toplevel_focus != FALSE;
7682 if (has_toplevel_focus != window->has_toplevel_focus)
7684 window->has_toplevel_focus = has_toplevel_focus;
7685 window_update_has_focus (window);
7687 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
7692 * gtk_window_set_auto_startup_notification:
7693 * @setting: %TRUE to automatically do startup notification
7695 * By default, after showing the first #GtkWindow for each #GdkScreen,
7696 * GTK+ calls gdk_screen_notify_startup_complete(). Call this
7697 * function to disable the automatic startup notification. You might
7698 * do this if your first window is a splash screen, and you want to
7699 * delay notification until after your real main window has been
7700 * shown, for example.
7702 * In that example, you would disable startup notification
7703 * temporarily, show your splash screen, then re-enable it so that
7704 * showing the main window would automatically result in notification.
7709 gtk_window_set_auto_startup_notification (gboolean setting)
7711 disable_startup_notification = !setting;
7716 #undef gtk_window_set_icon_from_file
7719 gtk_window_set_icon_from_file (GtkWindow *window,
7720 const gchar *filename,
7723 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
7726 if (utf8_filename == NULL)
7729 retval = gtk_window_set_icon_from_file_utf8 (window, utf8_filename, err);
7731 g_free (utf8_filename);
7736 #undef gtk_window_set_default_icon_from_file
7739 gtk_window_set_default_icon_from_file (const gchar *filename,
7742 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
7745 if (utf8_filename == NULL)
7748 retval = gtk_window_set_default_icon_from_file_utf8 (utf8_filename, err);
7750 g_free (utf8_filename);
7757 #define __GTK_WINDOW_C__
7758 #include "gtkaliasdef.c"