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/.
30 #include "gdk/gdkkeysyms.h"
32 #include "gtkprivate.h"
34 #include "gtkwindow.h"
35 #include "gtkwindow-decorate.h"
36 #include "gtkbindings.h"
37 #include "gtkkeyhash.h"
39 #include "gtkiconfactory.h"
41 #include "gtkmarshalers.h"
69 PROP_DESTROY_WITH_PARENT,
73 PROP_SKIP_TASKBAR_HINT,
76 /* Readonly properties */
78 PROP_HAS_TOPLEVEL_FOCUS,
86 GdkPixmap *icon_pixmap;
89 guint using_default_icon : 1;
90 guint using_parent_icon : 1;
94 GdkGeometry geometry; /* Last set of geometry hints we set */
96 GdkRectangle configure_request;
97 } GtkWindowLastGeometryInfo;
99 struct _GtkWindowGeometryInfo
101 /* Properties that the app has set on the window
103 GdkGeometry geometry; /* Geometry hints */
105 GtkWidget *widget; /* subwidget to which hints apply */
106 /* from last gtk_window_resize () - if > 0, indicates that
107 * we should resize to this size.
112 /* From last gtk_window_move () prior to mapping -
113 * only used if initial_pos_set
118 /* Default size - used only the FIRST time we map a window,
123 /* whether to use initial_x, initial_y */
124 guint initial_pos_set : 1;
125 /* CENTER_ALWAYS or other position constraint changed since
126 * we sent the last configure request.
128 guint position_constraints_changed : 1;
130 /* if true, default_width, height come from gtk_window_parse_geometry,
131 * and thus should be multiplied by the increments and affect the
132 * geometry widget only
134 guint default_is_geometry : 1;
136 GtkWindowLastGeometryInfo last;
139 typedef struct _GtkWindowMnemonic GtkWindowMnemonic;
141 struct _GtkWindowMnemonic {
148 typedef struct _GtkWindowPrivate GtkWindowPrivate;
150 struct _GtkWindowPrivate
152 guint fullscreen_initially : 1;
153 guint skips_taskbar : 1;
154 guint skips_pager : 1;
157 static void gtk_window_class_init (GtkWindowClass *klass);
158 static void gtk_window_init (GtkWindow *window);
159 static void gtk_window_dispose (GObject *object);
160 static void gtk_window_destroy (GtkObject *object);
161 static void gtk_window_finalize (GObject *object);
162 static void gtk_window_private_finalize (GtkWindowPrivate *priv);
163 static void gtk_window_show (GtkWidget *widget);
164 static void gtk_window_hide (GtkWidget *widget);
165 static void gtk_window_map (GtkWidget *widget);
166 static void gtk_window_unmap (GtkWidget *widget);
167 static void gtk_window_realize (GtkWidget *widget);
168 static void gtk_window_unrealize (GtkWidget *widget);
169 static void gtk_window_size_request (GtkWidget *widget,
170 GtkRequisition *requisition);
171 static void gtk_window_size_allocate (GtkWidget *widget,
172 GtkAllocation *allocation);
173 static gint gtk_window_event (GtkWidget *widget,
175 static gboolean gtk_window_frame_event (GtkWindow *window,
177 static gint gtk_window_configure_event (GtkWidget *widget,
178 GdkEventConfigure *event);
179 static gint gtk_window_key_press_event (GtkWidget *widget,
181 static gint gtk_window_key_release_event (GtkWidget *widget,
183 static gint gtk_window_enter_notify_event (GtkWidget *widget,
184 GdkEventCrossing *event);
185 static gint gtk_window_leave_notify_event (GtkWidget *widget,
186 GdkEventCrossing *event);
187 static gint gtk_window_focus_in_event (GtkWidget *widget,
188 GdkEventFocus *event);
189 static gint gtk_window_focus_out_event (GtkWidget *widget,
190 GdkEventFocus *event);
191 static gint gtk_window_client_event (GtkWidget *widget,
192 GdkEventClient *event);
193 static void gtk_window_check_resize (GtkContainer *container);
194 static gint gtk_window_focus (GtkWidget *widget,
195 GtkDirectionType direction);
196 static void gtk_window_real_set_focus (GtkWindow *window,
199 static void gtk_window_real_activate_default (GtkWindow *window);
200 static void gtk_window_real_activate_focus (GtkWindow *window);
201 static void gtk_window_move_focus (GtkWindow *window,
202 GtkDirectionType dir);
203 static void gtk_window_keys_changed (GtkWindow *window);
204 static void gtk_window_read_rcfiles (GtkWidget *widget,
205 GdkEventClient *event);
206 static void gtk_window_paint (GtkWidget *widget,
208 static gint gtk_window_expose (GtkWidget *widget,
209 GdkEventExpose *event);
210 static void gtk_window_unset_transient_for (GtkWindow *window);
211 static void gtk_window_transient_parent_realized (GtkWidget *parent,
213 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
216 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
219 static void gtk_window_move_resize (GtkWindow *window);
220 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
222 GdkGeometry *geometry_b,
224 static void gtk_window_constrain_size (GtkWindow *window,
225 GdkGeometry *geometry,
231 static void gtk_window_constrain_position (GtkWindow *window,
236 static void gtk_window_compute_hints (GtkWindow *window,
237 GdkGeometry *new_geometry,
239 static void gtk_window_compute_configure_request (GtkWindow *window,
240 GdkRectangle *request,
241 GdkGeometry *geometry,
244 static void gtk_window_set_default_size_internal (GtkWindow *window,
245 gboolean change_width,
247 gboolean change_height,
249 gboolean is_geometry);
251 static void gtk_window_realize_icon (GtkWindow *window);
252 static void gtk_window_unrealize_icon (GtkWindow *window);
254 static void gtk_window_notify_keys_changed (GtkWindow *window);
255 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
256 static void gtk_window_free_key_hash (GtkWindow *window);
258 static GSList *toplevel_list = NULL;
259 static GHashTable *mnemonic_hash_table = NULL;
260 static GtkBinClass *parent_class = NULL;
261 static guint window_signals[LAST_SIGNAL] = { 0 };
262 static GList *default_icon_list = NULL;
263 static guint default_icon_serial = 0;
264 static gboolean disable_startup_notification = FALSE;
265 static gboolean sent_startup_notification = FALSE;
267 static void gtk_window_set_property (GObject *object,
271 static void gtk_window_get_property (GObject *object,
278 mnemonic_hash (gconstpointer key)
280 const GtkWindowMnemonic *k;
283 k = (GtkWindowMnemonic *)key;
285 h = (gulong) k->window;
286 h ^= k->keyval << 16;
287 h ^= k->keyval >> 16;
293 mnemonic_equal (gconstpointer a, gconstpointer b)
295 const GtkWindowMnemonic *ka;
296 const GtkWindowMnemonic *kb;
298 ka = (GtkWindowMnemonic *)a;
299 kb = (GtkWindowMnemonic *)b;
302 (ka->window == kb->window) &&
303 (ka->keyval == kb->keyval);
307 gtk_window_get_private (GtkWindow *window)
309 GtkWindowPrivate *private;
310 static GQuark private_quark = 0;
313 private_quark = g_quark_from_static_string ("gtk-window-private");
315 private = g_object_get_qdata (G_OBJECT (window), private_quark);
319 private = g_new0 (GtkWindowPrivate, 1);
321 private->fullscreen_initially = FALSE;
322 private->skips_pager = FALSE;
323 private->skips_taskbar = FALSE;
325 g_object_set_qdata_full (G_OBJECT (window), private_quark,
327 (GDestroyNotify) gtk_window_private_finalize);
334 gtk_window_get_type (void)
336 static GType window_type = 0;
340 static const GTypeInfo window_info =
342 sizeof (GtkWindowClass),
343 NULL, /* base_init */
344 NULL, /* base_finalize */
345 (GClassInitFunc) gtk_window_class_init,
346 NULL, /* class_finalize */
347 NULL, /* class_data */
350 (GInstanceInitFunc) gtk_window_init,
353 window_type = g_type_register_static (GTK_TYPE_BIN, "GtkWindow",
361 add_tab_bindings (GtkBindingSet *binding_set,
362 GdkModifierType modifiers,
363 GtkDirectionType direction)
365 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
367 GTK_TYPE_DIRECTION_TYPE, direction);
368 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
370 GTK_TYPE_DIRECTION_TYPE, direction);
374 add_arrow_bindings (GtkBindingSet *binding_set,
376 GtkDirectionType direction)
378 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
380 gtk_binding_entry_add_signal (binding_set, keysym, 0,
382 GTK_TYPE_DIRECTION_TYPE, direction);
383 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
385 GTK_TYPE_DIRECTION_TYPE, direction);
386 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
388 GTK_TYPE_DIRECTION_TYPE, direction);
389 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
391 GTK_TYPE_DIRECTION_TYPE, direction);
396 gtk_window_class_init (GtkWindowClass *klass)
398 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
399 GtkObjectClass *object_class;
400 GtkWidgetClass *widget_class;
401 GtkContainerClass *container_class;
402 GtkBindingSet *binding_set;
404 object_class = (GtkObjectClass*) klass;
405 widget_class = (GtkWidgetClass*) klass;
406 container_class = (GtkContainerClass*) klass;
408 parent_class = g_type_class_peek_parent (klass);
410 mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
412 gobject_class->dispose = gtk_window_dispose;
413 gobject_class->finalize = gtk_window_finalize;
415 gobject_class->set_property = gtk_window_set_property;
416 gobject_class->get_property = gtk_window_get_property;
418 object_class->destroy = gtk_window_destroy;
420 widget_class->show = gtk_window_show;
421 widget_class->hide = gtk_window_hide;
422 widget_class->map = gtk_window_map;
423 widget_class->unmap = gtk_window_unmap;
424 widget_class->realize = gtk_window_realize;
425 widget_class->unrealize = gtk_window_unrealize;
426 widget_class->size_request = gtk_window_size_request;
427 widget_class->size_allocate = gtk_window_size_allocate;
428 widget_class->configure_event = gtk_window_configure_event;
429 widget_class->key_press_event = gtk_window_key_press_event;
430 widget_class->key_release_event = gtk_window_key_release_event;
431 widget_class->enter_notify_event = gtk_window_enter_notify_event;
432 widget_class->leave_notify_event = gtk_window_leave_notify_event;
433 widget_class->focus_in_event = gtk_window_focus_in_event;
434 widget_class->focus_out_event = gtk_window_focus_out_event;
435 widget_class->client_event = gtk_window_client_event;
436 widget_class->focus = gtk_window_focus;
438 widget_class->expose_event = gtk_window_expose;
440 container_class->check_resize = gtk_window_check_resize;
442 klass->set_focus = gtk_window_real_set_focus;
443 klass->frame_event = gtk_window_frame_event;
445 klass->activate_default = gtk_window_real_activate_default;
446 klass->activate_focus = gtk_window_real_activate_focus;
447 klass->move_focus = gtk_window_move_focus;
448 klass->keys_changed = gtk_window_keys_changed;
451 g_object_class_install_property (gobject_class,
453 g_param_spec_enum ("type",
455 _("The type of the window"),
456 GTK_TYPE_WINDOW_TYPE,
458 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
461 g_object_class_install_property (gobject_class,
463 g_param_spec_string ("title",
465 _("The title of the window"),
469 g_object_class_install_property (gobject_class,
471 g_param_spec_boolean ("allow_shrink",
473 /* xgettext:no-c-format */
474 _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
478 g_object_class_install_property (gobject_class,
480 g_param_spec_boolean ("allow_grow",
482 _("If TRUE, users can expand the window beyond its minimum size"),
486 g_object_class_install_property (gobject_class,
488 g_param_spec_boolean ("resizable",
490 _("If TRUE, users can resize the window"),
494 g_object_class_install_property (gobject_class,
496 g_param_spec_boolean ("modal",
498 _("If TRUE, the window is modal (other windows are not usable while this one is up)"),
502 g_object_class_install_property (gobject_class,
504 g_param_spec_enum ("window_position",
505 _("Window Position"),
506 _("The initial position of the window"),
507 GTK_TYPE_WINDOW_POSITION,
511 g_object_class_install_property (gobject_class,
513 g_param_spec_int ("default_width",
515 _("The default width of the window, used when initially showing the window"),
521 g_object_class_install_property (gobject_class,
523 g_param_spec_int ("default_height",
525 _("The default height of the window, used when initially showing the window"),
531 g_object_class_install_property (gobject_class,
532 PROP_DESTROY_WITH_PARENT,
533 g_param_spec_boolean ("destroy_with_parent",
534 _("Destroy with Parent"),
535 _("If this window should be destroyed when the parent is destroyed"),
539 g_object_class_install_property (gobject_class,
541 g_param_spec_object ("icon",
543 _("Icon for this window"),
547 g_object_class_install_property (gobject_class,
549 g_param_spec_object ("screen",
551 _("The screen where this window will be displayed"),
555 g_object_class_install_property (gobject_class,
557 g_param_spec_boolean ("is_active",
559 _("Whether the toplevel is the current active window"),
563 g_object_class_install_property (gobject_class,
564 PROP_HAS_TOPLEVEL_FOCUS,
565 g_param_spec_boolean ("has_toplevel_focus",
566 _("Focus in Toplevel"),
567 _("Whether the input focus is within this GtkWindow"),
571 g_object_class_install_property (gobject_class,
573 g_param_spec_enum ("type_hint",
575 _("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
576 GDK_TYPE_WINDOW_TYPE_HINT,
577 GDK_WINDOW_TYPE_HINT_NORMAL,
580 g_object_class_install_property (gobject_class,
581 PROP_SKIP_TASKBAR_HINT,
582 g_param_spec_boolean ("skip_taskbar_hint",
584 _("TRUE if the window should not be in the task bar."),
588 g_object_class_install_property (gobject_class,
589 PROP_SKIP_PAGER_HINT,
590 g_param_spec_boolean ("skip_pager_hint",
592 _("TRUE if the window should not be in the pager."),
596 window_signals[SET_FOCUS] =
597 g_signal_new ("set_focus",
598 G_TYPE_FROM_CLASS (gobject_class),
600 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
602 _gtk_marshal_VOID__OBJECT,
606 window_signals[FRAME_EVENT] =
607 g_signal_new ("frame_event",
608 G_TYPE_FROM_CLASS (gobject_class),
610 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
611 _gtk_boolean_handled_accumulator, NULL,
612 _gtk_marshal_BOOLEAN__BOXED,
616 window_signals[ACTIVATE_FOCUS] =
617 g_signal_new ("activate_focus",
618 G_TYPE_FROM_CLASS (gobject_class),
619 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
620 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
622 _gtk_marshal_VOID__VOID,
626 window_signals[ACTIVATE_DEFAULT] =
627 g_signal_new ("activate_default",
628 G_TYPE_FROM_CLASS (gobject_class),
629 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
630 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
632 _gtk_marshal_VOID__VOID,
636 window_signals[MOVE_FOCUS] =
637 g_signal_new ("move_focus",
638 G_TYPE_FROM_CLASS (gobject_class),
639 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
640 G_STRUCT_OFFSET (GtkWindowClass, move_focus),
642 _gtk_marshal_VOID__ENUM,
645 GTK_TYPE_DIRECTION_TYPE);
647 window_signals[KEYS_CHANGED] =
648 g_signal_new ("keys_changed",
649 G_TYPE_FROM_CLASS (gobject_class),
651 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
653 _gtk_marshal_VOID__VOID,
661 binding_set = gtk_binding_set_by_class (klass);
663 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
664 "activate_focus", 0);
665 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
666 "activate_focus", 0);
668 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
669 "activate_default", 0);
671 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
672 "activate_default", 0);
674 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
675 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
676 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
677 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
679 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
680 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
681 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
682 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
686 gtk_window_init (GtkWindow *window)
688 GdkColormap *colormap;
690 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
691 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
693 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
695 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
697 window->title = NULL;
698 window->wmclass_name = g_strdup (g_get_prgname ());
699 window->wmclass_class = g_strdup (gdk_get_program_class ());
700 window->wm_role = NULL;
701 window->geometry_info = NULL;
702 window->type = GTK_WINDOW_TOPLEVEL;
703 window->focus_widget = NULL;
704 window->default_widget = NULL;
705 window->configure_request_count = 0;
706 window->allow_shrink = FALSE;
707 window->allow_grow = TRUE;
708 window->configure_notify_received = FALSE;
709 window->position = GTK_WIN_POS_NONE;
710 window->need_default_size = TRUE;
711 window->need_default_position = TRUE;
712 window->modal = FALSE;
713 window->frame = NULL;
714 window->has_frame = FALSE;
715 window->frame_left = 0;
716 window->frame_right = 0;
717 window->frame_top = 0;
718 window->frame_bottom = 0;
719 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
720 window->gravity = GDK_GRAVITY_NORTH_WEST;
721 window->decorated = TRUE;
722 window->mnemonic_modifier = GDK_MOD1_MASK;
723 window->screen = gdk_screen_get_default ();
725 colormap = _gtk_widget_peek_colormap ();
727 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
729 g_object_ref (window);
730 gtk_object_sink (GTK_OBJECT (window));
731 window->has_user_ref_count = TRUE;
732 toplevel_list = g_slist_prepend (toplevel_list, window);
734 gtk_decorated_window_init (window);
736 g_signal_connect (window,
738 G_CALLBACK (gtk_window_event),
743 gtk_window_set_property (GObject *object,
750 window = GTK_WINDOW (object);
755 window->type = g_value_get_enum (value);
758 gtk_window_set_title (window, g_value_get_string (value));
760 case PROP_ALLOW_SHRINK:
761 window->allow_shrink = g_value_get_boolean (value);
762 gtk_widget_queue_resize (GTK_WIDGET (window));
764 case PROP_ALLOW_GROW:
765 window->allow_grow = g_value_get_boolean (value);
766 gtk_widget_queue_resize (GTK_WIDGET (window));
767 g_object_notify (G_OBJECT (window), "resizable");
770 window->allow_grow = g_value_get_boolean (value);
771 gtk_widget_queue_resize (GTK_WIDGET (window));
772 g_object_notify (G_OBJECT (window), "allow_grow");
775 gtk_window_set_modal (window, g_value_get_boolean (value));
778 gtk_window_set_position (window, g_value_get_enum (value));
780 case PROP_DEFAULT_WIDTH:
781 gtk_window_set_default_size_internal (window,
782 TRUE, g_value_get_int (value),
785 case PROP_DEFAULT_HEIGHT:
786 gtk_window_set_default_size_internal (window,
788 TRUE, g_value_get_int (value), FALSE);
790 case PROP_DESTROY_WITH_PARENT:
791 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
794 gtk_window_set_icon (window,
795 g_value_get_object (value));
798 gtk_window_set_screen (window, g_value_get_object (value));
801 gtk_window_set_type_hint (window,
802 g_value_get_enum (value));
804 case PROP_SKIP_TASKBAR_HINT:
805 gtk_window_set_skip_taskbar_hint (window,
806 g_value_get_boolean (value));
808 case PROP_SKIP_PAGER_HINT:
809 gtk_window_set_skip_pager_hint (window,
810 g_value_get_boolean (value));
819 gtk_window_get_property (GObject *object,
826 window = GTK_WINDOW (object);
830 GtkWindowGeometryInfo *info;
832 g_value_set_enum (value, window->type);
835 g_value_set_string (value, window->title);
837 case PROP_ALLOW_SHRINK:
838 g_value_set_boolean (value, window->allow_shrink);
840 case PROP_ALLOW_GROW:
841 g_value_set_boolean (value, window->allow_grow);
844 g_value_set_boolean (value, window->allow_grow);
847 g_value_set_boolean (value, window->modal);
850 g_value_set_enum (value, window->position);
852 case PROP_DEFAULT_WIDTH:
853 info = gtk_window_get_geometry_info (window, FALSE);
855 g_value_set_int (value, -1);
857 g_value_set_int (value, info->default_width);
859 case PROP_DEFAULT_HEIGHT:
860 info = gtk_window_get_geometry_info (window, FALSE);
862 g_value_set_int (value, -1);
864 g_value_set_int (value, info->default_height);
866 case PROP_DESTROY_WITH_PARENT:
867 g_value_set_boolean (value, window->destroy_with_parent);
870 g_value_set_object (value, gtk_window_get_icon (window));
873 g_value_set_object (value, window->screen);
876 g_value_set_boolean (value, window->is_active);
878 case PROP_HAS_TOPLEVEL_FOCUS:
879 g_value_set_boolean (value, window->has_toplevel_focus);
882 g_value_set_enum (value,
885 case PROP_SKIP_TASKBAR_HINT:
886 g_value_set_boolean (value,
887 gtk_window_get_skip_taskbar_hint (window));
889 case PROP_SKIP_PAGER_HINT:
890 g_value_set_boolean (value,
891 gtk_window_get_skip_pager_hint (window));
894 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
901 * @type: type of window
903 * Creates a new #GtkWindow, which is a toplevel window that can
904 * contain other widgets. Nearly always, the type of the window should
905 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
906 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
907 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
908 * dialogs, though in some other toolkits dialogs are called "popups".
909 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
910 * On X11, popup windows are not controlled by the <link
911 * linkend="gtk-X11-arch">window manager</link>.
913 * If you simply want an undecorated window (no window borders), use
914 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
916 * Return value: a new #GtkWindow.
919 gtk_window_new (GtkWindowType type)
923 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
925 window = g_object_new (GTK_TYPE_WINDOW, NULL);
929 return GTK_WIDGET (window);
933 * gtk_window_set_title:
934 * @window: a #GtkWindow
935 * @title: title of the window
937 * Sets the title of the #GtkWindow. The title of a window will be
938 * displayed in its title bar; on the X Window System, the title bar
939 * is rendered by the <link linkend="gtk-X11-arch">window
940 * manager</link>, so exactly how the title appears to users may vary
941 * according to a user's exact configuration. The title should help a
942 * user distinguish this window from other windows they may have
943 * open. A good title might include the application name and current
944 * document filename, for example.
948 gtk_window_set_title (GtkWindow *window,
951 g_return_if_fail (GTK_IS_WINDOW (window));
954 g_free (window->title);
955 window->title = g_strdup (title);
957 if (GTK_WIDGET_REALIZED (window))
959 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
961 gtk_decorated_window_set_title (window, title);
964 g_object_notify (G_OBJECT (window), "title");
968 * gtk_window_get_title:
969 * @window: a #GtkWindow
971 * Retrieves the title of the window. See gtk_window_set_title().
973 * Return value: the title of the window, or %NULL if none has
974 * been set explicitely. The returned string is owned by the widget
975 * and must not be modified or freed.
977 G_CONST_RETURN gchar *
978 gtk_window_get_title (GtkWindow *window)
980 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
982 return window->title;
986 * gtk_window_set_wmclass:
987 * @window: a #GtkWindow
988 * @wmclass_name: window name hint
989 * @wmclass_class: window class hint
991 * Don't use this function. It sets the X Window System "class" and
992 * "name" hints for a window. According to the ICCCM, you should
993 * always set these to the same value for all windows in an
994 * application, and GTK+ sets them to that value by default, so calling
995 * this function is sort of pointless. However, you may want to call
996 * gtk_window_set_role() on each window in your application, for the
997 * benefit of the session manager. Setting the role allows the window
998 * manager to restore window positions when loading a saved session.
1002 gtk_window_set_wmclass (GtkWindow *window,
1003 const gchar *wmclass_name,
1004 const gchar *wmclass_class)
1006 g_return_if_fail (GTK_IS_WINDOW (window));
1008 g_free (window->wmclass_name);
1009 window->wmclass_name = g_strdup (wmclass_name);
1011 g_free (window->wmclass_class);
1012 window->wmclass_class = g_strdup (wmclass_class);
1014 if (GTK_WIDGET_REALIZED (window))
1015 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1019 * gtk_window_set_role:
1020 * @window: a #GtkWindow
1021 * @role: unique identifier for the window to be used when restoring a session
1023 * This function is only useful on X11, not with other GTK+ targets.
1025 * In combination with the window title, the window role allows a
1026 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1027 * same" window when an application is restarted. So for example you
1028 * might set the "toolbox" role on your app's toolbox window, so that
1029 * when the user restarts their session, the window manager can put
1030 * the toolbox back in the same place.
1032 * If a window already has a unique title, you don't need to set the
1033 * role, since the WM can use the title to identify the window when
1034 * restoring the session.
1038 gtk_window_set_role (GtkWindow *window,
1041 g_return_if_fail (GTK_IS_WINDOW (window));
1043 if (role == window->wm_role)
1046 g_free (window->wm_role);
1047 window->wm_role = g_strdup (role);
1049 if (GTK_WIDGET_REALIZED (window))
1050 g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
1054 * gtk_window_get_role:
1055 * @window: a #GtkWindow
1057 * Returns the role of the window. See gtk_window_set_role() for
1058 * further explanation.
1060 * Return value: the role of the window if set, or %NULL. The
1061 * returned is owned by the widget and must not be modified
1064 G_CONST_RETURN gchar *
1065 gtk_window_get_role (GtkWindow *window)
1067 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1069 return window->wm_role;
1073 * gtk_window_set_focus:
1074 * @window: a #GtkWindow
1075 * @focus: widget to be the new focus widget, or %NULL to unset
1076 * any focus widget for the toplevel window.
1078 * If @focus is not the current focus widget, and is focusable, sets
1079 * it as the focus widget for the window. If @focus is %NULL, unsets
1080 * the focus widget for this window. To set the focus to a particular
1081 * widget in the toplevel, it is usually more convenient to use
1082 * gtk_widget_grab_focus() instead of this function.
1085 gtk_window_set_focus (GtkWindow *window,
1088 g_return_if_fail (GTK_IS_WINDOW (window));
1091 g_return_if_fail (GTK_IS_WIDGET (focus));
1092 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1096 gtk_widget_grab_focus (focus);
1099 /* Clear the existing focus chain, so that when we focus into
1100 * the window again, we start at the beginnning.
1102 GtkWidget *widget = window->focus_widget;
1105 while (widget->parent)
1107 widget = widget->parent;
1108 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1112 _gtk_window_internal_set_focus (window, NULL);
1117 _gtk_window_internal_set_focus (GtkWindow *window,
1120 g_return_if_fail (GTK_IS_WINDOW (window));
1122 if ((window->focus_widget != focus) ||
1123 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1124 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1128 * gtk_window_set_default:
1129 * @window: a #GtkWindow
1130 * @default_widget: widget to be the default, or %NULL to unset the
1131 * default widget for the toplevel.
1133 * The default widget is the widget that's activated when the user
1134 * presses Enter in a dialog (for example). This function sets or
1135 * unsets the default widget for a #GtkWindow about. When setting
1136 * (rather than unsetting) the default widget it's generally easier to
1137 * call gtk_widget_grab_focus() on the widget. Before making a widget
1138 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1139 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1142 gtk_window_set_default (GtkWindow *window,
1143 GtkWidget *default_widget)
1145 g_return_if_fail (GTK_IS_WINDOW (window));
1148 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1150 if (window->default_widget != default_widget)
1152 GtkWidget *old_default_widget = NULL;
1155 g_object_ref (default_widget);
1157 if (window->default_widget)
1159 old_default_widget = window->default_widget;
1161 if (window->focus_widget != window->default_widget ||
1162 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1163 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1164 gtk_widget_queue_draw (window->default_widget);
1167 window->default_widget = default_widget;
1169 if (window->default_widget)
1171 if (window->focus_widget == NULL ||
1172 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1173 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1174 gtk_widget_queue_draw (window->default_widget);
1177 if (old_default_widget)
1178 g_object_notify (G_OBJECT (old_default_widget), "has_default");
1182 g_object_notify (G_OBJECT (default_widget), "has_default");
1183 g_object_unref (default_widget);
1189 gtk_window_set_policy (GtkWindow *window,
1190 gboolean allow_shrink,
1191 gboolean allow_grow,
1192 gboolean auto_shrink)
1194 g_return_if_fail (GTK_IS_WINDOW (window));
1196 window->allow_shrink = (allow_shrink != FALSE);
1197 window->allow_grow = (allow_grow != FALSE);
1199 g_object_freeze_notify (G_OBJECT (window));
1200 g_object_notify (G_OBJECT (window), "allow_shrink");
1201 g_object_notify (G_OBJECT (window), "allow_grow");
1202 g_object_notify (G_OBJECT (window), "resizable");
1203 g_object_thaw_notify (G_OBJECT (window));
1205 gtk_widget_queue_resize (GTK_WIDGET (window));
1209 handle_keys_changed (gpointer data)
1213 GDK_THREADS_ENTER ();
1214 window = GTK_WINDOW (data);
1216 if (window->keys_changed_handler)
1218 gtk_idle_remove (window->keys_changed_handler);
1219 window->keys_changed_handler = 0;
1222 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1223 GDK_THREADS_LEAVE ();
1229 gtk_window_notify_keys_changed (GtkWindow *window)
1231 if (!window->keys_changed_handler)
1232 window->keys_changed_handler = gtk_idle_add (handle_keys_changed, window);
1236 * gtk_window_add_accel_group:
1237 * @window: window to attach accelerator group to
1238 * @accel_group: a #GtkAccelGroup
1240 * Associate @accel_group with @window, such that calling
1241 * gtk_accel_groups_activate() on @window will activate accelerators
1245 gtk_window_add_accel_group (GtkWindow *window,
1246 GtkAccelGroup *accel_group)
1248 g_return_if_fail (GTK_IS_WINDOW (window));
1249 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1251 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1252 g_signal_connect_object (accel_group, "accel_changed",
1253 G_CALLBACK (gtk_window_notify_keys_changed),
1254 window, G_CONNECT_SWAPPED);
1258 * gtk_window_remove_accel_group:
1259 * @window: a #GtkWindow
1260 * @accel_group: a #GtkAccelGroup
1262 * Reverses the effects of gtk_window_add_accel_group().
1265 gtk_window_remove_accel_group (GtkWindow *window,
1266 GtkAccelGroup *accel_group)
1268 g_return_if_fail (GTK_IS_WINDOW (window));
1269 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1271 g_signal_handlers_disconnect_by_func (accel_group,
1272 gtk_window_notify_keys_changed,
1274 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1278 * gtk_window_add_mnemonic:
1279 * @window: a #GtkWindow
1280 * @keyval: the mnemonic
1281 * @target: the widget that gets activated by the mnemonic
1283 * Adds a mnemonic to this window.
1286 gtk_window_add_mnemonic (GtkWindow *window,
1290 GtkWindowMnemonic key;
1291 GtkWindowMnemonic *mnemonic;
1293 g_return_if_fail (GTK_IS_WINDOW (window));
1294 g_return_if_fail (GTK_IS_WIDGET (target));
1296 key.window = window;
1297 key.keyval = keyval;
1298 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1302 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1303 mnemonic->targets = g_slist_append (mnemonic->targets, target);
1307 mnemonic = g_new (GtkWindowMnemonic, 1);
1309 mnemonic->targets = g_slist_prepend (NULL, target);
1310 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1312 gtk_window_notify_keys_changed (window);
1316 * gtk_window_remove_mnemonic:
1317 * @window: a #GtkWindow
1318 * @keyval: the mnemonic
1319 * @target: the widget that gets activated by the mnemonic
1321 * Removes a mnemonic from this window.
1324 gtk_window_remove_mnemonic (GtkWindow *window,
1328 GtkWindowMnemonic key;
1329 GtkWindowMnemonic *mnemonic;
1331 g_return_if_fail (GTK_IS_WINDOW (window));
1332 g_return_if_fail (GTK_IS_WIDGET (target));
1334 key.window = window;
1335 key.keyval = keyval;
1336 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1338 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1340 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1341 if (mnemonic->targets == NULL)
1343 g_hash_table_remove (mnemonic_hash_table, mnemonic);
1346 gtk_window_notify_keys_changed (window);
1350 * gtk_window_mnemonic_activate:
1351 * @window: a #GtkWindow
1352 * @keyval: the mnemonic
1353 * @modifier: the modifiers
1354 * @returns: %TRUE if the activation is done.
1356 * Activates the targets associated with the mnemonic.
1359 gtk_window_mnemonic_activate (GtkWindow *window,
1361 GdkModifierType modifier)
1363 GtkWindowMnemonic key;
1364 GtkWindowMnemonic *mnemonic;
1366 GtkWidget *widget, *chosen_widget;
1367 gboolean overloaded;
1369 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1371 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1374 key.window = window;
1375 key.keyval = keyval;
1376 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1382 chosen_widget = NULL;
1383 list = mnemonic->targets;
1386 widget = GTK_WIDGET (list->data);
1388 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1389 GTK_WIDGET_MAPPED (widget))
1397 chosen_widget = widget;
1399 list = g_slist_next (list);
1404 /* For round robin we put the activated entry on
1405 * the end of the list after activation
1407 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1408 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1410 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1416 * gtk_window_set_mnemonic_modifier:
1417 * @window: a #GtkWindow
1418 * @modifier: the modifier mask used to activate
1419 * mnemonics on this window.
1421 * Sets the mnemonic modifier for this window.
1424 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1425 GdkModifierType modifier)
1427 g_return_if_fail (GTK_IS_WINDOW (window));
1428 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1430 window->mnemonic_modifier = modifier;
1431 gtk_window_notify_keys_changed (window);
1435 * gtk_window_get_mnemonic_modifier:
1436 * @window: a #GtkWindow
1438 * Returns the mnemonic modifier for this window. See
1439 * gtk_window_set_mnemonic_modifier().
1441 * Return value: the modifier mask used to activate
1442 * mnemonics on this window.
1445 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1447 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1449 return window->mnemonic_modifier;
1453 * gtk_window_set_position:
1454 * @window: a #GtkWindow.
1455 * @position: a position constraint.
1457 * Sets a position constraint for this window. If the old or new
1458 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1459 * the window to be repositioned to satisfy the new constraint.
1462 gtk_window_set_position (GtkWindow *window,
1463 GtkWindowPosition position)
1465 g_return_if_fail (GTK_IS_WINDOW (window));
1467 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1468 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1470 GtkWindowGeometryInfo *info;
1472 info = gtk_window_get_geometry_info (window, TRUE);
1474 /* this flag causes us to re-request the CENTER_ALWAYS
1475 * constraint in gtk_window_move_resize(), see
1476 * comment in that function.
1478 info->position_constraints_changed = TRUE;
1480 gtk_widget_queue_resize (GTK_WIDGET (window));
1483 window->position = position;
1485 g_object_notify (G_OBJECT (window), "window_position");
1489 gtk_window_activate_focus (GtkWindow *window)
1491 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1493 if (window->focus_widget)
1495 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1496 gtk_widget_activate (window->focus_widget);
1504 * gtk_window_get_focus:
1505 * @window: a #GtkWindow
1507 * Retrieves the current focused widget within the window.
1508 * Note that this is the widget that would have the focus
1509 * if the toplevel window focused; if the toplevel window
1510 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1511 * not be %TRUE for the widget.
1513 * Return value: the currently focused widget.
1516 gtk_window_get_focus (GtkWindow *window)
1518 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1520 return window->focus_widget;
1524 gtk_window_activate_default (GtkWindow *window)
1526 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1528 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1529 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1531 gtk_widget_activate (window->default_widget);
1534 else if (window->focus_widget)
1536 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1537 gtk_widget_activate (window->focus_widget);
1545 * gtk_window_set_modal:
1546 * @window: a #GtkWindow
1547 * @modal: whether the window is modal
1549 * Sets a window modal or non-modal. Modal windows prevent interaction
1550 * with other windows in the same application. To keep modal dialogs
1551 * on top of main application windows, use
1552 * gtk_window_set_transient_for() to make the dialog transient for the
1553 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1554 * will then disallow lowering the dialog below the parent.
1559 gtk_window_set_modal (GtkWindow *window,
1562 g_return_if_fail (GTK_IS_WINDOW (window));
1564 window->modal = modal != FALSE;
1566 /* adjust desired modality state */
1567 if (GTK_WIDGET_VISIBLE (window) && window->modal)
1568 gtk_grab_add (GTK_WIDGET (window));
1570 gtk_grab_remove (GTK_WIDGET (window));
1572 g_object_notify (G_OBJECT (window), "modal");
1576 * gtk_window_get_modal:
1577 * @window: a #GtkWindow
1579 * Returns whether the window is modal. See gtk_window_set_modal().
1581 * Return value: %TRUE if the window is set to be modal and
1582 * establishes a grab when shown
1585 gtk_window_get_modal (GtkWindow *window)
1587 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1589 return window->modal;
1593 * gtk_window_list_toplevels:
1595 * Returns a list of all existing toplevel windows. The widgets
1596 * in the list are not individually referenced. If you want
1597 * to iterate through the list and perform actions involving
1598 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1599 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1600 * then unref all the widgets afterwards.
1602 * Return value: list of toplevel widgets
1605 gtk_window_list_toplevels (void)
1610 for (slist = toplevel_list; slist; slist = slist->next)
1611 list = g_list_prepend (list, slist->data);
1617 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1619 GList *embedded_windows;
1621 g_return_if_fail (GTK_IS_WINDOW (window));
1623 embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1624 if (embedded_windows)
1625 g_object_steal_qdata (G_OBJECT (window),
1626 g_quark_from_static_string ("gtk-embedded"));
1627 embedded_windows = g_list_prepend (embedded_windows,
1628 GUINT_TO_POINTER (xid));
1630 g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
1633 (GDestroyNotify) g_list_free : NULL);
1637 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1639 GList *embedded_windows;
1642 g_return_if_fail (GTK_IS_WINDOW (window));
1644 embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1645 if (embedded_windows)
1646 g_object_steal_qdata (G_OBJECT (window),
1647 g_quark_from_static_string ("gtk-embedded"));
1649 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1652 embedded_windows = g_list_remove_link (embedded_windows, node);
1653 g_list_free_1 (node);
1656 g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
1659 (GDestroyNotify) g_list_free : NULL);
1663 _gtk_window_reposition (GtkWindow *window,
1667 g_return_if_fail (GTK_IS_WINDOW (window));
1669 gtk_window_move (window, x, y);
1673 gtk_window_dispose (GObject *object)
1675 GtkWindow *window = GTK_WINDOW (object);
1677 gtk_window_set_focus (window, NULL);
1678 gtk_window_set_default (window, NULL);
1680 G_OBJECT_CLASS (parent_class)->dispose (object);
1684 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1686 gtk_widget_destroy (GTK_WIDGET (child));
1690 connect_parent_destroyed (GtkWindow *window)
1692 if (window->transient_parent)
1694 g_signal_connect (window->transient_parent,
1696 G_CALLBACK (parent_destroyed_callback),
1702 disconnect_parent_destroyed (GtkWindow *window)
1704 if (window->transient_parent)
1706 g_signal_handlers_disconnect_by_func (window->transient_parent,
1707 parent_destroyed_callback,
1713 gtk_window_transient_parent_realized (GtkWidget *parent,
1716 if (GTK_WIDGET_REALIZED (window))
1717 gdk_window_set_transient_for (window->window, parent->window);
1721 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1724 if (GTK_WIDGET_REALIZED (window))
1725 gdk_property_delete (window->window,
1726 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1730 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
1734 gtk_window_set_screen (window, parent->screen);
1738 gtk_window_unset_transient_for (GtkWindow *window)
1740 if (window->transient_parent)
1742 g_signal_handlers_disconnect_by_func (window->transient_parent,
1743 gtk_window_transient_parent_realized,
1745 g_signal_handlers_disconnect_by_func (window->transient_parent,
1746 gtk_window_transient_parent_unrealized,
1748 g_signal_handlers_disconnect_by_func (window->transient_parent,
1749 gtk_window_transient_parent_screen_changed,
1751 g_signal_handlers_disconnect_by_func (window->transient_parent,
1752 gtk_widget_destroyed,
1753 &window->transient_parent);
1755 if (window->destroy_with_parent)
1756 disconnect_parent_destroyed (window);
1758 window->transient_parent = NULL;
1763 * gtk_window_set_transient_for:
1764 * @window: a #GtkWindow
1765 * @parent: parent window
1767 * Dialog windows should be set transient for the main application
1768 * window they were spawned from. This allows <link
1769 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1770 * dialog on top of the main window, or center the dialog over the
1771 * main window. gtk_dialog_new_with_buttons() and other convenience
1772 * functions in GTK+ will sometimes call
1773 * gtk_window_set_transient_for() on your behalf.
1775 * On Windows, this function will and put the child window
1776 * on top of the parent, much as the window manager would have
1781 gtk_window_set_transient_for (GtkWindow *window,
1784 g_return_if_fail (GTK_IS_WINDOW (window));
1785 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1786 g_return_if_fail (window != parent);
1789 if (window->transient_parent)
1791 if (GTK_WIDGET_REALIZED (window) &&
1792 GTK_WIDGET_REALIZED (window->transient_parent) &&
1793 (!parent || !GTK_WIDGET_REALIZED (parent)))
1794 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1795 GTK_WIDGET (window));
1797 gtk_window_unset_transient_for (window);
1800 window->transient_parent = parent;
1804 g_signal_connect (parent, "destroy",
1805 G_CALLBACK (gtk_widget_destroyed),
1806 &window->transient_parent);
1807 g_signal_connect (parent, "realize",
1808 G_CALLBACK (gtk_window_transient_parent_realized),
1810 g_signal_connect (parent, "unrealize",
1811 G_CALLBACK (gtk_window_transient_parent_unrealized),
1813 g_signal_connect (parent, "notify::screen",
1814 G_CALLBACK (gtk_window_transient_parent_screen_changed),
1817 gtk_window_set_screen (window, parent->screen);
1819 if (window->destroy_with_parent)
1820 connect_parent_destroyed (window);
1822 if (GTK_WIDGET_REALIZED (window) &&
1823 GTK_WIDGET_REALIZED (parent))
1824 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1825 GTK_WIDGET (window));
1830 * gtk_window_get_transient_for:
1831 * @window: a #GtkWindow
1833 * Fetches the transient parent for this window. See
1834 * gtk_window_set_transient_for().
1836 * Return value: the transient parent for this window, or %NULL
1837 * if no transient parent has been set.
1840 gtk_window_get_transient_for (GtkWindow *window)
1842 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1844 return window->transient_parent;
1848 * gtk_window_set_type_hint:
1849 * @window: a #GtkWindow
1850 * @hint: the window type
1852 * By setting the type hint for the window, you allow the window
1853 * manager to decorate and handle the window in a way which is
1854 * suitable to the function of the window in your application.
1856 * This function should be called before the window becomes visible.
1858 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1859 * will sometimes call gtk_window_set_type_hint() on your behalf.
1863 gtk_window_set_type_hint (GtkWindow *window,
1864 GdkWindowTypeHint hint)
1866 g_return_if_fail (GTK_IS_WINDOW (window));
1867 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1868 window->type_hint = hint;
1872 * gtk_window_get_type_hint:
1873 * @window: a #GtkWindow
1875 * Gets the type hint for this window. See gtk_window_set_type_hint().
1877 * Return value: the type hint for @window.
1880 gtk_window_get_type_hint (GtkWindow *window)
1882 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1884 return window->type_hint;
1888 * gtk_window_set_skip_taskbar_hint:
1889 * @window: a #GtkWindow
1890 * @setting: %TRUE to keep this window from appearing in the task bar
1892 * Windows may set a hint asking the desktop environment not to display
1893 * the window in the task bar. This function toggles this hint.
1897 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
1900 GtkWindowPrivate *priv;
1902 g_return_if_fail (GTK_IS_WINDOW (window));
1904 priv = gtk_window_get_private (window);
1906 setting = setting != FALSE;
1908 if (priv->skips_taskbar != setting)
1910 priv->skips_taskbar = setting;
1911 if (GTK_WIDGET_REALIZED (window))
1912 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
1913 priv->skips_taskbar);
1914 g_object_notify (G_OBJECT (window), "skip_taskbar_hint");
1919 * gtk_window_get_skip_taskbar_hint:
1920 * @window: a #GtkWindow
1922 * Gets the value set by gtk_window_set_skip_taskbar_hint()
1924 * Return value: %TRUE if window shouldn't be in taskbar
1927 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
1929 GtkWindowPrivate *priv;
1931 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1933 priv = gtk_window_get_private (window);
1935 return priv->skips_taskbar;
1939 * gtk_window_set_skip_pager_hint:
1940 * @window: a #GtkWindow
1941 * @setting: %TRUE to keep this window from appearing in the pager
1943 * Windows may set a hint asking the desktop environment not to display
1944 * the window in the pager. This function toggles this hint.
1945 * (A "pager" is any desktop navigation tool such as a workspace
1946 * switcher that displays a thumbnail representation of the windows
1951 gtk_window_set_skip_pager_hint (GtkWindow *window,
1954 GtkWindowPrivate *priv;
1956 g_return_if_fail (GTK_IS_WINDOW (window));
1958 priv = gtk_window_get_private (window);
1960 setting = setting != FALSE;
1962 if (priv->skips_pager != setting)
1964 priv->skips_pager = setting;
1965 if (GTK_WIDGET_REALIZED (window))
1966 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
1968 g_object_notify (G_OBJECT (window), "skip_pager_hint");
1973 * gtk_window_get_skip_pager_hint:
1974 * @window: a #GtkWindow
1976 * Gets the value set by gtk_window_set_skip_pager_hint().
1978 * Return value: %TRUE if window shouldn't be in pager
1981 gtk_window_get_skip_pager_hint (GtkWindow *window)
1983 GtkWindowPrivate *priv;
1985 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1987 priv = gtk_window_get_private (window);
1989 return priv->skips_pager;
1993 * gtk_window_set_destroy_with_parent:
1994 * @window: a #GtkWindow
1995 * @setting: whether to destroy @window with its transient parent
1997 * If @setting is %TRUE, then destroying the transient parent of @window
1998 * will also destroy @window itself. This is useful for dialogs that
1999 * shouldn't persist beyond the lifetime of the main window they're
2000 * associated with, for example.
2003 gtk_window_set_destroy_with_parent (GtkWindow *window,
2006 g_return_if_fail (GTK_IS_WINDOW (window));
2008 if (window->destroy_with_parent == (setting != FALSE))
2011 if (window->destroy_with_parent)
2013 disconnect_parent_destroyed (window);
2017 connect_parent_destroyed (window);
2020 window->destroy_with_parent = setting;
2022 g_object_notify (G_OBJECT (window), "destroy_with_parent");
2026 * gtk_window_get_destroy_with_parent:
2027 * @window: a #GtkWindow
2029 * Returns whether the window will be destroyed with its transient parent. See
2030 * gtk_window_set_destroy_with_parent ().
2032 * Return value: %TRUE if the window will be destroyed with its transient parent.
2035 gtk_window_get_destroy_with_parent (GtkWindow *window)
2037 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2039 return window->destroy_with_parent;
2042 static GtkWindowGeometryInfo*
2043 gtk_window_get_geometry_info (GtkWindow *window,
2046 GtkWindowGeometryInfo *info;
2048 info = window->geometry_info;
2049 if (!info && create)
2051 info = g_new0 (GtkWindowGeometryInfo, 1);
2053 info->default_width = -1;
2054 info->default_height = -1;
2055 info->resize_width = -1;
2056 info->resize_height = -1;
2057 info->initial_x = 0;
2058 info->initial_y = 0;
2059 info->initial_pos_set = FALSE;
2060 info->default_is_geometry = FALSE;
2061 info->position_constraints_changed = FALSE;
2062 info->last.configure_request.x = 0;
2063 info->last.configure_request.y = 0;
2064 info->last.configure_request.width = -1;
2065 info->last.configure_request.height = -1;
2066 info->widget = NULL;
2068 window->geometry_info = info;
2075 * gtk_window_set_geometry_hints:
2076 * @window: a #GtkWindow
2077 * @geometry_widget: widget the geometry hints will be applied to
2078 * @geometry: struct containing geometry information
2079 * @geom_mask: mask indicating which struct fields should be paid attention to
2081 * This function sets up hints about how a window can be resized by
2082 * the user. You can set a minimum and maximum size; allowed resize
2083 * increments (e.g. for xterm, you can only resize by the size of a
2084 * character); aspect ratios; and more. See the #GdkGeometry struct.
2088 gtk_window_set_geometry_hints (GtkWindow *window,
2089 GtkWidget *geometry_widget,
2090 GdkGeometry *geometry,
2091 GdkWindowHints geom_mask)
2093 GtkWindowGeometryInfo *info;
2095 g_return_if_fail (GTK_IS_WINDOW (window));
2096 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2098 info = gtk_window_get_geometry_info (window, TRUE);
2101 g_signal_handlers_disconnect_by_func (info->widget,
2102 gtk_widget_destroyed,
2105 info->widget = geometry_widget;
2107 g_signal_connect (geometry_widget, "destroy",
2108 G_CALLBACK (gtk_widget_destroyed),
2112 info->geometry = *geometry;
2114 /* We store gravity in window->gravity not in the hints. */
2115 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2117 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2119 gtk_window_set_gravity (window, geometry->win_gravity);
2122 gtk_widget_queue_resize (GTK_WIDGET (window));
2126 * gtk_window_set_decorated:
2127 * @window: a #GtkWindow
2128 * @setting: %TRUE to decorate the window
2130 * By default, windows are decorated with a title bar, resize
2131 * controls, etc. Some <link linkend="gtk-X11-arch">window
2132 * managers</link> allow GTK+ to disable these decorations, creating a
2133 * borderless window. If you set the decorated property to %FALSE
2134 * using this function, GTK+ will do its best to convince the window
2135 * manager not to decorate the window. Depending on the system, this
2136 * function may not have any effect when called on a window that is
2137 * already visible, so you should call it before calling gtk_window_show().
2139 * On Windows, this function always works, since there's no window manager
2144 gtk_window_set_decorated (GtkWindow *window,
2147 g_return_if_fail (GTK_IS_WINDOW (window));
2149 setting = setting != FALSE;
2151 if (setting == window->decorated)
2154 window->decorated = setting;
2156 if (GTK_WIDGET (window)->window)
2158 if (window->decorated)
2159 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2162 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2168 * gtk_window_get_decorated:
2169 * @window: a #GtkWindow
2171 * Returns whether the window has been set to have decorations
2172 * such as a title bar via gtk_window_set_decorated().
2174 * Return value: %TRUE if the window has been set to have decorations
2177 gtk_window_get_decorated (GtkWindow *window)
2179 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2181 return window->decorated;
2184 static GtkWindowIconInfo*
2185 get_icon_info (GtkWindow *window)
2187 return g_object_get_data (G_OBJECT (window),
2188 "gtk-window-icon-info");
2191 static GtkWindowIconInfo*
2192 ensure_icon_info (GtkWindow *window)
2194 GtkWindowIconInfo *info;
2196 info = get_icon_info (window);
2200 info = g_new0 (GtkWindowIconInfo, 1);
2201 g_object_set_data_full (G_OBJECT (window),
2202 "gtk-window-icon-info",
2217 get_screen_icon_info (GdkScreen *screen)
2219 ScreenIconInfo *info = g_object_get_data (G_OBJECT (screen),
2220 "gtk-window-default-icon-pixmap");
2223 info = g_new0 (ScreenIconInfo, 1);
2224 g_object_set_data (G_OBJECT (screen), "gtk-window-default-icon-pixmap", info);
2227 if (info->serial != default_icon_serial)
2231 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2232 info->pixmap = NULL;
2237 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2241 info->serial = default_icon_serial;
2248 get_pixmap_and_mask (GdkWindow *window,
2249 GtkWindowIconInfo *parent_info,
2250 gboolean is_default_list,
2252 GdkPixmap **pmap_return,
2253 GdkBitmap **mask_return)
2255 GdkScreen *screen = gdk_drawable_get_screen (window);
2256 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2257 GdkPixbuf *best_icon;
2261 *pmap_return = NULL;
2262 *mask_return = NULL;
2264 if (is_default_list &&
2265 default_icon_info->pixmap != NULL)
2267 /* Use shared icon pixmap for all windows on this screen.
2269 if (default_icon_info->pixmap)
2270 g_object_ref (default_icon_info->pixmap);
2271 if (default_icon_info->mask)
2272 g_object_ref (default_icon_info->mask);
2274 *pmap_return = default_icon_info->pixmap;
2275 *mask_return = default_icon_info->mask;
2277 else if (parent_info && parent_info->icon_pixmap)
2279 if (parent_info->icon_pixmap)
2280 g_object_ref (parent_info->icon_pixmap);
2281 if (parent_info->icon_mask)
2282 g_object_ref (parent_info->icon_mask);
2284 *pmap_return = parent_info->icon_pixmap;
2285 *mask_return = parent_info->icon_mask;
2289 #define IDEAL_SIZE 48
2291 best_size = G_MAXINT;
2293 tmp_list = icon_list;
2294 while (tmp_list != NULL)
2296 GdkPixbuf *pixbuf = tmp_list->data;
2299 /* average width and height - if someone passes in a rectangular
2300 * icon they deserve what they get.
2302 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2305 if (best_icon == NULL)
2312 /* icon is better if it's 32 pixels or larger, and closer to
2313 * the ideal size than the current best.
2316 (ABS (best_size - IDEAL_SIZE) <
2317 ABS (this - IDEAL_SIZE)))
2324 tmp_list = tmp_list->next;
2328 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2329 gdk_screen_get_system_colormap (screen),
2334 /* Save pmap/mask for others to use if appropriate */
2337 parent_info->icon_pixmap = *pmap_return;
2338 parent_info->icon_mask = *mask_return;
2340 if (parent_info->icon_pixmap)
2341 g_object_ref (parent_info->icon_pixmap);
2342 if (parent_info->icon_mask)
2343 g_object_ref (parent_info->icon_mask);
2345 else if (is_default_list)
2347 default_icon_info->pixmap = *pmap_return;
2348 default_icon_info->mask = *mask_return;
2350 if (default_icon_info->pixmap)
2351 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2352 (gpointer*)&default_icon_info->pixmap);
2353 if (default_icon_info->mask)
2354 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2355 (gpointer*)&default_icon_info->mask);
2361 gtk_window_realize_icon (GtkWindow *window)
2364 GtkWindowIconInfo *info;
2367 widget = GTK_WIDGET (window);
2369 g_return_if_fail (widget->window != NULL);
2371 /* no point setting an icon on override-redirect */
2372 if (window->type == GTK_WINDOW_POPUP)
2377 info = ensure_icon_info (window);
2382 g_return_if_fail (info->icon_pixmap == NULL);
2383 g_return_if_fail (info->icon_mask == NULL);
2385 info->using_default_icon = FALSE;
2386 info->using_parent_icon = FALSE;
2388 icon_list = info->icon_list;
2390 /* Inherit from transient parent */
2391 if (icon_list == NULL && window->transient_parent)
2393 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2395 info->using_parent_icon = TRUE;
2398 /* Inherit from default */
2399 if (icon_list == NULL)
2401 icon_list = default_icon_list;
2403 info->using_default_icon = TRUE;
2406 gdk_window_set_icon_list (widget->window, icon_list);
2408 get_pixmap_and_mask (widget->window,
2409 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2410 info->using_default_icon,
2415 /* This is a slight ICCCM violation since it's a color pixmap not
2416 * a bitmap, but everyone does it.
2418 gdk_window_set_icon (widget->window,
2423 info->realized = TRUE;
2427 gtk_window_unrealize_icon (GtkWindow *window)
2429 GtkWindowIconInfo *info;
2432 widget = GTK_WIDGET (window);
2434 info = get_icon_info (window);
2439 if (info->icon_pixmap)
2440 g_object_unref (info->icon_pixmap);
2442 if (info->icon_mask)
2443 g_object_unref (info->icon_mask);
2445 info->icon_pixmap = NULL;
2446 info->icon_mask = NULL;
2448 /* We don't clear the properties on the window, just figure the
2449 * window is going away.
2452 info->realized = FALSE;
2456 * gtk_window_set_icon_list:
2457 * @window: a #GtkWindow
2458 * @list: list of #GdkPixbuf
2460 * Sets up the icon representing a #GtkWindow. The icon is used when
2461 * the window is minimized (also known as iconified). Some window
2462 * managers or desktop environments may also place it in the window
2463 * frame, or display it in other contexts.
2465 * gtk_window_set_icon_list() allows you to pass in the same icon in
2466 * several hand-drawn sizes. The list should contain the natural sizes
2467 * your icon is available in; that is, don't scale the image before
2468 * passing it to GTK+. Scaling is postponed until the last minute,
2469 * when the desired final size is known, to allow best quality.
2471 * By passing several sizes, you may improve the final image quality
2472 * of the icon, by reducing or eliminating automatic image scaling.
2474 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2475 * larger images (64x64, 128x128) if you have them.
2477 * See also gtk_window_set_default_icon_list() to set the icon
2478 * for all windows in your application in one go.
2480 * Note that transient windows (those who have been set transient for another
2481 * window using gtk_window_set_transient_for()) will inherit their
2482 * icon from their transient parent. So there's no need to explicitly
2483 * set the icon on transient windows.
2486 gtk_window_set_icon_list (GtkWindow *window,
2489 GtkWindowIconInfo *info;
2491 g_return_if_fail (GTK_IS_WINDOW (window));
2493 info = ensure_icon_info (window);
2495 if (info->icon_list == list) /* check for NULL mostly */
2498 g_list_foreach (info->icon_list,
2499 (GFunc) g_object_unref, NULL);
2501 g_list_free (info->icon_list);
2503 info->icon_list = g_list_copy (list);
2504 g_list_foreach (info->icon_list,
2505 (GFunc) g_object_ref, NULL);
2507 g_object_notify (G_OBJECT (window), "icon");
2509 gtk_window_unrealize_icon (window);
2511 if (GTK_WIDGET_REALIZED (window))
2512 gtk_window_realize_icon (window);
2514 /* We could try to update our transient children, but I don't think
2515 * it's really worth it. If we did it, the best way would probably
2516 * be to have children connect to notify::icon_list
2521 * gtk_window_get_icon_list:
2522 * @window: a #GtkWindow
2524 * Retrieves the list of icons set by gtk_window_set_icon_list().
2525 * The list is copied, but the reference count on each
2526 * member won't be incremented.
2528 * Return value: copy of window's icon list
2531 gtk_window_get_icon_list (GtkWindow *window)
2533 GtkWindowIconInfo *info;
2535 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2537 info = get_icon_info (window);
2540 return g_list_copy (info->icon_list);
2546 * gtk_window_set_icon:
2547 * @window: a #GtkWindow
2548 * @icon: icon image, or %NULL
2550 * Sets up the icon representing a #GtkWindow. This icon is used when
2551 * the window is minimized (also known as iconified). Some window
2552 * managers or desktop environments may also place it in the window
2553 * frame, or display it in other contexts.
2555 * The icon should be provided in whatever size it was naturally
2556 * drawn; that is, don't scale the image before passing it to
2557 * GTK+. Scaling is postponed until the last minute, when the desired
2558 * final size is known, to allow best quality.
2560 * If you have your icon hand-drawn in multiple sizes, use
2561 * gtk_window_set_icon_list(). Then the best size will be used.
2563 * This function is equivalent to calling gtk_window_set_icon_list()
2564 * with a 1-element list.
2566 * See also gtk_window_set_default_icon_list() to set the icon
2567 * for all windows in your application in one go.
2570 gtk_window_set_icon (GtkWindow *window,
2575 g_return_if_fail (GTK_IS_WINDOW (window));
2576 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2581 list = g_list_append (list, icon);
2583 gtk_window_set_icon_list (window, list);
2588 * gtk_window_get_icon:
2589 * @window: a #GtkWindow
2591 * Gets the value set by gtk_window_set_icon() (or if you've
2592 * called gtk_window_set_icon_list(), gets the first icon in
2595 * Return value: icon for window
2598 gtk_window_get_icon (GtkWindow *window)
2600 GtkWindowIconInfo *info;
2602 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2604 info = get_icon_info (window);
2605 if (info && info->icon_list)
2606 return GDK_PIXBUF (info->icon_list->data);
2611 /* Load pixbuf, printing warning on failure if error == NULL
2614 load_pixbuf_verbosely (const char *filename,
2617 GError *local_err = NULL;
2620 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
2628 g_warning ("Error loading icon from file '%s':\n\t%s",
2629 filename, local_err->message);
2630 g_error_free (local_err);
2638 * gtk_window_set_icon_from_file:
2639 * @window: a #GtkWindow
2640 * @filename: location of icon file
2641 * @err: location to store error, or %NULL.
2643 * Sets the icon for @window.
2644 * Warns on failure if @err is %NULL.
2646 * This function is equivalent to calling gtk_window_set_icon()
2647 * with a pixbuf created by loading the image from @filename.
2649 * Returns: %TRUE if setting the icon succeeded.
2652 gtk_window_set_icon_from_file (GtkWindow *window,
2653 const gchar *filename,
2656 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2660 gtk_window_set_icon (window, pixbuf);
2661 g_object_unref (pixbuf);
2670 * gtk_window_set_default_icon_list:
2671 * @list: a list of #GdkPixbuf
2673 * Sets an icon list to be used as fallback for windows that haven't
2674 * had gtk_window_set_icon_list() called on them to set up a
2675 * window-specific icon list. This function allows you to set up the
2676 * icon for all windows in your app at once.
2678 * See gtk_window_set_icon_list() for more details.
2682 gtk_window_set_default_icon_list (GList *list)
2686 if (list == default_icon_list)
2689 /* Update serial so we don't used cached pixmaps/masks
2691 default_icon_serial++;
2693 g_list_foreach (default_icon_list,
2694 (GFunc) g_object_unref, NULL);
2696 g_list_free (default_icon_list);
2698 default_icon_list = g_list_copy (list);
2699 g_list_foreach (default_icon_list,
2700 (GFunc) g_object_ref, NULL);
2702 /* Update all toplevels */
2703 toplevels = gtk_window_list_toplevels ();
2704 tmp_list = toplevels;
2705 while (tmp_list != NULL)
2707 GtkWindowIconInfo *info;
2708 GtkWindow *w = tmp_list->data;
2710 info = get_icon_info (w);
2711 if (info && info->using_default_icon)
2713 gtk_window_unrealize_icon (w);
2714 if (GTK_WIDGET_REALIZED (w))
2715 gtk_window_realize_icon (w);
2718 tmp_list = tmp_list->next;
2720 g_list_free (toplevels);
2724 * gtk_window_set_default_icon_from_file:
2725 * @filename: location of icon file
2726 * @err: location to store error, or %NULL.
2728 * Sets an icon to be used as fallback for windows that haven't
2729 * had gtk_window_set_icon_list() called on them from a file
2730 * on disk. Warns on failure if @err is %NULL.
2732 * Returns: %TRUE if setting the icon succeeded.
2735 gtk_window_set_default_icon_from_file (const gchar *filename,
2738 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2742 GList *list = g_list_prepend (NULL, pixbuf);
2743 gtk_window_set_default_icon_list (list);
2746 g_object_unref (pixbuf);
2755 * gtk_window_get_default_icon_list:
2757 * Gets the value set by gtk_window_set_default_icon_list().
2758 * The list is a copy and should be freed with g_list_free(),
2759 * but the pixbufs in the list have not had their reference count
2762 * Return value: copy of default icon list
2765 gtk_window_get_default_icon_list (void)
2767 return g_list_copy (default_icon_list);
2771 gtk_window_set_default_size_internal (GtkWindow *window,
2772 gboolean change_width,
2774 gboolean change_height,
2776 gboolean is_geometry)
2778 GtkWindowGeometryInfo *info;
2780 g_return_if_fail (change_width == FALSE || width >= -1);
2781 g_return_if_fail (change_height == FALSE || height >= -1);
2783 info = gtk_window_get_geometry_info (window, TRUE);
2785 g_object_freeze_notify (G_OBJECT (window));
2787 info->default_is_geometry = is_geometry != FALSE;
2797 info->default_width = width;
2799 g_object_notify (G_OBJECT (window), "default_width");
2810 info->default_height = height;
2812 g_object_notify (G_OBJECT (window), "default_height");
2815 g_object_thaw_notify (G_OBJECT (window));
2817 gtk_widget_queue_resize (GTK_WIDGET (window));
2821 * gtk_window_set_default_size:
2822 * @window: a #GtkWindow
2823 * @width: width in pixels, or -1 to unset the default width
2824 * @height: height in pixels, or -1 to unset the default height
2826 * Sets the default size of a window. If the window's "natural" size
2827 * (its size request) is larger than the default, the default will be
2828 * ignored. More generally, if the default size does not obey the
2829 * geometry hints for the window (gtk_window_set_geometry_hints() can
2830 * be used to set these explicitly), the default size will be clamped
2831 * to the nearest permitted size.
2833 * Unlike gtk_widget_set_size_request(), which sets a size request for
2834 * a widget and thus would keep users from shrinking the window, this
2835 * function only sets the initial size, just as if the user had
2836 * resized the window themselves. Users can still shrink the window
2837 * again as they normally would. Setting a default size of -1 means to
2838 * use the "natural" default size (the size request of the window).
2840 * For more control over a window's initial size and how resizing works,
2841 * investigate gtk_window_set_geometry_hints().
2843 * For some uses, gtk_window_resize() is a more appropriate function.
2844 * gtk_window_resize() changes the current size of the window, rather
2845 * than the size to be used on initial display. gtk_window_resize() always
2846 * affects the window itself, not the geometry widget.
2848 * The default size of a window only affects the first time a window is
2849 * shown; if a window is hidden and re-shown, it will remember the size
2850 * it had prior to hiding, rather than using the default size.
2852 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2853 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2856 gtk_window_set_default_size (GtkWindow *window,
2860 g_return_if_fail (GTK_IS_WINDOW (window));
2861 g_return_if_fail (width >= -1);
2862 g_return_if_fail (height >= -1);
2864 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
2868 * gtk_window_get_default_size:
2869 * @window: a #GtkWindow
2870 * @width: location to store the default width, or %NULL
2871 * @height: location to store the default height, or %NULL
2873 * Gets the default size of the window. A value of -1 for the width or
2874 * height indicates that a default size has not been explicitly set
2875 * for that dimension, so the "natural" size of the window will be
2880 gtk_window_get_default_size (GtkWindow *window,
2884 GtkWindowGeometryInfo *info;
2886 g_return_if_fail (GTK_IS_WINDOW (window));
2888 info = gtk_window_get_geometry_info (window, FALSE);
2891 *width = info->default_width;
2894 *height = info->default_height;
2898 * gtk_window_resize:
2899 * @window: a #GtkWindow
2900 * @width: width in pixels to resize the window to
2901 * @height: height in pixels to resize the window to
2903 * Resizes the window as if the user had done so, obeying geometry
2904 * constraints. The default geometry constraint is that windows may
2905 * not be smaller than their size request; to override this
2906 * constraint, call gtk_widget_set_size_request() to set the window's
2907 * request to a smaller value.
2909 * If gtk_window_resize() is called before showing a window for the
2910 * first time, it overrides any default size set with
2911 * gtk_window_set_default_size().
2913 * Windows may not be resized smaller than 1 by 1 pixels.
2917 gtk_window_resize (GtkWindow *window,
2921 GtkWindowGeometryInfo *info;
2923 g_return_if_fail (GTK_IS_WINDOW (window));
2924 g_return_if_fail (width > 0);
2925 g_return_if_fail (height > 0);
2927 info = gtk_window_get_geometry_info (window, TRUE);
2929 info->resize_width = width;
2930 info->resize_height = height;
2932 gtk_widget_queue_resize (GTK_WIDGET (window));
2936 * gtk_window_get_size:
2937 * @window: a #GtkWindow
2938 * @width: return location for width, or %NULL
2939 * @height: return location for height, or %NULL
2941 * Obtains the current size of @window. If @window is not onscreen,
2942 * it returns the size GTK+ will suggest to the <link
2943 * linkend="gtk-X11-arch">window manager</link> for the initial window
2944 * size (but this is not reliably the same as the size the window
2945 * manager will actually select). The size obtained by
2946 * gtk_window_get_size() is the last size received in a
2947 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2948 * rather than querying the X server for the size. As a result, if you
2949 * call gtk_window_resize() then immediately call
2950 * gtk_window_get_size(), the size won't have taken effect yet. After
2951 * the window manager processes the resize request, GTK+ receives
2952 * notification that the size has changed via a configure event, and
2953 * the size of the window gets updated.
2955 * Note 1: Nearly any use of this function creates a race condition,
2956 * because the size of the window may change between the time that you
2957 * get the size and the time that you perform some action assuming
2958 * that size is the current size. To avoid race conditions, connect to
2959 * "configure_event" on the window and adjust your size-dependent
2960 * state to match the size delivered in the #GdkEventConfigure.
2962 * Note 2: The returned size does <emphasis>not</emphasis> include the
2963 * size of the window manager decorations (aka the window frame or
2964 * border). Those are not drawn by GTK+ and GTK+ has no reliable
2965 * method of determining their size.
2967 * Note 3: If you are getting a window size in order to position
2968 * the window onscreen, there may be a better way. The preferred
2969 * way is to simply set the window's semantic type with
2970 * gtk_window_set_type_hint(), which allows the window manager to
2971 * e.g. center dialogs. Also, if you set the transient parent of
2972 * dialogs with gtk_window_set_transient_for() window managers
2973 * will often center the dialog over its parent window. It's
2974 * much preferred to let the window manager handle these
2975 * things rather than doing it yourself, because all apps will
2976 * behave consistently and according to user prefs if the window
2977 * manager handles it. Also, the window manager can take the size
2978 * of the window decorations/border into account, while your
2979 * application cannot.
2981 * In any case, if you insist on application-specified window
2982 * positioning, there's <emphasis>still</emphasis> a better way than
2983 * doing it yourself - gtk_window_set_position() will frequently
2984 * handle the details for you.
2988 gtk_window_get_size (GtkWindow *window,
2995 g_return_if_fail (GTK_IS_WINDOW (window));
2997 widget = GTK_WIDGET (window);
2999 if (width == NULL && height == NULL)
3002 if (GTK_WIDGET_MAPPED (window))
3004 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3009 GdkRectangle configure_request;
3011 gtk_window_compute_configure_request (window,
3015 w = configure_request.width;
3016 h = configure_request.height;
3027 * @window: a #GtkWindow
3028 * @x: X coordinate to move window to
3029 * @y: Y coordinate to move window to
3031 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3032 * @window to the given position. Window managers are free to ignore
3033 * this; most window managers ignore requests for initial window
3034 * positions (instead using a user-defined placement algorithm) and
3035 * honor requests after the window has already been shown.
3037 * Note: the position is the position of the gravity-determined
3038 * reference point for the window. The gravity determines two things:
3039 * first, the location of the reference point in root window
3040 * coordinates; and second, which point on the window is positioned at
3041 * the reference point.
3043 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3044 * point is simply the @x, @y supplied to gtk_window_move(). The
3045 * top-left corner of the window decorations (aka window frame or
3046 * border) will be placed at @x, @y. Therefore, to position a window
3047 * at the top left of the screen, you want to use the default gravity
3048 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3050 * To position a window at the bottom right corner of the screen, you
3051 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3052 * point is at @x + the window width and @y + the window height, and
3053 * the bottom-right corner of the window border will be placed at that
3054 * reference point. So, to place a window in the bottom right corner
3055 * you would first set gravity to south east, then write:
3056 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3057 * gdk_screen_height () - window_height)</literal>.
3059 * The extended window manager hints specification at <ulink
3060 * url="http://www.freedesktop.org/standards/wm-spec.html">
3061 * http://www.freedesktop.org/standards/wm-spec.html</ulink> has a
3062 * nice table of gravities in the "implementation notes" section.
3064 * The gtk_window_get_position() documentation may also be relevant.
3068 gtk_window_move (GtkWindow *window,
3072 GtkWindowGeometryInfo *info;
3075 g_return_if_fail (GTK_IS_WINDOW (window));
3077 widget = GTK_WIDGET (window);
3079 info = gtk_window_get_geometry_info (window, TRUE);
3081 if (GTK_WIDGET_MAPPED (window))
3083 /* we have now sent a request with this position
3084 * with currently-active constraints, so toggle flag.
3086 info->position_constraints_changed = FALSE;
3088 /* we only constrain if mapped - if not mapped,
3089 * then gtk_window_compute_configure_request()
3090 * will apply the constraints later, and we
3091 * don't want to lose information about
3092 * what position the user set before then.
3093 * i.e. if you do a move() then turn off POS_CENTER
3094 * then show the window, your move() will work.
3096 gtk_window_constrain_position (window,
3097 widget->allocation.width,
3098 widget->allocation.height,
3101 /* Note that this request doesn't go through our standard request
3102 * framework, e.g. doesn't increment configure_request_count,
3103 * doesn't set info->last, etc.; that's because
3104 * we don't save the info needed to arrive at this same request
3107 * To gtk_window_move_resize(), this will end up looking exactly
3108 * the same as the position being changed by the window
3112 /* FIXME are we handling gravity properly for framed windows? */
3114 gdk_window_move (window->frame,
3115 x - window->frame_left,
3116 y - window->frame_top);
3118 gdk_window_move (GTK_WIDGET (window)->window,
3123 /* Save this position to apply on mapping */
3124 info->initial_x = x;
3125 info->initial_y = y;
3126 info->initial_pos_set = TRUE;
3131 * gtk_window_get_position:
3132 * @window: a #GtkWindow
3133 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3134 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3136 * This function returns the position you need to pass to
3137 * gtk_window_move() to keep @window in its current position. This
3138 * means that the meaning of the returned value varies with window
3139 * gravity. See gtk_window_move() for more details.
3141 * If you haven't changed the window gravity, its gravity will be
3142 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3143 * gets the position of the top-left corner of the window manager
3144 * frame for the window. gtk_window_move() sets the position of this
3145 * same top-left corner.
3147 * gtk_window_get_position() is not 100% reliable because the X Window System
3148 * does not specify a way to obtain the geometry of the
3149 * decorations placed on a window by the window manager.
3150 * Thus GTK+ is using a "best guess" that works with most
3153 * Moreover, nearly all window managers are historically broken with
3154 * respect to their handling of window gravity. So moving a window to
3155 * its current position as returned by gtk_window_get_position() tends
3156 * to result in moving the window slightly. Window managers are
3157 * slowly getting better over time.
3159 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3160 * frame is not relevant, and thus gtk_window_get_position() will
3161 * always produce accurate results. However you can't use static
3162 * gravity to do things like place a window in a corner of the screen,
3163 * because static gravity ignores the window manager decorations.
3165 * If you are saving and restoring your application's window
3166 * positions, you should know that it's impossible for applications to
3167 * do this without getting it somewhat wrong because applications do
3168 * not have sufficient knowledge of window manager state. The Correct
3169 * Mechanism is to support the session management protocol (see the
3170 * "GnomeClient" object in the GNOME libraries for example) and allow
3171 * the window manager to save your window sizes and positions.
3176 gtk_window_get_position (GtkWindow *window,
3182 g_return_if_fail (GTK_IS_WINDOW (window));
3184 widget = GTK_WIDGET (window);
3186 if (window->gravity == GDK_GRAVITY_STATIC)
3188 if (GTK_WIDGET_MAPPED (widget))
3190 /* This does a server round-trip, which is sort of wrong;
3191 * but a server round-trip is inevitable for
3192 * gdk_window_get_frame_extents() in the usual
3193 * NorthWestGravity case below, so not sure what else to
3194 * do. We should likely be consistent about whether we get
3195 * the client-side info or the server-side info.
3197 gdk_window_get_origin (widget->window, root_x, root_y);
3201 GdkRectangle configure_request;
3203 gtk_window_compute_configure_request (window,
3207 *root_x = configure_request.x;
3208 *root_y = configure_request.y;
3213 GdkRectangle frame_extents;
3218 if (GTK_WIDGET_MAPPED (widget))
3221 gdk_window_get_frame_extents (window->frame, &frame_extents);
3223 gdk_window_get_frame_extents (widget->window, &frame_extents);
3224 x = frame_extents.x;
3225 y = frame_extents.y;
3226 gtk_window_get_size (window, &w, &h);
3230 /* We just say the frame has 0 size on all sides.
3231 * Not sure what else to do.
3233 gtk_window_compute_configure_request (window,
3236 x = frame_extents.x;
3237 y = frame_extents.y;
3238 w = frame_extents.width;
3239 h = frame_extents.height;
3242 switch (window->gravity)
3244 case GDK_GRAVITY_NORTH:
3245 case GDK_GRAVITY_CENTER:
3246 case GDK_GRAVITY_SOUTH:
3247 /* Find center of frame. */
3248 x += frame_extents.width / 2;
3249 /* Center client window on that point. */
3253 case GDK_GRAVITY_SOUTH_EAST:
3254 case GDK_GRAVITY_EAST:
3255 case GDK_GRAVITY_NORTH_EAST:
3256 /* Find right edge of frame */
3257 x += frame_extents.width;
3258 /* Align left edge of client at that point. */
3265 switch (window->gravity)
3267 case GDK_GRAVITY_WEST:
3268 case GDK_GRAVITY_CENTER:
3269 case GDK_GRAVITY_EAST:
3270 /* Find center of frame. */
3271 y += frame_extents.height / 2;
3272 /* Center client window there. */
3275 case GDK_GRAVITY_SOUTH_WEST:
3276 case GDK_GRAVITY_SOUTH:
3277 case GDK_GRAVITY_SOUTH_EAST:
3278 /* Find south edge of frame */
3279 y += frame_extents.height;
3280 /* Place bottom edge of client there */
3295 * gtk_window_reshow_with_initial_size:
3296 * @window: a #GtkWindow
3298 * Hides @window, then reshows it, resetting the
3299 * default size and position of the window. Used
3300 * by GUI builders only.
3303 gtk_window_reshow_with_initial_size (GtkWindow *window)
3307 g_return_if_fail (GTK_IS_WINDOW (window));
3309 widget = GTK_WIDGET (window);
3311 gtk_widget_hide (widget);
3312 gtk_widget_unrealize (widget);
3313 gtk_widget_show (widget);
3317 gtk_window_destroy (GtkObject *object)
3319 GtkWindow *window = GTK_WINDOW (object);
3321 if (window->transient_parent)
3322 gtk_window_set_transient_for (window, NULL);
3324 /* frees the icons */
3325 gtk_window_set_icon_list (window, NULL);
3327 if (window->has_user_ref_count)
3329 window->has_user_ref_count = FALSE;
3330 g_object_unref (window);
3334 gtk_window_group_remove_window (window->group, window);
3336 gtk_window_free_key_hash (window);
3338 GTK_OBJECT_CLASS (parent_class)->destroy (object);
3342 gtk_window_mnemonic_hash_remove (gpointer key,
3346 GtkWindowMnemonic *mnemonic = key;
3347 GtkWindow *window = user;
3349 if (mnemonic->window == window)
3351 if (mnemonic->targets)
3353 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
3355 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
3356 name, mnemonic->targets->data);
3359 g_slist_free (mnemonic->targets);
3368 gtk_window_private_finalize (GtkWindowPrivate *priv)
3375 gtk_window_finalize (GObject *object)
3377 GtkWindow *window = GTK_WINDOW (object);
3379 toplevel_list = g_slist_remove (toplevel_list, window);
3381 g_free (window->title);
3382 g_free (window->wmclass_name);
3383 g_free (window->wmclass_class);
3384 g_free (window->wm_role);
3386 g_hash_table_foreach_remove (mnemonic_hash_table,
3387 gtk_window_mnemonic_hash_remove,
3389 if (window->geometry_info)
3391 if (window->geometry_info->widget)
3392 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3393 gtk_widget_destroyed,
3394 &window->geometry_info->widget);
3395 g_free (window->geometry_info);
3398 if (window->keys_changed_handler)
3400 gtk_idle_remove (window->keys_changed_handler);
3401 window->keys_changed_handler = 0;
3404 G_OBJECT_CLASS (parent_class)->finalize (object);
3408 gtk_window_show (GtkWidget *widget)
3410 GtkWindow *window = GTK_WINDOW (widget);
3411 GtkContainer *container = GTK_CONTAINER (window);
3412 gboolean need_resize;
3414 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3416 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3417 container->need_resize = FALSE;
3421 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3422 GtkAllocation allocation = { 0, 0 };
3423 GdkRectangle configure_request;
3424 GdkGeometry new_geometry;
3426 gboolean was_realized;
3428 /* We are going to go ahead and perform this configure request
3429 * and then emulate a configure notify by going ahead and
3430 * doing a size allocate. Sort of a synchronous
3431 * mini-copy of gtk_window_move_resize() here.
3433 gtk_window_compute_configure_request (window,
3438 /* We update this because we are going to go ahead
3439 * and gdk_window_resize() below, rather than
3442 info->last.configure_request.width = configure_request.width;
3443 info->last.configure_request.height = configure_request.height;
3445 /* and allocate the window - this is normally done
3446 * in move_resize in response to configure notify
3448 allocation.width = configure_request.width;
3449 allocation.height = configure_request.height;
3450 gtk_widget_size_allocate (widget, &allocation);
3452 /* Then we guarantee we have a realize */
3453 was_realized = FALSE;
3454 if (!GTK_WIDGET_REALIZED (widget))
3456 gtk_widget_realize (widget);
3457 was_realized = TRUE;
3460 /* Must be done after the windows are realized,
3461 * so that the decorations can be read
3463 gtk_decorated_window_calculate_frame_size (window);
3465 /* We only send configure request if we didn't just finish
3466 * creating the window; if we just created the window
3467 * then we created it with widget->allocation anyhow.
3470 gdk_window_resize (widget->window,
3471 configure_request.width,
3472 configure_request.height);
3475 gtk_container_check_resize (container);
3477 gtk_widget_map (widget);
3479 /* Try to make sure that we have some focused widget
3481 #ifdef GDK_WINDOWING_X11
3482 if (!window->focus_widget && !GTK_IS_PLUG (window))
3484 if (!window->focus_widget)
3486 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
3489 gtk_grab_add (widget);
3493 gtk_window_hide (GtkWidget *widget)
3495 GtkWindow *window = GTK_WINDOW (widget);
3497 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3498 gtk_widget_unmap (widget);
3501 gtk_grab_remove (widget);
3505 gtk_window_map (GtkWidget *widget)
3507 GtkWindow *window = GTK_WINDOW (widget);
3508 GdkWindow *toplevel;
3509 GtkWindowPrivate *priv;
3511 priv = gtk_window_get_private (window);
3513 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3515 if (window->bin.child &&
3516 GTK_WIDGET_VISIBLE (window->bin.child) &&
3517 !GTK_WIDGET_MAPPED (window->bin.child))
3518 gtk_widget_map (window->bin.child);
3521 toplevel = window->frame;
3523 toplevel = widget->window;
3525 if (window->maximize_initially)
3526 gdk_window_maximize (toplevel);
3528 gdk_window_unmaximize (toplevel);
3530 if (window->stick_initially)
3531 gdk_window_stick (toplevel);
3533 gdk_window_unstick (toplevel);
3535 if (window->iconify_initially)
3536 gdk_window_iconify (toplevel);
3538 gdk_window_deiconify (toplevel);
3540 if (priv->fullscreen_initially)
3541 gdk_window_fullscreen (toplevel);
3543 gdk_window_unfullscreen (toplevel);
3545 /* No longer use the default settings */
3546 window->need_default_size = FALSE;
3547 window->need_default_position = FALSE;
3549 gdk_window_show (widget->window);
3552 gdk_window_show (window->frame);
3554 if (!disable_startup_notification &&
3555 !sent_startup_notification)
3557 sent_startup_notification = TRUE;
3558 gdk_notify_startup_complete ();
3563 gtk_window_unmap (GtkWidget *widget)
3565 GtkWindow *window = GTK_WINDOW (widget);
3566 GtkWindowGeometryInfo *info;
3567 GdkWindowState state;
3569 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3571 gdk_window_withdraw (window->frame);
3573 gdk_window_withdraw (widget->window);
3575 window->configure_request_count = 0;
3576 window->configure_notify_received = FALSE;
3578 /* on unmap, we reset the default positioning of the window,
3579 * so it's placed again, but we don't reset the default
3580 * size of the window, so it's remembered.
3582 window->need_default_position = TRUE;
3584 info = gtk_window_get_geometry_info (window, FALSE);
3587 info->initial_pos_set = FALSE;
3588 info->position_constraints_changed = FALSE;
3591 state = gdk_window_get_state (widget->window);
3592 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
3593 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
3594 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
3598 gtk_window_realize (GtkWidget *widget)
3601 GdkWindow *parent_window;
3602 GdkWindowAttr attributes;
3603 gint attributes_mask;
3605 window = GTK_WINDOW (widget);
3607 /* ensure widget tree is properly size allocated */
3608 if (widget->allocation.x == -1 &&
3609 widget->allocation.y == -1 &&
3610 widget->allocation.width == 1 &&
3611 widget->allocation.height == 1)
3613 GtkRequisition requisition;
3614 GtkAllocation allocation = { 0, 0, 200, 200 };
3616 gtk_widget_size_request (widget, &requisition);
3617 if (requisition.width || requisition.height)
3619 /* non-empty window */
3620 allocation.width = requisition.width;
3621 allocation.height = requisition.height;
3623 gtk_widget_size_allocate (widget, &allocation);
3625 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3627 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3630 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3632 switch (window->type)
3634 case GTK_WINDOW_TOPLEVEL:
3635 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3637 case GTK_WINDOW_POPUP:
3638 attributes.window_type = GDK_WINDOW_TEMP;
3641 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3645 attributes.title = window->title;
3646 attributes.wmclass_name = window->wmclass_name;
3647 attributes.wmclass_class = window->wmclass_class;
3648 attributes.wclass = GDK_INPUT_OUTPUT;
3649 attributes.visual = gtk_widget_get_visual (widget);
3650 attributes.colormap = gtk_widget_get_colormap (widget);
3652 if (window->has_frame)
3654 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3655 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3656 attributes.event_mask = (GDK_EXPOSURE_MASK |
3657 GDK_KEY_PRESS_MASK |
3658 GDK_ENTER_NOTIFY_MASK |
3659 GDK_LEAVE_NOTIFY_MASK |
3660 GDK_FOCUS_CHANGE_MASK |
3661 GDK_STRUCTURE_MASK |
3662 GDK_BUTTON_MOTION_MASK |
3663 GDK_POINTER_MOTION_HINT_MASK |
3664 GDK_BUTTON_PRESS_MASK |
3665 GDK_BUTTON_RELEASE_MASK);
3667 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3669 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
3670 &attributes, attributes_mask);
3672 gdk_window_set_user_data (window->frame, widget);
3674 attributes.window_type = GDK_WINDOW_CHILD;
3675 attributes.x = window->frame_left;
3676 attributes.y = window->frame_top;
3678 attributes_mask = GDK_WA_X | GDK_WA_Y;
3680 parent_window = window->frame;
3684 attributes_mask = 0;
3685 parent_window = gtk_widget_get_root_window (widget);
3688 attributes.width = widget->allocation.width;
3689 attributes.height = widget->allocation.height;
3690 attributes.event_mask = gtk_widget_get_events (widget);
3691 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3692 GDK_KEY_PRESS_MASK |
3693 GDK_KEY_RELEASE_MASK |
3694 GDK_ENTER_NOTIFY_MASK |
3695 GDK_LEAVE_NOTIFY_MASK |
3696 GDK_FOCUS_CHANGE_MASK |
3697 GDK_STRUCTURE_MASK);
3699 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3700 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3701 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3703 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3705 gdk_window_set_user_data (widget->window, window);
3707 widget->style = gtk_style_attach (widget->style, widget->window);
3708 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3710 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3712 /* This is a bad hack to set the window background. */
3713 gtk_window_paint (widget, NULL);
3715 if (window->transient_parent &&
3716 GTK_WIDGET_REALIZED (window->transient_parent))
3717 gdk_window_set_transient_for (widget->window,
3718 GTK_WIDGET (window->transient_parent)->window);
3720 if (window->wm_role)
3721 gdk_window_set_role (widget->window, window->wm_role);
3723 if (!window->decorated)
3724 gdk_window_set_decorations (widget->window, 0);
3726 gdk_window_set_type_hint (widget->window, window->type_hint);
3728 if (gtk_window_get_skip_pager_hint (window))
3729 gdk_window_set_skip_pager_hint (widget->window, TRUE);
3731 if (gtk_window_get_skip_taskbar_hint (window))
3732 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
3734 /* transient_for must be set to allow the modal hint */
3735 if (window->transient_parent && window->modal)
3736 gdk_window_set_modal_hint (widget->window, TRUE);
3738 gdk_window_set_modal_hint (widget->window, FALSE);
3741 gtk_window_realize_icon (window);
3745 gtk_window_unrealize (GtkWidget *widget)
3748 GtkWindowGeometryInfo *info;
3750 window = GTK_WINDOW (widget);
3752 /* On unrealize, we reset the size of the window such
3753 * that we will re-apply the default sizing stuff
3754 * next time we show the window.
3756 * Default positioning is reset on unmap, instead of unrealize.
3758 window->need_default_size = TRUE;
3759 info = gtk_window_get_geometry_info (window, FALSE);
3762 info->resize_width = -1;
3763 info->resize_height = -1;
3764 info->last.configure_request.x = 0;
3765 info->last.configure_request.y = 0;
3766 info->last.configure_request.width = -1;
3767 info->last.configure_request.height = -1;
3768 /* be sure we reset geom hints on re-realize */
3769 info->last.flags = 0;
3774 gdk_window_set_user_data (window->frame, NULL);
3775 gdk_window_destroy (window->frame);
3776 window->frame = NULL;
3780 gtk_window_unrealize_icon (window);
3782 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3786 gtk_window_size_request (GtkWidget *widget,
3787 GtkRequisition *requisition)
3792 window = GTK_WINDOW (widget);
3793 bin = GTK_BIN (window);
3795 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3796 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3798 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3800 GtkRequisition child_requisition;
3802 gtk_widget_size_request (bin->child, &child_requisition);
3804 requisition->width += child_requisition.width;
3805 requisition->height += child_requisition.height;
3810 gtk_window_size_allocate (GtkWidget *widget,
3811 GtkAllocation *allocation)
3814 GtkAllocation child_allocation;
3816 window = GTK_WINDOW (widget);
3817 widget->allocation = *allocation;
3819 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3821 child_allocation.x = GTK_CONTAINER (window)->border_width;
3822 child_allocation.y = GTK_CONTAINER (window)->border_width;
3823 child_allocation.width =
3824 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3825 child_allocation.height =
3826 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3828 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3831 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3833 gdk_window_resize (window->frame,
3834 allocation->width + window->frame_left + window->frame_right,
3835 allocation->height + window->frame_top + window->frame_bottom);
3840 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3843 gboolean return_val;
3845 window = GTK_WINDOW (widget);
3847 if (window->frame && (event->any.window == window->frame))
3849 if ((event->type != GDK_KEY_PRESS) &&
3850 (event->type != GDK_KEY_RELEASE) &&
3851 (event->type != GDK_FOCUS_CHANGE))
3853 g_signal_stop_emission_by_name (widget, "event");
3855 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
3860 g_object_unref (event->any.window);
3861 event->any.window = g_object_ref (widget->window);
3869 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3871 GdkEventConfigure *configure_event;
3874 switch (event->type)
3877 configure_event = (GdkEventConfigure *)event;
3879 /* Invalidate the decorations */
3882 rect.width = configure_event->width;
3883 rect.height = configure_event->height;
3885 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3887 /* Pass on the (modified) configure event */
3888 configure_event->width -= window->frame_left + window->frame_right;
3889 configure_event->height -= window->frame_top + window->frame_bottom;
3890 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3899 gtk_window_configure_event (GtkWidget *widget,
3900 GdkEventConfigure *event)
3902 GtkWindow *window = GTK_WINDOW (widget);
3903 gboolean expected_reply = window->configure_request_count > 0;
3905 /* window->configure_request_count incremented for each
3906 * configure request, and decremented to a min of 0 for
3907 * each configure notify.
3909 * All it means is that we know we will get at least
3910 * window->configure_request_count more configure notifies.
3911 * We could get more configure notifies than that; some
3912 * of the configure notifies we get may be unrelated to
3913 * the configure requests. But we will get at least
3914 * window->configure_request_count notifies.
3917 if (window->configure_request_count > 0)
3918 window->configure_request_count -= 1;
3920 /* As an optimization, we avoid a resize when possible.
3922 * The only times we can avoid a resize are:
3923 * - we know only the position changed, not the size
3924 * - we know we have made more requests and so will get more
3925 * notifies and can wait to resize when we get them
3928 if (!expected_reply &&
3929 (widget->allocation.width == event->width &&
3930 widget->allocation.height == event->height))
3934 * If we do need to resize, we do that by:
3935 * - filling in widget->allocation with the new size
3936 * - setting configure_notify_received to TRUE
3937 * for use in gtk_window_move_resize()
3938 * - queueing a resize, leading to invocation of
3939 * gtk_window_move_resize() in an idle handler
3943 window->configure_notify_received = TRUE;
3945 widget->allocation.width = event->width;
3946 widget->allocation.height = event->height;
3948 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3953 /* the accel_key and accel_mods fields of the key have to be setup
3954 * upon calling this function. it'll then return whether that key
3955 * is at all used as accelerator, and if so will OR in the
3956 * accel_flags member of the key.
3959 _gtk_window_query_nonaccels (GtkWindow *window,
3961 GdkModifierType accel_mods)
3963 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3965 /* movement keys are considered locked accels */
3968 static const guint bindings[] = {
3969 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
3970 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
3974 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
3975 if (bindings[i] == accel_key)
3979 /* mnemonics are considered locked accels */
3980 if (accel_mods == window->mnemonic_modifier)
3982 GtkWindowMnemonic mkey;
3984 mkey.window = window;
3985 mkey.keyval = accel_key;
3986 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
3994 gtk_window_key_press_event (GtkWidget *widget,
4001 window = GTK_WINDOW (widget);
4005 /* Check for mnemonics and accelerators
4008 handled = _gtk_window_activate_key (window, event);
4012 focus = window->focus_widget;
4014 g_object_ref (focus);
4017 focus && focus != widget &&
4018 gtk_widget_get_toplevel (focus) == widget)
4022 if (GTK_WIDGET_IS_SENSITIVE (focus))
4023 handled = gtk_widget_event (focus, (GdkEvent*) event);
4025 parent = focus->parent;
4027 g_object_ref (parent);
4029 g_object_unref (focus);
4035 g_object_unref (focus);
4038 /* Chain up, invokes binding set */
4039 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
4040 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4046 gtk_window_key_release_event (GtkWidget *widget,
4052 window = GTK_WINDOW (widget);
4054 if (window->focus_widget &&
4055 window->focus_widget != widget &&
4056 GTK_WIDGET_SENSITIVE (window->focus_widget))
4058 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
4061 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
4062 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
4068 gtk_window_real_activate_default (GtkWindow *window)
4070 gtk_window_activate_default (window);
4074 gtk_window_real_activate_focus (GtkWindow *window)
4076 gtk_window_activate_focus (window);
4080 gtk_window_move_focus (GtkWindow *window,
4081 GtkDirectionType dir)
4083 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4085 if (!GTK_CONTAINER (window)->focus_child)
4086 gtk_window_set_focus (window, NULL);
4090 gtk_window_enter_notify_event (GtkWidget *widget,
4091 GdkEventCrossing *event)
4097 gtk_window_leave_notify_event (GtkWidget *widget,
4098 GdkEventCrossing *event)
4104 do_focus_change (GtkWidget *widget,
4107 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4109 g_object_ref (widget);
4112 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4114 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4116 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4117 fevent->focus_change.window = g_object_ref (widget->window);
4118 fevent->focus_change.in = in;
4120 gtk_widget_event (widget, fevent);
4122 g_object_notify (G_OBJECT (widget), "has_focus");
4124 g_object_unref (widget);
4125 gdk_event_free (fevent);
4129 gtk_window_focus_in_event (GtkWidget *widget,
4130 GdkEventFocus *event)
4132 GtkWindow *window = GTK_WINDOW (widget);
4134 /* It appears spurious focus in events can occur when
4135 * the window is hidden. So we'll just check to see if
4136 * the window is visible before actually handling the
4139 if (GTK_WIDGET_VISIBLE (widget))
4141 _gtk_window_set_has_toplevel_focus (window, TRUE);
4142 _gtk_window_set_is_active (window, TRUE);
4149 gtk_window_focus_out_event (GtkWidget *widget,
4150 GdkEventFocus *event)
4152 GtkWindow *window = GTK_WINDOW (widget);
4154 _gtk_window_set_has_toplevel_focus (window, FALSE);
4155 _gtk_window_set_is_active (window, FALSE);
4160 static GdkAtom atom_rcfiles = GDK_NONE;
4163 gtk_window_read_rcfiles (GtkWidget *widget,
4164 GdkEventClient *event)
4166 GList *embedded_windows;
4168 embedded_windows = g_object_get_data (G_OBJECT (widget), "gtk-embedded");
4169 if (embedded_windows)
4171 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4174 for (i = 0; i < 5; i++)
4175 send_event->client.data.l[i] = 0;
4176 send_event->client.data_format = 32;
4177 send_event->client.message_type = atom_rcfiles;
4179 while (embedded_windows)
4181 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4182 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4183 embedded_windows = embedded_windows->next;
4186 gdk_event_free (send_event);
4189 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4193 gtk_window_client_event (GtkWidget *widget,
4194 GdkEventClient *event)
4197 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
4199 if (event->message_type == atom_rcfiles)
4200 gtk_window_read_rcfiles (widget, event);
4206 gtk_window_check_resize (GtkContainer *container)
4208 GtkWindow *window = GTK_WINDOW (container);
4210 if (GTK_WIDGET_VISIBLE (container))
4211 gtk_window_move_resize (window);
4215 gtk_window_focus (GtkWidget *widget,
4216 GtkDirectionType direction)
4220 GtkContainer *container;
4221 GtkWidget *old_focus_child;
4224 container = GTK_CONTAINER (widget);
4225 window = GTK_WINDOW (widget);
4226 bin = GTK_BIN (widget);
4228 old_focus_child = container->focus_child;
4230 /* We need a special implementation here to deal properly with wrapping
4231 * around in the tab chain without the danger of going into an
4234 if (old_focus_child)
4236 if (gtk_widget_child_focus (old_focus_child, direction))
4240 if (window->focus_widget)
4242 /* Wrapped off the end, clear the focus setting for the toplpevel */
4243 parent = window->focus_widget->parent;
4246 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4247 parent = GTK_WIDGET (parent)->parent;
4250 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4253 /* Now try to focus the first widget in the window */
4256 if (gtk_widget_child_focus (bin->child, direction))
4264 gtk_window_real_set_focus (GtkWindow *window,
4267 GtkWidget *old_focus = window->focus_widget;
4268 gboolean def_flags = 0;
4272 g_object_ref (old_focus);
4273 g_object_freeze_notify (G_OBJECT (old_focus));
4277 g_object_ref (focus);
4278 g_object_freeze_notify (G_OBJECT (focus));
4281 if (window->default_widget)
4282 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4284 if (window->focus_widget)
4286 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4287 (window->focus_widget != window->default_widget))
4289 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4291 if (window->default_widget)
4292 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4295 if (window->has_focus)
4296 do_focus_change (window->focus_widget, FALSE);
4298 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4301 window->focus_widget = focus;
4303 if (window->focus_widget)
4305 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4306 (window->focus_widget != window->default_widget))
4308 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4309 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4311 if (window->default_widget)
4312 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4315 if (window->has_focus)
4316 do_focus_change (window->focus_widget, TRUE);
4318 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4321 if (window->default_widget &&
4322 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
4323 gtk_widget_queue_draw (window->default_widget);
4327 g_object_thaw_notify (G_OBJECT (old_focus));
4328 g_object_unref (old_focus);
4332 g_object_thaw_notify (G_OBJECT (focus));
4333 g_object_unref (focus);
4337 /*********************************
4338 * Functions related to resizing *
4339 *********************************/
4341 /* This function doesn't constrain to geometry hints */
4343 gtk_window_compute_configure_request_size (GtkWindow *window,
4347 GtkRequisition requisition;
4348 GtkWindowGeometryInfo *info;
4352 * - we've done a size request
4355 widget = GTK_WIDGET (window);
4357 info = gtk_window_get_geometry_info (window, FALSE);
4359 if (window->need_default_size)
4361 gtk_widget_get_child_requisition (widget, &requisition);
4363 /* Default to requisition */
4364 *width = requisition.width;
4365 *height = requisition.height;
4367 /* If window is empty so requests 0, default to random nonzero size */
4368 if (*width == 0 && *height == 0)
4374 /* Override requisition with default size */
4378 gint base_width = 0;
4379 gint base_height = 0;
4381 gint height_inc = 1;
4383 if (info->default_is_geometry &&
4384 (info->default_width > 0 || info->default_height > 0))
4386 GdkGeometry geometry;
4389 gtk_window_compute_hints (window, &geometry, &flags);
4391 if (flags & GDK_HINT_BASE_SIZE)
4393 base_width = geometry.base_width;
4394 base_height = geometry.base_height;
4396 else if (flags & GDK_HINT_MIN_SIZE)
4398 base_width = geometry.min_width;
4399 base_height = geometry.min_height;
4401 if (flags & GDK_HINT_RESIZE_INC)
4403 width_inc = geometry.width_inc;
4404 height_inc = geometry.height_inc;
4408 if (info->default_width > 0)
4409 *width = info->default_width * width_inc + base_width;
4411 if (info->default_height > 0)
4412 *height = info->default_height * height_inc + base_height;
4417 /* Default to keeping current size */
4418 *width = widget->allocation.width;
4419 *height = widget->allocation.height;
4422 /* Override any size with gtk_window_resize() values */
4425 if (info->resize_width > 0)
4426 *width = info->resize_width;
4428 if (info->resize_height > 0)
4429 *height = info->resize_height;
4433 static GtkWindowPosition
4434 get_effective_position (GtkWindow *window)
4436 GtkWindowPosition pos = window->position;
4437 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
4438 (window->transient_parent == NULL ||
4439 !GTK_WIDGET_MAPPED (window->transient_parent)))
4440 pos = GTK_WIN_POS_NONE;
4446 get_center_monitor_of_window (GtkWindow *window)
4448 /* We could try to sort out the relative positions of the monitors and
4449 * stuff, or we could just be losers and assume you have a row
4450 * or column of monitors.
4452 return gdk_screen_get_n_monitors (window->screen) / 2;
4456 get_monitor_containing_pointer (GtkWindow *window)
4460 GdkScreen *pointer_screen;
4462 gdk_display_get_pointer (gdk_screen_get_display (window->screen),
4466 if (pointer_screen == window->screen)
4467 monitor_num = gdk_screen_get_monitor_at_point (window->screen, px, py);
4475 center_window_on_monitor (GtkWindow *window,
4481 GdkRectangle monitor;
4484 monitor_num = get_monitor_containing_pointer (window);
4486 if (monitor_num == -1)
4487 monitor_num = get_center_monitor_of_window (window);
4489 gdk_screen_get_monitor_geometry (window->screen, monitor_num, &monitor);
4491 *x = (monitor.width - w) / 2 + monitor.x;
4492 *y = (monitor.height - h) / 2 + monitor.y;
4494 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
4495 * and WM decorations.
4504 clamp_window_to_rectangle (gint *x,
4508 const GdkRectangle *rect)
4510 gint outside_w, outside_h;
4512 outside_w = (*x + w) - (rect->x + rect->width);
4516 outside_h = (*y + h) - (rect->y + rect->height);
4520 /* if larger than the screen, center on the screen. */
4522 *x += (rect->x - *x) / 2;
4524 *y += (rect->y - *y) / 2;
4529 gtk_window_compute_configure_request (GtkWindow *window,
4530 GdkRectangle *request,
4531 GdkGeometry *geometry,
4534 GdkGeometry new_geometry;
4538 GtkWindowPosition pos;
4539 GtkWidget *parent_widget;
4540 GtkWindowGeometryInfo *info;
4543 widget = GTK_WIDGET (window);
4545 gtk_widget_size_request (widget, NULL);
4546 gtk_window_compute_configure_request_size (window, &w, &h);
4548 gtk_window_compute_hints (window, &new_geometry, &new_flags);
4549 gtk_window_constrain_size (window,
4550 &new_geometry, new_flags,
4554 parent_widget = (GtkWidget*) window->transient_parent;
4556 pos = get_effective_position (window);
4557 info = gtk_window_get_geometry_info (window, TRUE);
4559 /* by default, don't change position requested */
4560 x = info->last.configure_request.x;
4561 y = info->last.configure_request.y;
4563 if (window->need_default_position)
4566 /* FIXME this all interrelates with window gravity.
4567 * For most of them I think we want to set GRAVITY_CENTER.
4569 * Not sure how to go about that.
4574 /* here we are only handling CENTER_ALWAYS
4575 * as it relates to default positioning,
4576 * where it's equivalent to simply CENTER
4578 case GTK_WIN_POS_CENTER_ALWAYS:
4579 case GTK_WIN_POS_CENTER:
4580 center_window_on_monitor (window, w, h, &x, &y);
4583 case GTK_WIN_POS_CENTER_ON_PARENT:
4586 GdkRectangle monitor;
4589 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
4591 if (parent_widget->window != NULL)
4592 monitor_num = gdk_screen_get_monitor_at_window (window->screen,
4593 parent_widget->window);
4597 gdk_window_get_origin (parent_widget->window,
4600 x = ox + (parent_widget->allocation.width - w) / 2;
4601 y = oy + (parent_widget->allocation.height - h) / 2;
4603 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4604 * WM decorations. If parent wasn't on a monitor, just
4607 if (monitor_num >= 0)
4609 gdk_screen_get_monitor_geometry (window->screen, monitor_num, &monitor);
4610 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4615 case GTK_WIN_POS_MOUSE:
4617 gint screen_width = gdk_screen_get_width (window->screen);
4618 gint screen_height = gdk_screen_get_height (window->screen);
4620 GdkRectangle monitor;
4621 GdkScreen *pointer_screen;
4624 gdk_display_get_pointer (gdk_screen_get_display (window->screen),
4628 if (pointer_screen == window->screen)
4629 monitor_num = gdk_screen_get_monitor_at_point (window->screen, px, py);
4635 x = CLAMP (x, 0, screen_width - w);
4636 y = CLAMP (y, 0, screen_height - h);
4638 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4639 * WM decorations. Don't try to figure out what's going
4640 * on if the mouse wasn't inside a monitor.
4642 if (monitor_num >= 0)
4644 gdk_screen_get_monitor_geometry (window->screen, monitor_num, &monitor);
4645 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4653 } /* if (window->need_default_position) */
4655 if (window->need_default_position &&
4656 info->initial_pos_set)
4658 x = info->initial_x;
4659 y = info->initial_y;
4660 gtk_window_constrain_position (window, w, h, &x, &y);
4666 request->height = h;
4669 *geometry = new_geometry;
4675 gtk_window_constrain_position (GtkWindow *window,
4681 /* See long comments in gtk_window_move_resize()
4682 * on when it's safe to call this function.
4684 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4686 gint center_x, center_y;
4688 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
4696 gtk_window_move_resize (GtkWindow *window)
4700 * First we determine whether any information has changed that would
4701 * cause us to revise our last configure request. If we would send
4702 * a different configure request from last time, then
4703 * configure_request_size_changed = TRUE or
4704 * configure_request_pos_changed = TRUE. configure_request_size_changed
4705 * may be true due to new hints, a gtk_window_resize(), or whatever.
4706 * configure_request_pos_changed may be true due to gtk_window_set_position()
4707 * or gtk_window_move().
4709 * If the configure request has changed, we send off a new one. To
4710 * ensure GTK+ invariants are maintained (resize queue does what it
4711 * should), we go ahead and size_allocate the requested size in this
4714 * If the configure request has not changed, we don't ever resend
4715 * it, because it could mean fighting the user or window manager.
4718 * To prepare the configure request, we come up with a base size/pos:
4719 * - the one from gtk_window_move()/gtk_window_resize()
4720 * - else default_width, default_height if we haven't ever
4722 * - else the size request if we haven't ever been mapped,
4723 * as a substitute default size
4724 * - else the current size of the window, as received from
4725 * configure notifies (i.e. the current allocation)
4727 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4728 * the position request to be centered.
4731 GtkContainer *container;
4732 GtkWindowGeometryInfo *info;
4733 GdkGeometry new_geometry;
4735 GdkRectangle new_request;
4736 gboolean configure_request_size_changed;
4737 gboolean configure_request_pos_changed;
4738 gboolean hints_changed; /* do we need to send these again */
4739 GtkWindowLastGeometryInfo saved_last_info;
4741 widget = GTK_WIDGET (window);
4742 container = GTK_CONTAINER (widget);
4743 info = gtk_window_get_geometry_info (window, TRUE);
4745 configure_request_size_changed = FALSE;
4746 configure_request_pos_changed = FALSE;
4748 gtk_window_compute_configure_request (window, &new_request,
4749 &new_geometry, &new_flags);
4751 /* This check implies the invariant that we never set info->last
4752 * without setting the hints and sending off a configure request.
4754 * If we change info->last without sending the request, we may
4757 if (info->last.configure_request.x != new_request.x ||
4758 info->last.configure_request.y != new_request.y)
4759 configure_request_pos_changed = TRUE;
4761 if ((info->last.configure_request.width != new_request.width ||
4762 info->last.configure_request.height != new_request.height))
4763 configure_request_size_changed = TRUE;
4765 hints_changed = FALSE;
4767 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4768 &new_geometry, new_flags))
4770 hints_changed = TRUE;
4773 /* Position Constraints
4774 * ====================
4776 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4777 * a default. The other POS_ values are used only when the
4778 * window is shown, not after that.
4780 * However, we can't implement a position constraint as
4781 * "anytime the window size changes, center the window"
4782 * because this may well end up fighting the WM or user. In
4783 * fact it gets in an infinite loop with at least one WM.
4785 * Basically, applications are in no way in a position to
4786 * constrain the position of a window, with one exception:
4787 * override redirect windows. (Really the intended purpose
4788 * of CENTER_ALWAYS anyhow, I would think.)
4790 * So the way we implement this "constraint" is to say that when WE
4791 * cause a move or resize, i.e. we make a configure request changing
4792 * window size, we recompute the CENTER_ALWAYS position to reflect
4793 * the new window size, and include it in our request. Also, if we
4794 * just turned on CENTER_ALWAYS we snap to center with a new
4795 * request. Otherwise, if we are just NOTIFIED of a move or resize
4796 * done by someone else e.g. the window manager, we do NOT send a
4797 * new configure request.
4799 * For override redirect windows, this works fine; all window
4800 * sizes are from our configure requests. For managed windows,
4801 * it is at least semi-sane, though who knows what the
4802 * app author is thinking.
4805 /* This condition should be kept in sync with the condition later on
4806 * that determines whether we send a configure request. i.e. we
4807 * should do this position constraining anytime we were going to
4808 * send a configure request anyhow, plus when constraints have
4811 if (configure_request_pos_changed ||
4812 configure_request_size_changed ||
4814 info->position_constraints_changed)
4816 /* We request the constrained position if:
4817 * - we were changing position, and need to clamp
4818 * the change to the constraint
4819 * - we're changing the size anyway
4820 * - set_position() was called to toggle CENTER_ALWAYS on
4823 gtk_window_constrain_position (window,
4829 /* Update whether we need to request a move */
4830 if (info->last.configure_request.x != new_request.x ||
4831 info->last.configure_request.y != new_request.y)
4832 configure_request_pos_changed = TRUE;
4834 configure_request_pos_changed = FALSE;
4838 if (window->type == GTK_WINDOW_TOPLEVEL)
4840 int notify_x, notify_y;
4842 /* this is the position from the last configure notify */
4843 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4845 g_message ("--- %s ---\n"
4846 "last : %d,%d\t%d x %d\n"
4847 "this : %d,%d\t%d x %d\n"
4848 "alloc : %d,%d\t%d x %d\n"
4850 "resize: \t%d x %d\n"
4851 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4852 "configure_notify_received: %d\n"
4853 "configure_request_count: %d\n"
4854 "position_constraints_changed: %d\n",
4855 window->title ? window->title : "(no title)",
4856 info->last.configure_request.x,
4857 info->last.configure_request.y,
4858 info->last.configure_request.width,
4859 info->last.configure_request.height,
4865 widget->allocation.width,
4866 widget->allocation.height,
4867 widget->requisition.width,
4868 widget->requisition.height,
4870 info->resize_height,
4871 configure_request_pos_changed,
4872 configure_request_size_changed,
4874 window->configure_notify_received,
4875 window->configure_request_count,
4876 info->position_constraints_changed);
4880 saved_last_info = info->last;
4881 info->last.geometry = new_geometry;
4882 info->last.flags = new_flags;
4883 info->last.configure_request = new_request;
4885 /* need to set PPosition so the WM will look at our position,
4886 * but we don't want to count PPosition coming and going as a hints
4887 * change for future iterations. So we saved info->last prior to
4891 /* Also, if the initial position was explicitly set, then we always
4892 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4896 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4897 * this is an initial map
4900 if ((configure_request_pos_changed ||
4901 info->initial_pos_set ||
4902 (window->need_default_position &&
4903 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
4904 (new_flags & GDK_HINT_POS) == 0)
4906 new_flags |= GDK_HINT_POS;
4907 hints_changed = TRUE;
4910 /* Set hints if necessary
4913 gdk_window_set_geometry_hints (widget->window,
4917 /* handle resizing/moving and widget tree allocation
4919 if (window->configure_notify_received)
4921 GtkAllocation allocation;
4923 /* If we have received a configure event since
4924 * the last time in this function, we need to
4925 * accept our new size and size_allocate child widgets.
4926 * (see gtk_window_configure_event() for more details).
4928 * 1 or more configure notifies may have been received.
4929 * Also, configure_notify_received will only be TRUE
4930 * if all expected configure notifies have been received
4931 * (one per configure request), as an optimization.
4934 window->configure_notify_received = FALSE;
4936 /* gtk_window_configure_event() filled in widget->allocation */
4937 allocation = widget->allocation;
4938 gtk_widget_size_allocate (widget, &allocation);
4940 /* If the configure request changed, it means that
4942 * 1) coincidentally changed hints or widget properties
4943 * impacting the configure request before getting
4944 * a configure notify, or
4945 * 2) some broken widget is changing its size request
4946 * during size allocation, resulting in
4947 * a false appearance of changed configure request.
4949 * For 1), we could just go ahead and ask for the
4950 * new size right now, but doing that for 2)
4951 * might well be fighting the user (and can even
4952 * trigger a loop). Since we really don't want to
4953 * do that, we requeue a resize in hopes that
4954 * by the time it gets handled, the child has seen
4955 * the light and is willing to go along with the
4956 * new size. (this happens for the zvt widget, since
4957 * the size_allocate() above will have stored the
4958 * requisition corresponding to the new size in the
4961 * This doesn't buy us anything for 1), but it shouldn't
4962 * hurt us too badly, since it is what would have
4963 * happened if we had gotten the configure event before
4964 * the new size had been set.
4967 if (configure_request_size_changed ||
4968 configure_request_pos_changed)
4970 /* Don't change the recorded last info after all, because we
4971 * haven't actually updated to the new info yet - we decided
4972 * to postpone our configure request until later.
4974 info->last = saved_last_info;
4976 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
4979 return; /* Bail out, we didn't really process the move/resize */
4981 else if ((configure_request_size_changed || hints_changed) &&
4982 (widget->allocation.width != new_request.width ||
4983 widget->allocation.height != new_request.height))
4986 /* We are in one of the following situations:
4987 * A. configure_request_size_changed
4988 * our requisition has changed and we need a different window size,
4989 * so we request it from the window manager.
4990 * B. !configure_request_size_changed && hints_changed
4991 * the window manager rejects our size, but we have just changed the
4992 * window manager hints, so there's a chance our request will
4993 * be honoured this time, so we try again.
4995 * However, if the new requisition is the same as the current allocation,
4996 * we don't request it again, since we won't get a ConfigureNotify back from
4997 * the window manager unless it decides to change our requisition. If
4998 * we don't get the ConfigureNotify back, the resize queue will never be run.
5001 /* Now send the configure request */
5002 if (configure_request_pos_changed)
5006 gdk_window_move_resize (window->frame,
5007 new_request.x - window->frame_left,
5008 new_request.y - window->frame_top,
5009 new_request.width + window->frame_left + window->frame_right,
5010 new_request.height + window->frame_top + window->frame_bottom);
5011 gdk_window_resize (widget->window,
5012 new_request.width, new_request.height);
5016 gdk_window_move_resize (widget->window,
5017 new_request.x, new_request.y,
5018 new_request.width, new_request.height);
5020 else /* only size changed */
5023 gdk_window_resize (window->frame,
5024 new_request.width + window->frame_left + window->frame_right,
5025 new_request.height + window->frame_top + window->frame_bottom);
5027 gdk_window_resize (widget->window,
5028 new_request.width, new_request.height);
5031 /* Increment the number of have-not-yet-received-notify requests */
5032 window->configure_request_count += 1;
5034 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5035 * configure event in response to our resizing request.
5036 * the configure event will cause a new resize with
5037 * ->configure_notify_received=TRUE.
5038 * until then, we want to
5039 * - discard expose events
5040 * - coalesce resizes for our children
5041 * - defer any window resizes until the configure event arrived
5042 * to achieve this, we queue a resize for the window, but remove its
5043 * resizing handler, so resizing will not be handled from the next
5044 * idle handler but when the configure event arrives.
5046 * FIXME: we should also dequeue the pending redraws here, since
5047 * we handle those ourselves upon ->configure_notify_received==TRUE.
5049 if (container->resize_mode == GTK_RESIZE_QUEUE)
5051 gtk_widget_queue_resize (widget);
5052 _gtk_container_dequeue_resize_handler (container);
5057 /* Handle any position changes.
5059 if (configure_request_pos_changed)
5063 gdk_window_move (window->frame,
5064 new_request.x - window->frame_left,
5065 new_request.y - window->frame_top);
5068 gdk_window_move (widget->window,
5069 new_request.x, new_request.y);
5072 /* And run the resize queue.
5074 gtk_container_resize_children (container);
5077 /* We have now processed a move/resize since the last position
5078 * constraint change, setting of the initial position, or resize.
5079 * (Not resetting these flags here can lead to infinite loops for
5080 * GTK_RESIZE_IMMEDIATE containers)
5082 info->position_constraints_changed = FALSE;
5083 info->initial_pos_set = FALSE;
5084 info->resize_width = -1;
5085 info->resize_height = -1;
5088 /* Compare two sets of Geometry hints for equality.
5091 gtk_window_compare_hints (GdkGeometry *geometry_a,
5093 GdkGeometry *geometry_b,
5096 if (flags_a != flags_b)
5099 if ((flags_a & GDK_HINT_MIN_SIZE) &&
5100 (geometry_a->min_width != geometry_b->min_width ||
5101 geometry_a->min_height != geometry_b->min_height))
5104 if ((flags_a & GDK_HINT_MAX_SIZE) &&
5105 (geometry_a->max_width != geometry_b->max_width ||
5106 geometry_a->max_height != geometry_b->max_height))
5109 if ((flags_a & GDK_HINT_BASE_SIZE) &&
5110 (geometry_a->base_width != geometry_b->base_width ||
5111 geometry_a->base_height != geometry_b->base_height))
5114 if ((flags_a & GDK_HINT_ASPECT) &&
5115 (geometry_a->min_aspect != geometry_b->min_aspect ||
5116 geometry_a->max_aspect != geometry_b->max_aspect))
5119 if ((flags_a & GDK_HINT_RESIZE_INC) &&
5120 (geometry_a->width_inc != geometry_b->width_inc ||
5121 geometry_a->height_inc != geometry_b->height_inc))
5124 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5125 geometry_a->win_gravity != geometry_b->win_gravity)
5132 _gtk_window_constrain_size (GtkWindow *window,
5138 GtkWindowGeometryInfo *info;
5140 g_return_if_fail (GTK_IS_WINDOW (window));
5142 info = window->geometry_info;
5145 GdkWindowHints flags = info->last.flags;
5146 GdkGeometry *geometry = &info->last.geometry;
5148 gtk_window_constrain_size (window,
5159 gtk_window_constrain_size (GtkWindow *window,
5160 GdkGeometry *geometry,
5167 gdk_window_constrain_size (geometry, flags, width, height,
5168 new_width, new_height);
5171 /* Compute the set of geometry hints and flags for a window
5172 * based on the application set geometry, and requisiition
5173 * of the window. gtk_widget_size_request() must have been
5177 gtk_window_compute_hints (GtkWindow *window,
5178 GdkGeometry *new_geometry,
5182 gint extra_width = 0;
5183 gint extra_height = 0;
5184 GtkWindowGeometryInfo *geometry_info;
5185 GtkRequisition requisition;
5187 widget = GTK_WIDGET (window);
5189 gtk_widget_get_child_requisition (widget, &requisition);
5190 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5194 *new_flags = geometry_info->mask;
5195 *new_geometry = geometry_info->geometry;
5202 if (geometry_info && geometry_info->widget)
5204 GtkRequisition child_requisition;
5206 /* FIXME: This really isn't right. It gets the min size wrong and forces
5207 * callers to do horrible hacks like set a huge usize on the child requisition
5208 * to get the base size right. We really want to find the answers to:
5210 * - If the geometry widget was infinitely big, how much extra space
5211 * would be needed for the stuff around it.
5213 * - If the geometry widget was infinitely small, how big would the
5214 * window still have to be.
5216 * Finding these answers would be a bit of a mess here. (Bug #68668)
5218 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5220 extra_width = widget->requisition.width - child_requisition.width;
5221 extra_height = widget->requisition.height - child_requisition.height;
5224 /* We don't want to set GDK_HINT_POS in here, we just set it
5225 * in gtk_window_move_resize() when we want the position
5229 if (*new_flags & GDK_HINT_BASE_SIZE)
5231 new_geometry->base_width += extra_width;
5232 new_geometry->base_height += extra_height;
5234 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5235 (*new_flags & GDK_HINT_RESIZE_INC) &&
5236 ((extra_width != 0) || (extra_height != 0)))
5238 *new_flags |= GDK_HINT_BASE_SIZE;
5240 new_geometry->base_width = extra_width;
5241 new_geometry->base_height = extra_height;
5244 if (*new_flags & GDK_HINT_MIN_SIZE)
5246 if (new_geometry->min_width < 0)
5247 new_geometry->min_width = requisition.width;
5249 new_geometry->min_width += extra_width;
5251 if (new_geometry->min_height < 0)
5252 new_geometry->min_height = requisition.height;
5254 new_geometry->min_height += extra_height;
5256 else if (!window->allow_shrink)
5258 *new_flags |= GDK_HINT_MIN_SIZE;
5260 new_geometry->min_width = requisition.width;
5261 new_geometry->min_height = requisition.height;
5264 if (*new_flags & GDK_HINT_MAX_SIZE)
5266 if (new_geometry->max_width < 0)
5267 new_geometry->max_width = requisition.width;
5269 new_geometry->max_width += extra_width;
5271 if (new_geometry->max_height < 0)
5272 new_geometry->max_width = requisition.height;
5274 new_geometry->max_height += extra_height;
5276 else if (!window->allow_grow)
5278 *new_flags |= GDK_HINT_MAX_SIZE;
5280 new_geometry->max_width = requisition.width;
5281 new_geometry->max_height = requisition.height;
5284 *new_flags |= GDK_HINT_WIN_GRAVITY;
5285 new_geometry->win_gravity = window->gravity;
5288 /***********************
5289 * Redrawing functions *
5290 ***********************/
5293 gtk_window_paint (GtkWidget *widget,
5296 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
5297 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
5301 gtk_window_expose (GtkWidget *widget,
5302 GdkEventExpose *event)
5304 if (!GTK_WIDGET_APP_PAINTABLE (widget))
5305 gtk_window_paint (widget, &event->area);
5307 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
5308 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
5314 * gtk_window_set_has_frame:
5315 * @window: a #GtkWindow
5316 * @setting: a boolean
5318 * (Note: this is a special-purpose function for the framebuffer port,
5319 * that causes GTK+ to draw its own window border. For most applications,
5320 * you want gtk_window_set_decorated() instead, which tells the window
5321 * manager whether to draw the window border.)
5323 * If this function is called on a window with setting of %TRUE, before
5324 * it is realized or showed, it will have a "frame" window around
5325 * @window->window, accessible in @window->frame. Using the signal
5326 * frame_event you can recieve all events targeted at the frame.
5328 * This function is used by the linux-fb port to implement managed
5329 * windows, but it could concievably be used by X-programs that
5330 * want to do their own window decorations.
5334 gtk_window_set_has_frame (GtkWindow *window,
5337 g_return_if_fail (GTK_IS_WINDOW (window));
5338 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
5340 window->has_frame = setting != FALSE;
5344 * gtk_window_get_has_frame:
5345 * @window: a #GtkWindow
5347 * Accessor for whether the window has a frame window exterior to
5348 * @window->window. Gets the value set by gtk_window_set_has_frame ().
5350 * Return value: %TRUE if a frame has been added to the window
5351 * via gtk_window_set_has_frame().
5354 gtk_window_get_has_frame (GtkWindow *window)
5356 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5358 return window->has_frame;
5362 * gtk_window_set_frame_dimensions:
5363 * @window: a #GtkWindow that has a frame
5364 * @left: The width of the left border
5365 * @top: The height of the top border
5366 * @right: The width of the right border
5367 * @bottom: The height of the bottom border
5369 * (Note: this is a special-purpose function intended for the framebuffer
5370 * port; see gtk_window_set_has_frame(). It will have no effect on the
5371 * window border drawn by the window manager, which is the normal
5372 * case when using the X Window system.)
5374 * For windows with frames (see gtk_window_set_has_frame()) this function
5375 * can be used to change the size of the frame border.
5378 gtk_window_set_frame_dimensions (GtkWindow *window,
5386 g_return_if_fail (GTK_IS_WINDOW (window));
5388 widget = GTK_WIDGET (window);
5390 if (window->frame_left == left &&
5391 window->frame_top == top &&
5392 window->frame_right == right &&
5393 window->frame_bottom == bottom)
5396 window->frame_left = left;
5397 window->frame_top = top;
5398 window->frame_right = right;
5399 window->frame_bottom = bottom;
5401 if (GTK_WIDGET_REALIZED (widget) && window->frame)
5403 gint width = widget->allocation.width + left + right;
5404 gint height = widget->allocation.height + top + bottom;
5405 gdk_window_resize (window->frame, width, height);
5406 gtk_decorated_window_move_resize_window (window,
5408 widget->allocation.width,
5409 widget->allocation.height);
5414 * gtk_window_present:
5415 * @window: a #GtkWindow
5417 * Presents a window to the user. This may mean raising the window
5418 * in the stacking order, deiconifying it, moving it to the current
5419 * desktop, and/or giving it the keyboard focus, possibly dependent
5420 * on the user's platform, window manager, and preferences.
5422 * If @window is hidden, this function calls gtk_widget_show()
5425 * This function should be used when the user tries to open a window
5426 * that's already open. Say for example the preferences dialog is
5427 * currently open, and the user chooses Preferences from the menu
5428 * a second time; use gtk_window_present() to move the already-open dialog
5429 * where the user can see it.
5433 gtk_window_present (GtkWindow *window)
5437 g_return_if_fail (GTK_IS_WINDOW (window));
5439 widget = GTK_WIDGET (window);
5441 if (GTK_WIDGET_VISIBLE (window))
5443 g_assert (widget->window != NULL);
5445 gdk_window_show (widget->window);
5447 /* note that gdk_window_focus() will also move the window to
5448 * the current desktop, for WM spec compliant window managers.
5450 gdk_window_focus (widget->window,
5451 gtk_get_current_event_time ());
5455 gtk_widget_show (widget);
5460 * gtk_window_iconify:
5461 * @window: a #GtkWindow
5463 * Asks to iconify (i.e. minimize) the specified @window. Note that
5464 * you shouldn't assume the window is definitely iconified afterward,
5465 * because other entities (e.g. the user or <link
5466 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
5467 * again, or there may not be a window manager in which case
5468 * iconification isn't possible, etc. But normally the window will end
5469 * up iconified. Just don't write code that crashes if not.
5471 * It's permitted to call this function before showing a window,
5472 * in which case the window will be iconified before it ever appears
5475 * You can track iconification via the "window_state_event" signal
5480 gtk_window_iconify (GtkWindow *window)
5483 GdkWindow *toplevel;
5485 g_return_if_fail (GTK_IS_WINDOW (window));
5487 widget = GTK_WIDGET (window);
5489 window->iconify_initially = TRUE;
5492 toplevel = window->frame;
5494 toplevel = widget->window;
5496 if (toplevel != NULL)
5497 gdk_window_iconify (toplevel);
5501 * gtk_window_deiconify:
5502 * @window: a #GtkWindow
5504 * Asks to deiconify (i.e. unminimize) the specified @window. Note
5505 * that you shouldn't assume the window is definitely deiconified
5506 * afterward, because other entities (e.g. the user or <link
5507 * linkend="gtk-X11-arch">window manager</link>) could iconify it
5508 * again before your code which assumes deiconification gets to run.
5510 * You can track iconification via the "window_state_event" signal
5514 gtk_window_deiconify (GtkWindow *window)
5517 GdkWindow *toplevel;
5519 g_return_if_fail (GTK_IS_WINDOW (window));
5521 widget = GTK_WIDGET (window);
5523 window->iconify_initially = FALSE;
5526 toplevel = window->frame;
5528 toplevel = widget->window;
5530 if (toplevel != NULL)
5531 gdk_window_deiconify (toplevel);
5536 * @window: a #GtkWindow
5538 * Asks to stick @window, which means that it will appear on all user
5539 * desktops. Note that you shouldn't assume the window is definitely
5540 * stuck afterward, because other entities (e.g. the user or <link
5541 * linkend="gtk-X11-arch">window manager</link>) could unstick it
5542 * again, and some window managers do not support sticking
5543 * windows. But normally the window will end up stuck. Just don't
5544 * write code that crashes if not.
5546 * It's permitted to call this function before showing a window.
5548 * You can track stickiness via the "window_state_event" signal
5553 gtk_window_stick (GtkWindow *window)
5556 GdkWindow *toplevel;
5558 g_return_if_fail (GTK_IS_WINDOW (window));
5560 widget = GTK_WIDGET (window);
5562 window->stick_initially = TRUE;
5565 toplevel = window->frame;
5567 toplevel = widget->window;
5569 if (toplevel != NULL)
5570 gdk_window_stick (toplevel);
5574 * gtk_window_unstick:
5575 * @window: a #GtkWindow
5577 * Asks to unstick @window, which means that it will appear on only
5578 * one of the user's desktops. Note that you shouldn't assume the
5579 * window is definitely unstuck afterward, because other entities
5580 * (e.g. the user or <link linkend="gtk-X11-arch">window
5581 * manager</link>) could stick it again. But normally the window will
5582 * end up stuck. Just don't write code that crashes if not.
5584 * You can track stickiness via the "window_state_event" signal
5589 gtk_window_unstick (GtkWindow *window)
5592 GdkWindow *toplevel;
5594 g_return_if_fail (GTK_IS_WINDOW (window));
5596 widget = GTK_WIDGET (window);
5598 window->stick_initially = FALSE;
5601 toplevel = window->frame;
5603 toplevel = widget->window;
5605 if (toplevel != NULL)
5606 gdk_window_unstick (toplevel);
5610 * gtk_window_maximize:
5611 * @window: a #GtkWindow
5613 * Asks to maximize @window, so that it becomes full-screen. Note that
5614 * you shouldn't assume the window is definitely maximized afterward,
5615 * because other entities (e.g. the user or <link
5616 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
5617 * again, and not all window managers support maximization. But
5618 * normally the window will end up maximized. Just don't write code
5619 * that crashes if not.
5621 * It's permitted to call this function before showing a window,
5622 * in which case the window will be maximized when it appears onscreen
5625 * You can track maximization via the "window_state_event" signal
5630 gtk_window_maximize (GtkWindow *window)
5633 GdkWindow *toplevel;
5635 g_return_if_fail (GTK_IS_WINDOW (window));
5637 widget = GTK_WIDGET (window);
5639 window->maximize_initially = TRUE;
5642 toplevel = window->frame;
5644 toplevel = widget->window;
5646 if (toplevel != NULL)
5647 gdk_window_maximize (toplevel);
5651 * gtk_window_unmaximize:
5652 * @window: a #GtkWindow
5654 * Asks to unmaximize @window. Note that you shouldn't assume the
5655 * window is definitely unmaximized afterward, because other entities
5656 * (e.g. the user or <link linkend="gtk-X11-arch">window
5657 * manager</link>) could maximize it again, and not all window
5658 * managers honor requests to unmaximize. But normally the window will
5659 * end up unmaximized. Just don't write code that crashes if not.
5661 * You can track maximization via the "window_state_event" signal
5666 gtk_window_unmaximize (GtkWindow *window)
5669 GdkWindow *toplevel;
5671 g_return_if_fail (GTK_IS_WINDOW (window));
5673 widget = GTK_WIDGET (window);
5675 window->maximize_initially = FALSE;
5678 toplevel = window->frame;
5680 toplevel = widget->window;
5682 if (toplevel != NULL)
5683 gdk_window_unmaximize (toplevel);
5687 * gtk_window_fullscreen:
5688 * @window: a #GtkWindow
5690 * Asks to place @window in the fullscreen state. Note that you
5691 * shouldn't assume the window is definitely full screen afterward,
5692 * because other entities (e.g. the user or <link
5693 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
5694 * again, and not all window managers honor requests to fullscreen
5695 * windows. But normally the window will end up fullscreen. Just
5696 * don't write code that crashes if not.
5698 * You can track the fullscreen state via the "window_state_event" signal
5703 gtk_window_fullscreen (GtkWindow *window)
5706 GdkWindow *toplevel;
5707 GtkWindowPrivate *priv;
5709 g_return_if_fail (GTK_IS_WINDOW (window));
5711 widget = GTK_WIDGET (window);
5712 priv = gtk_window_get_private (window);
5714 priv->fullscreen_initially = TRUE;
5717 toplevel = window->frame;
5719 toplevel = widget->window;
5721 if (toplevel != NULL)
5722 gdk_window_fullscreen (toplevel);
5726 * gtk_window_unfullscreen:
5727 * @window: a #GtkWindow
5729 * Asks to toggle off the fullscreen state for @window. Note that you
5730 * shouldn't assume the window is definitely not full screen
5731 * afterward, because other entities (e.g. the user or <link
5732 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
5733 * again, and not all window managers honor requests to unfullscreen
5734 * windows. But normally the window will end up restored to its normal
5735 * state. Just don't write code that crashes if not.
5737 * You can track the fullscreen state via the "window_state_event" signal
5742 gtk_window_unfullscreen (GtkWindow *window)
5745 GdkWindow *toplevel;
5746 GtkWindowPrivate *priv;
5748 g_return_if_fail (GTK_IS_WINDOW (window));
5750 widget = GTK_WIDGET (window);
5751 priv = gtk_window_get_private (window);
5753 priv->fullscreen_initially = FALSE;
5756 toplevel = window->frame;
5758 toplevel = widget->window;
5760 if (toplevel != NULL)
5761 gdk_window_unfullscreen (toplevel);
5766 * gtk_window_set_resizable:
5767 * @window: a #GtkWindow
5768 * @resizable: %TRUE if the user can resize this window
5770 * Sets whether the user can resize a window. Windows are user resizable
5774 gtk_window_set_resizable (GtkWindow *window,
5777 g_return_if_fail (GTK_IS_WINDOW (window));
5779 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5783 * gtk_window_get_resizable:
5784 * @window: a #GtkWindow
5786 * Gets the value set by gtk_window_set_resizable().
5788 * Return value: %TRUE if the user can resize the window
5791 gtk_window_get_resizable (GtkWindow *window)
5793 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5795 /* allow_grow is most likely to indicate the semantic concept we
5796 * mean by "resizable" (and will be a reliable indicator if
5797 * set_policy() hasn't been called)
5799 return window->allow_grow;
5803 * gtk_window_set_gravity:
5804 * @window: a #GtkWindow
5805 * @gravity: window gravity
5807 * Window gravity defines the meaning of coordinates passed to
5808 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5811 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5812 * typically "do what you mean."
5816 gtk_window_set_gravity (GtkWindow *window,
5819 g_return_if_fail (GTK_IS_WINDOW (window));
5821 if (gravity != window->gravity)
5823 window->gravity = gravity;
5825 /* gtk_window_move_resize() will adapt gravity
5827 gtk_widget_queue_resize (GTK_WIDGET (window));
5832 * gtk_window_get_gravity:
5833 * @window: a #GtkWindow
5835 * Gets the value set by gtk_window_set_gravity().
5837 * Return value: window gravity
5840 gtk_window_get_gravity (GtkWindow *window)
5842 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5844 return window->gravity;
5848 * gtk_window_begin_resize_drag:
5849 * @window: a #GtkWindow
5850 * @button: mouse button that initiated the drag
5851 * @edge: position of the resize control
5852 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5853 * @root_y: Y position where the user clicked to initiate the drag
5854 * @timestamp: timestamp from the click event that initiated the drag
5856 * Starts resizing a window. This function is used if an application
5857 * has window resizing controls. When GDK can support it, the resize
5858 * will be done using the standard mechanism for the <link
5859 * linkend="gtk-X11-arch">window manager</link> or windowing
5860 * system. Otherwise, GDK will try to emulate window resizing,
5861 * potentially not all that well, depending on the windowing system.
5865 gtk_window_begin_resize_drag (GtkWindow *window,
5873 GdkWindow *toplevel;
5875 g_return_if_fail (GTK_IS_WINDOW (window));
5876 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5878 widget = GTK_WIDGET (window);
5881 toplevel = window->frame;
5883 toplevel = widget->window;
5885 gdk_window_begin_resize_drag (toplevel,
5892 * gtk_window_get_frame_dimensions:
5893 * @window: a #GtkWindow
5894 * @left: location to store the width of the frame at the left, or %NULL
5895 * @top: location to store the height of the frame at the top, or %NULL
5896 * @right: location to store the width of the frame at the returns, or %NULL
5897 * @bottom: location to store the height of the frame at the bottom, or %NULL
5899 * (Note: this is a special-purpose function intended for the
5900 * framebuffer port; see gtk_window_set_has_frame(). It will not
5901 * return the size of the window border drawn by the <link
5902 * linkend="gtk-X11-arch">window manager</link>, which is the normal
5903 * case when using a windowing system. See
5904 * gdk_window_get_frame_extents() to get the standard window border
5907 * Retrieves the dimensions of the frame window for this toplevel.
5908 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5911 gtk_window_get_frame_dimensions (GtkWindow *window,
5917 g_return_if_fail (GTK_IS_WINDOW (window));
5920 *left = window->frame_left;
5922 *top = window->frame_top;
5924 *right = window->frame_right;
5926 *bottom = window->frame_bottom;
5930 * gtk_window_begin_move_drag:
5931 * @window: a #GtkWindow
5932 * @button: mouse button that initiated the drag
5933 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5934 * @root_y: Y position where the user clicked to initiate the drag
5935 * @timestamp: timestamp from the click event that initiated the drag
5937 * Starts moving a window. This function is used if an application has
5938 * window movement grips. When GDK can support it, the window movement
5939 * will be done using the standard mechanism for the <link
5940 * linkend="gtk-X11-arch">window manager</link> or windowing
5941 * system. Otherwise, GDK will try to emulate window movement,
5942 * potentially not all that well, depending on the windowing system.
5946 gtk_window_begin_move_drag (GtkWindow *window,
5953 GdkWindow *toplevel;
5955 g_return_if_fail (GTK_IS_WINDOW (window));
5956 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5958 widget = GTK_WIDGET (window);
5961 toplevel = window->frame;
5963 toplevel = widget->window;
5965 gdk_window_begin_move_drag (toplevel,
5972 * gtk_window_set_screen:
5973 * @window: a #GtkWindow.
5974 * @screen: a #GdkScreen.
5976 * Sets the #GdkScreen where the @window is displayed; if
5977 * the window is already mapped, it will be unmapped, and
5978 * then remapped on the new screen.
5981 gtk_window_set_screen (GtkWindow *window,
5985 GdkScreen *previous_screen;
5986 GdkScreen *new_screen;
5987 gboolean was_mapped;
5989 g_return_if_fail (GTK_IS_WINDOW (window));
5990 g_return_if_fail (GDK_IS_SCREEN (screen));
5992 if (screen == window->screen)
5995 widget = GTK_WIDGET (window);
5997 previous_screen = window->screen;
5998 was_mapped = GTK_WIDGET_MAPPED (widget);
6001 gtk_widget_unmap (widget);
6002 if (GTK_WIDGET_REALIZED (widget))
6003 gtk_widget_unrealize (widget);
6005 gtk_window_free_key_hash (window);
6006 window->screen = screen;
6007 gtk_widget_reset_rc_styles (widget);
6008 if (screen != previous_screen)
6009 _gtk_widget_propagate_screen_changed (widget, previous_screen);
6010 g_object_notify (G_OBJECT (window), "screen");
6013 gtk_widget_map (widget);
6017 * gtk_window_get_screen:
6018 * @window: a #GtkWindow.
6020 * Returns the #GdkScreen associated with @window.
6022 * Return value: a #GdkScreen.
6025 gtk_window_get_screen (GtkWindow *window)
6027 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6029 return window->screen;
6034 gtk_window_group_class_init (GtkWindowGroupClass *klass)
6039 gtk_window_group_get_type (void)
6041 static GType window_group_type = 0;
6043 if (!window_group_type)
6045 static const GTypeInfo window_group_info =
6047 sizeof (GtkWindowGroupClass),
6048 NULL, /* base_init */
6049 NULL, /* base_finalize */
6050 (GClassInitFunc) gtk_window_group_class_init,
6051 NULL, /* class_finalize */
6052 NULL, /* class_data */
6053 sizeof (GtkWindowGroup),
6054 16, /* n_preallocs */
6055 (GInstanceInitFunc) NULL,
6058 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
6061 return window_group_type;
6065 * gtk_window_group_new:
6067 * Creates a new #GtkWindowGroup object. Grabs added with
6068 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
6070 * Return value: a new #GtkWindowGroup.
6073 gtk_window_group_new (void)
6075 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
6079 window_group_cleanup_grabs (GtkWindowGroup *group,
6083 GSList *to_remove = NULL;
6085 tmp_list = group->grabs;
6088 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
6089 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
6090 tmp_list = tmp_list->next;
6095 gtk_grab_remove (to_remove->data);
6096 g_object_unref (to_remove->data);
6097 to_remove = g_slist_delete_link (to_remove, to_remove);
6102 * gtk_window_group_add_window:
6103 * @window_group: a #GtkWindowGroup
6104 * @window: the #GtkWindow to add
6106 * Adds a window to a #GtkWindowGroup.
6109 gtk_window_group_add_window (GtkWindowGroup *window_group,
6112 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6113 g_return_if_fail (GTK_IS_WINDOW (window));
6115 if (window->group != window_group)
6117 g_object_ref (window);
6118 g_object_ref (window_group);
6121 gtk_window_group_remove_window (window->group, window);
6123 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
6125 window->group = window_group;
6127 g_object_unref (window);
6132 * gtk_window_group_remove_window:
6133 * @window_group: a #GtkWindowGroup
6134 * @window: the #GtkWindow to remove
6136 * Removes a window from a #GtkWindowGroup.
6139 gtk_window_group_remove_window (GtkWindowGroup *window_group,
6142 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6143 g_return_if_fail (GTK_IS_WIDGET (window));
6144 g_return_if_fail (window->group == window_group);
6146 g_object_ref (window);
6148 window_group_cleanup_grabs (window_group, window);
6149 window->group = NULL;
6151 g_object_unref (window_group);
6152 g_object_unref (window);
6155 /* Return the group for the window or the default group
6158 _gtk_window_get_group (GtkWindow *window)
6160 if (window && window->group)
6161 return window->group;
6164 static GtkWindowGroup *default_group = NULL;
6167 default_group = gtk_window_group_new ();
6169 return default_group;
6175 Derived from XParseGeometry() in XFree86
6177 Copyright 1985, 1986, 1987,1998 The Open Group
6179 All Rights Reserved.
6181 The above copyright notice and this permission notice shall be included
6182 in all copies or substantial portions of the Software.
6184 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
6185 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6186 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6187 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
6188 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
6189 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
6190 OTHER DEALINGS IN THE SOFTWARE.
6192 Except as contained in this notice, the name of The Open Group shall
6193 not be used in advertising or otherwise to promote the sale, use or
6194 other dealings in this Software without prior written authorization
6195 from The Open Group.
6200 * XParseGeometry parses strings of the form
6201 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
6202 * width, height, xoffset, and yoffset are unsigned integers.
6203 * Example: "=80x24+300-49"
6204 * The equal sign is optional.
6205 * It returns a bitmask that indicates which of the four values
6206 * were actually found in the string. For each value found,
6207 * the corresponding argument is updated; for each value
6208 * not found, the corresponding argument is left unchanged.
6211 /* The following code is from Xlib, and is minimally modified, so we
6212 * can track any upstream changes if required. Don't change this
6213 * code. Or if you do, put in a huge comment marking which thing
6218 read_int (gchar *string,
6226 else if (*string == '-')
6232 for (; (*string >= '0') && (*string <= '9'); string++)
6234 result = (result * 10) + (*string - '0');
6246 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
6247 * value (x, y, width, height) was found in the parsed string.
6249 #define NoValue 0x0000
6250 #define XValue 0x0001
6251 #define YValue 0x0002
6252 #define WidthValue 0x0004
6253 #define HeightValue 0x0008
6254 #define AllValues 0x000F
6255 #define XNegative 0x0010
6256 #define YNegative 0x0020
6258 /* Try not to reformat/modify, so we can compare/sync with X sources */
6260 gtk_XParseGeometry (const char *string,
6263 unsigned int *width,
6264 unsigned int *height)
6268 unsigned int tempWidth, tempHeight;
6270 char *nextCharacter;
6272 /* These initializations are just to silence gcc */
6278 if ( (string == NULL) || (*string == '\0')) return(mask);
6280 string++; /* ignore possible '=' at beg of geometry spec */
6282 strind = (char *)string;
6283 if (*strind != '+' && *strind != '-' && *strind != 'x') {
6284 tempWidth = read_int(strind, &nextCharacter);
6285 if (strind == nextCharacter)
6287 strind = nextCharacter;
6291 if (*strind == 'x' || *strind == 'X') {
6293 tempHeight = read_int(strind, &nextCharacter);
6294 if (strind == nextCharacter)
6296 strind = nextCharacter;
6297 mask |= HeightValue;
6300 if ((*strind == '+') || (*strind == '-')) {
6301 if (*strind == '-') {
6303 tempX = -read_int(strind, &nextCharacter);
6304 if (strind == nextCharacter)
6306 strind = nextCharacter;
6312 tempX = read_int(strind, &nextCharacter);
6313 if (strind == nextCharacter)
6315 strind = nextCharacter;
6318 if ((*strind == '+') || (*strind == '-')) {
6319 if (*strind == '-') {
6321 tempY = -read_int(strind, &nextCharacter);
6322 if (strind == nextCharacter)
6324 strind = nextCharacter;
6331 tempY = read_int(strind, &nextCharacter);
6332 if (strind == nextCharacter)
6334 strind = nextCharacter;
6340 /* If strind isn't at the end of the string the it's an invalid
6341 geometry specification. */
6343 if (*strind != '\0') return (0);
6349 if (mask & WidthValue)
6351 if (mask & HeightValue)
6352 *height = tempHeight;
6357 * gtk_window_parse_geometry:
6358 * @window: a #GtkWindow
6359 * @geometry: geometry string
6361 * Parses a standard X Window System geometry string - see the
6362 * manual page for X (type 'man X') for details on this.
6363 * gtk_window_parse_geometry() does work on all GTK+ ports
6364 * including Win32 but is primarily intended for an X environment.
6366 * If either a size or a position can be extracted from the
6367 * geometry string, gtk_window_parse_geometry() returns %TRUE
6368 * and calls gtk_window_set_default_size() and/or gtk_window_move()
6369 * to resize/move the window.
6371 * If gtk_window_parse_geometry() returns %TRUE, it will also
6372 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
6373 * indicating to the window manager that the size/position of
6374 * the window was user-specified. This causes most window
6375 * managers to honor the geometry.
6377 * Return value: %TRUE if string was parsed successfully
6380 gtk_window_parse_geometry (GtkWindow *window,
6381 const gchar *geometry)
6386 gboolean size_set, pos_set;
6388 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6389 g_return_val_if_fail (geometry != NULL, FALSE);
6391 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
6393 if ((result & WidthValue) == 0 ||
6396 if ((result & HeightValue) == 0 ||
6401 if ((result & WidthValue) || (result & HeightValue))
6403 gtk_window_set_default_size_internal (window, TRUE, w, TRUE, h, TRUE);
6407 gtk_window_get_size (window, &w, &h);
6409 grav = GDK_GRAVITY_NORTH_WEST;
6411 if ((result & XNegative) && (result & YNegative))
6412 grav = GDK_GRAVITY_SOUTH_EAST;
6413 else if (result & XNegative)
6414 grav = GDK_GRAVITY_NORTH_EAST;
6415 else if (result & YNegative)
6416 grav = GDK_GRAVITY_SOUTH_WEST;
6418 if ((result & XValue) == 0)
6421 if ((result & YValue) == 0)
6424 if (grav == GDK_GRAVITY_SOUTH_WEST ||
6425 grav == GDK_GRAVITY_SOUTH_EAST)
6426 y = gdk_screen_get_height (window->screen) - h + y;
6428 if (grav == GDK_GRAVITY_SOUTH_EAST ||
6429 grav == GDK_GRAVITY_NORTH_EAST)
6430 x = gdk_screen_get_width (window->screen) - w + x;
6432 /* we don't let you put a window offscreen; maybe some people would
6433 * prefer to be able to, but it's kind of a bogus thing to do.
6442 if ((result & XValue) || (result & YValue))
6444 gtk_window_set_gravity (window, grav);
6445 gtk_window_move (window, x, y);
6449 if (size_set || pos_set)
6451 /* Set USSize, USPosition hints */
6452 GtkWindowGeometryInfo *info;
6454 info = gtk_window_get_geometry_info (window, TRUE);
6457 info->mask |= GDK_HINT_USER_POS;
6459 info->mask |= GDK_HINT_USER_SIZE;
6466 gtk_window_mnemonic_hash_foreach (gpointer key,
6472 GtkWindowKeysForeachFunc func;
6476 GtkWindowMnemonic *mnemonic = value;
6478 if (mnemonic->window == info->window)
6479 (*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
6483 _gtk_window_keys_foreach (GtkWindow *window,
6484 GtkWindowKeysForeachFunc func,
6491 GtkWindowKeysForeachFunc func;
6495 info.window = window;
6497 info.func_data = func_data;
6499 g_hash_table_foreach (mnemonic_hash_table,
6500 gtk_window_mnemonic_hash_foreach,
6503 groups = gtk_accel_groups_from_object (G_OBJECT (window));
6506 GtkAccelGroup *group = groups->data;
6509 for (i = 0; i < group->n_accels; i++)
6511 GtkAccelKey *key = &group->priv_accels[i].key;
6514 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
6517 groups = groups->next;
6522 gtk_window_keys_changed (GtkWindow *window)
6524 gtk_window_free_key_hash (window);
6525 gtk_window_get_key_hash (window);
6528 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
6530 struct _GtkWindowKeyEntry
6534 gboolean is_mnemonic;
6538 add_to_key_hash (GtkWindow *window,
6540 GdkModifierType modifiers,
6541 gboolean is_mnemonic,
6544 GtkKeyHash *key_hash = data;
6546 GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
6548 entry->keyval = keyval;
6549 entry->modifiers = modifiers;
6550 entry->is_mnemonic = is_mnemonic;
6552 /* GtkAccelGroup stores lowercased accelerators. To deal
6553 * with this, if <Shift> was specified, uppercase.
6555 if (modifiers & GDK_SHIFT_MASK)
6557 if (keyval == GDK_Tab)
6558 keyval = GDK_ISO_Left_Tab;
6560 keyval = gdk_keyval_to_upper (keyval);
6563 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
6567 gtk_window_get_key_hash (GtkWindow *window)
6569 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6573 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (window->screen)),
6574 (GDestroyNotify)g_free);
6575 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
6576 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
6582 gtk_window_free_key_hash (GtkWindow *window)
6584 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6587 _gtk_key_hash_free (key_hash);
6588 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
6593 * _gtk_window_activate_key:
6594 * @window: a #GtkWindow
6595 * @event: a #GdkEventKey
6597 * Activates mnemonics and accelerators for this #GtKWindow
6599 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
6602 _gtk_window_activate_key (GtkWindow *window,
6605 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6606 GtkWindowKeyEntry *found_entry = NULL;
6610 gtk_window_keys_changed (window);
6611 key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6616 GSList *entries = _gtk_key_hash_lookup (key_hash,
6617 event->hardware_keycode,
6618 event->state & gtk_accelerator_get_default_mod_mask (),
6622 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
6624 GtkWindowKeyEntry *entry = tmp_list->data;
6625 if (entry->is_mnemonic)
6627 found_entry = entry;
6632 if (!found_entry && entries)
6633 found_entry = entries->data;
6635 g_slist_free (entries);
6640 if (found_entry->is_mnemonic)
6641 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
6643 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
6650 window_update_has_focus (GtkWindow *window)
6652 GtkWidget *widget = GTK_WIDGET (window);
6653 gboolean has_focus = window->has_toplevel_focus && window->is_active;
6655 if (has_focus != window->has_focus)
6657 window->has_focus = has_focus;
6661 if (window->focus_widget &&
6662 window->focus_widget != widget &&
6663 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6664 do_focus_change (window->focus_widget, TRUE);
6668 if (window->focus_widget &&
6669 window->focus_widget != widget &&
6670 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6671 do_focus_change (window->focus_widget, FALSE);
6677 * _gtk_window_set_is_active:
6678 * @window: a #GtkWindow
6679 * @is_active: %TRUE if the window is in the currently active toplevel
6681 * Internal function that sets whether the #GtkWindow is part
6682 * of the currently active toplevel window (taking into account inter-process
6686 _gtk_window_set_is_active (GtkWindow *window,
6689 g_return_if_fail (GTK_IS_WINDOW (window));
6691 is_active = is_active != FALSE;
6693 if (is_active != window->is_active)
6695 window->is_active = is_active;
6696 window_update_has_focus (window);
6698 g_object_notify (G_OBJECT (window), "is_active");
6703 * _gtk_window_set_has_toplevel_focus:
6704 * @window: a #GtkWindow
6705 * @has_toplevel_focus: %TRUE if the in
6707 * Internal function that sets whether the keyboard focus for the
6708 * toplevel window (taking into account inter-process embedding.)
6711 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
6712 gboolean has_toplevel_focus)
6714 g_return_if_fail (GTK_IS_WINDOW (window));
6716 has_toplevel_focus = has_toplevel_focus != FALSE;
6718 if (has_toplevel_focus != window->has_toplevel_focus)
6720 window->has_toplevel_focus = has_toplevel_focus;
6721 window_update_has_focus (window);
6723 g_object_notify (G_OBJECT (window), "has_toplevel_focus");
6728 * gtk_window_set_auto_startup_notification:
6729 * @setting: %TRUE to automatically do startup notification
6731 * By default, after showing the first #GtkWindow for each #GdkScreen,
6732 * GTK+ calls gdk_screen_notify_startup_complete(). Call this
6733 * function to disable the automatic startup notification. You might
6734 * do this if your first window is a splash screen, and you want to
6735 * delay notification until after your real main window has been
6736 * shown, for example.
6738 * In that example, you would disable startup notification
6739 * temporarily, show your splash screen, then re-enable it so that
6740 * showing the main window would automatically result in notification.
6744 gtk_window_set_auto_startup_notification (gboolean setting)
6746 disable_startup_notification = !setting;