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 * gtk_window_set_deletable:
2471 * @window: a #GtkWindow
2472 * @setting: %TRUE to decorate the window as deletable
2474 * By default, windows have a close button in the window frame. Some
2475 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
2476 * disable this button. If you set the deletable property to %FALSE
2477 * using this function, GTK+ will do its best to convince the window
2478 * manager not to show a close button. Depending on the system, this
2479 * function may not have any effect when called on a window that is
2480 * already visible, so you should call it before calling gtk_window_show().
2482 * On Windows, this function always works, since there's no window manager
2488 gtk_window_set_deletable (GtkWindow *window,
2491 GtkWindowPrivate *priv;
2493 g_return_if_fail (GTK_IS_WINDOW (window));
2495 priv = GTK_WINDOW_GET_PRIVATE (window);
2497 setting = setting != FALSE;
2499 if (setting == priv->deletable)
2502 priv->deletable = setting;
2504 if (GTK_WIDGET (window)->window)
2506 if (priv->deletable)
2507 gdk_window_set_functions (GTK_WIDGET (window)->window,
2510 gdk_window_set_functions (GTK_WIDGET (window)->window,
2511 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
2514 g_object_notify (G_OBJECT (window), "deletable");
2518 * gtk_window_get_deletable:
2519 * @window: a #GtkWindow
2521 * Returns whether the window has been set to have a close button
2522 * via gtk_window_set_deletable().
2524 * Return value: %TRUE if the window has been set to have a close button
2527 gtk_window_get_deletable (GtkWindow *window)
2529 GtkWindowPrivate *priv;
2531 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2533 priv = GTK_WINDOW_GET_PRIVATE (window);
2535 return priv->deletable;
2538 static GtkWindowIconInfo*
2539 get_icon_info (GtkWindow *window)
2541 return g_object_get_data (G_OBJECT (window),
2542 "gtk-window-icon-info");
2546 free_icon_info (GtkWindowIconInfo *info)
2548 g_free (info->icon_name);
2553 static GtkWindowIconInfo*
2554 ensure_icon_info (GtkWindow *window)
2556 GtkWindowIconInfo *info;
2558 info = get_icon_info (window);
2562 info = g_new0 (GtkWindowIconInfo, 1);
2563 g_object_set_data_full (G_OBJECT (window),
2564 I_("gtk-window-icon-info"),
2566 (GDestroyNotify)free_icon_info);
2578 static ScreenIconInfo *
2579 get_screen_icon_info (GdkScreen *screen)
2581 ScreenIconInfo *info = g_object_get_data (G_OBJECT (screen),
2582 "gtk-window-default-icon-pixmap");
2585 info = g_new0 (ScreenIconInfo, 1);
2586 g_object_set_data (G_OBJECT (screen), I_("gtk-window-default-icon-pixmap"), info);
2589 if (info->serial != default_icon_serial)
2593 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2594 info->pixmap = NULL;
2599 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2603 info->serial = default_icon_serial;
2610 get_pixmap_and_mask (GdkWindow *window,
2611 GtkWindowIconInfo *parent_info,
2612 gboolean is_default_list,
2614 GdkPixmap **pmap_return,
2615 GdkBitmap **mask_return)
2617 GdkScreen *screen = gdk_drawable_get_screen (window);
2618 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2619 GdkPixbuf *best_icon;
2623 *pmap_return = NULL;
2624 *mask_return = NULL;
2626 if (is_default_list &&
2627 default_icon_info->pixmap != NULL)
2629 /* Use shared icon pixmap for all windows on this screen.
2631 if (default_icon_info->pixmap)
2632 g_object_ref (default_icon_info->pixmap);
2633 if (default_icon_info->mask)
2634 g_object_ref (default_icon_info->mask);
2636 *pmap_return = default_icon_info->pixmap;
2637 *mask_return = default_icon_info->mask;
2639 else if (parent_info && parent_info->icon_pixmap)
2641 if (parent_info->icon_pixmap)
2642 g_object_ref (parent_info->icon_pixmap);
2643 if (parent_info->icon_mask)
2644 g_object_ref (parent_info->icon_mask);
2646 *pmap_return = parent_info->icon_pixmap;
2647 *mask_return = parent_info->icon_mask;
2651 #define IDEAL_SIZE 48
2653 best_size = G_MAXINT;
2655 tmp_list = icon_list;
2656 while (tmp_list != NULL)
2658 GdkPixbuf *pixbuf = tmp_list->data;
2661 /* average width and height - if someone passes in a rectangular
2662 * icon they deserve what they get.
2664 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2667 if (best_icon == NULL)
2674 /* icon is better if it's 32 pixels or larger, and closer to
2675 * the ideal size than the current best.
2678 (ABS (best_size - IDEAL_SIZE) <
2679 ABS (this - IDEAL_SIZE)))
2686 tmp_list = tmp_list->next;
2690 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2691 gdk_screen_get_system_colormap (screen),
2696 /* Save pmap/mask for others to use if appropriate */
2699 parent_info->icon_pixmap = *pmap_return;
2700 parent_info->icon_mask = *mask_return;
2702 if (parent_info->icon_pixmap)
2703 g_object_ref (parent_info->icon_pixmap);
2704 if (parent_info->icon_mask)
2705 g_object_ref (parent_info->icon_mask);
2707 else if (is_default_list)
2709 default_icon_info->pixmap = *pmap_return;
2710 default_icon_info->mask = *mask_return;
2712 if (default_icon_info->pixmap)
2713 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2714 (gpointer*)&default_icon_info->pixmap);
2715 if (default_icon_info->mask)
2716 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2717 (gpointer*)&default_icon_info->mask);
2723 icon_list_from_theme (GtkWidget *widget,
2728 GtkIconTheme *icon_theme;
2733 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
2735 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
2738 for (i = 0; sizes[i]; i++)
2741 * We need an EWMH extension to handle scalable icons
2742 * by passing their name to the WM. For now just use a
2746 icon = gtk_icon_theme_load_icon (icon_theme, name,
2749 icon = gtk_icon_theme_load_icon (icon_theme, name,
2752 list = g_list_append (list, icon);
2762 gtk_window_realize_icon (GtkWindow *window)
2765 GtkWindowIconInfo *info;
2768 widget = GTK_WIDGET (window);
2770 g_return_if_fail (widget->window != NULL);
2772 /* no point setting an icon on override-redirect */
2773 if (window->type == GTK_WINDOW_POPUP)
2778 info = ensure_icon_info (window);
2783 g_return_if_fail (info->icon_pixmap == NULL);
2784 g_return_if_fail (info->icon_mask == NULL);
2786 info->using_default_icon = FALSE;
2787 info->using_parent_icon = FALSE;
2788 info->using_themed_icon = FALSE;
2790 icon_list = info->icon_list;
2792 /* Look up themed icon */
2793 if (icon_list == NULL && info->icon_name)
2795 icon_list = icon_list_from_theme (widget, info->icon_name);
2797 info->using_themed_icon = TRUE;
2800 /* Inherit from transient parent */
2801 if (icon_list == NULL && window->transient_parent)
2803 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2805 info->using_parent_icon = TRUE;
2808 /* Inherit from default */
2809 if (icon_list == NULL)
2811 icon_list = default_icon_list;
2813 info->using_default_icon = TRUE;
2816 /* Look up themed icon */
2817 if (icon_list == NULL && default_icon_name)
2819 icon_list = icon_list_from_theme (widget, default_icon_name);
2820 info->using_default_icon = TRUE;
2821 info->using_themed_icon = TRUE;
2824 gdk_window_set_icon_list (widget->window, icon_list);
2826 get_pixmap_and_mask (widget->window,
2827 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2828 info->using_default_icon,
2833 /* This is a slight ICCCM violation since it's a color pixmap not
2834 * a bitmap, but everyone does it.
2836 gdk_window_set_icon (widget->window,
2841 info->realized = TRUE;
2843 if (info->using_themed_icon)
2845 GtkIconTheme *icon_theme;
2847 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
2848 g_list_free (icon_list);
2850 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2851 g_signal_connect (icon_theme, "changed",
2852 G_CALLBACK (update_themed_icon), window);
2857 gtk_window_unrealize_icon (GtkWindow *window)
2859 GtkWindowIconInfo *info;
2861 info = get_icon_info (window);
2866 if (info->icon_pixmap)
2867 g_object_unref (info->icon_pixmap);
2869 if (info->icon_mask)
2870 g_object_unref (info->icon_mask);
2872 info->icon_pixmap = NULL;
2873 info->icon_mask = NULL;
2875 if (info->using_themed_icon)
2877 GtkIconTheme *icon_theme;
2879 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2881 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
2884 /* We don't clear the properties on the window, just figure the
2885 * window is going away.
2888 info->realized = FALSE;
2893 * gtk_window_set_icon_list:
2894 * @window: a #GtkWindow
2895 * @list: list of #GdkPixbuf
2897 * Sets up the icon representing a #GtkWindow. The icon is used when
2898 * the window is minimized (also known as iconified). Some window
2899 * managers or desktop environments may also place it in the window
2900 * frame, or display it in other contexts.
2902 * gtk_window_set_icon_list() allows you to pass in the same icon in
2903 * several hand-drawn sizes. The list should contain the natural sizes
2904 * your icon is available in; that is, don't scale the image before
2905 * passing it to GTK+. Scaling is postponed until the last minute,
2906 * when the desired final size is known, to allow best quality.
2908 * By passing several sizes, you may improve the final image quality
2909 * of the icon, by reducing or eliminating automatic image scaling.
2911 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2912 * larger images (64x64, 128x128) if you have them.
2914 * See also gtk_window_set_default_icon_list() to set the icon
2915 * for all windows in your application in one go.
2917 * Note that transient windows (those who have been set transient for another
2918 * window using gtk_window_set_transient_for()) will inherit their
2919 * icon from their transient parent. So there's no need to explicitly
2920 * set the icon on transient windows.
2923 gtk_window_set_icon_list (GtkWindow *window,
2926 GtkWindowIconInfo *info;
2928 g_return_if_fail (GTK_IS_WINDOW (window));
2930 info = ensure_icon_info (window);
2932 if (info->icon_list == list) /* check for NULL mostly */
2935 g_list_foreach (list,
2936 (GFunc) g_object_ref, NULL);
2938 g_list_foreach (info->icon_list,
2939 (GFunc) g_object_unref, NULL);
2941 g_list_free (info->icon_list);
2943 info->icon_list = g_list_copy (list);
2945 g_object_notify (G_OBJECT (window), "icon");
2947 gtk_window_unrealize_icon (window);
2949 if (GTK_WIDGET_REALIZED (window))
2950 gtk_window_realize_icon (window);
2952 /* We could try to update our transient children, but I don't think
2953 * it's really worth it. If we did it, the best way would probably
2954 * be to have children connect to notify::icon-list
2959 * gtk_window_get_icon_list:
2960 * @window: a #GtkWindow
2962 * Retrieves the list of icons set by gtk_window_set_icon_list().
2963 * The list is copied, but the reference count on each
2964 * member won't be incremented.
2966 * Return value: copy of window's icon list
2969 gtk_window_get_icon_list (GtkWindow *window)
2971 GtkWindowIconInfo *info;
2973 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2975 info = get_icon_info (window);
2978 return g_list_copy (info->icon_list);
2984 * gtk_window_set_icon:
2985 * @window: a #GtkWindow
2986 * @icon: icon image, or %NULL
2988 * Sets up the icon representing a #GtkWindow. This icon is used when
2989 * the window is minimized (also known as iconified). Some window
2990 * managers or desktop environments may also place it in the window
2991 * frame, or display it in other contexts.
2993 * The icon should be provided in whatever size it was naturally
2994 * drawn; that is, don't scale the image before passing it to
2995 * GTK+. Scaling is postponed until the last minute, when the desired
2996 * final size is known, to allow best quality.
2998 * If you have your icon hand-drawn in multiple sizes, use
2999 * gtk_window_set_icon_list(). Then the best size will be used.
3001 * This function is equivalent to calling gtk_window_set_icon_list()
3002 * with a 1-element list.
3004 * See also gtk_window_set_default_icon_list() to set the icon
3005 * for all windows in your application in one go.
3008 gtk_window_set_icon (GtkWindow *window,
3013 g_return_if_fail (GTK_IS_WINDOW (window));
3014 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3019 list = g_list_append (list, icon);
3021 gtk_window_set_icon_list (window, list);
3027 update_themed_icon (GtkIconTheme *icon_theme,
3030 g_object_notify (G_OBJECT (window), "icon");
3032 gtk_window_unrealize_icon (window);
3034 if (GTK_WIDGET_REALIZED (window))
3035 gtk_window_realize_icon (window);
3039 * gtk_window_set_icon_name:
3040 * @window: a #GtkWindow
3041 * @name: the name of the themed icon
3043 * Sets the icon for the window from a named themed icon. See
3044 * the docs for #GtkIconTheme for more details.
3046 * Note that this has nothing to do with the WM_ICON_NAME
3047 * property which is mentioned in the ICCCM.
3052 gtk_window_set_icon_name (GtkWindow *window,
3055 GtkWindowIconInfo *info;
3058 g_return_if_fail (GTK_IS_WINDOW (window));
3060 info = ensure_icon_info (window);
3062 tmp = info->icon_name;
3063 info->icon_name = g_strdup (name);
3066 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3067 g_list_free (info->icon_list);
3068 info->icon_list = NULL;
3070 update_themed_icon (NULL, window);
3072 g_object_notify (G_OBJECT (window), "icon-name");
3076 * gtk_window_get_icon_name:
3077 * @window: a #GtkWindow
3079 * Returns the name of the themed icon for the window,
3080 * see gtk_window_set_icon_name().
3082 * Returns: the icon name or %NULL if the window has
3087 G_CONST_RETURN gchar *
3088 gtk_window_get_icon_name (GtkWindow *window)
3090 GtkWindowIconInfo *info;
3092 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3094 info = ensure_icon_info (window);
3096 return info->icon_name;
3100 * gtk_window_get_icon:
3101 * @window: a #GtkWindow
3103 * Gets the value set by gtk_window_set_icon() (or if you've
3104 * called gtk_window_set_icon_list(), gets the first icon in
3107 * Return value: icon for window
3110 gtk_window_get_icon (GtkWindow *window)
3112 GtkWindowIconInfo *info;
3114 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3116 info = get_icon_info (window);
3117 if (info && info->icon_list)
3118 return GDK_PIXBUF (info->icon_list->data);
3123 /* Load pixbuf, printing warning on failure if error == NULL
3126 load_pixbuf_verbosely (const char *filename,
3129 GError *local_err = NULL;
3132 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3140 g_warning ("Error loading icon from file '%s':\n\t%s",
3141 filename, local_err->message);
3142 g_error_free (local_err);
3150 * gtk_window_set_icon_from_file:
3151 * @window: a #GtkWindow
3152 * @filename: location of icon file
3153 * @err: location to store error, or %NULL.
3155 * Sets the icon for @window.
3156 * Warns on failure if @err is %NULL.
3158 * This function is equivalent to calling gtk_window_set_icon()
3159 * with a pixbuf created by loading the image from @filename.
3161 * Returns: %TRUE if setting the icon succeeded.
3166 gtk_window_set_icon_from_file (GtkWindow *window,
3167 const gchar *filename,
3170 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3174 gtk_window_set_icon (window, pixbuf);
3175 g_object_unref (pixbuf);
3184 * gtk_window_set_default_icon_list:
3185 * @list: a list of #GdkPixbuf
3187 * Sets an icon list to be used as fallback for windows that haven't
3188 * had gtk_window_set_icon_list() called on them to set up a
3189 * window-specific icon list. This function allows you to set up the
3190 * icon for all windows in your app at once.
3192 * See gtk_window_set_icon_list() for more details.
3196 gtk_window_set_default_icon_list (GList *list)
3200 if (list == default_icon_list)
3203 /* Update serial so we don't used cached pixmaps/masks
3205 default_icon_serial++;
3207 g_list_foreach (list,
3208 (GFunc) g_object_ref, NULL);
3210 g_list_foreach (default_icon_list,
3211 (GFunc) g_object_unref, NULL);
3213 g_list_free (default_icon_list);
3215 default_icon_list = g_list_copy (list);
3217 /* Update all toplevels */
3218 toplevels = gtk_window_list_toplevels ();
3219 tmp_list = toplevels;
3220 while (tmp_list != NULL)
3222 GtkWindowIconInfo *info;
3223 GtkWindow *w = tmp_list->data;
3225 info = get_icon_info (w);
3226 if (info && info->using_default_icon)
3228 gtk_window_unrealize_icon (w);
3229 if (GTK_WIDGET_REALIZED (w))
3230 gtk_window_realize_icon (w);
3233 tmp_list = tmp_list->next;
3235 g_list_free (toplevels);
3239 * gtk_window_set_default_icon:
3242 * Sets an icon to be used as fallback for windows that haven't
3243 * had gtk_window_set_icon() called on them from a pixbuf.
3248 gtk_window_set_default_icon (GdkPixbuf *icon)
3252 g_return_if_fail (GDK_IS_PIXBUF (icon));
3254 list = g_list_prepend (NULL, icon);
3255 gtk_window_set_default_icon_list (list);
3260 * gtk_window_set_default_icon_name:
3261 * @name: the name of the themed icon
3263 * Sets an icon to be used as fallback for windows that haven't
3264 * had gtk_window_set_icon_list() called on them from a named
3265 * themed icon, see gtk_window_set_icon_name().
3270 gtk_window_set_default_icon_name (const gchar *name)
3275 /* Update serial so we don't used cached pixmaps/masks
3277 default_icon_serial++;
3279 g_free (default_icon_name);
3280 default_icon_name = g_strdup (name);
3282 g_list_foreach (default_icon_list,
3283 (GFunc) g_object_unref, NULL);
3285 g_list_free (default_icon_list);
3286 default_icon_list = NULL;
3288 /* Update all toplevels */
3289 toplevels = gtk_window_list_toplevels ();
3290 tmp_list = toplevels;
3291 while (tmp_list != NULL)
3293 GtkWindowIconInfo *info;
3294 GtkWindow *w = tmp_list->data;
3296 info = get_icon_info (w);
3297 if (info && info->using_default_icon && info->using_themed_icon)
3299 gtk_window_unrealize_icon (w);
3300 if (GTK_WIDGET_REALIZED (w))
3301 gtk_window_realize_icon (w);
3304 tmp_list = tmp_list->next;
3306 g_list_free (toplevels);
3310 * gtk_window_set_default_icon_from_file:
3311 * @filename: location of icon file
3312 * @err: location to store error, or %NULL.
3314 * Sets an icon to be used as fallback for windows that haven't
3315 * had gtk_window_set_icon_list() called on them from a file
3316 * on disk. Warns on failure if @err is %NULL.
3318 * Returns: %TRUE if setting the icon succeeded.
3323 gtk_window_set_default_icon_from_file (const gchar *filename,
3326 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3330 gtk_window_set_default_icon (pixbuf);
3331 g_object_unref (pixbuf);
3340 * gtk_window_get_default_icon_list:
3342 * Gets the value set by gtk_window_set_default_icon_list().
3343 * The list is a copy and should be freed with g_list_free(),
3344 * but the pixbufs in the list have not had their reference count
3347 * Return value: copy of default icon list
3350 gtk_window_get_default_icon_list (void)
3352 return g_list_copy (default_icon_list);
3356 gtk_window_set_default_size_internal (GtkWindow *window,
3357 gboolean change_width,
3359 gboolean change_height,
3361 gboolean is_geometry)
3363 GtkWindowGeometryInfo *info;
3365 g_return_if_fail (change_width == FALSE || width >= -1);
3366 g_return_if_fail (change_height == FALSE || height >= -1);
3368 info = gtk_window_get_geometry_info (window, TRUE);
3370 g_object_freeze_notify (G_OBJECT (window));
3372 info->default_is_geometry = is_geometry != FALSE;
3382 info->default_width = width;
3384 g_object_notify (G_OBJECT (window), "default-width");
3395 info->default_height = height;
3397 g_object_notify (G_OBJECT (window), "default-height");
3400 g_object_thaw_notify (G_OBJECT (window));
3402 gtk_widget_queue_resize (GTK_WIDGET (window));
3406 * gtk_window_set_default_size:
3407 * @window: a #GtkWindow
3408 * @width: width in pixels, or -1 to unset the default width
3409 * @height: height in pixels, or -1 to unset the default height
3411 * Sets the default size of a window. If the window's "natural" size
3412 * (its size request) is larger than the default, the default will be
3413 * ignored. More generally, if the default size does not obey the
3414 * geometry hints for the window (gtk_window_set_geometry_hints() can
3415 * be used to set these explicitly), the default size will be clamped
3416 * to the nearest permitted size.
3418 * Unlike gtk_widget_set_size_request(), which sets a size request for
3419 * a widget and thus would keep users from shrinking the window, this
3420 * function only sets the initial size, just as if the user had
3421 * resized the window themselves. Users can still shrink the window
3422 * again as they normally would. Setting a default size of -1 means to
3423 * use the "natural" default size (the size request of the window).
3425 * For more control over a window's initial size and how resizing works,
3426 * investigate gtk_window_set_geometry_hints().
3428 * For some uses, gtk_window_resize() is a more appropriate function.
3429 * gtk_window_resize() changes the current size of the window, rather
3430 * than the size to be used on initial display. gtk_window_resize() always
3431 * affects the window itself, not the geometry widget.
3433 * The default size of a window only affects the first time a window is
3434 * shown; if a window is hidden and re-shown, it will remember the size
3435 * it had prior to hiding, rather than using the default size.
3437 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3438 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3441 gtk_window_set_default_size (GtkWindow *window,
3445 g_return_if_fail (GTK_IS_WINDOW (window));
3446 g_return_if_fail (width >= -1);
3447 g_return_if_fail (height >= -1);
3449 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3453 * gtk_window_get_default_size:
3454 * @window: a #GtkWindow
3455 * @width: location to store the default width, or %NULL
3456 * @height: location to store the default height, or %NULL
3458 * Gets the default size of the window. A value of -1 for the width or
3459 * height indicates that a default size has not been explicitly set
3460 * for that dimension, so the "natural" size of the window will be
3465 gtk_window_get_default_size (GtkWindow *window,
3469 GtkWindowGeometryInfo *info;
3471 g_return_if_fail (GTK_IS_WINDOW (window));
3473 info = gtk_window_get_geometry_info (window, FALSE);
3476 *width = info ? info->default_width : -1;
3479 *height = info ? info->default_height : -1;
3483 * gtk_window_resize:
3484 * @window: a #GtkWindow
3485 * @width: width in pixels to resize the window to
3486 * @height: height in pixels to resize the window to
3488 * Resizes the window as if the user had done so, obeying geometry
3489 * constraints. The default geometry constraint is that windows may
3490 * not be smaller than their size request; to override this
3491 * constraint, call gtk_widget_set_size_request() to set the window's
3492 * request to a smaller value.
3494 * If gtk_window_resize() is called before showing a window for the
3495 * first time, it overrides any default size set with
3496 * gtk_window_set_default_size().
3498 * Windows may not be resized smaller than 1 by 1 pixels.
3502 gtk_window_resize (GtkWindow *window,
3506 GtkWindowGeometryInfo *info;
3508 g_return_if_fail (GTK_IS_WINDOW (window));
3509 g_return_if_fail (width > 0);
3510 g_return_if_fail (height > 0);
3512 info = gtk_window_get_geometry_info (window, TRUE);
3514 info->resize_width = width;
3515 info->resize_height = height;
3517 gtk_widget_queue_resize (GTK_WIDGET (window));
3521 * gtk_window_get_size:
3522 * @window: a #GtkWindow
3523 * @width: return location for width, or %NULL
3524 * @height: return location for height, or %NULL
3526 * Obtains the current size of @window. If @window is not onscreen,
3527 * it returns the size GTK+ will suggest to the <link
3528 * linkend="gtk-X11-arch">window manager</link> for the initial window
3529 * size (but this is not reliably the same as the size the window
3530 * manager will actually select). The size obtained by
3531 * gtk_window_get_size() is the last size received in a
3532 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
3533 * rather than querying the X server for the size. As a result, if you
3534 * call gtk_window_resize() then immediately call
3535 * gtk_window_get_size(), the size won't have taken effect yet. After
3536 * the window manager processes the resize request, GTK+ receives
3537 * notification that the size has changed via a configure event, and
3538 * the size of the window gets updated.
3540 * Note 1: Nearly any use of this function creates a race condition,
3541 * because the size of the window may change between the time that you
3542 * get the size and the time that you perform some action assuming
3543 * that size is the current size. To avoid race conditions, connect to
3544 * "configure_event" on the window and adjust your size-dependent
3545 * state to match the size delivered in the #GdkEventConfigure.
3547 * Note 2: The returned size does <emphasis>not</emphasis> include the
3548 * size of the window manager decorations (aka the window frame or
3549 * border). Those are not drawn by GTK+ and GTK+ has no reliable
3550 * method of determining their size.
3552 * Note 3: If you are getting a window size in order to position
3553 * the window onscreen, there may be a better way. The preferred
3554 * way is to simply set the window's semantic type with
3555 * gtk_window_set_type_hint(), which allows the window manager to
3556 * e.g. center dialogs. Also, if you set the transient parent of
3557 * dialogs with gtk_window_set_transient_for() window managers
3558 * will often center the dialog over its parent window. It's
3559 * much preferred to let the window manager handle these
3560 * things rather than doing it yourself, because all apps will
3561 * behave consistently and according to user prefs if the window
3562 * manager handles it. Also, the window manager can take the size
3563 * of the window decorations/border into account, while your
3564 * application cannot.
3566 * In any case, if you insist on application-specified window
3567 * positioning, there's <emphasis>still</emphasis> a better way than
3568 * doing it yourself - gtk_window_set_position() will frequently
3569 * handle the details for you.
3573 gtk_window_get_size (GtkWindow *window,
3579 g_return_if_fail (GTK_IS_WINDOW (window));
3581 if (width == NULL && height == NULL)
3584 if (GTK_WIDGET_MAPPED (window))
3586 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3591 GdkRectangle configure_request;
3593 gtk_window_compute_configure_request (window,
3597 w = configure_request.width;
3598 h = configure_request.height;
3609 * @window: a #GtkWindow
3610 * @x: X coordinate to move window to
3611 * @y: Y coordinate to move window to
3613 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3614 * @window to the given position. Window managers are free to ignore
3615 * this; most window managers ignore requests for initial window
3616 * positions (instead using a user-defined placement algorithm) and
3617 * honor requests after the window has already been shown.
3619 * Note: the position is the position of the gravity-determined
3620 * reference point for the window. The gravity determines two things:
3621 * first, the location of the reference point in root window
3622 * coordinates; and second, which point on the window is positioned at
3623 * the reference point.
3625 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3626 * point is simply the @x, @y supplied to gtk_window_move(). The
3627 * top-left corner of the window decorations (aka window frame or
3628 * border) will be placed at @x, @y. Therefore, to position a window
3629 * at the top left of the screen, you want to use the default gravity
3630 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3632 * To position a window at the bottom right corner of the screen, you
3633 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3634 * point is at @x + the window width and @y + the window height, and
3635 * the bottom-right corner of the window border will be placed at that
3636 * reference point. So, to place a window in the bottom right corner
3637 * you would first set gravity to south east, then write:
3638 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3639 * gdk_screen_height () - window_height)</literal>.
3641 * The Extended Window Manager Hints specification at <ulink
3642 * url="http://www.freedesktop.org/Standards/wm-spec">
3643 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
3644 * nice table of gravities in the "implementation notes" section.
3646 * The gtk_window_get_position() documentation may also be relevant.
3650 gtk_window_move (GtkWindow *window,
3654 GtkWindowGeometryInfo *info;
3657 g_return_if_fail (GTK_IS_WINDOW (window));
3659 widget = GTK_WIDGET (window);
3661 info = gtk_window_get_geometry_info (window, TRUE);
3663 if (GTK_WIDGET_MAPPED (window))
3665 /* we have now sent a request with this position
3666 * with currently-active constraints, so toggle flag.
3668 info->position_constraints_changed = FALSE;
3670 /* we only constrain if mapped - if not mapped,
3671 * then gtk_window_compute_configure_request()
3672 * will apply the constraints later, and we
3673 * don't want to lose information about
3674 * what position the user set before then.
3675 * i.e. if you do a move() then turn off POS_CENTER
3676 * then show the window, your move() will work.
3678 gtk_window_constrain_position (window,
3679 widget->allocation.width,
3680 widget->allocation.height,
3683 /* Note that this request doesn't go through our standard request
3684 * framework, e.g. doesn't increment configure_request_count,
3685 * doesn't set info->last, etc.; that's because
3686 * we don't save the info needed to arrive at this same request
3689 * To gtk_window_move_resize(), this will end up looking exactly
3690 * the same as the position being changed by the window
3694 /* FIXME are we handling gravity properly for framed windows? */
3696 gdk_window_move (window->frame,
3697 x - window->frame_left,
3698 y - window->frame_top);
3700 gdk_window_move (GTK_WIDGET (window)->window,
3705 /* Save this position to apply on mapping */
3706 info->initial_x = x;
3707 info->initial_y = y;
3708 info->initial_pos_set = TRUE;
3713 * gtk_window_get_position:
3714 * @window: a #GtkWindow
3715 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3716 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3718 * This function returns the position you need to pass to
3719 * gtk_window_move() to keep @window in its current position. This
3720 * means that the meaning of the returned value varies with window
3721 * gravity. See gtk_window_move() for more details.
3723 * If you haven't changed the window gravity, its gravity will be
3724 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3725 * gets the position of the top-left corner of the window manager
3726 * frame for the window. gtk_window_move() sets the position of this
3727 * same top-left corner.
3729 * gtk_window_get_position() is not 100% reliable because the X Window System
3730 * does not specify a way to obtain the geometry of the
3731 * decorations placed on a window by the window manager.
3732 * Thus GTK+ is using a "best guess" that works with most
3735 * Moreover, nearly all window managers are historically broken with
3736 * respect to their handling of window gravity. So moving a window to
3737 * its current position as returned by gtk_window_get_position() tends
3738 * to result in moving the window slightly. Window managers are
3739 * slowly getting better over time.
3741 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3742 * frame is not relevant, and thus gtk_window_get_position() will
3743 * always produce accurate results. However you can't use static
3744 * gravity to do things like place a window in a corner of the screen,
3745 * because static gravity ignores the window manager decorations.
3747 * If you are saving and restoring your application's window
3748 * positions, you should know that it's impossible for applications to
3749 * do this without getting it somewhat wrong because applications do
3750 * not have sufficient knowledge of window manager state. The Correct
3751 * Mechanism is to support the session management protocol (see the
3752 * "GnomeClient" object in the GNOME libraries for example) and allow
3753 * the window manager to save your window sizes and positions.
3758 gtk_window_get_position (GtkWindow *window,
3764 g_return_if_fail (GTK_IS_WINDOW (window));
3766 widget = GTK_WIDGET (window);
3768 if (window->gravity == GDK_GRAVITY_STATIC)
3770 if (GTK_WIDGET_MAPPED (widget))
3772 /* This does a server round-trip, which is sort of wrong;
3773 * but a server round-trip is inevitable for
3774 * gdk_window_get_frame_extents() in the usual
3775 * NorthWestGravity case below, so not sure what else to
3776 * do. We should likely be consistent about whether we get
3777 * the client-side info or the server-side info.
3779 gdk_window_get_origin (widget->window, root_x, root_y);
3783 GdkRectangle configure_request;
3785 gtk_window_compute_configure_request (window,
3789 *root_x = configure_request.x;
3790 *root_y = configure_request.y;
3795 GdkRectangle frame_extents;
3800 if (GTK_WIDGET_MAPPED (widget))
3803 gdk_window_get_frame_extents (window->frame, &frame_extents);
3805 gdk_window_get_frame_extents (widget->window, &frame_extents);
3806 x = frame_extents.x;
3807 y = frame_extents.y;
3808 gtk_window_get_size (window, &w, &h);
3812 /* We just say the frame has 0 size on all sides.
3813 * Not sure what else to do.
3815 gtk_window_compute_configure_request (window,
3818 x = frame_extents.x;
3819 y = frame_extents.y;
3820 w = frame_extents.width;
3821 h = frame_extents.height;
3824 switch (window->gravity)
3826 case GDK_GRAVITY_NORTH:
3827 case GDK_GRAVITY_CENTER:
3828 case GDK_GRAVITY_SOUTH:
3829 /* Find center of frame. */
3830 x += frame_extents.width / 2;
3831 /* Center client window on that point. */
3835 case GDK_GRAVITY_SOUTH_EAST:
3836 case GDK_GRAVITY_EAST:
3837 case GDK_GRAVITY_NORTH_EAST:
3838 /* Find right edge of frame */
3839 x += frame_extents.width;
3840 /* Align left edge of client at that point. */
3847 switch (window->gravity)
3849 case GDK_GRAVITY_WEST:
3850 case GDK_GRAVITY_CENTER:
3851 case GDK_GRAVITY_EAST:
3852 /* Find center of frame. */
3853 y += frame_extents.height / 2;
3854 /* Center client window there. */
3857 case GDK_GRAVITY_SOUTH_WEST:
3858 case GDK_GRAVITY_SOUTH:
3859 case GDK_GRAVITY_SOUTH_EAST:
3860 /* Find south edge of frame */
3861 y += frame_extents.height;
3862 /* Place bottom edge of client there */
3877 * gtk_window_reshow_with_initial_size:
3878 * @window: a #GtkWindow
3880 * Hides @window, then reshows it, resetting the
3881 * default size and position of the window. Used
3882 * by GUI builders only.
3885 gtk_window_reshow_with_initial_size (GtkWindow *window)
3889 g_return_if_fail (GTK_IS_WINDOW (window));
3891 widget = GTK_WIDGET (window);
3893 gtk_widget_hide (widget);
3894 gtk_widget_unrealize (widget);
3895 gtk_widget_show (widget);
3899 gtk_window_destroy (GtkObject *object)
3901 GtkWindow *window = GTK_WINDOW (object);
3903 toplevel_list = g_slist_remove (toplevel_list, window);
3905 if (window->transient_parent)
3906 gtk_window_set_transient_for (window, NULL);
3908 /* frees the icons */
3909 gtk_window_set_icon_list (window, NULL);
3911 if (window->has_user_ref_count)
3913 window->has_user_ref_count = FALSE;
3914 g_object_unref (window);
3918 gtk_window_group_remove_window (window->group, window);
3920 gtk_window_free_key_hash (window);
3922 GTK_OBJECT_CLASS (parent_class)->destroy (object);
3926 gtk_window_finalize (GObject *object)
3928 GtkWindow *window = GTK_WINDOW (object);
3929 GtkMnemonicHash *mnemonic_hash;
3931 g_free (window->title);
3932 g_free (window->wmclass_name);
3933 g_free (window->wmclass_class);
3934 g_free (window->wm_role);
3936 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
3938 _gtk_mnemonic_hash_free (mnemonic_hash);
3940 if (window->geometry_info)
3942 if (window->geometry_info->widget)
3943 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3944 gtk_widget_destroyed,
3945 &window->geometry_info->widget);
3946 g_free (window->geometry_info);
3949 if (window->keys_changed_handler)
3951 g_source_remove (window->keys_changed_handler);
3952 window->keys_changed_handler = 0;
3955 G_OBJECT_CLASS (parent_class)->finalize (object);
3959 gtk_window_show (GtkWidget *widget)
3961 GtkWindow *window = GTK_WINDOW (widget);
3962 GtkContainer *container = GTK_CONTAINER (window);
3963 gboolean need_resize;
3965 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3967 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3968 container->need_resize = FALSE;
3972 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3973 GtkAllocation allocation = { 0, 0 };
3974 GdkRectangle configure_request;
3975 GdkGeometry new_geometry;
3977 gboolean was_realized;
3979 /* We are going to go ahead and perform this configure request
3980 * and then emulate a configure notify by going ahead and
3981 * doing a size allocate. Sort of a synchronous
3982 * mini-copy of gtk_window_move_resize() here.
3984 gtk_window_compute_configure_request (window,
3989 /* We update this because we are going to go ahead
3990 * and gdk_window_resize() below, rather than
3993 info->last.configure_request.width = configure_request.width;
3994 info->last.configure_request.height = configure_request.height;
3996 /* and allocate the window - this is normally done
3997 * in move_resize in response to configure notify
3999 allocation.width = configure_request.width;
4000 allocation.height = configure_request.height;
4001 gtk_widget_size_allocate (widget, &allocation);
4003 /* Then we guarantee we have a realize */
4004 was_realized = FALSE;
4005 if (!GTK_WIDGET_REALIZED (widget))
4007 gtk_widget_realize (widget);
4008 was_realized = TRUE;
4011 /* Must be done after the windows are realized,
4012 * so that the decorations can be read
4014 gtk_decorated_window_calculate_frame_size (window);
4016 /* We only send configure request if we didn't just finish
4017 * creating the window; if we just created the window
4018 * then we created it with widget->allocation anyhow.
4021 gdk_window_move_resize (widget->window,
4022 configure_request.x,
4023 configure_request.y,
4024 configure_request.width,
4025 configure_request.height);
4028 gtk_container_check_resize (container);
4030 gtk_widget_map (widget);
4032 /* Try to make sure that we have some focused widget
4034 if (!window->focus_widget && !GTK_IS_PLUG (window))
4035 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4038 gtk_grab_add (widget);
4042 gtk_window_hide (GtkWidget *widget)
4044 GtkWindow *window = GTK_WINDOW (widget);
4046 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4047 gtk_widget_unmap (widget);
4050 gtk_grab_remove (widget);
4054 gtk_window_map (GtkWidget *widget)
4056 GtkWindow *window = GTK_WINDOW (widget);
4057 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4058 GdkWindow *toplevel;
4060 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4062 if (window->bin.child &&
4063 GTK_WIDGET_VISIBLE (window->bin.child) &&
4064 !GTK_WIDGET_MAPPED (window->bin.child))
4065 gtk_widget_map (window->bin.child);
4068 toplevel = window->frame;
4070 toplevel = widget->window;
4072 if (window->maximize_initially)
4073 gdk_window_maximize (toplevel);
4075 gdk_window_unmaximize (toplevel);
4077 if (window->stick_initially)
4078 gdk_window_stick (toplevel);
4080 gdk_window_unstick (toplevel);
4082 if (window->iconify_initially)
4083 gdk_window_iconify (toplevel);
4085 gdk_window_deiconify (toplevel);
4087 if (priv->fullscreen_initially)
4088 gdk_window_fullscreen (toplevel);
4090 gdk_window_unfullscreen (toplevel);
4092 gdk_window_set_keep_above (toplevel, priv->above_initially);
4094 gdk_window_set_keep_below (toplevel, priv->below_initially);
4096 /* No longer use the default settings */
4097 window->need_default_size = FALSE;
4098 window->need_default_position = FALSE;
4100 gdk_window_show (widget->window);
4103 gdk_window_show (window->frame);
4105 if (!disable_startup_notification &&
4106 !sent_startup_notification)
4108 sent_startup_notification = TRUE;
4109 gdk_notify_startup_complete ();
4114 gtk_window_map_event (GtkWidget *widget,
4117 if (!GTK_WIDGET_MAPPED (widget))
4119 /* we should be be unmapped, but are getting a MapEvent, this may happen
4120 * to toplevel XWindows if mapping was intercepted by a window manager
4121 * and an unmap request occoured while the MapRequestEvent was still
4122 * being handled. we work around this situaiton here by re-requesting
4123 * the window being unmapped. more details can be found in:
4124 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4126 gdk_window_hide (widget->window);
4132 gtk_window_unmap (GtkWidget *widget)
4134 GtkWindow *window = GTK_WINDOW (widget);
4135 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
4136 GtkWindowGeometryInfo *info;
4137 GdkWindowState state;
4139 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4141 gdk_window_withdraw (window->frame);
4143 gdk_window_withdraw (widget->window);
4145 window->configure_request_count = 0;
4146 window->configure_notify_received = FALSE;
4148 /* on unmap, we reset the default positioning of the window,
4149 * so it's placed again, but we don't reset the default
4150 * size of the window, so it's remembered.
4152 window->need_default_position = TRUE;
4154 info = gtk_window_get_geometry_info (window, FALSE);
4157 info->initial_pos_set = FALSE;
4158 info->position_constraints_changed = FALSE;
4161 state = gdk_window_get_state (widget->window);
4162 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
4163 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
4164 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
4165 priv->above_initially = state & GDK_WINDOW_STATE_ABOVE;
4166 priv->below_initially = state & GDK_WINDOW_STATE_BELOW;
4170 gtk_window_realize (GtkWidget *widget)
4173 GdkWindow *parent_window;
4174 GdkWindowAttr attributes;
4175 gint attributes_mask;
4176 GtkWindowPrivate *priv;
4178 window = GTK_WINDOW (widget);
4180 priv = GTK_WINDOW_GET_PRIVATE (window);
4182 /* ensure widget tree is properly size allocated */
4183 if (widget->allocation.x == -1 &&
4184 widget->allocation.y == -1 &&
4185 widget->allocation.width == 1 &&
4186 widget->allocation.height == 1)
4188 GtkRequisition requisition;
4189 GtkAllocation allocation = { 0, 0, 200, 200 };
4191 gtk_widget_size_request (widget, &requisition);
4192 if (requisition.width || requisition.height)
4194 /* non-empty window */
4195 allocation.width = requisition.width;
4196 allocation.height = requisition.height;
4198 gtk_widget_size_allocate (widget, &allocation);
4200 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4202 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
4205 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4207 switch (window->type)
4209 case GTK_WINDOW_TOPLEVEL:
4210 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4212 case GTK_WINDOW_POPUP:
4213 attributes.window_type = GDK_WINDOW_TEMP;
4216 g_warning (G_STRLOC": Unknown window type %d!", window->type);
4220 attributes.title = window->title;
4221 attributes.wmclass_name = window->wmclass_name;
4222 attributes.wmclass_class = window->wmclass_class;
4223 attributes.wclass = GDK_INPUT_OUTPUT;
4224 attributes.visual = gtk_widget_get_visual (widget);
4225 attributes.colormap = gtk_widget_get_colormap (widget);
4227 if (window->has_frame)
4229 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
4230 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
4231 attributes.event_mask = (GDK_EXPOSURE_MASK |
4232 GDK_KEY_PRESS_MASK |
4233 GDK_ENTER_NOTIFY_MASK |
4234 GDK_LEAVE_NOTIFY_MASK |
4235 GDK_FOCUS_CHANGE_MASK |
4236 GDK_STRUCTURE_MASK |
4237 GDK_BUTTON_MOTION_MASK |
4238 GDK_POINTER_MOTION_HINT_MASK |
4239 GDK_BUTTON_PRESS_MASK |
4240 GDK_BUTTON_RELEASE_MASK);
4242 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4244 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4245 &attributes, attributes_mask);
4247 gdk_window_set_user_data (window->frame, widget);
4249 attributes.window_type = GDK_WINDOW_CHILD;
4250 attributes.x = window->frame_left;
4251 attributes.y = window->frame_top;
4253 attributes_mask = GDK_WA_X | GDK_WA_Y;
4255 parent_window = window->frame;
4259 attributes_mask = 0;
4260 parent_window = gtk_widget_get_root_window (widget);
4263 attributes.width = widget->allocation.width;
4264 attributes.height = widget->allocation.height;
4265 attributes.event_mask = gtk_widget_get_events (widget);
4266 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4267 GDK_KEY_PRESS_MASK |
4268 GDK_KEY_RELEASE_MASK |
4269 GDK_ENTER_NOTIFY_MASK |
4270 GDK_LEAVE_NOTIFY_MASK |
4271 GDK_FOCUS_CHANGE_MASK |
4272 GDK_STRUCTURE_MASK);
4274 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
4275 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
4276 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
4278 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
4280 gdk_window_enable_synchronized_configure (widget->window);
4282 gdk_window_set_user_data (widget->window, window);
4284 widget->style = gtk_style_attach (widget->style, widget->window);
4285 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4287 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
4289 /* This is a bad hack to set the window background. */
4290 gtk_window_paint (widget, NULL);
4292 if (window->transient_parent &&
4293 GTK_WIDGET_REALIZED (window->transient_parent))
4294 gdk_window_set_transient_for (widget->window,
4295 GTK_WIDGET (window->transient_parent)->window);
4297 if (window->wm_role)
4298 gdk_window_set_role (widget->window, window->wm_role);
4300 if (!window->decorated)
4301 gdk_window_set_decorations (widget->window, 0);
4303 if (!priv->deletable)
4304 gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4306 gdk_window_set_type_hint (widget->window, window->type_hint);
4308 if (gtk_window_get_skip_pager_hint (window))
4309 gdk_window_set_skip_pager_hint (widget->window, TRUE);
4311 if (gtk_window_get_skip_taskbar_hint (window))
4312 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
4314 if (gtk_window_get_accept_focus (window))
4315 gdk_window_set_accept_focus (widget->window, TRUE);
4317 gdk_window_set_accept_focus (widget->window, FALSE);
4319 if (gtk_window_get_focus_on_map (window))
4320 gdk_window_set_focus_on_map (widget->window, TRUE);
4322 gdk_window_set_focus_on_map (widget->window, FALSE);
4325 gdk_window_set_modal_hint (widget->window, TRUE);
4327 gdk_window_set_modal_hint (widget->window, FALSE);
4330 gtk_window_realize_icon (window);
4334 gtk_window_unrealize (GtkWidget *widget)
4337 GtkWindowGeometryInfo *info;
4339 window = GTK_WINDOW (widget);
4341 /* On unrealize, we reset the size of the window such
4342 * that we will re-apply the default sizing stuff
4343 * next time we show the window.
4345 * Default positioning is reset on unmap, instead of unrealize.
4347 window->need_default_size = TRUE;
4348 info = gtk_window_get_geometry_info (window, FALSE);
4351 info->resize_width = -1;
4352 info->resize_height = -1;
4353 info->last.configure_request.x = 0;
4354 info->last.configure_request.y = 0;
4355 info->last.configure_request.width = -1;
4356 info->last.configure_request.height = -1;
4357 /* be sure we reset geom hints on re-realize */
4358 info->last.flags = 0;
4363 gdk_window_set_user_data (window->frame, NULL);
4364 gdk_window_destroy (window->frame);
4365 window->frame = NULL;
4369 gtk_window_unrealize_icon (window);
4371 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
4375 gtk_window_size_request (GtkWidget *widget,
4376 GtkRequisition *requisition)
4381 window = GTK_WINDOW (widget);
4382 bin = GTK_BIN (window);
4384 requisition->width = GTK_CONTAINER (window)->border_width * 2;
4385 requisition->height = GTK_CONTAINER (window)->border_width * 2;
4387 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
4389 GtkRequisition child_requisition;
4391 gtk_widget_size_request (bin->child, &child_requisition);
4393 requisition->width += child_requisition.width;
4394 requisition->height += child_requisition.height;
4399 gtk_window_size_allocate (GtkWidget *widget,
4400 GtkAllocation *allocation)
4403 GtkAllocation child_allocation;
4405 window = GTK_WINDOW (widget);
4406 widget->allocation = *allocation;
4408 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
4410 child_allocation.x = GTK_CONTAINER (window)->border_width;
4411 child_allocation.y = GTK_CONTAINER (window)->border_width;
4412 child_allocation.width =
4413 MAX (1, (gint)allocation->width - child_allocation.x * 2);
4414 child_allocation.height =
4415 MAX (1, (gint)allocation->height - child_allocation.y * 2);
4417 gtk_widget_size_allocate (window->bin.child, &child_allocation);
4420 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4422 gdk_window_resize (window->frame,
4423 allocation->width + window->frame_left + window->frame_right,
4424 allocation->height + window->frame_top + window->frame_bottom);
4429 gtk_window_event (GtkWidget *widget, GdkEvent *event)
4432 gboolean return_val;
4434 window = GTK_WINDOW (widget);
4436 if (window->frame && (event->any.window == window->frame))
4438 if ((event->type != GDK_KEY_PRESS) &&
4439 (event->type != GDK_KEY_RELEASE) &&
4440 (event->type != GDK_FOCUS_CHANGE))
4442 g_signal_stop_emission_by_name (widget, "event");
4444 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
4449 g_object_unref (event->any.window);
4450 event->any.window = g_object_ref (widget->window);
4458 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
4460 GdkEventConfigure *configure_event;
4463 switch (event->type)
4466 configure_event = (GdkEventConfigure *)event;
4468 /* Invalidate the decorations */
4471 rect.width = configure_event->width;
4472 rect.height = configure_event->height;
4474 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
4476 /* Pass on the (modified) configure event */
4477 configure_event->width -= window->frame_left + window->frame_right;
4478 configure_event->height -= window->frame_top + window->frame_bottom;
4479 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
4488 gtk_window_configure_event (GtkWidget *widget,
4489 GdkEventConfigure *event)
4491 GtkWindow *window = GTK_WINDOW (widget);
4492 gboolean expected_reply = window->configure_request_count > 0;
4494 /* window->configure_request_count incremented for each
4495 * configure request, and decremented to a min of 0 for
4496 * each configure notify.
4498 * All it means is that we know we will get at least
4499 * window->configure_request_count more configure notifies.
4500 * We could get more configure notifies than that; some
4501 * of the configure notifies we get may be unrelated to
4502 * the configure requests. But we will get at least
4503 * window->configure_request_count notifies.
4506 if (window->configure_request_count > 0)
4507 window->configure_request_count -= 1;
4509 /* As an optimization, we avoid a resize when possible.
4511 * The only times we can avoid a resize are:
4512 * - we know only the position changed, not the size
4513 * - we know we have made more requests and so will get more
4514 * notifies and can wait to resize when we get them
4517 if (!expected_reply &&
4518 (widget->allocation.width == event->width &&
4519 widget->allocation.height == event->height))
4521 gdk_window_configure_finished (widget->window);
4526 * If we do need to resize, we do that by:
4527 * - filling in widget->allocation with the new size
4528 * - setting configure_notify_received to TRUE
4529 * for use in gtk_window_move_resize()
4530 * - queueing a resize, leading to invocation of
4531 * gtk_window_move_resize() in an idle handler
4535 window->configure_notify_received = TRUE;
4537 widget->allocation.width = event->width;
4538 widget->allocation.height = event->height;
4540 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4545 /* the accel_key and accel_mods fields of the key have to be setup
4546 * upon calling this function. it'll then return whether that key
4547 * is at all used as accelerator, and if so will OR in the
4548 * accel_flags member of the key.
4551 _gtk_window_query_nonaccels (GtkWindow *window,
4553 GdkModifierType accel_mods)
4555 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4557 /* movement keys are considered locked accels */
4560 static const guint bindings[] = {
4561 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
4562 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
4566 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
4567 if (bindings[i] == accel_key)
4571 /* mnemonics are considered locked accels */
4572 if (accel_mods == window->mnemonic_modifier)
4574 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4575 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
4583 * gtk_window_propagate_key_event:
4584 * @window: a #GtkWindow
4585 * @event: a #GdkEventKey
4587 * Propagate a key press or release event to the focus widget and
4588 * up the focus container chain until a widget handles @event.
4589 * This is normally called by the default ::key_press_event and
4590 * ::key_release_event handlers for toplevel windows,
4591 * however in some cases it may be useful to call this directly when
4592 * overriding the standard key handling for a toplevel window.
4594 * Return value: %TRUE if a widget in the focus chain handled the event.
4597 gtk_window_propagate_key_event (GtkWindow *window,
4600 gboolean handled = FALSE;
4601 GtkWidget *widget, *focus;
4603 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4605 widget = GTK_WIDGET (window);
4606 focus = window->focus_widget;
4608 g_object_ref (focus);
4611 focus && focus != widget &&
4612 gtk_widget_get_toplevel (focus) == widget)
4616 if (GTK_WIDGET_IS_SENSITIVE (focus))
4617 handled = gtk_widget_event (focus, (GdkEvent*) event);
4619 parent = focus->parent;
4621 g_object_ref (parent);
4623 g_object_unref (focus);
4629 g_object_unref (focus);
4635 gtk_window_key_press_event (GtkWidget *widget,
4638 GtkWindow *window = GTK_WINDOW (widget);
4639 gboolean handled = FALSE;
4641 /* handle mnemonics and accelerators */
4643 handled = gtk_window_activate_key (window, event);
4645 /* handle focus widget key events */
4647 handled = gtk_window_propagate_key_event (window, event);
4649 /* Chain up, invokes binding set */
4651 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4657 gtk_window_key_release_event (GtkWidget *widget,
4660 GtkWindow *window = GTK_WINDOW (widget);
4661 gboolean handled = FALSE;
4663 /* handle focus widget key events */
4665 handled = gtk_window_propagate_key_event (window, event);
4667 /* Chain up, invokes binding set */
4669 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4675 gtk_window_real_activate_default (GtkWindow *window)
4677 gtk_window_activate_default (window);
4681 gtk_window_real_activate_focus (GtkWindow *window)
4683 gtk_window_activate_focus (window);
4687 gtk_window_move_focus (GtkWindow *window,
4688 GtkDirectionType dir)
4690 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4692 if (!GTK_CONTAINER (window)->focus_child)
4693 gtk_window_set_focus (window, NULL);
4697 gtk_window_enter_notify_event (GtkWidget *widget,
4698 GdkEventCrossing *event)
4704 gtk_window_leave_notify_event (GtkWidget *widget,
4705 GdkEventCrossing *event)
4711 do_focus_change (GtkWidget *widget,
4714 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4716 g_object_ref (widget);
4719 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4721 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4723 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4724 fevent->focus_change.window = widget->window;
4726 g_object_ref (widget->window);
4727 fevent->focus_change.in = in;
4729 gtk_widget_event (widget, fevent);
4731 g_object_notify (G_OBJECT (widget), "has-focus");
4733 g_object_unref (widget);
4734 gdk_event_free (fevent);
4738 gtk_window_focus_in_event (GtkWidget *widget,
4739 GdkEventFocus *event)
4741 GtkWindow *window = GTK_WINDOW (widget);
4743 /* It appears spurious focus in events can occur when
4744 * the window is hidden. So we'll just check to see if
4745 * the window is visible before actually handling the
4748 if (GTK_WIDGET_VISIBLE (widget))
4750 _gtk_window_set_has_toplevel_focus (window, TRUE);
4751 _gtk_window_set_is_active (window, TRUE);
4758 gtk_window_focus_out_event (GtkWidget *widget,
4759 GdkEventFocus *event)
4761 GtkWindow *window = GTK_WINDOW (widget);
4763 _gtk_window_set_has_toplevel_focus (window, FALSE);
4764 _gtk_window_set_is_active (window, FALSE);
4769 static GdkAtom atom_rcfiles = GDK_NONE;
4770 static GdkAtom atom_iconthemes = GDK_NONE;
4773 send_client_message_to_embedded_windows (GtkWidget *widget,
4774 GdkAtom message_type)
4776 GList *embedded_windows;
4778 embedded_windows = g_object_get_data (G_OBJECT (widget), "gtk-embedded");
4779 if (embedded_windows)
4781 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4784 for (i = 0; i < 5; i++)
4785 send_event->client.data.l[i] = 0;
4786 send_event->client.data_format = 32;
4787 send_event->client.message_type = message_type;
4789 while (embedded_windows)
4791 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4792 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4793 embedded_windows = embedded_windows->next;
4796 gdk_event_free (send_event);
4801 gtk_window_client_event (GtkWidget *widget,
4802 GdkEventClient *event)
4806 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
4807 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
4810 if (event->message_type == atom_rcfiles)
4812 send_client_message_to_embedded_windows (widget, atom_rcfiles);
4813 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4816 if (event->message_type == atom_iconthemes)
4818 send_client_message_to_embedded_windows (widget, atom_iconthemes);
4819 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
4826 gtk_window_check_resize (GtkContainer *container)
4828 GtkWindow *window = GTK_WINDOW (container);
4830 if (GTK_WIDGET_VISIBLE (container))
4831 gtk_window_move_resize (window);
4835 gtk_window_focus (GtkWidget *widget,
4836 GtkDirectionType direction)
4840 GtkContainer *container;
4841 GtkWidget *old_focus_child;
4844 container = GTK_CONTAINER (widget);
4845 window = GTK_WINDOW (widget);
4846 bin = GTK_BIN (widget);
4848 old_focus_child = container->focus_child;
4850 /* We need a special implementation here to deal properly with wrapping
4851 * around in the tab chain without the danger of going into an
4854 if (old_focus_child)
4856 if (gtk_widget_child_focus (old_focus_child, direction))
4860 if (window->focus_widget)
4862 if (direction == GTK_DIR_LEFT ||
4863 direction == GTK_DIR_RIGHT ||
4864 direction == GTK_DIR_UP ||
4865 direction == GTK_DIR_DOWN)
4870 /* Wrapped off the end, clear the focus setting for the toplpevel */
4871 parent = window->focus_widget->parent;
4874 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4875 parent = GTK_WIDGET (parent)->parent;
4878 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4881 /* Now try to focus the first widget in the window */
4884 if (gtk_widget_child_focus (bin->child, direction))
4892 gtk_window_real_set_focus (GtkWindow *window,
4895 GtkWidget *old_focus = window->focus_widget;
4896 gboolean had_default = FALSE;
4897 gboolean focus_had_default = FALSE;
4898 gboolean old_focus_had_default = FALSE;
4902 g_object_ref (old_focus);
4903 g_object_freeze_notify (G_OBJECT (old_focus));
4904 old_focus_had_default = GTK_WIDGET_HAS_DEFAULT (old_focus);
4908 g_object_ref (focus);
4909 g_object_freeze_notify (G_OBJECT (focus));
4910 focus_had_default = GTK_WIDGET_HAS_DEFAULT (focus);
4913 if (window->default_widget)
4914 had_default = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4916 if (window->focus_widget)
4918 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4919 (window->focus_widget != window->default_widget))
4921 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4922 gtk_widget_queue_draw (window->focus_widget);
4924 if (window->default_widget)
4925 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4928 window->focus_widget = NULL;
4930 if (window->has_focus)
4931 do_focus_change (old_focus, FALSE);
4933 g_object_notify (G_OBJECT (old_focus), "is-focus");
4936 /* The above notifications may have set a new focus widget,
4937 * if so, we don't want to override it.
4939 if (focus && !window->focus_widget)
4941 window->focus_widget = focus;
4943 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4944 (window->focus_widget != window->default_widget))
4946 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4947 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4949 if (window->default_widget)
4950 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4953 if (window->has_focus)
4954 do_focus_change (window->focus_widget, TRUE);
4956 g_object_notify (G_OBJECT (window->focus_widget), "is-focus");
4959 /* If the default widget changed, a redraw will have been queued
4960 * on the old and new default widgets by gtk_window_set_default(), so
4961 * we only have to worry about the case where it didn't change.
4962 * We'll sometimes queue a draw twice on the new widget but that
4965 if (window->default_widget &&
4966 (had_default != GTK_WIDGET_HAS_DEFAULT (window->default_widget)))
4967 gtk_widget_queue_draw (window->default_widget);
4971 if (old_focus_had_default != GTK_WIDGET_HAS_DEFAULT (old_focus))
4972 gtk_widget_queue_draw (old_focus);
4974 g_object_thaw_notify (G_OBJECT (old_focus));
4975 g_object_unref (old_focus);
4979 if (focus_had_default != GTK_WIDGET_HAS_DEFAULT (focus))
4980 gtk_widget_queue_draw (focus);
4982 g_object_thaw_notify (G_OBJECT (focus));
4983 g_object_unref (focus);
4988 * _gtk_window_unset_focus_and_default:
4989 * @window: a #GtkWindow
4990 * @widget: a widget inside of @window
4992 * Checks whether the focus and default widgets of @window are
4993 * @widget or a descendent of @widget, and if so, unset them.
4996 _gtk_window_unset_focus_and_default (GtkWindow *window,
5002 g_object_ref (window);
5003 g_object_ref (widget);
5005 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
5007 child = window->focus_widget;
5009 while (child && child != widget)
5010 child = child->parent;
5012 if (child == widget)
5013 gtk_window_set_focus (GTK_WINDOW (window), NULL);
5016 child = window->default_widget;
5018 while (child && child != widget)
5019 child = child->parent;
5021 if (child == widget)
5022 gtk_window_set_default (window, NULL);
5024 g_object_unref (widget);
5025 g_object_unref (window);
5028 /*********************************
5029 * Functions related to resizing *
5030 *********************************/
5032 /* This function doesn't constrain to geometry hints */
5034 gtk_window_compute_configure_request_size (GtkWindow *window,
5038 GtkRequisition requisition;
5039 GtkWindowGeometryInfo *info;
5043 * - we've done a size request
5046 widget = GTK_WIDGET (window);
5048 info = gtk_window_get_geometry_info (window, FALSE);
5050 if (window->need_default_size)
5052 gtk_widget_get_child_requisition (widget, &requisition);
5054 /* Default to requisition */
5055 *width = requisition.width;
5056 *height = requisition.height;
5058 /* If window is empty so requests 0, default to random nonzero size */
5059 if (*width == 0 && *height == 0)
5065 /* Override requisition with default size */
5069 gint base_width = 0;
5070 gint base_height = 0;
5072 gint height_inc = 1;
5074 if (info->default_is_geometry &&
5075 (info->default_width > 0 || info->default_height > 0))
5077 GdkGeometry geometry;
5080 gtk_window_compute_hints (window, &geometry, &flags);
5082 if (flags & GDK_HINT_BASE_SIZE)
5084 base_width = geometry.base_width;
5085 base_height = geometry.base_height;
5087 else if (flags & GDK_HINT_MIN_SIZE)
5089 base_width = geometry.min_width;
5090 base_height = geometry.min_height;
5092 if (flags & GDK_HINT_RESIZE_INC)
5094 width_inc = geometry.width_inc;
5095 height_inc = geometry.height_inc;
5099 if (info->default_width > 0)
5100 *width = info->default_width * width_inc + base_width;
5102 if (info->default_height > 0)
5103 *height = info->default_height * height_inc + base_height;
5108 /* Default to keeping current size */
5109 *width = widget->allocation.width;
5110 *height = widget->allocation.height;
5113 /* Override any size with gtk_window_resize() values */
5116 if (info->resize_width > 0)
5117 *width = info->resize_width;
5119 if (info->resize_height > 0)
5120 *height = info->resize_height;
5124 static GtkWindowPosition
5125 get_effective_position (GtkWindow *window)
5127 GtkWindowPosition pos = window->position;
5128 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5129 (window->transient_parent == NULL ||
5130 !GTK_WIDGET_MAPPED (window->transient_parent)))
5131 pos = GTK_WIN_POS_NONE;
5137 get_center_monitor_of_window (GtkWindow *window)
5139 /* We could try to sort out the relative positions of the monitors and
5140 * stuff, or we could just be losers and assume you have a row
5141 * or column of monitors.
5143 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5147 get_monitor_containing_pointer (GtkWindow *window)
5151 GdkScreen *window_screen;
5152 GdkScreen *pointer_screen;
5154 window_screen = gtk_window_check_screen (window);
5155 gdk_display_get_pointer (gdk_screen_get_display (window_screen),
5159 if (pointer_screen == window_screen)
5160 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5168 center_window_on_monitor (GtkWindow *window,
5174 GdkRectangle monitor;
5177 monitor_num = get_monitor_containing_pointer (window);
5179 if (monitor_num == -1)
5180 monitor_num = get_center_monitor_of_window (window);
5182 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5183 monitor_num, &monitor);
5185 *x = (monitor.width - w) / 2 + monitor.x;
5186 *y = (monitor.height - h) / 2 + monitor.y;
5188 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5189 * and WM decorations.
5198 clamp_window_to_rectangle (gint *x,
5202 const GdkRectangle *rect)
5204 gint outside_w, outside_h;
5206 outside_w = (*x + w) - (rect->x + rect->width);
5210 outside_h = (*y + h) - (rect->y + rect->height);
5214 /* if larger than the screen, center on the screen. */
5216 *x += (rect->x - *x) / 2;
5218 *y += (rect->y - *y) / 2;
5223 gtk_window_compute_configure_request (GtkWindow *window,
5224 GdkRectangle *request,
5225 GdkGeometry *geometry,
5228 GdkGeometry new_geometry;
5232 GtkWindowPosition pos;
5233 GtkWidget *parent_widget;
5234 GtkWindowGeometryInfo *info;
5238 widget = GTK_WIDGET (window);
5240 screen = gtk_window_check_screen (window);
5242 gtk_widget_size_request (widget, NULL);
5243 gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
5245 gtk_window_compute_hints (window, &new_geometry, &new_flags);
5246 gtk_window_constrain_size (window,
5247 &new_geometry, new_flags,
5251 parent_widget = (GtkWidget*) window->transient_parent;
5253 pos = get_effective_position (window);
5254 info = gtk_window_get_geometry_info (window, TRUE);
5256 /* by default, don't change position requested */
5257 x = info->last.configure_request.x;
5258 y = info->last.configure_request.y;
5260 if (window->need_default_position)
5263 /* FIXME this all interrelates with window gravity.
5264 * For most of them I think we want to set GRAVITY_CENTER.
5266 * Not sure how to go about that.
5271 /* here we are only handling CENTER_ALWAYS
5272 * as it relates to default positioning,
5273 * where it's equivalent to simply CENTER
5275 case GTK_WIN_POS_CENTER_ALWAYS:
5276 case GTK_WIN_POS_CENTER:
5277 center_window_on_monitor (window, w, h, &x, &y);
5280 case GTK_WIN_POS_CENTER_ON_PARENT:
5283 GdkRectangle monitor;
5286 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
5288 if (parent_widget->window != NULL)
5289 monitor_num = gdk_screen_get_monitor_at_window (screen,
5290 parent_widget->window);
5294 gdk_window_get_origin (parent_widget->window,
5297 x = ox + (parent_widget->allocation.width - w) / 2;
5298 y = oy + (parent_widget->allocation.height - h) / 2;
5300 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5301 * WM decorations. If parent wasn't on a monitor, just
5304 if (monitor_num >= 0)
5306 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5307 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5312 case GTK_WIN_POS_MOUSE:
5314 gint screen_width = gdk_screen_get_width (screen);
5315 gint screen_height = gdk_screen_get_height (screen);
5317 GdkRectangle monitor;
5318 GdkScreen *pointer_screen;
5321 gdk_display_get_pointer (gdk_screen_get_display (screen),
5325 if (pointer_screen == screen)
5326 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
5332 x = CLAMP (x, 0, screen_width - w);
5333 y = CLAMP (y, 0, screen_height - h);
5335 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5336 * WM decorations. Don't try to figure out what's going
5337 * on if the mouse wasn't inside a monitor.
5339 if (monitor_num >= 0)
5341 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5342 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5350 } /* if (window->need_default_position) */
5352 if (window->need_default_position &&
5353 info->initial_pos_set)
5355 x = info->initial_x;
5356 y = info->initial_y;
5357 gtk_window_constrain_position (window, w, h, &x, &y);
5363 request->height = h;
5366 *geometry = new_geometry;
5372 gtk_window_constrain_position (GtkWindow *window,
5378 /* See long comments in gtk_window_move_resize()
5379 * on when it's safe to call this function.
5381 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
5383 gint center_x, center_y;
5385 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
5393 gtk_window_move_resize (GtkWindow *window)
5397 * First we determine whether any information has changed that would
5398 * cause us to revise our last configure request. If we would send
5399 * a different configure request from last time, then
5400 * configure_request_size_changed = TRUE or
5401 * configure_request_pos_changed = TRUE. configure_request_size_changed
5402 * may be true due to new hints, a gtk_window_resize(), or whatever.
5403 * configure_request_pos_changed may be true due to gtk_window_set_position()
5404 * or gtk_window_move().
5406 * If the configure request has changed, we send off a new one. To
5407 * ensure GTK+ invariants are maintained (resize queue does what it
5408 * should), we go ahead and size_allocate the requested size in this
5411 * If the configure request has not changed, we don't ever resend
5412 * it, because it could mean fighting the user or window manager.
5415 * To prepare the configure request, we come up with a base size/pos:
5416 * - the one from gtk_window_move()/gtk_window_resize()
5417 * - else default_width, default_height if we haven't ever
5419 * - else the size request if we haven't ever been mapped,
5420 * as a substitute default size
5421 * - else the current size of the window, as received from
5422 * configure notifies (i.e. the current allocation)
5424 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
5425 * the position request to be centered.
5428 GtkContainer *container;
5429 GtkWindowGeometryInfo *info;
5430 GdkGeometry new_geometry;
5432 GdkRectangle new_request;
5433 gboolean configure_request_size_changed;
5434 gboolean configure_request_pos_changed;
5435 gboolean hints_changed; /* do we need to send these again */
5436 GtkWindowLastGeometryInfo saved_last_info;
5438 widget = GTK_WIDGET (window);
5439 container = GTK_CONTAINER (widget);
5440 info = gtk_window_get_geometry_info (window, TRUE);
5442 configure_request_size_changed = FALSE;
5443 configure_request_pos_changed = FALSE;
5445 gtk_window_compute_configure_request (window, &new_request,
5446 &new_geometry, &new_flags);
5448 /* This check implies the invariant that we never set info->last
5449 * without setting the hints and sending off a configure request.
5451 * If we change info->last without sending the request, we may
5454 if (info->last.configure_request.x != new_request.x ||
5455 info->last.configure_request.y != new_request.y)
5456 configure_request_pos_changed = TRUE;
5458 if ((info->last.configure_request.width != new_request.width ||
5459 info->last.configure_request.height != new_request.height))
5460 configure_request_size_changed = TRUE;
5462 hints_changed = FALSE;
5464 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
5465 &new_geometry, new_flags))
5467 hints_changed = TRUE;
5470 /* Position Constraints
5471 * ====================
5473 * POS_CENTER_ALWAYS is conceptually a constraint rather than
5474 * a default. The other POS_ values are used only when the
5475 * window is shown, not after that.
5477 * However, we can't implement a position constraint as
5478 * "anytime the window size changes, center the window"
5479 * because this may well end up fighting the WM or user. In
5480 * fact it gets in an infinite loop with at least one WM.
5482 * Basically, applications are in no way in a position to
5483 * constrain the position of a window, with one exception:
5484 * override redirect windows. (Really the intended purpose
5485 * of CENTER_ALWAYS anyhow, I would think.)
5487 * So the way we implement this "constraint" is to say that when WE
5488 * cause a move or resize, i.e. we make a configure request changing
5489 * window size, we recompute the CENTER_ALWAYS position to reflect
5490 * the new window size, and include it in our request. Also, if we
5491 * just turned on CENTER_ALWAYS we snap to center with a new
5492 * request. Otherwise, if we are just NOTIFIED of a move or resize
5493 * done by someone else e.g. the window manager, we do NOT send a
5494 * new configure request.
5496 * For override redirect windows, this works fine; all window
5497 * sizes are from our configure requests. For managed windows,
5498 * it is at least semi-sane, though who knows what the
5499 * app author is thinking.
5502 /* This condition should be kept in sync with the condition later on
5503 * that determines whether we send a configure request. i.e. we
5504 * should do this position constraining anytime we were going to
5505 * send a configure request anyhow, plus when constraints have
5508 if (configure_request_pos_changed ||
5509 configure_request_size_changed ||
5511 info->position_constraints_changed)
5513 /* We request the constrained position if:
5514 * - we were changing position, and need to clamp
5515 * the change to the constraint
5516 * - we're changing the size anyway
5517 * - set_position() was called to toggle CENTER_ALWAYS on
5520 gtk_window_constrain_position (window,
5526 /* Update whether we need to request a move */
5527 if (info->last.configure_request.x != new_request.x ||
5528 info->last.configure_request.y != new_request.y)
5529 configure_request_pos_changed = TRUE;
5531 configure_request_pos_changed = FALSE;
5535 if (window->type == GTK_WINDOW_TOPLEVEL)
5537 int notify_x, notify_y;
5539 /* this is the position from the last configure notify */
5540 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
5542 g_message ("--- %s ---\n"
5543 "last : %d,%d\t%d x %d\n"
5544 "this : %d,%d\t%d x %d\n"
5545 "alloc : %d,%d\t%d x %d\n"
5547 "resize: \t%d x %d\n"
5548 "size_changed: %d pos_changed: %d hints_changed: %d\n"
5549 "configure_notify_received: %d\n"
5550 "configure_request_count: %d\n"
5551 "position_constraints_changed: %d\n",
5552 window->title ? window->title : "(no title)",
5553 info->last.configure_request.x,
5554 info->last.configure_request.y,
5555 info->last.configure_request.width,
5556 info->last.configure_request.height,
5562 widget->allocation.width,
5563 widget->allocation.height,
5564 widget->requisition.width,
5565 widget->requisition.height,
5567 info->resize_height,
5568 configure_request_pos_changed,
5569 configure_request_size_changed,
5571 window->configure_notify_received,
5572 window->configure_request_count,
5573 info->position_constraints_changed);
5577 saved_last_info = info->last;
5578 info->last.geometry = new_geometry;
5579 info->last.flags = new_flags;
5580 info->last.configure_request = new_request;
5582 /* need to set PPosition so the WM will look at our position,
5583 * but we don't want to count PPosition coming and going as a hints
5584 * change for future iterations. So we saved info->last prior to
5588 /* Also, if the initial position was explicitly set, then we always
5589 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
5593 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
5594 * this is an initial map
5597 if ((configure_request_pos_changed ||
5598 info->initial_pos_set ||
5599 (window->need_default_position &&
5600 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
5601 (new_flags & GDK_HINT_POS) == 0)
5603 new_flags |= GDK_HINT_POS;
5604 hints_changed = TRUE;
5607 /* Set hints if necessary
5610 gdk_window_set_geometry_hints (widget->window,
5614 /* handle resizing/moving and widget tree allocation
5616 if (window->configure_notify_received)
5618 GtkAllocation allocation;
5620 /* If we have received a configure event since
5621 * the last time in this function, we need to
5622 * accept our new size and size_allocate child widgets.
5623 * (see gtk_window_configure_event() for more details).
5625 * 1 or more configure notifies may have been received.
5626 * Also, configure_notify_received will only be TRUE
5627 * if all expected configure notifies have been received
5628 * (one per configure request), as an optimization.
5631 window->configure_notify_received = FALSE;
5633 /* gtk_window_configure_event() filled in widget->allocation */
5634 allocation = widget->allocation;
5635 gtk_widget_size_allocate (widget, &allocation);
5637 gdk_window_process_all_updates ();
5639 gdk_window_configure_finished (widget->window);
5641 /* If the configure request changed, it means that
5643 * 1) coincidentally changed hints or widget properties
5644 * impacting the configure request before getting
5645 * a configure notify, or
5646 * 2) some broken widget is changing its size request
5647 * during size allocation, resulting in
5648 * a false appearance of changed configure request.
5650 * For 1), we could just go ahead and ask for the
5651 * new size right now, but doing that for 2)
5652 * might well be fighting the user (and can even
5653 * trigger a loop). Since we really don't want to
5654 * do that, we requeue a resize in hopes that
5655 * by the time it gets handled, the child has seen
5656 * the light and is willing to go along with the
5657 * new size. (this happens for the zvt widget, since
5658 * the size_allocate() above will have stored the
5659 * requisition corresponding to the new size in the
5662 * This doesn't buy us anything for 1), but it shouldn't
5663 * hurt us too badly, since it is what would have
5664 * happened if we had gotten the configure event before
5665 * the new size had been set.
5668 if (configure_request_size_changed ||
5669 configure_request_pos_changed)
5671 /* Don't change the recorded last info after all, because we
5672 * haven't actually updated to the new info yet - we decided
5673 * to postpone our configure request until later.
5675 info->last = saved_last_info;
5677 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
5680 return; /* Bail out, we didn't really process the move/resize */
5682 else if ((configure_request_size_changed || hints_changed) &&
5683 (widget->allocation.width != new_request.width ||
5684 widget->allocation.height != new_request.height))
5687 /* We are in one of the following situations:
5688 * A. configure_request_size_changed
5689 * our requisition has changed and we need a different window size,
5690 * so we request it from the window manager.
5691 * B. !configure_request_size_changed && hints_changed
5692 * the window manager rejects our size, but we have just changed the
5693 * window manager hints, so there's a chance our request will
5694 * be honoured this time, so we try again.
5696 * However, if the new requisition is the same as the current allocation,
5697 * we don't request it again, since we won't get a ConfigureNotify back from
5698 * the window manager unless it decides to change our requisition. If
5699 * we don't get the ConfigureNotify back, the resize queue will never be run.
5702 /* Now send the configure request */
5703 if (configure_request_pos_changed)
5707 gdk_window_move_resize (window->frame,
5708 new_request.x - window->frame_left,
5709 new_request.y - window->frame_top,
5710 new_request.width + window->frame_left + window->frame_right,
5711 new_request.height + window->frame_top + window->frame_bottom);
5712 gdk_window_resize (widget->window,
5713 new_request.width, new_request.height);
5716 gdk_window_move_resize (widget->window,
5717 new_request.x, new_request.y,
5718 new_request.width, new_request.height);
5720 else /* only size changed */
5723 gdk_window_resize (window->frame,
5724 new_request.width + window->frame_left + window->frame_right,
5725 new_request.height + window->frame_top + window->frame_bottom);
5726 gdk_window_resize (widget->window,
5727 new_request.width, new_request.height);
5730 /* Increment the number of have-not-yet-received-notify requests */
5731 window->configure_request_count += 1;
5733 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5734 * configure event in response to our resizing request.
5735 * the configure event will cause a new resize with
5736 * ->configure_notify_received=TRUE.
5737 * until then, we want to
5738 * - discard expose events
5739 * - coalesce resizes for our children
5740 * - defer any window resizes until the configure event arrived
5741 * to achieve this, we queue a resize for the window, but remove its
5742 * resizing handler, so resizing will not be handled from the next
5743 * idle handler but when the configure event arrives.
5745 * FIXME: we should also dequeue the pending redraws here, since
5746 * we handle those ourselves upon ->configure_notify_received==TRUE.
5748 if (container->resize_mode == GTK_RESIZE_QUEUE)
5750 gtk_widget_queue_resize (widget);
5751 _gtk_container_dequeue_resize_handler (container);
5756 /* Handle any position changes.
5758 if (configure_request_pos_changed)
5762 gdk_window_move (window->frame,
5763 new_request.x - window->frame_left,
5764 new_request.y - window->frame_top);
5767 gdk_window_move (widget->window,
5768 new_request.x, new_request.y);
5771 /* And run the resize queue.
5773 gtk_container_resize_children (container);
5776 /* We have now processed a move/resize since the last position
5777 * constraint change, setting of the initial position, or resize.
5778 * (Not resetting these flags here can lead to infinite loops for
5779 * GTK_RESIZE_IMMEDIATE containers)
5781 info->position_constraints_changed = FALSE;
5782 info->initial_pos_set = FALSE;
5783 info->resize_width = -1;
5784 info->resize_height = -1;
5787 /* Compare two sets of Geometry hints for equality.
5790 gtk_window_compare_hints (GdkGeometry *geometry_a,
5792 GdkGeometry *geometry_b,
5795 if (flags_a != flags_b)
5798 if ((flags_a & GDK_HINT_MIN_SIZE) &&
5799 (geometry_a->min_width != geometry_b->min_width ||
5800 geometry_a->min_height != geometry_b->min_height))
5803 if ((flags_a & GDK_HINT_MAX_SIZE) &&
5804 (geometry_a->max_width != geometry_b->max_width ||
5805 geometry_a->max_height != geometry_b->max_height))
5808 if ((flags_a & GDK_HINT_BASE_SIZE) &&
5809 (geometry_a->base_width != geometry_b->base_width ||
5810 geometry_a->base_height != geometry_b->base_height))
5813 if ((flags_a & GDK_HINT_ASPECT) &&
5814 (geometry_a->min_aspect != geometry_b->min_aspect ||
5815 geometry_a->max_aspect != geometry_b->max_aspect))
5818 if ((flags_a & GDK_HINT_RESIZE_INC) &&
5819 (geometry_a->width_inc != geometry_b->width_inc ||
5820 geometry_a->height_inc != geometry_b->height_inc))
5823 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5824 geometry_a->win_gravity != geometry_b->win_gravity)
5831 _gtk_window_constrain_size (GtkWindow *window,
5837 GtkWindowGeometryInfo *info;
5839 g_return_if_fail (GTK_IS_WINDOW (window));
5841 info = window->geometry_info;
5844 GdkWindowHints flags = info->last.flags;
5845 GdkGeometry *geometry = &info->last.geometry;
5847 gtk_window_constrain_size (window,
5858 gtk_window_constrain_size (GtkWindow *window,
5859 GdkGeometry *geometry,
5866 gdk_window_constrain_size (geometry, flags, width, height,
5867 new_width, new_height);
5870 /* Compute the set of geometry hints and flags for a window
5871 * based on the application set geometry, and requisiition
5872 * of the window. gtk_widget_size_request() must have been
5876 gtk_window_compute_hints (GtkWindow *window,
5877 GdkGeometry *new_geometry,
5881 gint extra_width = 0;
5882 gint extra_height = 0;
5883 GtkWindowGeometryInfo *geometry_info;
5884 GtkRequisition requisition;
5886 widget = GTK_WIDGET (window);
5888 gtk_widget_get_child_requisition (widget, &requisition);
5889 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5893 *new_flags = geometry_info->mask;
5894 *new_geometry = geometry_info->geometry;
5901 if (geometry_info && geometry_info->widget)
5903 GtkRequisition child_requisition;
5905 /* FIXME: This really isn't right. It gets the min size wrong and forces
5906 * callers to do horrible hacks like set a huge usize on the child requisition
5907 * to get the base size right. We really want to find the answers to:
5909 * - If the geometry widget was infinitely big, how much extra space
5910 * would be needed for the stuff around it.
5912 * - If the geometry widget was infinitely small, how big would the
5913 * window still have to be.
5915 * Finding these answers would be a bit of a mess here. (Bug #68668)
5917 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5919 extra_width = widget->requisition.width - child_requisition.width;
5920 extra_height = widget->requisition.height - child_requisition.height;
5923 /* We don't want to set GDK_HINT_POS in here, we just set it
5924 * in gtk_window_move_resize() when we want the position
5928 if (*new_flags & GDK_HINT_BASE_SIZE)
5930 new_geometry->base_width += extra_width;
5931 new_geometry->base_height += extra_height;
5933 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5934 (*new_flags & GDK_HINT_RESIZE_INC) &&
5935 ((extra_width != 0) || (extra_height != 0)))
5937 *new_flags |= GDK_HINT_BASE_SIZE;
5939 new_geometry->base_width = extra_width;
5940 new_geometry->base_height = extra_height;
5943 if (*new_flags & GDK_HINT_MIN_SIZE)
5945 if (new_geometry->min_width < 0)
5946 new_geometry->min_width = requisition.width;
5948 new_geometry->min_width += extra_width;
5950 if (new_geometry->min_height < 0)
5951 new_geometry->min_height = requisition.height;
5953 new_geometry->min_height += extra_height;
5955 else if (!window->allow_shrink)
5957 *new_flags |= GDK_HINT_MIN_SIZE;
5959 new_geometry->min_width = requisition.width;
5960 new_geometry->min_height = requisition.height;
5963 if (*new_flags & GDK_HINT_MAX_SIZE)
5965 if (new_geometry->max_width < 0)
5966 new_geometry->max_width = requisition.width;
5968 new_geometry->max_width += extra_width;
5970 if (new_geometry->max_height < 0)
5971 new_geometry->max_height = requisition.height;
5973 new_geometry->max_height += extra_height;
5975 else if (!window->allow_grow)
5977 *new_flags |= GDK_HINT_MAX_SIZE;
5979 new_geometry->max_width = requisition.width;
5980 new_geometry->max_height = requisition.height;
5983 *new_flags |= GDK_HINT_WIN_GRAVITY;
5984 new_geometry->win_gravity = window->gravity;
5987 /***********************
5988 * Redrawing functions *
5989 ***********************/
5992 gtk_window_paint (GtkWidget *widget,
5995 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
5996 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
6000 gtk_window_expose (GtkWidget *widget,
6001 GdkEventExpose *event)
6003 if (!GTK_WIDGET_APP_PAINTABLE (widget))
6004 gtk_window_paint (widget, &event->area);
6006 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
6007 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
6013 * gtk_window_set_has_frame:
6014 * @window: a #GtkWindow
6015 * @setting: a boolean
6017 * (Note: this is a special-purpose function for the framebuffer port,
6018 * that causes GTK+ to draw its own window border. For most applications,
6019 * you want gtk_window_set_decorated() instead, which tells the window
6020 * manager whether to draw the window border.)
6022 * If this function is called on a window with setting of %TRUE, before
6023 * it is realized or showed, it will have a "frame" window around
6024 * @window->window, accessible in @window->frame. Using the signal
6025 * frame_event you can receive all events targeted at the frame.
6027 * This function is used by the linux-fb port to implement managed
6028 * windows, but it could concievably be used by X-programs that
6029 * want to do their own window decorations.
6033 gtk_window_set_has_frame (GtkWindow *window,
6036 g_return_if_fail (GTK_IS_WINDOW (window));
6037 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
6039 window->has_frame = setting != FALSE;
6043 * gtk_window_get_has_frame:
6044 * @window: a #GtkWindow
6046 * Accessor for whether the window has a frame window exterior to
6047 * @window->window. Gets the value set by gtk_window_set_has_frame ().
6049 * Return value: %TRUE if a frame has been added to the window
6050 * via gtk_window_set_has_frame().
6053 gtk_window_get_has_frame (GtkWindow *window)
6055 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6057 return window->has_frame;
6061 * gtk_window_set_frame_dimensions:
6062 * @window: a #GtkWindow that has a frame
6063 * @left: The width of the left border
6064 * @top: The height of the top border
6065 * @right: The width of the right border
6066 * @bottom: The height of the bottom border
6068 * (Note: this is a special-purpose function intended for the framebuffer
6069 * port; see gtk_window_set_has_frame(). It will have no effect on the
6070 * window border drawn by the window manager, which is the normal
6071 * case when using the X Window system.)
6073 * For windows with frames (see gtk_window_set_has_frame()) this function
6074 * can be used to change the size of the frame border.
6077 gtk_window_set_frame_dimensions (GtkWindow *window,
6085 g_return_if_fail (GTK_IS_WINDOW (window));
6087 widget = GTK_WIDGET (window);
6089 if (window->frame_left == left &&
6090 window->frame_top == top &&
6091 window->frame_right == right &&
6092 window->frame_bottom == bottom)
6095 window->frame_left = left;
6096 window->frame_top = top;
6097 window->frame_right = right;
6098 window->frame_bottom = bottom;
6100 if (GTK_WIDGET_REALIZED (widget) && window->frame)
6102 gint width = widget->allocation.width + left + right;
6103 gint height = widget->allocation.height + top + bottom;
6104 gdk_window_resize (window->frame, width, height);
6105 gtk_decorated_window_move_resize_window (window,
6107 widget->allocation.width,
6108 widget->allocation.height);
6113 * gtk_window_present:
6114 * @window: a #GtkWindow
6116 * Presents a window to the user. This may mean raising the window
6117 * in the stacking order, deiconifying it, moving it to the current
6118 * desktop, and/or giving it the keyboard focus, possibly dependent
6119 * on the user's platform, window manager, and preferences.
6121 * If @window is hidden, this function calls gtk_widget_show()
6124 * This function should be used when the user tries to open a window
6125 * that's already open. Say for example the preferences dialog is
6126 * currently open, and the user chooses Preferences from the menu
6127 * a second time; use gtk_window_present() to move the already-open dialog
6128 * where the user can see it.
6130 * If you are calling this function in response to a user interaction,
6131 * it is preferable to use gdk_window_present_with_time().
6135 gtk_window_present (GtkWindow *window)
6137 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6141 * gtk_window_present_with_time:
6142 * @window: a #GtkWindow
6143 * @timestamp: the timestamp of the user interaction (typically a
6144 * button or key press event) which triggered this call
6146 * Presents a window to the user in response to a user interaction.
6147 * If you need to present a window without a timestamp, use
6148 * gtk_window_present(). See gtk_window_present() for details.
6153 gtk_window_present_with_time (GtkWindow *window,
6158 g_return_if_fail (GTK_IS_WINDOW (window));
6160 widget = GTK_WIDGET (window);
6162 if (GTK_WIDGET_VISIBLE (window))
6164 g_assert (widget->window != NULL);
6166 gdk_window_show (widget->window);
6168 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
6169 if (timestamp == GDK_CURRENT_TIME)
6171 #ifdef GDK_WINDOWING_X11
6172 GdkDisplay *display;
6174 display = gtk_widget_get_display (GTK_WIDGET (window));
6175 timestamp = gdk_x11_display_get_user_time (display);
6177 timestamp = gtk_get_current_event_time ();
6181 gdk_window_focus (widget->window, timestamp);
6185 gtk_widget_show (widget);
6190 * gtk_window_iconify:
6191 * @window: a #GtkWindow
6193 * Asks to iconify (i.e. minimize) the specified @window. Note that
6194 * you shouldn't assume the window is definitely iconified afterward,
6195 * because other entities (e.g. the user or <link
6196 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
6197 * again, or there may not be a window manager in which case
6198 * iconification isn't possible, etc. But normally the window will end
6199 * up iconified. Just don't write code that crashes if not.
6201 * It's permitted to call this function before showing a window,
6202 * in which case the window will be iconified before it ever appears
6205 * You can track iconification via the "window_state_event" signal
6210 gtk_window_iconify (GtkWindow *window)
6213 GdkWindow *toplevel;
6215 g_return_if_fail (GTK_IS_WINDOW (window));
6217 widget = GTK_WIDGET (window);
6219 window->iconify_initially = TRUE;
6222 toplevel = window->frame;
6224 toplevel = widget->window;
6226 if (toplevel != NULL)
6227 gdk_window_iconify (toplevel);
6231 * gtk_window_deiconify:
6232 * @window: a #GtkWindow
6234 * Asks to deiconify (i.e. unminimize) the specified @window. Note
6235 * that you shouldn't assume the window is definitely deiconified
6236 * afterward, because other entities (e.g. the user or <link
6237 * linkend="gtk-X11-arch">window manager</link>) could iconify it
6238 * again before your code which assumes deiconification gets to run.
6240 * You can track iconification via the "window_state_event" signal
6244 gtk_window_deiconify (GtkWindow *window)
6247 GdkWindow *toplevel;
6249 g_return_if_fail (GTK_IS_WINDOW (window));
6251 widget = GTK_WIDGET (window);
6253 window->iconify_initially = FALSE;
6256 toplevel = window->frame;
6258 toplevel = widget->window;
6260 if (toplevel != NULL)
6261 gdk_window_deiconify (toplevel);
6266 * @window: a #GtkWindow
6268 * Asks to stick @window, which means that it will appear on all user
6269 * desktops. Note that you shouldn't assume the window is definitely
6270 * stuck afterward, because other entities (e.g. the user or <link
6271 * linkend="gtk-X11-arch">window manager</link>) could unstick it
6272 * again, and some window managers do not support sticking
6273 * windows. But normally the window will end up stuck. Just don't
6274 * write code that crashes if not.
6276 * It's permitted to call this function before showing a window.
6278 * You can track stickiness via the "window_state_event" signal
6283 gtk_window_stick (GtkWindow *window)
6286 GdkWindow *toplevel;
6288 g_return_if_fail (GTK_IS_WINDOW (window));
6290 widget = GTK_WIDGET (window);
6292 window->stick_initially = TRUE;
6295 toplevel = window->frame;
6297 toplevel = widget->window;
6299 if (toplevel != NULL)
6300 gdk_window_stick (toplevel);
6304 * gtk_window_unstick:
6305 * @window: a #GtkWindow
6307 * Asks to unstick @window, which means that it will appear on only
6308 * one of the user's desktops. Note that you shouldn't assume the
6309 * window is definitely unstuck afterward, because other entities
6310 * (e.g. the user or <link linkend="gtk-X11-arch">window
6311 * manager</link>) could stick it again. But normally the window will
6312 * end up stuck. Just don't write code that crashes if not.
6314 * You can track stickiness via the "window_state_event" signal
6319 gtk_window_unstick (GtkWindow *window)
6322 GdkWindow *toplevel;
6324 g_return_if_fail (GTK_IS_WINDOW (window));
6326 widget = GTK_WIDGET (window);
6328 window->stick_initially = FALSE;
6331 toplevel = window->frame;
6333 toplevel = widget->window;
6335 if (toplevel != NULL)
6336 gdk_window_unstick (toplevel);
6340 * gtk_window_maximize:
6341 * @window: a #GtkWindow
6343 * Asks to maximize @window, so that it becomes full-screen. Note that
6344 * you shouldn't assume the window is definitely maximized afterward,
6345 * because other entities (e.g. the user or <link
6346 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
6347 * again, and not all window managers support maximization. But
6348 * normally the window will end up maximized. Just don't write code
6349 * that crashes if not.
6351 * It's permitted to call this function before showing a window,
6352 * in which case the window will be maximized when it appears onscreen
6355 * You can track maximization via the "window_state_event" signal
6360 gtk_window_maximize (GtkWindow *window)
6363 GdkWindow *toplevel;
6365 g_return_if_fail (GTK_IS_WINDOW (window));
6367 widget = GTK_WIDGET (window);
6369 window->maximize_initially = TRUE;
6372 toplevel = window->frame;
6374 toplevel = widget->window;
6376 if (toplevel != NULL)
6377 gdk_window_maximize (toplevel);
6381 * gtk_window_unmaximize:
6382 * @window: a #GtkWindow
6384 * Asks to unmaximize @window. Note that you shouldn't assume the
6385 * window is definitely unmaximized afterward, because other entities
6386 * (e.g. the user or <link linkend="gtk-X11-arch">window
6387 * manager</link>) could maximize it again, and not all window
6388 * managers honor requests to unmaximize. But normally the window will
6389 * end up unmaximized. Just don't write code that crashes if not.
6391 * You can track maximization via the "window_state_event" signal
6396 gtk_window_unmaximize (GtkWindow *window)
6399 GdkWindow *toplevel;
6401 g_return_if_fail (GTK_IS_WINDOW (window));
6403 widget = GTK_WIDGET (window);
6405 window->maximize_initially = FALSE;
6408 toplevel = window->frame;
6410 toplevel = widget->window;
6412 if (toplevel != NULL)
6413 gdk_window_unmaximize (toplevel);
6417 * gtk_window_fullscreen:
6418 * @window: a #GtkWindow
6420 * Asks to place @window in the fullscreen state. Note that you
6421 * shouldn't assume the window is definitely full screen afterward,
6422 * because other entities (e.g. the user or <link
6423 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
6424 * again, and not all window managers honor requests to fullscreen
6425 * windows. But normally the window will end up fullscreen. Just
6426 * don't write code that crashes if not.
6428 * You can track the fullscreen state via the "window_state_event" signal
6434 gtk_window_fullscreen (GtkWindow *window)
6437 GdkWindow *toplevel;
6438 GtkWindowPrivate *priv;
6440 g_return_if_fail (GTK_IS_WINDOW (window));
6442 widget = GTK_WIDGET (window);
6443 priv = GTK_WINDOW_GET_PRIVATE (window);
6445 priv->fullscreen_initially = TRUE;
6448 toplevel = window->frame;
6450 toplevel = widget->window;
6452 if (toplevel != NULL)
6453 gdk_window_fullscreen (toplevel);
6457 * gtk_window_unfullscreen:
6458 * @window: a #GtkWindow
6460 * Asks to toggle off the fullscreen state for @window. Note that you
6461 * shouldn't assume the window is definitely not full screen
6462 * afterward, because other entities (e.g. the user or <link
6463 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
6464 * again, and not all window managers honor requests to unfullscreen
6465 * windows. But normally the window will end up restored to its normal
6466 * state. Just don't write code that crashes if not.
6468 * You can track the fullscreen state via the "window_state_event" signal
6474 gtk_window_unfullscreen (GtkWindow *window)
6477 GdkWindow *toplevel;
6478 GtkWindowPrivate *priv;
6480 g_return_if_fail (GTK_IS_WINDOW (window));
6482 widget = GTK_WIDGET (window);
6483 priv = GTK_WINDOW_GET_PRIVATE (window);
6485 priv->fullscreen_initially = FALSE;
6488 toplevel = window->frame;
6490 toplevel = widget->window;
6492 if (toplevel != NULL)
6493 gdk_window_unfullscreen (toplevel);
6497 * gtk_window_set_keep_above:
6498 * @window: a #GtkWindow
6499 * @setting: whether to keep @window above other windows
6501 * Asks to keep @window above, so that it stays on top. Note that
6502 * you shouldn't assume the window is definitely above afterward,
6503 * because other entities (e.g. the user or <link
6504 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
6505 * and not all window managers support keeping windows above. But
6506 * normally the window will end kept above. Just don't write code
6507 * that crashes if not.
6509 * It's permitted to call this function before showing a window,
6510 * in which case the window will be kept above when it appears onscreen
6513 * You can track the above state via the "window_state_event" signal
6516 * Note that, according to the <ulink
6517 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
6518 * Manager Hints</ulink> specification, the above state is mainly meant
6519 * for user preferences and should not be used by applications e.g. for
6520 * drawing attention to their dialogs.
6525 gtk_window_set_keep_above (GtkWindow *window,
6529 GtkWindowPrivate *priv;
6530 GdkWindow *toplevel;
6532 g_return_if_fail (GTK_IS_WINDOW (window));
6534 widget = GTK_WIDGET (window);
6535 priv = GTK_WINDOW_GET_PRIVATE (window);
6537 priv->above_initially = setting;
6539 priv->below_initially = FALSE;
6542 toplevel = window->frame;
6544 toplevel = widget->window;
6546 if (toplevel != NULL)
6547 gdk_window_set_keep_above (toplevel, setting);
6551 * gtk_window_set_keep_below:
6552 * @window: a #GtkWindow
6553 * @setting: whether to keep @window below other windows
6555 * Asks to keep @window below, so that it stays in bottom. Note that
6556 * you shouldn't assume the window is definitely below afterward,
6557 * because other entities (e.g. the user or <link
6558 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
6559 * and not all window managers support putting windows below. But
6560 * normally the window will be kept below. Just don't write code
6561 * that crashes if not.
6563 * It's permitted to call this function before showing a window,
6564 * in which case the window will be kept below when it appears onscreen
6567 * You can track the below state via the "window_state_event" signal
6570 * Note that, according to the <ulink
6571 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
6572 * Manager Hints</ulink> specification, the above state is mainly meant
6573 * for user preferences and should not be used by applications e.g. for
6574 * drawing attention to their dialogs.
6579 gtk_window_set_keep_below (GtkWindow *window,
6583 GtkWindowPrivate *priv;
6584 GdkWindow *toplevel;
6586 g_return_if_fail (GTK_IS_WINDOW (window));
6588 widget = GTK_WIDGET (window);
6589 priv = GTK_WINDOW_GET_PRIVATE (window);
6591 priv->below_initially = setting;
6593 priv->above_initially = FALSE;
6596 toplevel = window->frame;
6598 toplevel = widget->window;
6600 if (toplevel != NULL)
6601 gdk_window_set_keep_below (toplevel, setting);
6605 * gtk_window_set_resizable:
6606 * @window: a #GtkWindow
6607 * @resizable: %TRUE if the user can resize this window
6609 * Sets whether the user can resize a window. Windows are user resizable
6613 gtk_window_set_resizable (GtkWindow *window,
6616 g_return_if_fail (GTK_IS_WINDOW (window));
6618 gtk_window_set_policy (window, FALSE, resizable, FALSE);
6622 * gtk_window_get_resizable:
6623 * @window: a #GtkWindow
6625 * Gets the value set by gtk_window_set_resizable().
6627 * Return value: %TRUE if the user can resize the window
6630 gtk_window_get_resizable (GtkWindow *window)
6632 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6634 /* allow_grow is most likely to indicate the semantic concept we
6635 * mean by "resizable" (and will be a reliable indicator if
6636 * set_policy() hasn't been called)
6638 return window->allow_grow;
6642 * gtk_window_set_gravity:
6643 * @window: a #GtkWindow
6644 * @gravity: window gravity
6646 * Window gravity defines the meaning of coordinates passed to
6647 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
6650 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
6651 * typically "do what you mean."
6655 gtk_window_set_gravity (GtkWindow *window,
6658 g_return_if_fail (GTK_IS_WINDOW (window));
6660 if (gravity != window->gravity)
6662 window->gravity = gravity;
6664 /* gtk_window_move_resize() will adapt gravity
6666 gtk_widget_queue_resize (GTK_WIDGET (window));
6668 g_object_notify (G_OBJECT (window), "gravity");
6673 * gtk_window_get_gravity:
6674 * @window: a #GtkWindow
6676 * Gets the value set by gtk_window_set_gravity().
6678 * Return value: window gravity
6681 gtk_window_get_gravity (GtkWindow *window)
6683 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
6685 return window->gravity;
6689 * gtk_window_begin_resize_drag:
6690 * @window: a #GtkWindow
6691 * @button: mouse button that initiated the drag
6692 * @edge: position of the resize control
6693 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6694 * @root_y: Y position where the user clicked to initiate the drag
6695 * @timestamp: timestamp from the click event that initiated the drag
6697 * Starts resizing a window. This function is used if an application
6698 * has window resizing controls. When GDK can support it, the resize
6699 * will be done using the standard mechanism for the <link
6700 * linkend="gtk-X11-arch">window manager</link> or windowing
6701 * system. Otherwise, GDK will try to emulate window resizing,
6702 * potentially not all that well, depending on the windowing system.
6706 gtk_window_begin_resize_drag (GtkWindow *window,
6714 GdkWindow *toplevel;
6716 g_return_if_fail (GTK_IS_WINDOW (window));
6717 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6719 widget = GTK_WIDGET (window);
6722 toplevel = window->frame;
6724 toplevel = widget->window;
6726 gdk_window_begin_resize_drag (toplevel,
6733 * gtk_window_get_frame_dimensions:
6734 * @window: a #GtkWindow
6735 * @left: location to store the width of the frame at the left, or %NULL
6736 * @top: location to store the height of the frame at the top, or %NULL
6737 * @right: location to store the width of the frame at the returns, or %NULL
6738 * @bottom: location to store the height of the frame at the bottom, or %NULL
6740 * (Note: this is a special-purpose function intended for the
6741 * framebuffer port; see gtk_window_set_has_frame(). It will not
6742 * return the size of the window border drawn by the <link
6743 * linkend="gtk-X11-arch">window manager</link>, which is the normal
6744 * case when using a windowing system. See
6745 * gdk_window_get_frame_extents() to get the standard window border
6748 * Retrieves the dimensions of the frame window for this toplevel.
6749 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
6752 gtk_window_get_frame_dimensions (GtkWindow *window,
6758 g_return_if_fail (GTK_IS_WINDOW (window));
6761 *left = window->frame_left;
6763 *top = window->frame_top;
6765 *right = window->frame_right;
6767 *bottom = window->frame_bottom;
6771 * gtk_window_begin_move_drag:
6772 * @window: a #GtkWindow
6773 * @button: mouse button that initiated the drag
6774 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6775 * @root_y: Y position where the user clicked to initiate the drag
6776 * @timestamp: timestamp from the click event that initiated the drag
6778 * Starts moving a window. This function is used if an application has
6779 * window movement grips. When GDK can support it, the window movement
6780 * will be done using the standard mechanism for the <link
6781 * linkend="gtk-X11-arch">window manager</link> or windowing
6782 * system. Otherwise, GDK will try to emulate window movement,
6783 * potentially not all that well, depending on the windowing system.
6787 gtk_window_begin_move_drag (GtkWindow *window,
6794 GdkWindow *toplevel;
6796 g_return_if_fail (GTK_IS_WINDOW (window));
6797 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6799 widget = GTK_WIDGET (window);
6802 toplevel = window->frame;
6804 toplevel = widget->window;
6806 gdk_window_begin_move_drag (toplevel,
6813 * gtk_window_set_screen:
6814 * @window: a #GtkWindow.
6815 * @screen: a #GdkScreen.
6817 * Sets the #GdkScreen where the @window is displayed; if
6818 * the window is already mapped, it will be unmapped, and
6819 * then remapped on the new screen.
6824 gtk_window_set_screen (GtkWindow *window,
6828 GdkScreen *previous_screen;
6829 gboolean was_mapped;
6831 g_return_if_fail (GTK_IS_WINDOW (window));
6832 g_return_if_fail (GDK_IS_SCREEN (screen));
6834 if (screen == window->screen)
6837 widget = GTK_WIDGET (window);
6839 previous_screen = window->screen;
6840 was_mapped = GTK_WIDGET_MAPPED (widget);
6843 gtk_widget_unmap (widget);
6844 if (GTK_WIDGET_REALIZED (widget))
6845 gtk_widget_unrealize (widget);
6847 gtk_window_free_key_hash (window);
6848 window->screen = screen;
6849 gtk_widget_reset_rc_styles (widget);
6850 if (screen != previous_screen)
6851 _gtk_widget_propagate_screen_changed (widget, previous_screen);
6852 g_object_notify (G_OBJECT (window), "screen");
6855 gtk_widget_map (widget);
6859 gtk_window_check_screen (GtkWindow *window)
6862 return window->screen;
6865 g_warning ("Screen for GtkWindow not set; you must always set\n"
6866 "a screen for a GtkWindow before using the window");
6872 * gtk_window_get_screen:
6873 * @window: a #GtkWindow.
6875 * Returns the #GdkScreen associated with @window.
6877 * Return value: a #GdkScreen.
6882 gtk_window_get_screen (GtkWindow *window)
6884 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6886 return window->screen;
6890 * gtk_window_is_active:
6891 * @window: a #GtkWindow
6893 * Returns whether the window is part of the current active toplevel.
6894 * (That is, the toplevel window receiving keystrokes.)
6895 * The return value is %TRUE if the window is active toplevel
6896 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
6897 * You might use this function if you wanted to draw a widget
6898 * differently in an active window from a widget in an inactive window.
6899 * See gtk_window_has_toplevel_focus()
6901 * Return value: %TRUE if the window part of the current active window.
6906 gtk_window_is_active (GtkWindow *window)
6908 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6910 return window->is_active;
6914 * gtk_window_has_toplevel_focus:
6915 * @window: a #GtkWindow
6917 * Returns whether the input focus is within this GtkWindow.
6918 * For real toplevel windows, this is identical to gtk_window_is_active(),
6919 * but for embedded windows, like #GtkPlug, the results will differ.
6921 * Return value: %TRUE if the input focus is within this GtkWindow
6926 gtk_window_has_toplevel_focus (GtkWindow *window)
6928 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6930 return window->has_toplevel_focus;
6934 gtk_window_group_class_init (GtkWindowGroupClass *klass)
6939 gtk_window_group_get_type (void)
6941 static GType window_group_type = 0;
6943 if (!window_group_type)
6945 static const GTypeInfo window_group_info =
6947 sizeof (GtkWindowGroupClass),
6948 NULL, /* base_init */
6949 NULL, /* base_finalize */
6950 (GClassInitFunc) gtk_window_group_class_init,
6951 NULL, /* class_finalize */
6952 NULL, /* class_data */
6953 sizeof (GtkWindowGroup),
6954 0, /* n_preallocs */
6955 (GInstanceInitFunc) NULL,
6958 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
6959 &window_group_info, 0);
6962 return window_group_type;
6966 * gtk_window_group_new:
6968 * Creates a new #GtkWindowGroup object. Grabs added with
6969 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
6971 * Return value: a new #GtkWindowGroup.
6974 gtk_window_group_new (void)
6976 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
6980 window_group_cleanup_grabs (GtkWindowGroup *group,
6984 GSList *to_remove = NULL;
6986 tmp_list = group->grabs;
6989 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
6990 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
6991 tmp_list = tmp_list->next;
6996 gtk_grab_remove (to_remove->data);
6997 g_object_unref (to_remove->data);
6998 to_remove = g_slist_delete_link (to_remove, to_remove);
7003 * gtk_window_group_add_window:
7004 * @window_group: a #GtkWindowGroup
7005 * @window: the #GtkWindow to add
7007 * Adds a window to a #GtkWindowGroup.
7010 gtk_window_group_add_window (GtkWindowGroup *window_group,
7013 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7014 g_return_if_fail (GTK_IS_WINDOW (window));
7016 if (window->group != window_group)
7018 g_object_ref (window);
7019 g_object_ref (window_group);
7022 gtk_window_group_remove_window (window->group, window);
7024 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
7026 window->group = window_group;
7028 g_object_unref (window);
7033 * gtk_window_group_remove_window:
7034 * @window_group: a #GtkWindowGroup
7035 * @window: the #GtkWindow to remove
7037 * Removes a window from a #GtkWindowGroup.
7040 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7043 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7044 g_return_if_fail (GTK_IS_WIDGET (window));
7045 g_return_if_fail (window->group == window_group);
7047 g_object_ref (window);
7049 window_group_cleanup_grabs (window_group, window);
7050 window->group = NULL;
7052 g_object_unref (window_group);
7053 g_object_unref (window);
7056 /* Return the group for the window or the default group
7059 _gtk_window_get_group (GtkWindow *window)
7061 if (window && window->group)
7062 return window->group;
7065 static GtkWindowGroup *default_group = NULL;
7068 default_group = gtk_window_group_new ();
7070 return default_group;
7074 /* Return the current grab widget of the given group
7077 _gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
7079 if (window_group->grabs)
7080 return GTK_WIDGET (window_group->grabs->data);
7085 Derived from XParseGeometry() in XFree86
7087 Copyright 1985, 1986, 1987,1998 The Open Group
7089 All Rights Reserved.
7091 The above copyright notice and this permission notice shall be included
7092 in all copies or substantial portions of the Software.
7094 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
7095 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7096 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7097 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
7098 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7099 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
7100 OTHER DEALINGS IN THE SOFTWARE.
7102 Except as contained in this notice, the name of The Open Group shall
7103 not be used in advertising or otherwise to promote the sale, use or
7104 other dealings in this Software without prior written authorization
7105 from The Open Group.
7110 * XParseGeometry parses strings of the form
7111 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
7112 * width, height, xoffset, and yoffset are unsigned integers.
7113 * Example: "=80x24+300-49"
7114 * The equal sign is optional.
7115 * It returns a bitmask that indicates which of the four values
7116 * were actually found in the string. For each value found,
7117 * the corresponding argument is updated; for each value
7118 * not found, the corresponding argument is left unchanged.
7121 /* The following code is from Xlib, and is minimally modified, so we
7122 * can track any upstream changes if required. Don't change this
7123 * code. Or if you do, put in a huge comment marking which thing
7128 read_int (gchar *string,
7136 else if (*string == '-')
7142 for (; (*string >= '0') && (*string <= '9'); string++)
7144 result = (result * 10) + (*string - '0');
7156 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
7157 * value (x, y, width, height) was found in the parsed string.
7159 #define NoValue 0x0000
7160 #define XValue 0x0001
7161 #define YValue 0x0002
7162 #define WidthValue 0x0004
7163 #define HeightValue 0x0008
7164 #define AllValues 0x000F
7165 #define XNegative 0x0010
7166 #define YNegative 0x0020
7168 /* Try not to reformat/modify, so we can compare/sync with X sources */
7170 gtk_XParseGeometry (const char *string,
7173 unsigned int *width,
7174 unsigned int *height)
7178 unsigned int tempWidth, tempHeight;
7180 char *nextCharacter;
7182 /* These initializations are just to silence gcc */
7188 if ( (string == NULL) || (*string == '\0')) return(mask);
7190 string++; /* ignore possible '=' at beg of geometry spec */
7192 strind = (char *)string;
7193 if (*strind != '+' && *strind != '-' && *strind != 'x') {
7194 tempWidth = read_int(strind, &nextCharacter);
7195 if (strind == nextCharacter)
7197 strind = nextCharacter;
7201 if (*strind == 'x' || *strind == 'X') {
7203 tempHeight = read_int(strind, &nextCharacter);
7204 if (strind == nextCharacter)
7206 strind = nextCharacter;
7207 mask |= HeightValue;
7210 if ((*strind == '+') || (*strind == '-')) {
7211 if (*strind == '-') {
7213 tempX = -read_int(strind, &nextCharacter);
7214 if (strind == nextCharacter)
7216 strind = nextCharacter;
7222 tempX = read_int(strind, &nextCharacter);
7223 if (strind == nextCharacter)
7225 strind = nextCharacter;
7228 if ((*strind == '+') || (*strind == '-')) {
7229 if (*strind == '-') {
7231 tempY = -read_int(strind, &nextCharacter);
7232 if (strind == nextCharacter)
7234 strind = nextCharacter;
7241 tempY = read_int(strind, &nextCharacter);
7242 if (strind == nextCharacter)
7244 strind = nextCharacter;
7250 /* If strind isn't at the end of the string the it's an invalid
7251 geometry specification. */
7253 if (*strind != '\0') return (0);
7259 if (mask & WidthValue)
7261 if (mask & HeightValue)
7262 *height = tempHeight;
7267 * gtk_window_parse_geometry:
7268 * @window: a #GtkWindow
7269 * @geometry: geometry string
7271 * Parses a standard X Window System geometry string - see the
7272 * manual page for X (type 'man X') for details on this.
7273 * gtk_window_parse_geometry() does work on all GTK+ ports
7274 * including Win32 but is primarily intended for an X environment.
7276 * If either a size or a position can be extracted from the
7277 * geometry string, gtk_window_parse_geometry() returns %TRUE
7278 * and calls gtk_window_set_default_size() and/or gtk_window_move()
7279 * to resize/move the window.
7281 * If gtk_window_parse_geometry() returns %TRUE, it will also
7282 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
7283 * indicating to the window manager that the size/position of
7284 * the window was user-specified. This causes most window
7285 * managers to honor the geometry.
7287 * Note that for gtk_window_parse_geometry() to work as expected, it has
7288 * to be called when the window has its "final" size, i.e. after calling
7289 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
7292 * <informalexample><programlisting>
7293 * #include <gtk/gtk.h>
7296 * fill_with_content (GtkWidget *vbox)
7298 * /<!-- -->* fill with content... *<!-- -->/
7302 * main (int argc, char *argv[])
7304 * GtkWidget *window, *vbox;
7305 * GdkGeometry size_hints = {
7306 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
7309 * gtk_init (&argc, &argv);
7311 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7312 * vbox = gtk_vbox_new (FALSE, 0);
7314 * gtk_container_add (GTK_CONTAINER (window), vbox);
7315 * fill_with_content (vbox);
7316 * gtk_widget_show_all (vbox);
7318 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
7321 * GDK_HINT_MIN_SIZE |
7322 * GDK_HINT_BASE_SIZE |
7323 * GDK_HINT_RESIZE_INC);
7327 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
7328 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
7331 * gtk_widget_show_all (window);
7336 * </programlisting></informalexample>
7338 * Return value: %TRUE if string was parsed successfully
7341 gtk_window_parse_geometry (GtkWindow *window,
7342 const gchar *geometry)
7344 gint result, x = 0, y = 0;
7347 gboolean size_set, pos_set;
7350 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7351 g_return_val_if_fail (geometry != NULL, FALSE);
7353 screen = gtk_window_check_screen (window);
7355 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
7358 if ((result & WidthValue) || (result & HeightValue))
7360 gtk_window_set_default_size_internal (window,
7361 TRUE, result & WidthValue ? w : -1,
7362 TRUE, result & HeightValue ? h : -1,
7367 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
7369 grav = GDK_GRAVITY_NORTH_WEST;
7371 if ((result & XNegative) && (result & YNegative))
7372 grav = GDK_GRAVITY_SOUTH_EAST;
7373 else if (result & XNegative)
7374 grav = GDK_GRAVITY_NORTH_EAST;
7375 else if (result & YNegative)
7376 grav = GDK_GRAVITY_SOUTH_WEST;
7378 if ((result & XValue) == 0)
7381 if ((result & YValue) == 0)
7384 if (grav == GDK_GRAVITY_SOUTH_WEST ||
7385 grav == GDK_GRAVITY_SOUTH_EAST)
7386 y = gdk_screen_get_height (screen) - h + y;
7388 if (grav == GDK_GRAVITY_SOUTH_EAST ||
7389 grav == GDK_GRAVITY_NORTH_EAST)
7390 x = gdk_screen_get_width (screen) - w + x;
7392 /* we don't let you put a window offscreen; maybe some people would
7393 * prefer to be able to, but it's kind of a bogus thing to do.
7402 if ((result & XValue) || (result & YValue))
7404 gtk_window_set_gravity (window, grav);
7405 gtk_window_move (window, x, y);
7409 if (size_set || pos_set)
7411 /* Set USSize, USPosition hints */
7412 GtkWindowGeometryInfo *info;
7414 info = gtk_window_get_geometry_info (window, TRUE);
7417 info->mask |= GDK_HINT_USER_POS;
7419 info->mask |= GDK_HINT_USER_SIZE;
7426 gtk_window_mnemonic_hash_foreach (guint keyval,
7432 GtkWindowKeysForeachFunc func;
7436 (*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
7440 _gtk_window_keys_foreach (GtkWindow *window,
7441 GtkWindowKeysForeachFunc func,
7445 GtkMnemonicHash *mnemonic_hash;
7449 GtkWindowKeysForeachFunc func;
7453 info.window = window;
7455 info.func_data = func_data;
7457 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
7459 _gtk_mnemonic_hash_foreach (mnemonic_hash,
7460 gtk_window_mnemonic_hash_foreach, &info);
7462 groups = gtk_accel_groups_from_object (G_OBJECT (window));
7465 GtkAccelGroup *group = groups->data;
7468 for (i = 0; i < group->n_accels; i++)
7470 GtkAccelKey *key = &group->priv_accels[i].key;
7473 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
7476 groups = groups->next;
7481 gtk_window_keys_changed (GtkWindow *window)
7483 gtk_window_free_key_hash (window);
7484 gtk_window_get_key_hash (window);
7487 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
7489 struct _GtkWindowKeyEntry
7493 gboolean is_mnemonic;
7497 add_to_key_hash (GtkWindow *window,
7499 GdkModifierType modifiers,
7500 gboolean is_mnemonic,
7503 GtkKeyHash *key_hash = data;
7505 GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
7507 entry->keyval = keyval;
7508 entry->modifiers = modifiers;
7509 entry->is_mnemonic = is_mnemonic;
7511 /* GtkAccelGroup stores lowercased accelerators. To deal
7512 * with this, if <Shift> was specified, uppercase.
7514 if (modifiers & GDK_SHIFT_MASK)
7516 if (keyval == GDK_Tab)
7517 keyval = GDK_ISO_Left_Tab;
7519 keyval = gdk_keyval_to_upper (keyval);
7522 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
7526 gtk_window_get_key_hash (GtkWindow *window)
7528 GdkScreen *screen = gtk_window_check_screen (window);
7529 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
7534 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
7535 (GDestroyNotify)g_free);
7536 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
7537 g_object_set_data (G_OBJECT (window), I_("gtk-window-key-hash"), key_hash);
7543 gtk_window_free_key_hash (GtkWindow *window)
7545 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
7548 _gtk_key_hash_free (key_hash);
7549 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
7554 * gtk_window_activate_key:
7555 * @window: a #GtkWindow
7556 * @event: a #GdkEventKey
7558 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
7559 * called by the default ::key_press_event handler for toplevel windows,
7560 * however in some cases it may be useful to call this directly when
7561 * overriding the standard key handling for a toplevel window.
7563 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
7566 gtk_window_activate_key (GtkWindow *window,
7569 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
7570 GtkWindowKeyEntry *found_entry = NULL;
7574 gtk_window_keys_changed (window);
7575 key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
7580 GSList *entries = _gtk_key_hash_lookup (key_hash,
7581 event->hardware_keycode,
7583 gtk_accelerator_get_default_mod_mask (),
7587 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
7589 GtkWindowKeyEntry *entry = tmp_list->data;
7590 if (entry->is_mnemonic)
7592 found_entry = entry;
7597 if (!found_entry && entries)
7598 found_entry = entries->data;
7600 g_slist_free (entries);
7605 if (found_entry->is_mnemonic)
7606 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
7608 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
7615 window_update_has_focus (GtkWindow *window)
7617 GtkWidget *widget = GTK_WIDGET (window);
7618 gboolean has_focus = window->has_toplevel_focus && window->is_active;
7620 if (has_focus != window->has_focus)
7622 window->has_focus = has_focus;
7626 if (window->focus_widget &&
7627 window->focus_widget != widget &&
7628 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7629 do_focus_change (window->focus_widget, TRUE);
7633 if (window->focus_widget &&
7634 window->focus_widget != widget &&
7635 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7636 do_focus_change (window->focus_widget, FALSE);
7642 * _gtk_window_set_is_active:
7643 * @window: a #GtkWindow
7644 * @is_active: %TRUE if the window is in the currently active toplevel
7646 * Internal function that sets whether the #GtkWindow is part
7647 * of the currently active toplevel window (taking into account inter-process
7651 _gtk_window_set_is_active (GtkWindow *window,
7654 g_return_if_fail (GTK_IS_WINDOW (window));
7656 is_active = is_active != FALSE;
7658 if (is_active != window->is_active)
7660 window->is_active = is_active;
7661 window_update_has_focus (window);
7663 g_object_notify (G_OBJECT (window), "is-active");
7668 * _gtk_window_set_has_toplevel_focus:
7669 * @window: a #GtkWindow
7670 * @has_toplevel_focus: %TRUE if the in
7672 * Internal function that sets whether the keyboard focus for the
7673 * toplevel window (taking into account inter-process embedding.)
7676 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
7677 gboolean has_toplevel_focus)
7679 g_return_if_fail (GTK_IS_WINDOW (window));
7681 has_toplevel_focus = has_toplevel_focus != FALSE;
7683 if (has_toplevel_focus != window->has_toplevel_focus)
7685 window->has_toplevel_focus = has_toplevel_focus;
7686 window_update_has_focus (window);
7688 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
7693 * gtk_window_set_auto_startup_notification:
7694 * @setting: %TRUE to automatically do startup notification
7696 * By default, after showing the first #GtkWindow for each #GdkScreen,
7697 * GTK+ calls gdk_screen_notify_startup_complete(). Call this
7698 * function to disable the automatic startup notification. You might
7699 * do this if your first window is a splash screen, and you want to
7700 * delay notification until after your real main window has been
7701 * shown, for example.
7703 * In that example, you would disable startup notification
7704 * temporarily, show your splash screen, then re-enable it so that
7705 * showing the main window would automatically result in notification.
7710 gtk_window_set_auto_startup_notification (gboolean setting)
7712 disable_startup_notification = !setting;
7717 #undef gtk_window_set_icon_from_file
7720 gtk_window_set_icon_from_file (GtkWindow *window,
7721 const gchar *filename,
7724 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
7727 if (utf8_filename == NULL)
7730 retval = gtk_window_set_icon_from_file_utf8 (window, utf8_filename, err);
7732 g_free (utf8_filename);
7737 #undef gtk_window_set_default_icon_from_file
7740 gtk_window_set_default_icon_from_file (const gchar *filename,
7743 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
7746 if (utf8_filename == NULL)
7749 retval = gtk_window_set_default_icon_from_file_utf8 (utf8_filename, err);
7751 g_free (utf8_filename);
7758 #define __GTK_WINDOW_C__
7759 #include "gtkaliasdef.c"