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"
70 PROP_DESTROY_WITH_PARENT,
74 PROP_SKIP_TASKBAR_HINT,
79 /* Readonly properties */
81 PROP_HAS_TOPLEVEL_FOCUS,
89 GdkPixmap *icon_pixmap;
92 guint using_default_icon : 1;
93 guint using_parent_icon : 1;
97 GdkGeometry geometry; /* Last set of geometry hints we set */
99 GdkRectangle configure_request;
100 } GtkWindowLastGeometryInfo;
102 struct _GtkWindowGeometryInfo
104 /* Properties that the app has set on the window
106 GdkGeometry geometry; /* Geometry hints */
108 GtkWidget *widget; /* subwidget to which hints apply */
109 /* from last gtk_window_resize () - if > 0, indicates that
110 * we should resize to this size.
115 /* From last gtk_window_move () prior to mapping -
116 * only used if initial_pos_set
121 /* Default size - used only the FIRST time we map a window,
126 /* whether to use initial_x, initial_y */
127 guint initial_pos_set : 1;
128 /* CENTER_ALWAYS or other position constraint changed since
129 * we sent the last configure request.
131 guint position_constraints_changed : 1;
133 /* if true, default_width, height come from gtk_window_parse_geometry,
134 * and thus should be multiplied by the increments and affect the
135 * geometry widget only
137 guint default_is_geometry : 1;
139 GtkWindowLastGeometryInfo last;
142 typedef struct _GtkWindowMnemonic GtkWindowMnemonic;
144 struct _GtkWindowMnemonic {
151 #define GTK_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW, GtkWindowPrivate))
153 typedef struct _GtkWindowPrivate GtkWindowPrivate;
155 struct _GtkWindowPrivate
157 guint above_initially : 1;
158 guint below_initially : 1;
159 guint fullscreen_initially : 1;
160 guint skips_taskbar : 1;
161 guint skips_pager : 1;
164 static void gtk_window_class_init (GtkWindowClass *klass);
165 static void gtk_window_init (GtkWindow *window);
166 static void gtk_window_dispose (GObject *object);
167 static void gtk_window_destroy (GtkObject *object);
168 static void gtk_window_finalize (GObject *object);
169 static void gtk_window_show (GtkWidget *widget);
170 static void gtk_window_hide (GtkWidget *widget);
171 static void gtk_window_map (GtkWidget *widget);
172 static void gtk_window_unmap (GtkWidget *widget);
173 static void gtk_window_realize (GtkWidget *widget);
174 static void gtk_window_unrealize (GtkWidget *widget);
175 static void gtk_window_size_request (GtkWidget *widget,
176 GtkRequisition *requisition);
177 static void gtk_window_size_allocate (GtkWidget *widget,
178 GtkAllocation *allocation);
179 static gint gtk_window_event (GtkWidget *widget,
181 static gboolean gtk_window_frame_event (GtkWindow *window,
183 static gint gtk_window_configure_event (GtkWidget *widget,
184 GdkEventConfigure *event);
185 static gint gtk_window_key_press_event (GtkWidget *widget,
187 static gint gtk_window_key_release_event (GtkWidget *widget,
189 static gint gtk_window_enter_notify_event (GtkWidget *widget,
190 GdkEventCrossing *event);
191 static gint gtk_window_leave_notify_event (GtkWidget *widget,
192 GdkEventCrossing *event);
193 static gint gtk_window_focus_in_event (GtkWidget *widget,
194 GdkEventFocus *event);
195 static gint gtk_window_focus_out_event (GtkWidget *widget,
196 GdkEventFocus *event);
197 static gint gtk_window_client_event (GtkWidget *widget,
198 GdkEventClient *event);
199 static void gtk_window_check_resize (GtkContainer *container);
200 static gint gtk_window_focus (GtkWidget *widget,
201 GtkDirectionType direction);
202 static void gtk_window_real_set_focus (GtkWindow *window,
205 static void gtk_window_real_activate_default (GtkWindow *window);
206 static void gtk_window_real_activate_focus (GtkWindow *window);
207 static void gtk_window_move_focus (GtkWindow *window,
208 GtkDirectionType dir);
209 static void gtk_window_keys_changed (GtkWindow *window);
210 static void gtk_window_read_rcfiles (GtkWidget *widget,
211 GdkEventClient *event);
212 static void gtk_window_paint (GtkWidget *widget,
214 static gint gtk_window_expose (GtkWidget *widget,
215 GdkEventExpose *event);
216 static void gtk_window_unset_transient_for (GtkWindow *window);
217 static void gtk_window_transient_parent_realized (GtkWidget *parent,
219 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
222 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
224 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
227 static void gtk_window_move_resize (GtkWindow *window);
228 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
230 GdkGeometry *geometry_b,
232 static void gtk_window_constrain_size (GtkWindow *window,
233 GdkGeometry *geometry,
239 static void gtk_window_constrain_position (GtkWindow *window,
244 static void gtk_window_compute_hints (GtkWindow *window,
245 GdkGeometry *new_geometry,
247 static void gtk_window_compute_configure_request (GtkWindow *window,
248 GdkRectangle *request,
249 GdkGeometry *geometry,
252 static void gtk_window_set_default_size_internal (GtkWindow *window,
253 gboolean change_width,
255 gboolean change_height,
257 gboolean is_geometry);
259 static void gtk_window_realize_icon (GtkWindow *window);
260 static void gtk_window_unrealize_icon (GtkWindow *window);
262 static void gtk_window_notify_keys_changed (GtkWindow *window);
263 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
264 static void gtk_window_free_key_hash (GtkWindow *window);
266 static GSList *toplevel_list = NULL;
267 static GHashTable *mnemonic_hash_table = NULL;
268 static GtkBinClass *parent_class = NULL;
269 static guint window_signals[LAST_SIGNAL] = { 0 };
270 static GList *default_icon_list = NULL;
271 static guint default_icon_serial = 0;
272 static gboolean disable_startup_notification = FALSE;
273 static gboolean sent_startup_notification = FALSE;
275 static void gtk_window_set_property (GObject *object,
279 static void gtk_window_get_property (GObject *object,
286 mnemonic_hash (gconstpointer key)
288 const GtkWindowMnemonic *k;
291 k = (GtkWindowMnemonic *)key;
293 h = (gulong) k->window;
294 h ^= k->keyval << 16;
295 h ^= k->keyval >> 16;
301 mnemonic_equal (gconstpointer a, gconstpointer b)
303 const GtkWindowMnemonic *ka;
304 const GtkWindowMnemonic *kb;
306 ka = (GtkWindowMnemonic *)a;
307 kb = (GtkWindowMnemonic *)b;
310 (ka->window == kb->window) &&
311 (ka->keyval == kb->keyval);
315 gtk_window_get_type (void)
317 static GType window_type = 0;
321 static const GTypeInfo window_info =
323 sizeof (GtkWindowClass),
324 NULL, /* base_init */
325 NULL, /* base_finalize */
326 (GClassInitFunc) gtk_window_class_init,
327 NULL, /* class_finalize */
328 NULL, /* class_data */
331 (GInstanceInitFunc) gtk_window_init,
334 window_type = g_type_register_static (GTK_TYPE_BIN, "GtkWindow",
342 add_tab_bindings (GtkBindingSet *binding_set,
343 GdkModifierType modifiers,
344 GtkDirectionType direction)
346 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
348 GTK_TYPE_DIRECTION_TYPE, direction);
349 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
351 GTK_TYPE_DIRECTION_TYPE, direction);
355 add_arrow_bindings (GtkBindingSet *binding_set,
357 GtkDirectionType direction)
359 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
361 gtk_binding_entry_add_signal (binding_set, keysym, 0,
363 GTK_TYPE_DIRECTION_TYPE, direction);
364 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
366 GTK_TYPE_DIRECTION_TYPE, direction);
367 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
369 GTK_TYPE_DIRECTION_TYPE, direction);
370 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
372 GTK_TYPE_DIRECTION_TYPE, direction);
377 gtk_window_class_init (GtkWindowClass *klass)
379 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
380 GtkObjectClass *object_class;
381 GtkWidgetClass *widget_class;
382 GtkContainerClass *container_class;
383 GtkBindingSet *binding_set;
385 object_class = (GtkObjectClass*) klass;
386 widget_class = (GtkWidgetClass*) klass;
387 container_class = (GtkContainerClass*) klass;
389 parent_class = g_type_class_peek_parent (klass);
391 mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
393 gobject_class->dispose = gtk_window_dispose;
394 gobject_class->finalize = gtk_window_finalize;
396 gobject_class->set_property = gtk_window_set_property;
397 gobject_class->get_property = gtk_window_get_property;
399 object_class->destroy = gtk_window_destroy;
401 widget_class->show = gtk_window_show;
402 widget_class->hide = gtk_window_hide;
403 widget_class->map = gtk_window_map;
404 widget_class->unmap = gtk_window_unmap;
405 widget_class->realize = gtk_window_realize;
406 widget_class->unrealize = gtk_window_unrealize;
407 widget_class->size_request = gtk_window_size_request;
408 widget_class->size_allocate = gtk_window_size_allocate;
409 widget_class->configure_event = gtk_window_configure_event;
410 widget_class->key_press_event = gtk_window_key_press_event;
411 widget_class->key_release_event = gtk_window_key_release_event;
412 widget_class->enter_notify_event = gtk_window_enter_notify_event;
413 widget_class->leave_notify_event = gtk_window_leave_notify_event;
414 widget_class->focus_in_event = gtk_window_focus_in_event;
415 widget_class->focus_out_event = gtk_window_focus_out_event;
416 widget_class->client_event = gtk_window_client_event;
417 widget_class->focus = gtk_window_focus;
419 widget_class->expose_event = gtk_window_expose;
421 container_class->check_resize = gtk_window_check_resize;
423 klass->set_focus = gtk_window_real_set_focus;
424 klass->frame_event = gtk_window_frame_event;
426 klass->activate_default = gtk_window_real_activate_default;
427 klass->activate_focus = gtk_window_real_activate_focus;
428 klass->move_focus = gtk_window_move_focus;
429 klass->keys_changed = gtk_window_keys_changed;
431 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
434 g_object_class_install_property (gobject_class,
436 g_param_spec_enum ("type",
438 _("The type of the window"),
439 GTK_TYPE_WINDOW_TYPE,
441 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
443 g_object_class_install_property (gobject_class,
445 g_param_spec_string ("title",
447 _("The title of the window"),
451 g_object_class_install_property (gobject_class,
453 g_param_spec_string ("role",
455 _("Unique identifier for the window to be used when restoring a session"),
459 g_object_class_install_property (gobject_class,
461 g_param_spec_boolean ("allow_shrink",
463 /* xgettext:no-c-format */
464 _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
468 g_object_class_install_property (gobject_class,
470 g_param_spec_boolean ("allow_grow",
472 _("If TRUE, users can expand the window beyond its minimum size"),
476 g_object_class_install_property (gobject_class,
478 g_param_spec_boolean ("resizable",
480 _("If TRUE, users can resize the window"),
484 g_object_class_install_property (gobject_class,
486 g_param_spec_boolean ("modal",
488 _("If TRUE, the window is modal (other windows are not usable while this one is up)"),
492 g_object_class_install_property (gobject_class,
494 g_param_spec_enum ("window_position",
495 _("Window Position"),
496 _("The initial position of the window"),
497 GTK_TYPE_WINDOW_POSITION,
501 g_object_class_install_property (gobject_class,
503 g_param_spec_int ("default_width",
505 _("The default width of the window, used when initially showing the window"),
511 g_object_class_install_property (gobject_class,
513 g_param_spec_int ("default_height",
515 _("The default height of the window, used when initially showing the window"),
521 g_object_class_install_property (gobject_class,
522 PROP_DESTROY_WITH_PARENT,
523 g_param_spec_boolean ("destroy_with_parent",
524 _("Destroy with Parent"),
525 _("If this window should be destroyed when the parent is destroyed"),
529 g_object_class_install_property (gobject_class,
531 g_param_spec_object ("icon",
533 _("Icon for this window"),
537 g_object_class_install_property (gobject_class,
539 g_param_spec_object ("screen",
541 _("The screen where this window will be displayed"),
545 g_object_class_install_property (gobject_class,
547 g_param_spec_boolean ("is_active",
549 _("Whether the toplevel is the current active window"),
553 g_object_class_install_property (gobject_class,
554 PROP_HAS_TOPLEVEL_FOCUS,
555 g_param_spec_boolean ("has_toplevel_focus",
556 _("Focus in Toplevel"),
557 _("Whether the input focus is within this GtkWindow"),
561 g_object_class_install_property (gobject_class,
563 g_param_spec_enum ("type_hint",
565 _("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
566 GDK_TYPE_WINDOW_TYPE_HINT,
567 GDK_WINDOW_TYPE_HINT_NORMAL,
570 g_object_class_install_property (gobject_class,
571 PROP_SKIP_TASKBAR_HINT,
572 g_param_spec_boolean ("skip_taskbar_hint",
574 _("TRUE if the window should not be in the task bar."),
578 g_object_class_install_property (gobject_class,
579 PROP_SKIP_PAGER_HINT,
580 g_param_spec_boolean ("skip_pager_hint",
582 _("TRUE if the window should not be in the pager."),
587 * GtkWindow:decorated:
589 * Whether the window should be decorated by the window manager.
593 g_object_class_install_property (gobject_class,
595 g_param_spec_boolean ("decorated",
597 _("Whether the window should be decorated by the window manager"),
604 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
605 * more details about window gravity.
609 g_object_class_install_property (gobject_class,
611 g_param_spec_enum ("gravity",
613 _("The window gravity of the window"),
615 GDK_GRAVITY_NORTH_WEST,
618 window_signals[SET_FOCUS] =
619 g_signal_new ("set_focus",
620 G_TYPE_FROM_CLASS (gobject_class),
622 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
624 _gtk_marshal_VOID__OBJECT,
628 window_signals[FRAME_EVENT] =
629 g_signal_new ("frame_event",
630 G_TYPE_FROM_CLASS (gobject_class),
632 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
633 _gtk_boolean_handled_accumulator, NULL,
634 _gtk_marshal_BOOLEAN__BOXED,
638 window_signals[ACTIVATE_FOCUS] =
639 g_signal_new ("activate_focus",
640 G_TYPE_FROM_CLASS (gobject_class),
641 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
642 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
644 _gtk_marshal_VOID__VOID,
648 window_signals[ACTIVATE_DEFAULT] =
649 g_signal_new ("activate_default",
650 G_TYPE_FROM_CLASS (gobject_class),
651 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
652 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
654 _gtk_marshal_VOID__VOID,
658 window_signals[MOVE_FOCUS] =
659 g_signal_new ("move_focus",
660 G_TYPE_FROM_CLASS (gobject_class),
661 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
662 G_STRUCT_OFFSET (GtkWindowClass, move_focus),
664 _gtk_marshal_VOID__ENUM,
667 GTK_TYPE_DIRECTION_TYPE);
669 window_signals[KEYS_CHANGED] =
670 g_signal_new ("keys_changed",
671 G_TYPE_FROM_CLASS (gobject_class),
673 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
675 _gtk_marshal_VOID__VOID,
683 binding_set = gtk_binding_set_by_class (klass);
685 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
686 "activate_focus", 0);
687 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
688 "activate_focus", 0);
690 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
691 "activate_default", 0);
693 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
694 "activate_default", 0);
696 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
697 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
698 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
699 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
701 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
702 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
703 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
704 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
708 gtk_window_init (GtkWindow *window)
710 GdkColormap *colormap;
712 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
713 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
715 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
717 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
719 window->title = NULL;
720 window->wmclass_name = g_strdup (g_get_prgname ());
721 window->wmclass_class = g_strdup (gdk_get_program_class ());
722 window->wm_role = NULL;
723 window->geometry_info = NULL;
724 window->type = GTK_WINDOW_TOPLEVEL;
725 window->focus_widget = NULL;
726 window->default_widget = NULL;
727 window->configure_request_count = 0;
728 window->allow_shrink = FALSE;
729 window->allow_grow = TRUE;
730 window->configure_notify_received = FALSE;
731 window->position = GTK_WIN_POS_NONE;
732 window->need_default_size = TRUE;
733 window->need_default_position = TRUE;
734 window->modal = FALSE;
735 window->frame = NULL;
736 window->has_frame = FALSE;
737 window->frame_left = 0;
738 window->frame_right = 0;
739 window->frame_top = 0;
740 window->frame_bottom = 0;
741 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
742 window->gravity = GDK_GRAVITY_NORTH_WEST;
743 window->decorated = TRUE;
744 window->mnemonic_modifier = GDK_MOD1_MASK;
745 window->screen = gdk_screen_get_default ();
747 colormap = _gtk_widget_peek_colormap ();
749 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
751 g_object_ref (window);
752 gtk_object_sink (GTK_OBJECT (window));
753 window->has_user_ref_count = TRUE;
754 toplevel_list = g_slist_prepend (toplevel_list, window);
756 gtk_decorated_window_init (window);
758 g_signal_connect (window,
760 G_CALLBACK (gtk_window_event),
765 gtk_window_set_property (GObject *object,
772 window = GTK_WINDOW (object);
777 window->type = g_value_get_enum (value);
780 gtk_window_set_title (window, g_value_get_string (value));
783 gtk_window_set_role (window, g_value_get_string (value));
785 case PROP_ALLOW_SHRINK:
786 window->allow_shrink = g_value_get_boolean (value);
787 gtk_widget_queue_resize (GTK_WIDGET (window));
789 case PROP_ALLOW_GROW:
790 window->allow_grow = g_value_get_boolean (value);
791 gtk_widget_queue_resize (GTK_WIDGET (window));
792 g_object_notify (G_OBJECT (window), "resizable");
795 window->allow_grow = g_value_get_boolean (value);
796 gtk_widget_queue_resize (GTK_WIDGET (window));
797 g_object_notify (G_OBJECT (window), "allow_grow");
800 gtk_window_set_modal (window, g_value_get_boolean (value));
803 gtk_window_set_position (window, g_value_get_enum (value));
805 case PROP_DEFAULT_WIDTH:
806 gtk_window_set_default_size_internal (window,
807 TRUE, g_value_get_int (value),
810 case PROP_DEFAULT_HEIGHT:
811 gtk_window_set_default_size_internal (window,
813 TRUE, g_value_get_int (value), FALSE);
815 case PROP_DESTROY_WITH_PARENT:
816 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
819 gtk_window_set_icon (window,
820 g_value_get_object (value));
823 gtk_window_set_screen (window, g_value_get_object (value));
826 gtk_window_set_type_hint (window,
827 g_value_get_enum (value));
829 case PROP_SKIP_TASKBAR_HINT:
830 gtk_window_set_skip_taskbar_hint (window,
831 g_value_get_boolean (value));
833 case PROP_SKIP_PAGER_HINT:
834 gtk_window_set_skip_pager_hint (window,
835 g_value_get_boolean (value));
838 gtk_window_set_decorated (window, g_value_get_boolean (value));
841 gtk_window_set_gravity (window, g_value_get_enum (value));
849 gtk_window_get_property (GObject *object,
856 window = GTK_WINDOW (object);
860 GtkWindowGeometryInfo *info;
862 g_value_set_enum (value, window->type);
865 g_value_set_string (value, window->wm_role);
868 g_value_set_string (value, window->title);
870 case PROP_ALLOW_SHRINK:
871 g_value_set_boolean (value, window->allow_shrink);
873 case PROP_ALLOW_GROW:
874 g_value_set_boolean (value, window->allow_grow);
877 g_value_set_boolean (value, window->allow_grow);
880 g_value_set_boolean (value, window->modal);
883 g_value_set_enum (value, window->position);
885 case PROP_DEFAULT_WIDTH:
886 info = gtk_window_get_geometry_info (window, FALSE);
888 g_value_set_int (value, -1);
890 g_value_set_int (value, info->default_width);
892 case PROP_DEFAULT_HEIGHT:
893 info = gtk_window_get_geometry_info (window, FALSE);
895 g_value_set_int (value, -1);
897 g_value_set_int (value, info->default_height);
899 case PROP_DESTROY_WITH_PARENT:
900 g_value_set_boolean (value, window->destroy_with_parent);
903 g_value_set_object (value, gtk_window_get_icon (window));
906 g_value_set_object (value, window->screen);
909 g_value_set_boolean (value, window->is_active);
911 case PROP_HAS_TOPLEVEL_FOCUS:
912 g_value_set_boolean (value, window->has_toplevel_focus);
915 g_value_set_enum (value,
918 case PROP_SKIP_TASKBAR_HINT:
919 g_value_set_boolean (value,
920 gtk_window_get_skip_taskbar_hint (window));
922 case PROP_SKIP_PAGER_HINT:
923 g_value_set_boolean (value,
924 gtk_window_get_skip_pager_hint (window));
927 g_value_set_boolean (value, gtk_window_get_decorated (window));
930 g_value_set_enum (value, gtk_window_get_gravity (window));
933 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
940 * @type: type of window
942 * Creates a new #GtkWindow, which is a toplevel window that can
943 * contain other widgets. Nearly always, the type of the window should
944 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
945 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
946 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
947 * dialogs, though in some other toolkits dialogs are called "popups".
948 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
949 * On X11, popup windows are not controlled by the <link
950 * linkend="gtk-X11-arch">window manager</link>.
952 * If you simply want an undecorated window (no window borders), use
953 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
955 * Return value: a new #GtkWindow.
958 gtk_window_new (GtkWindowType type)
962 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
964 window = g_object_new (GTK_TYPE_WINDOW, NULL);
968 return GTK_WIDGET (window);
972 * gtk_window_set_title:
973 * @window: a #GtkWindow
974 * @title: title of the window
976 * Sets the title of the #GtkWindow. The title of a window will be
977 * displayed in its title bar; on the X Window System, the title bar
978 * is rendered by the <link linkend="gtk-X11-arch">window
979 * manager</link>, so exactly how the title appears to users may vary
980 * according to a user's exact configuration. The title should help a
981 * user distinguish this window from other windows they may have
982 * open. A good title might include the application name and current
983 * document filename, for example.
987 gtk_window_set_title (GtkWindow *window,
992 g_return_if_fail (GTK_IS_WINDOW (window));
994 new_title = g_strdup (title);
995 g_free (window->title);
996 window->title = new_title;
998 if (GTK_WIDGET_REALIZED (window))
1000 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
1002 gtk_decorated_window_set_title (window, title);
1005 g_object_notify (G_OBJECT (window), "title");
1009 * gtk_window_get_title:
1010 * @window: a #GtkWindow
1012 * Retrieves the title of the window. See gtk_window_set_title().
1014 * Return value: the title of the window, or %NULL if none has
1015 * been set explicitely. The returned string is owned by the widget
1016 * and must not be modified or freed.
1018 G_CONST_RETURN gchar *
1019 gtk_window_get_title (GtkWindow *window)
1021 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1023 return window->title;
1027 * gtk_window_set_wmclass:
1028 * @window: a #GtkWindow
1029 * @wmclass_name: window name hint
1030 * @wmclass_class: window class hint
1032 * Don't use this function. It sets the X Window System "class" and
1033 * "name" hints for a window. According to the ICCCM, you should
1034 * always set these to the same value for all windows in an
1035 * application, and GTK+ sets them to that value by default, so calling
1036 * this function is sort of pointless. However, you may want to call
1037 * gtk_window_set_role() on each window in your application, for the
1038 * benefit of the session manager. Setting the role allows the window
1039 * manager to restore window positions when loading a saved session.
1043 gtk_window_set_wmclass (GtkWindow *window,
1044 const gchar *wmclass_name,
1045 const gchar *wmclass_class)
1047 g_return_if_fail (GTK_IS_WINDOW (window));
1049 g_free (window->wmclass_name);
1050 window->wmclass_name = g_strdup (wmclass_name);
1052 g_free (window->wmclass_class);
1053 window->wmclass_class = g_strdup (wmclass_class);
1055 if (GTK_WIDGET_REALIZED (window))
1056 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1060 * gtk_window_set_role:
1061 * @window: a #GtkWindow
1062 * @role: unique identifier for the window to be used when restoring a session
1064 * This function is only useful on X11, not with other GTK+ targets.
1066 * In combination with the window title, the window role allows a
1067 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1068 * same" window when an application is restarted. So for example you
1069 * might set the "toolbox" role on your app's toolbox window, so that
1070 * when the user restarts their session, the window manager can put
1071 * the toolbox back in the same place.
1073 * If a window already has a unique title, you don't need to set the
1074 * role, since the WM can use the title to identify the window when
1075 * restoring the session.
1079 gtk_window_set_role (GtkWindow *window,
1084 g_return_if_fail (GTK_IS_WINDOW (window));
1086 new_role = g_strdup (role);
1087 g_free (window->wm_role);
1088 window->wm_role = new_role;
1090 if (GTK_WIDGET_REALIZED (window))
1091 gdk_window_set_role (GTK_WIDGET (window)->window, window->wm_role);
1093 g_object_notify (G_OBJECT (window), "role");
1097 * gtk_window_get_role:
1098 * @window: a #GtkWindow
1100 * Returns the role of the window. See gtk_window_set_role() for
1101 * further explanation.
1103 * Return value: the role of the window if set, or %NULL. The
1104 * returned is owned by the widget and must not be modified
1107 G_CONST_RETURN gchar *
1108 gtk_window_get_role (GtkWindow *window)
1110 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1112 return window->wm_role;
1116 * gtk_window_set_focus:
1117 * @window: a #GtkWindow
1118 * @focus: widget to be the new focus widget, or %NULL to unset
1119 * any focus widget for the toplevel window.
1121 * If @focus is not the current focus widget, and is focusable, sets
1122 * it as the focus widget for the window. If @focus is %NULL, unsets
1123 * the focus widget for this window. To set the focus to a particular
1124 * widget in the toplevel, it is usually more convenient to use
1125 * gtk_widget_grab_focus() instead of this function.
1128 gtk_window_set_focus (GtkWindow *window,
1131 g_return_if_fail (GTK_IS_WINDOW (window));
1134 g_return_if_fail (GTK_IS_WIDGET (focus));
1135 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1139 gtk_widget_grab_focus (focus);
1142 /* Clear the existing focus chain, so that when we focus into
1143 * the window again, we start at the beginnning.
1145 GtkWidget *widget = window->focus_widget;
1148 while (widget->parent)
1150 widget = widget->parent;
1151 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1155 _gtk_window_internal_set_focus (window, NULL);
1160 _gtk_window_internal_set_focus (GtkWindow *window,
1163 g_return_if_fail (GTK_IS_WINDOW (window));
1165 if ((window->focus_widget != focus) ||
1166 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1167 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1171 * gtk_window_set_default:
1172 * @window: a #GtkWindow
1173 * @default_widget: widget to be the default, or %NULL to unset the
1174 * default widget for the toplevel.
1176 * The default widget is the widget that's activated when the user
1177 * presses Enter in a dialog (for example). This function sets or
1178 * unsets the default widget for a #GtkWindow about. When setting
1179 * (rather than unsetting) the default widget it's generally easier to
1180 * call gtk_widget_grab_focus() on the widget. Before making a widget
1181 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1182 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1185 gtk_window_set_default (GtkWindow *window,
1186 GtkWidget *default_widget)
1188 g_return_if_fail (GTK_IS_WINDOW (window));
1191 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1193 if (window->default_widget != default_widget)
1195 GtkWidget *old_default_widget = NULL;
1198 g_object_ref (default_widget);
1200 if (window->default_widget)
1202 old_default_widget = window->default_widget;
1204 if (window->focus_widget != window->default_widget ||
1205 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1206 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1207 gtk_widget_queue_draw (window->default_widget);
1210 window->default_widget = default_widget;
1212 if (window->default_widget)
1214 if (window->focus_widget == NULL ||
1215 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1216 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1217 gtk_widget_queue_draw (window->default_widget);
1220 if (old_default_widget)
1221 g_object_notify (G_OBJECT (old_default_widget), "has_default");
1225 g_object_notify (G_OBJECT (default_widget), "has_default");
1226 g_object_unref (default_widget);
1232 gtk_window_set_policy (GtkWindow *window,
1233 gboolean allow_shrink,
1234 gboolean allow_grow,
1235 gboolean auto_shrink)
1237 g_return_if_fail (GTK_IS_WINDOW (window));
1239 window->allow_shrink = (allow_shrink != FALSE);
1240 window->allow_grow = (allow_grow != FALSE);
1242 g_object_freeze_notify (G_OBJECT (window));
1243 g_object_notify (G_OBJECT (window), "allow_shrink");
1244 g_object_notify (G_OBJECT (window), "allow_grow");
1245 g_object_notify (G_OBJECT (window), "resizable");
1246 g_object_thaw_notify (G_OBJECT (window));
1248 gtk_widget_queue_resize (GTK_WIDGET (window));
1252 handle_keys_changed (gpointer data)
1256 GDK_THREADS_ENTER ();
1257 window = GTK_WINDOW (data);
1259 if (window->keys_changed_handler)
1261 g_source_remove (window->keys_changed_handler);
1262 window->keys_changed_handler = 0;
1265 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1266 GDK_THREADS_LEAVE ();
1272 gtk_window_notify_keys_changed (GtkWindow *window)
1274 if (!window->keys_changed_handler)
1275 window->keys_changed_handler = g_idle_add (handle_keys_changed, window);
1279 * gtk_window_add_accel_group:
1280 * @window: window to attach accelerator group to
1281 * @accel_group: a #GtkAccelGroup
1283 * Associate @accel_group with @window, such that calling
1284 * gtk_accel_groups_activate() on @window will activate accelerators
1288 gtk_window_add_accel_group (GtkWindow *window,
1289 GtkAccelGroup *accel_group)
1291 g_return_if_fail (GTK_IS_WINDOW (window));
1292 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1294 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1295 g_signal_connect_object (accel_group, "accel_changed",
1296 G_CALLBACK (gtk_window_notify_keys_changed),
1297 window, G_CONNECT_SWAPPED);
1301 * gtk_window_remove_accel_group:
1302 * @window: a #GtkWindow
1303 * @accel_group: a #GtkAccelGroup
1305 * Reverses the effects of gtk_window_add_accel_group().
1308 gtk_window_remove_accel_group (GtkWindow *window,
1309 GtkAccelGroup *accel_group)
1311 g_return_if_fail (GTK_IS_WINDOW (window));
1312 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1314 g_signal_handlers_disconnect_by_func (accel_group,
1315 gtk_window_notify_keys_changed,
1317 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1321 * gtk_window_add_mnemonic:
1322 * @window: a #GtkWindow
1323 * @keyval: the mnemonic
1324 * @target: the widget that gets activated by the mnemonic
1326 * Adds a mnemonic to this window.
1329 gtk_window_add_mnemonic (GtkWindow *window,
1333 GtkWindowMnemonic key;
1334 GtkWindowMnemonic *mnemonic;
1336 g_return_if_fail (GTK_IS_WINDOW (window));
1337 g_return_if_fail (GTK_IS_WIDGET (target));
1339 key.window = window;
1340 key.keyval = keyval;
1341 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1345 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1346 mnemonic->targets = g_slist_append (mnemonic->targets, target);
1350 mnemonic = g_new (GtkWindowMnemonic, 1);
1352 mnemonic->targets = g_slist_prepend (NULL, target);
1353 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1355 gtk_window_notify_keys_changed (window);
1359 * gtk_window_remove_mnemonic:
1360 * @window: a #GtkWindow
1361 * @keyval: the mnemonic
1362 * @target: the widget that gets activated by the mnemonic
1364 * Removes a mnemonic from this window.
1367 gtk_window_remove_mnemonic (GtkWindow *window,
1371 GtkWindowMnemonic key;
1372 GtkWindowMnemonic *mnemonic;
1374 g_return_if_fail (GTK_IS_WINDOW (window));
1375 g_return_if_fail (GTK_IS_WIDGET (target));
1377 key.window = window;
1378 key.keyval = keyval;
1379 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1381 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1383 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1384 if (mnemonic->targets == NULL)
1386 g_hash_table_remove (mnemonic_hash_table, mnemonic);
1389 gtk_window_notify_keys_changed (window);
1393 * gtk_window_mnemonic_activate:
1394 * @window: a #GtkWindow
1395 * @keyval: the mnemonic
1396 * @modifier: the modifiers
1397 * @returns: %TRUE if the activation is done.
1399 * Activates the targets associated with the mnemonic.
1402 gtk_window_mnemonic_activate (GtkWindow *window,
1404 GdkModifierType modifier)
1406 GtkWindowMnemonic key;
1407 GtkWindowMnemonic *mnemonic;
1409 GtkWidget *widget, *chosen_widget;
1410 gboolean overloaded;
1412 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1414 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1417 key.window = window;
1418 key.keyval = keyval;
1419 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1425 chosen_widget = NULL;
1426 list = mnemonic->targets;
1429 widget = GTK_WIDGET (list->data);
1431 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1432 GTK_WIDGET_MAPPED (widget))
1440 chosen_widget = widget;
1442 list = g_slist_next (list);
1447 /* For round robin we put the activated entry on
1448 * the end of the list after activation
1450 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1451 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1453 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1459 * gtk_window_set_mnemonic_modifier:
1460 * @window: a #GtkWindow
1461 * @modifier: the modifier mask used to activate
1462 * mnemonics on this window.
1464 * Sets the mnemonic modifier for this window.
1467 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1468 GdkModifierType modifier)
1470 g_return_if_fail (GTK_IS_WINDOW (window));
1471 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1473 window->mnemonic_modifier = modifier;
1474 gtk_window_notify_keys_changed (window);
1478 * gtk_window_get_mnemonic_modifier:
1479 * @window: a #GtkWindow
1481 * Returns the mnemonic modifier for this window. See
1482 * gtk_window_set_mnemonic_modifier().
1484 * Return value: the modifier mask used to activate
1485 * mnemonics on this window.
1488 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1490 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1492 return window->mnemonic_modifier;
1496 * gtk_window_set_position:
1497 * @window: a #GtkWindow.
1498 * @position: a position constraint.
1500 * Sets a position constraint for this window. If the old or new
1501 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1502 * the window to be repositioned to satisfy the new constraint.
1505 gtk_window_set_position (GtkWindow *window,
1506 GtkWindowPosition position)
1508 g_return_if_fail (GTK_IS_WINDOW (window));
1510 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1511 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1513 GtkWindowGeometryInfo *info;
1515 info = gtk_window_get_geometry_info (window, TRUE);
1517 /* this flag causes us to re-request the CENTER_ALWAYS
1518 * constraint in gtk_window_move_resize(), see
1519 * comment in that function.
1521 info->position_constraints_changed = TRUE;
1523 gtk_widget_queue_resize (GTK_WIDGET (window));
1526 window->position = position;
1528 g_object_notify (G_OBJECT (window), "window_position");
1532 * gtk_window_activate_focus:
1533 * @window: a #GtkWindow
1535 * Activates the current focused widget within the window.
1537 * Return value: %TRUE if a widget got activated.
1540 gtk_window_activate_focus (GtkWindow *window)
1542 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1544 if (window->focus_widget)
1546 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1547 gtk_widget_activate (window->focus_widget);
1555 * gtk_window_get_focus:
1556 * @window: a #GtkWindow
1558 * Retrieves the current focused widget within the window.
1559 * Note that this is the widget that would have the focus
1560 * if the toplevel window focused; if the toplevel window
1561 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1562 * not be %TRUE for the widget.
1564 * Return value: the currently focused widget, or %NULL if there is none.
1567 gtk_window_get_focus (GtkWindow *window)
1569 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1571 return window->focus_widget;
1575 * gtk_window_activate_default:
1576 * @window: a #GtkWindow
1578 * Activates the default widget for the window, unless the current
1579 * focused widget has been configured to receive the default action
1580 * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
1581 * focused widget is activated.
1583 * Return value: %TRUE if a widget got activated.
1586 gtk_window_activate_default (GtkWindow *window)
1588 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1590 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1591 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1593 gtk_widget_activate (window->default_widget);
1596 else if (window->focus_widget)
1598 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1599 gtk_widget_activate (window->focus_widget);
1607 * gtk_window_set_modal:
1608 * @window: a #GtkWindow
1609 * @modal: whether the window is modal
1611 * Sets a window modal or non-modal. Modal windows prevent interaction
1612 * with other windows in the same application. To keep modal dialogs
1613 * on top of main application windows, use
1614 * gtk_window_set_transient_for() to make the dialog transient for the
1615 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1616 * will then disallow lowering the dialog below the parent.
1621 gtk_window_set_modal (GtkWindow *window,
1624 g_return_if_fail (GTK_IS_WINDOW (window));
1626 modal = modal != FALSE;
1627 if (window->modal == modal)
1630 window->modal = modal;
1632 /* adjust desired modality state */
1633 if (GTK_WIDGET_REALIZED (window))
1635 GtkWidget *widget = GTK_WIDGET (window);
1638 gdk_window_set_modal_hint (widget->window, TRUE);
1640 gdk_window_set_modal_hint (widget->window, FALSE);
1643 if (GTK_WIDGET_VISIBLE (window))
1646 gtk_grab_add (GTK_WIDGET (window));
1648 gtk_grab_remove (GTK_WIDGET (window));
1651 g_object_notify (G_OBJECT (window), "modal");
1655 * gtk_window_get_modal:
1656 * @window: a #GtkWindow
1658 * Returns whether the window is modal. See gtk_window_set_modal().
1660 * Return value: %TRUE if the window is set to be modal and
1661 * establishes a grab when shown
1664 gtk_window_get_modal (GtkWindow *window)
1666 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1668 return window->modal;
1672 * gtk_window_list_toplevels:
1674 * Returns a list of all existing toplevel windows. The widgets
1675 * in the list are not individually referenced. If you want
1676 * to iterate through the list and perform actions involving
1677 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1678 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1679 * then unref all the widgets afterwards.
1681 * Return value: list of toplevel widgets
1684 gtk_window_list_toplevels (void)
1689 for (slist = toplevel_list; slist; slist = slist->next)
1690 list = g_list_prepend (list, slist->data);
1696 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1698 GList *embedded_windows;
1700 g_return_if_fail (GTK_IS_WINDOW (window));
1702 embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1703 if (embedded_windows)
1704 g_object_steal_qdata (G_OBJECT (window),
1705 g_quark_from_static_string ("gtk-embedded"));
1706 embedded_windows = g_list_prepend (embedded_windows,
1707 GUINT_TO_POINTER (xid));
1709 g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
1712 (GDestroyNotify) g_list_free : NULL);
1716 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1718 GList *embedded_windows;
1721 g_return_if_fail (GTK_IS_WINDOW (window));
1723 embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1724 if (embedded_windows)
1725 g_object_steal_qdata (G_OBJECT (window),
1726 g_quark_from_static_string ("gtk-embedded"));
1728 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1731 embedded_windows = g_list_remove_link (embedded_windows, node);
1732 g_list_free_1 (node);
1735 g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
1738 (GDestroyNotify) g_list_free : NULL);
1742 _gtk_window_reposition (GtkWindow *window,
1746 g_return_if_fail (GTK_IS_WINDOW (window));
1748 gtk_window_move (window, x, y);
1752 gtk_window_dispose (GObject *object)
1754 GtkWindow *window = GTK_WINDOW (object);
1756 gtk_window_set_focus (window, NULL);
1757 gtk_window_set_default (window, NULL);
1759 G_OBJECT_CLASS (parent_class)->dispose (object);
1763 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1765 gtk_widget_destroy (GTK_WIDGET (child));
1769 connect_parent_destroyed (GtkWindow *window)
1771 if (window->transient_parent)
1773 g_signal_connect (window->transient_parent,
1775 G_CALLBACK (parent_destroyed_callback),
1781 disconnect_parent_destroyed (GtkWindow *window)
1783 if (window->transient_parent)
1785 g_signal_handlers_disconnect_by_func (window->transient_parent,
1786 parent_destroyed_callback,
1792 gtk_window_transient_parent_realized (GtkWidget *parent,
1795 if (GTK_WIDGET_REALIZED (window))
1796 gdk_window_set_transient_for (window->window, parent->window);
1800 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1803 if (GTK_WIDGET_REALIZED (window))
1804 gdk_property_delete (window->window,
1805 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1809 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
1813 gtk_window_set_screen (window, parent->screen);
1817 gtk_window_unset_transient_for (GtkWindow *window)
1819 if (window->transient_parent)
1821 g_signal_handlers_disconnect_by_func (window->transient_parent,
1822 gtk_window_transient_parent_realized,
1824 g_signal_handlers_disconnect_by_func (window->transient_parent,
1825 gtk_window_transient_parent_unrealized,
1827 g_signal_handlers_disconnect_by_func (window->transient_parent,
1828 gtk_window_transient_parent_screen_changed,
1830 g_signal_handlers_disconnect_by_func (window->transient_parent,
1831 gtk_widget_destroyed,
1832 &window->transient_parent);
1834 if (window->destroy_with_parent)
1835 disconnect_parent_destroyed (window);
1837 window->transient_parent = NULL;
1842 * gtk_window_set_transient_for:
1843 * @window: a #GtkWindow
1844 * @parent: parent window
1846 * Dialog windows should be set transient for the main application
1847 * window they were spawned from. This allows <link
1848 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1849 * dialog on top of the main window, or center the dialog over the
1850 * main window. gtk_dialog_new_with_buttons() and other convenience
1851 * functions in GTK+ will sometimes call
1852 * gtk_window_set_transient_for() on your behalf.
1854 * On Windows, this function will and put the child window
1855 * on top of the parent, much as the window manager would have
1860 gtk_window_set_transient_for (GtkWindow *window,
1863 g_return_if_fail (GTK_IS_WINDOW (window));
1864 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1865 g_return_if_fail (window != parent);
1868 if (window->transient_parent)
1870 if (GTK_WIDGET_REALIZED (window) &&
1871 GTK_WIDGET_REALIZED (window->transient_parent) &&
1872 (!parent || !GTK_WIDGET_REALIZED (parent)))
1873 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1874 GTK_WIDGET (window));
1876 gtk_window_unset_transient_for (window);
1879 window->transient_parent = parent;
1883 g_signal_connect (parent, "destroy",
1884 G_CALLBACK (gtk_widget_destroyed),
1885 &window->transient_parent);
1886 g_signal_connect (parent, "realize",
1887 G_CALLBACK (gtk_window_transient_parent_realized),
1889 g_signal_connect (parent, "unrealize",
1890 G_CALLBACK (gtk_window_transient_parent_unrealized),
1892 g_signal_connect (parent, "notify::screen",
1893 G_CALLBACK (gtk_window_transient_parent_screen_changed),
1896 gtk_window_set_screen (window, parent->screen);
1898 if (window->destroy_with_parent)
1899 connect_parent_destroyed (window);
1901 if (GTK_WIDGET_REALIZED (window) &&
1902 GTK_WIDGET_REALIZED (parent))
1903 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1904 GTK_WIDGET (window));
1909 * gtk_window_get_transient_for:
1910 * @window: a #GtkWindow
1912 * Fetches the transient parent for this window. See
1913 * gtk_window_set_transient_for().
1915 * Return value: the transient parent for this window, or %NULL
1916 * if no transient parent has been set.
1919 gtk_window_get_transient_for (GtkWindow *window)
1921 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1923 return window->transient_parent;
1927 * gtk_window_set_type_hint:
1928 * @window: a #GtkWindow
1929 * @hint: the window type
1931 * By setting the type hint for the window, you allow the window
1932 * manager to decorate and handle the window in a way which is
1933 * suitable to the function of the window in your application.
1935 * This function should be called before the window becomes visible.
1937 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1938 * will sometimes call gtk_window_set_type_hint() on your behalf.
1942 gtk_window_set_type_hint (GtkWindow *window,
1943 GdkWindowTypeHint hint)
1945 g_return_if_fail (GTK_IS_WINDOW (window));
1946 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1947 window->type_hint = hint;
1951 * gtk_window_get_type_hint:
1952 * @window: a #GtkWindow
1954 * Gets the type hint for this window. See gtk_window_set_type_hint().
1956 * Return value: the type hint for @window.
1959 gtk_window_get_type_hint (GtkWindow *window)
1961 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1963 return window->type_hint;
1967 * gtk_window_set_skip_taskbar_hint:
1968 * @window: a #GtkWindow
1969 * @setting: %TRUE to keep this window from appearing in the task bar
1971 * Windows may set a hint asking the desktop environment not to display
1972 * the window in the task bar. This function toggles this hint.
1977 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
1980 GtkWindowPrivate *priv;
1982 g_return_if_fail (GTK_IS_WINDOW (window));
1984 priv = GTK_WINDOW_GET_PRIVATE (window);
1986 setting = setting != FALSE;
1988 if (priv->skips_taskbar != setting)
1990 priv->skips_taskbar = setting;
1991 if (GTK_WIDGET_REALIZED (window))
1992 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
1993 priv->skips_taskbar);
1994 g_object_notify (G_OBJECT (window), "skip_taskbar_hint");
1999 * gtk_window_get_skip_taskbar_hint:
2000 * @window: a #GtkWindow
2002 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2004 * Return value: %TRUE if window shouldn't be in taskbar
2009 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2011 GtkWindowPrivate *priv;
2013 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2015 priv = GTK_WINDOW_GET_PRIVATE (window);
2017 return priv->skips_taskbar;
2021 * gtk_window_set_skip_pager_hint:
2022 * @window: a #GtkWindow
2023 * @setting: %TRUE to keep this window from appearing in the pager
2025 * Windows may set a hint asking the desktop environment not to display
2026 * the window in the pager. This function toggles this hint.
2027 * (A "pager" is any desktop navigation tool such as a workspace
2028 * switcher that displays a thumbnail representation of the windows
2034 gtk_window_set_skip_pager_hint (GtkWindow *window,
2037 GtkWindowPrivate *priv;
2039 g_return_if_fail (GTK_IS_WINDOW (window));
2041 priv = GTK_WINDOW_GET_PRIVATE (window);
2043 setting = setting != FALSE;
2045 if (priv->skips_pager != setting)
2047 priv->skips_pager = setting;
2048 if (GTK_WIDGET_REALIZED (window))
2049 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2051 g_object_notify (G_OBJECT (window), "skip_pager_hint");
2056 * gtk_window_get_skip_pager_hint:
2057 * @window: a #GtkWindow
2059 * Gets the value set by gtk_window_set_skip_pager_hint().
2061 * Return value: %TRUE if window shouldn't be in pager
2066 gtk_window_get_skip_pager_hint (GtkWindow *window)
2068 GtkWindowPrivate *priv;
2070 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2072 priv = GTK_WINDOW_GET_PRIVATE (window);
2074 return priv->skips_pager;
2078 * gtk_window_set_destroy_with_parent:
2079 * @window: a #GtkWindow
2080 * @setting: whether to destroy @window with its transient parent
2082 * If @setting is %TRUE, then destroying the transient parent of @window
2083 * will also destroy @window itself. This is useful for dialogs that
2084 * shouldn't persist beyond the lifetime of the main window they're
2085 * associated with, for example.
2088 gtk_window_set_destroy_with_parent (GtkWindow *window,
2091 g_return_if_fail (GTK_IS_WINDOW (window));
2093 if (window->destroy_with_parent == (setting != FALSE))
2096 if (window->destroy_with_parent)
2098 disconnect_parent_destroyed (window);
2102 connect_parent_destroyed (window);
2105 window->destroy_with_parent = setting;
2107 g_object_notify (G_OBJECT (window), "destroy_with_parent");
2111 * gtk_window_get_destroy_with_parent:
2112 * @window: a #GtkWindow
2114 * Returns whether the window will be destroyed with its transient parent. See
2115 * gtk_window_set_destroy_with_parent ().
2117 * Return value: %TRUE if the window will be destroyed with its transient parent.
2120 gtk_window_get_destroy_with_parent (GtkWindow *window)
2122 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2124 return window->destroy_with_parent;
2127 static GtkWindowGeometryInfo*
2128 gtk_window_get_geometry_info (GtkWindow *window,
2131 GtkWindowGeometryInfo *info;
2133 info = window->geometry_info;
2134 if (!info && create)
2136 info = g_new0 (GtkWindowGeometryInfo, 1);
2138 info->default_width = -1;
2139 info->default_height = -1;
2140 info->resize_width = -1;
2141 info->resize_height = -1;
2142 info->initial_x = 0;
2143 info->initial_y = 0;
2144 info->initial_pos_set = FALSE;
2145 info->default_is_geometry = FALSE;
2146 info->position_constraints_changed = FALSE;
2147 info->last.configure_request.x = 0;
2148 info->last.configure_request.y = 0;
2149 info->last.configure_request.width = -1;
2150 info->last.configure_request.height = -1;
2151 info->widget = NULL;
2153 window->geometry_info = info;
2160 * gtk_window_set_geometry_hints:
2161 * @window: a #GtkWindow
2162 * @geometry_widget: widget the geometry hints will be applied to
2163 * @geometry: struct containing geometry information
2164 * @geom_mask: mask indicating which struct fields should be paid attention to
2166 * This function sets up hints about how a window can be resized by
2167 * the user. You can set a minimum and maximum size; allowed resize
2168 * increments (e.g. for xterm, you can only resize by the size of a
2169 * character); aspect ratios; and more. See the #GdkGeometry struct.
2173 gtk_window_set_geometry_hints (GtkWindow *window,
2174 GtkWidget *geometry_widget,
2175 GdkGeometry *geometry,
2176 GdkWindowHints geom_mask)
2178 GtkWindowGeometryInfo *info;
2180 g_return_if_fail (GTK_IS_WINDOW (window));
2181 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2183 info = gtk_window_get_geometry_info (window, TRUE);
2186 g_signal_handlers_disconnect_by_func (info->widget,
2187 gtk_widget_destroyed,
2190 info->widget = geometry_widget;
2192 g_signal_connect (geometry_widget, "destroy",
2193 G_CALLBACK (gtk_widget_destroyed),
2197 info->geometry = *geometry;
2199 /* We store gravity in window->gravity not in the hints. */
2200 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2202 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2204 gtk_window_set_gravity (window, geometry->win_gravity);
2207 gtk_widget_queue_resize (GTK_WIDGET (window));
2211 * gtk_window_set_decorated:
2212 * @window: a #GtkWindow
2213 * @setting: %TRUE to decorate the window
2215 * By default, windows are decorated with a title bar, resize
2216 * controls, etc. Some <link linkend="gtk-X11-arch">window
2217 * managers</link> allow GTK+ to disable these decorations, creating a
2218 * borderless window. If you set the decorated property to %FALSE
2219 * using this function, GTK+ will do its best to convince the window
2220 * manager not to decorate the window. Depending on the system, this
2221 * function may not have any effect when called on a window that is
2222 * already visible, so you should call it before calling gtk_window_show().
2224 * On Windows, this function always works, since there's no window manager
2229 gtk_window_set_decorated (GtkWindow *window,
2232 g_return_if_fail (GTK_IS_WINDOW (window));
2234 setting = setting != FALSE;
2236 if (setting == window->decorated)
2239 window->decorated = setting;
2241 if (GTK_WIDGET (window)->window)
2243 if (window->decorated)
2244 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2247 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2251 g_object_notify (G_OBJECT (window), "decorated");
2255 * gtk_window_get_decorated:
2256 * @window: a #GtkWindow
2258 * Returns whether the window has been set to have decorations
2259 * such as a title bar via gtk_window_set_decorated().
2261 * Return value: %TRUE if the window has been set to have decorations
2264 gtk_window_get_decorated (GtkWindow *window)
2266 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2268 return window->decorated;
2271 static GtkWindowIconInfo*
2272 get_icon_info (GtkWindow *window)
2274 return g_object_get_data (G_OBJECT (window),
2275 "gtk-window-icon-info");
2278 static GtkWindowIconInfo*
2279 ensure_icon_info (GtkWindow *window)
2281 GtkWindowIconInfo *info;
2283 info = get_icon_info (window);
2287 info = g_new0 (GtkWindowIconInfo, 1);
2288 g_object_set_data_full (G_OBJECT (window),
2289 "gtk-window-icon-info",
2304 get_screen_icon_info (GdkScreen *screen)
2306 ScreenIconInfo *info = g_object_get_data (G_OBJECT (screen),
2307 "gtk-window-default-icon-pixmap");
2310 info = g_new0 (ScreenIconInfo, 1);
2311 g_object_set_data (G_OBJECT (screen), "gtk-window-default-icon-pixmap", info);
2314 if (info->serial != default_icon_serial)
2318 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2319 info->pixmap = NULL;
2324 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2328 info->serial = default_icon_serial;
2335 get_pixmap_and_mask (GdkWindow *window,
2336 GtkWindowIconInfo *parent_info,
2337 gboolean is_default_list,
2339 GdkPixmap **pmap_return,
2340 GdkBitmap **mask_return)
2342 GdkScreen *screen = gdk_drawable_get_screen (window);
2343 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2344 GdkPixbuf *best_icon;
2348 *pmap_return = NULL;
2349 *mask_return = NULL;
2351 if (is_default_list &&
2352 default_icon_info->pixmap != NULL)
2354 /* Use shared icon pixmap for all windows on this screen.
2356 if (default_icon_info->pixmap)
2357 g_object_ref (default_icon_info->pixmap);
2358 if (default_icon_info->mask)
2359 g_object_ref (default_icon_info->mask);
2361 *pmap_return = default_icon_info->pixmap;
2362 *mask_return = default_icon_info->mask;
2364 else if (parent_info && parent_info->icon_pixmap)
2366 if (parent_info->icon_pixmap)
2367 g_object_ref (parent_info->icon_pixmap);
2368 if (parent_info->icon_mask)
2369 g_object_ref (parent_info->icon_mask);
2371 *pmap_return = parent_info->icon_pixmap;
2372 *mask_return = parent_info->icon_mask;
2376 #define IDEAL_SIZE 48
2378 best_size = G_MAXINT;
2380 tmp_list = icon_list;
2381 while (tmp_list != NULL)
2383 GdkPixbuf *pixbuf = tmp_list->data;
2386 /* average width and height - if someone passes in a rectangular
2387 * icon they deserve what they get.
2389 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2392 if (best_icon == NULL)
2399 /* icon is better if it's 32 pixels or larger, and closer to
2400 * the ideal size than the current best.
2403 (ABS (best_size - IDEAL_SIZE) <
2404 ABS (this - IDEAL_SIZE)))
2411 tmp_list = tmp_list->next;
2415 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2416 gdk_screen_get_system_colormap (screen),
2421 /* Save pmap/mask for others to use if appropriate */
2424 parent_info->icon_pixmap = *pmap_return;
2425 parent_info->icon_mask = *mask_return;
2427 if (parent_info->icon_pixmap)
2428 g_object_ref (parent_info->icon_pixmap);
2429 if (parent_info->icon_mask)
2430 g_object_ref (parent_info->icon_mask);
2432 else if (is_default_list)
2434 default_icon_info->pixmap = *pmap_return;
2435 default_icon_info->mask = *mask_return;
2437 if (default_icon_info->pixmap)
2438 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2439 (gpointer*)&default_icon_info->pixmap);
2440 if (default_icon_info->mask)
2441 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2442 (gpointer*)&default_icon_info->mask);
2448 gtk_window_realize_icon (GtkWindow *window)
2451 GtkWindowIconInfo *info;
2454 widget = GTK_WIDGET (window);
2456 g_return_if_fail (widget->window != NULL);
2458 /* no point setting an icon on override-redirect */
2459 if (window->type == GTK_WINDOW_POPUP)
2464 info = ensure_icon_info (window);
2469 g_return_if_fail (info->icon_pixmap == NULL);
2470 g_return_if_fail (info->icon_mask == NULL);
2472 info->using_default_icon = FALSE;
2473 info->using_parent_icon = FALSE;
2475 icon_list = info->icon_list;
2477 /* Inherit from transient parent */
2478 if (icon_list == NULL && window->transient_parent)
2480 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2482 info->using_parent_icon = TRUE;
2485 /* Inherit from default */
2486 if (icon_list == NULL)
2488 icon_list = default_icon_list;
2490 info->using_default_icon = TRUE;
2493 gdk_window_set_icon_list (widget->window, icon_list);
2495 get_pixmap_and_mask (widget->window,
2496 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2497 info->using_default_icon,
2502 /* This is a slight ICCCM violation since it's a color pixmap not
2503 * a bitmap, but everyone does it.
2505 gdk_window_set_icon (widget->window,
2510 info->realized = TRUE;
2514 gtk_window_unrealize_icon (GtkWindow *window)
2516 GtkWindowIconInfo *info;
2519 widget = GTK_WIDGET (window);
2521 info = get_icon_info (window);
2526 if (info->icon_pixmap)
2527 g_object_unref (info->icon_pixmap);
2529 if (info->icon_mask)
2530 g_object_unref (info->icon_mask);
2532 info->icon_pixmap = NULL;
2533 info->icon_mask = NULL;
2535 /* We don't clear the properties on the window, just figure the
2536 * window is going away.
2539 info->realized = FALSE;
2543 * gtk_window_set_icon_list:
2544 * @window: a #GtkWindow
2545 * @list: list of #GdkPixbuf
2547 * Sets up the icon representing a #GtkWindow. The icon is used when
2548 * the window is minimized (also known as iconified). Some window
2549 * managers or desktop environments may also place it in the window
2550 * frame, or display it in other contexts.
2552 * gtk_window_set_icon_list() allows you to pass in the same icon in
2553 * several hand-drawn sizes. The list should contain the natural sizes
2554 * your icon is available in; that is, don't scale the image before
2555 * passing it to GTK+. Scaling is postponed until the last minute,
2556 * when the desired final size is known, to allow best quality.
2558 * By passing several sizes, you may improve the final image quality
2559 * of the icon, by reducing or eliminating automatic image scaling.
2561 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2562 * larger images (64x64, 128x128) if you have them.
2564 * See also gtk_window_set_default_icon_list() to set the icon
2565 * for all windows in your application in one go.
2567 * Note that transient windows (those who have been set transient for another
2568 * window using gtk_window_set_transient_for()) will inherit their
2569 * icon from their transient parent. So there's no need to explicitly
2570 * set the icon on transient windows.
2573 gtk_window_set_icon_list (GtkWindow *window,
2576 GtkWindowIconInfo *info;
2578 g_return_if_fail (GTK_IS_WINDOW (window));
2580 info = ensure_icon_info (window);
2582 if (info->icon_list == list) /* check for NULL mostly */
2585 g_list_foreach (info->icon_list,
2586 (GFunc) g_object_unref, NULL);
2588 g_list_free (info->icon_list);
2590 info->icon_list = g_list_copy (list);
2591 g_list_foreach (info->icon_list,
2592 (GFunc) g_object_ref, NULL);
2594 g_object_notify (G_OBJECT (window), "icon");
2596 gtk_window_unrealize_icon (window);
2598 if (GTK_WIDGET_REALIZED (window))
2599 gtk_window_realize_icon (window);
2601 /* We could try to update our transient children, but I don't think
2602 * it's really worth it. If we did it, the best way would probably
2603 * be to have children connect to notify::icon_list
2608 * gtk_window_get_icon_list:
2609 * @window: a #GtkWindow
2611 * Retrieves the list of icons set by gtk_window_set_icon_list().
2612 * The list is copied, but the reference count on each
2613 * member won't be incremented.
2615 * Return value: copy of window's icon list
2618 gtk_window_get_icon_list (GtkWindow *window)
2620 GtkWindowIconInfo *info;
2622 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2624 info = get_icon_info (window);
2627 return g_list_copy (info->icon_list);
2633 * gtk_window_set_icon:
2634 * @window: a #GtkWindow
2635 * @icon: icon image, or %NULL
2637 * Sets up the icon representing a #GtkWindow. This icon is used when
2638 * the window is minimized (also known as iconified). Some window
2639 * managers or desktop environments may also place it in the window
2640 * frame, or display it in other contexts.
2642 * The icon should be provided in whatever size it was naturally
2643 * drawn; that is, don't scale the image before passing it to
2644 * GTK+. Scaling is postponed until the last minute, when the desired
2645 * final size is known, to allow best quality.
2647 * If you have your icon hand-drawn in multiple sizes, use
2648 * gtk_window_set_icon_list(). Then the best size will be used.
2650 * This function is equivalent to calling gtk_window_set_icon_list()
2651 * with a 1-element list.
2653 * See also gtk_window_set_default_icon_list() to set the icon
2654 * for all windows in your application in one go.
2657 gtk_window_set_icon (GtkWindow *window,
2662 g_return_if_fail (GTK_IS_WINDOW (window));
2663 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2668 list = g_list_append (list, icon);
2670 gtk_window_set_icon_list (window, list);
2675 * gtk_window_get_icon:
2676 * @window: a #GtkWindow
2678 * Gets the value set by gtk_window_set_icon() (or if you've
2679 * called gtk_window_set_icon_list(), gets the first icon in
2682 * Return value: icon for window
2685 gtk_window_get_icon (GtkWindow *window)
2687 GtkWindowIconInfo *info;
2689 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2691 info = get_icon_info (window);
2692 if (info && info->icon_list)
2693 return GDK_PIXBUF (info->icon_list->data);
2698 /* Load pixbuf, printing warning on failure if error == NULL
2701 load_pixbuf_verbosely (const char *filename,
2704 GError *local_err = NULL;
2707 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
2715 g_warning ("Error loading icon from file '%s':\n\t%s",
2716 filename, local_err->message);
2717 g_error_free (local_err);
2725 * gtk_window_set_icon_from_file:
2726 * @window: a #GtkWindow
2727 * @filename: location of icon file
2728 * @err: location to store error, or %NULL.
2730 * Sets the icon for @window.
2731 * Warns on failure if @err is %NULL.
2733 * This function is equivalent to calling gtk_window_set_icon()
2734 * with a pixbuf created by loading the image from @filename.
2736 * Returns: %TRUE if setting the icon succeeded.
2741 gtk_window_set_icon_from_file (GtkWindow *window,
2742 const gchar *filename,
2745 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2749 gtk_window_set_icon (window, pixbuf);
2750 g_object_unref (pixbuf);
2759 * gtk_window_set_default_icon_list:
2760 * @list: a list of #GdkPixbuf
2762 * Sets an icon list to be used as fallback for windows that haven't
2763 * had gtk_window_set_icon_list() called on them to set up a
2764 * window-specific icon list. This function allows you to set up the
2765 * icon for all windows in your app at once.
2767 * See gtk_window_set_icon_list() for more details.
2771 gtk_window_set_default_icon_list (GList *list)
2775 if (list == default_icon_list)
2778 /* Update serial so we don't used cached pixmaps/masks
2780 default_icon_serial++;
2782 g_list_foreach (default_icon_list,
2783 (GFunc) g_object_unref, NULL);
2785 g_list_free (default_icon_list);
2787 default_icon_list = g_list_copy (list);
2788 g_list_foreach (default_icon_list,
2789 (GFunc) g_object_ref, NULL);
2791 /* Update all toplevels */
2792 toplevels = gtk_window_list_toplevels ();
2793 tmp_list = toplevels;
2794 while (tmp_list != NULL)
2796 GtkWindowIconInfo *info;
2797 GtkWindow *w = tmp_list->data;
2799 info = get_icon_info (w);
2800 if (info && info->using_default_icon)
2802 gtk_window_unrealize_icon (w);
2803 if (GTK_WIDGET_REALIZED (w))
2804 gtk_window_realize_icon (w);
2807 tmp_list = tmp_list->next;
2809 g_list_free (toplevels);
2813 * gtk_window_set_default_icon:
2816 * Sets an icon to be used as fallback for windows that haven't
2817 * had gtk_window_set_icon() called on them from a pixbuf.
2822 gtk_window_set_default_icon (GdkPixbuf *icon)
2826 g_return_if_fail (GDK_IS_PIXBUF (icon));
2828 list = g_list_prepend (NULL, icon);
2829 gtk_window_set_default_icon_list (list);
2834 * gtk_window_set_default_icon_from_file:
2835 * @filename: location of icon file
2836 * @err: location to store error, or %NULL.
2838 * Sets an icon to be used as fallback for windows that haven't
2839 * had gtk_window_set_icon_list() called on them from a file
2840 * on disk. Warns on failure if @err is %NULL.
2842 * Returns: %TRUE if setting the icon succeeded.
2847 gtk_window_set_default_icon_from_file (const gchar *filename,
2850 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2854 gtk_window_set_default_icon (pixbuf);
2855 g_object_unref (pixbuf);
2864 * gtk_window_get_default_icon_list:
2866 * Gets the value set by gtk_window_set_default_icon_list().
2867 * The list is a copy and should be freed with g_list_free(),
2868 * but the pixbufs in the list have not had their reference count
2871 * Return value: copy of default icon list
2874 gtk_window_get_default_icon_list (void)
2876 return g_list_copy (default_icon_list);
2880 gtk_window_set_default_size_internal (GtkWindow *window,
2881 gboolean change_width,
2883 gboolean change_height,
2885 gboolean is_geometry)
2887 GtkWindowGeometryInfo *info;
2889 g_return_if_fail (change_width == FALSE || width >= -1);
2890 g_return_if_fail (change_height == FALSE || height >= -1);
2892 info = gtk_window_get_geometry_info (window, TRUE);
2894 g_object_freeze_notify (G_OBJECT (window));
2896 info->default_is_geometry = is_geometry != FALSE;
2906 info->default_width = width;
2908 g_object_notify (G_OBJECT (window), "default_width");
2919 info->default_height = height;
2921 g_object_notify (G_OBJECT (window), "default_height");
2924 g_object_thaw_notify (G_OBJECT (window));
2926 gtk_widget_queue_resize (GTK_WIDGET (window));
2930 * gtk_window_set_default_size:
2931 * @window: a #GtkWindow
2932 * @width: width in pixels, or -1 to unset the default width
2933 * @height: height in pixels, or -1 to unset the default height
2935 * Sets the default size of a window. If the window's "natural" size
2936 * (its size request) is larger than the default, the default will be
2937 * ignored. More generally, if the default size does not obey the
2938 * geometry hints for the window (gtk_window_set_geometry_hints() can
2939 * be used to set these explicitly), the default size will be clamped
2940 * to the nearest permitted size.
2942 * Unlike gtk_widget_set_size_request(), which sets a size request for
2943 * a widget and thus would keep users from shrinking the window, this
2944 * function only sets the initial size, just as if the user had
2945 * resized the window themselves. Users can still shrink the window
2946 * again as they normally would. Setting a default size of -1 means to
2947 * use the "natural" default size (the size request of the window).
2949 * For more control over a window's initial size and how resizing works,
2950 * investigate gtk_window_set_geometry_hints().
2952 * For some uses, gtk_window_resize() is a more appropriate function.
2953 * gtk_window_resize() changes the current size of the window, rather
2954 * than the size to be used on initial display. gtk_window_resize() always
2955 * affects the window itself, not the geometry widget.
2957 * The default size of a window only affects the first time a window is
2958 * shown; if a window is hidden and re-shown, it will remember the size
2959 * it had prior to hiding, rather than using the default size.
2961 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2962 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2965 gtk_window_set_default_size (GtkWindow *window,
2969 g_return_if_fail (GTK_IS_WINDOW (window));
2970 g_return_if_fail (width >= -1);
2971 g_return_if_fail (height >= -1);
2973 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
2977 * gtk_window_get_default_size:
2978 * @window: a #GtkWindow
2979 * @width: location to store the default width, or %NULL
2980 * @height: location to store the default height, or %NULL
2982 * Gets the default size of the window. A value of -1 for the width or
2983 * height indicates that a default size has not been explicitly set
2984 * for that dimension, so the "natural" size of the window will be
2989 gtk_window_get_default_size (GtkWindow *window,
2993 GtkWindowGeometryInfo *info;
2995 g_return_if_fail (GTK_IS_WINDOW (window));
2997 info = gtk_window_get_geometry_info (window, FALSE);
3000 *width = info ? info->default_width : -1;
3003 *height = info ? info->default_height : -1;
3007 * gtk_window_resize:
3008 * @window: a #GtkWindow
3009 * @width: width in pixels to resize the window to
3010 * @height: height in pixels to resize the window to
3012 * Resizes the window as if the user had done so, obeying geometry
3013 * constraints. The default geometry constraint is that windows may
3014 * not be smaller than their size request; to override this
3015 * constraint, call gtk_widget_set_size_request() to set the window's
3016 * request to a smaller value.
3018 * If gtk_window_resize() is called before showing a window for the
3019 * first time, it overrides any default size set with
3020 * gtk_window_set_default_size().
3022 * Windows may not be resized smaller than 1 by 1 pixels.
3026 gtk_window_resize (GtkWindow *window,
3030 GtkWindowGeometryInfo *info;
3032 g_return_if_fail (GTK_IS_WINDOW (window));
3033 g_return_if_fail (width > 0);
3034 g_return_if_fail (height > 0);
3036 info = gtk_window_get_geometry_info (window, TRUE);
3038 info->resize_width = width;
3039 info->resize_height = height;
3041 gtk_widget_queue_resize (GTK_WIDGET (window));
3045 * gtk_window_get_size:
3046 * @window: a #GtkWindow
3047 * @width: return location for width, or %NULL
3048 * @height: return location for height, or %NULL
3050 * Obtains the current size of @window. If @window is not onscreen,
3051 * it returns the size GTK+ will suggest to the <link
3052 * linkend="gtk-X11-arch">window manager</link> for the initial window
3053 * size (but this is not reliably the same as the size the window
3054 * manager will actually select). The size obtained by
3055 * gtk_window_get_size() is the last size received in a
3056 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
3057 * rather than querying the X server for the size. As a result, if you
3058 * call gtk_window_resize() then immediately call
3059 * gtk_window_get_size(), the size won't have taken effect yet. After
3060 * the window manager processes the resize request, GTK+ receives
3061 * notification that the size has changed via a configure event, and
3062 * the size of the window gets updated.
3064 * Note 1: Nearly any use of this function creates a race condition,
3065 * because the size of the window may change between the time that you
3066 * get the size and the time that you perform some action assuming
3067 * that size is the current size. To avoid race conditions, connect to
3068 * "configure_event" on the window and adjust your size-dependent
3069 * state to match the size delivered in the #GdkEventConfigure.
3071 * Note 2: The returned size does <emphasis>not</emphasis> include the
3072 * size of the window manager decorations (aka the window frame or
3073 * border). Those are not drawn by GTK+ and GTK+ has no reliable
3074 * method of determining their size.
3076 * Note 3: If you are getting a window size in order to position
3077 * the window onscreen, there may be a better way. The preferred
3078 * way is to simply set the window's semantic type with
3079 * gtk_window_set_type_hint(), which allows the window manager to
3080 * e.g. center dialogs. Also, if you set the transient parent of
3081 * dialogs with gtk_window_set_transient_for() window managers
3082 * will often center the dialog over its parent window. It's
3083 * much preferred to let the window manager handle these
3084 * things rather than doing it yourself, because all apps will
3085 * behave consistently and according to user prefs if the window
3086 * manager handles it. Also, the window manager can take the size
3087 * of the window decorations/border into account, while your
3088 * application cannot.
3090 * In any case, if you insist on application-specified window
3091 * positioning, there's <emphasis>still</emphasis> a better way than
3092 * doing it yourself - gtk_window_set_position() will frequently
3093 * handle the details for you.
3097 gtk_window_get_size (GtkWindow *window,
3104 g_return_if_fail (GTK_IS_WINDOW (window));
3106 widget = GTK_WIDGET (window);
3108 if (width == NULL && height == NULL)
3111 if (GTK_WIDGET_MAPPED (window))
3113 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3118 GdkRectangle configure_request;
3120 gtk_window_compute_configure_request (window,
3124 w = configure_request.width;
3125 h = configure_request.height;
3136 * @window: a #GtkWindow
3137 * @x: X coordinate to move window to
3138 * @y: Y coordinate to move window to
3140 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3141 * @window to the given position. Window managers are free to ignore
3142 * this; most window managers ignore requests for initial window
3143 * positions (instead using a user-defined placement algorithm) and
3144 * honor requests after the window has already been shown.
3146 * Note: the position is the position of the gravity-determined
3147 * reference point for the window. The gravity determines two things:
3148 * first, the location of the reference point in root window
3149 * coordinates; and second, which point on the window is positioned at
3150 * the reference point.
3152 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3153 * point is simply the @x, @y supplied to gtk_window_move(). The
3154 * top-left corner of the window decorations (aka window frame or
3155 * border) will be placed at @x, @y. Therefore, to position a window
3156 * at the top left of the screen, you want to use the default gravity
3157 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3159 * To position a window at the bottom right corner of the screen, you
3160 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3161 * point is at @x + the window width and @y + the window height, and
3162 * the bottom-right corner of the window border will be placed at that
3163 * reference point. So, to place a window in the bottom right corner
3164 * you would first set gravity to south east, then write:
3165 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3166 * gdk_screen_height () - window_height)</literal>.
3168 * The Extended Window Manager Hints specification at <ulink
3169 * url="http://www.freedesktop.org/standards/wm-spec.html">
3170 * http://www.freedesktop.org/standards/wm-spec.html</ulink> has a
3171 * nice table of gravities in the "implementation notes" section.
3173 * The gtk_window_get_position() documentation may also be relevant.
3177 gtk_window_move (GtkWindow *window,
3181 GtkWindowGeometryInfo *info;
3184 g_return_if_fail (GTK_IS_WINDOW (window));
3186 widget = GTK_WIDGET (window);
3188 info = gtk_window_get_geometry_info (window, TRUE);
3190 if (GTK_WIDGET_MAPPED (window))
3192 /* we have now sent a request with this position
3193 * with currently-active constraints, so toggle flag.
3195 info->position_constraints_changed = FALSE;
3197 /* we only constrain if mapped - if not mapped,
3198 * then gtk_window_compute_configure_request()
3199 * will apply the constraints later, and we
3200 * don't want to lose information about
3201 * what position the user set before then.
3202 * i.e. if you do a move() then turn off POS_CENTER
3203 * then show the window, your move() will work.
3205 gtk_window_constrain_position (window,
3206 widget->allocation.width,
3207 widget->allocation.height,
3210 /* Note that this request doesn't go through our standard request
3211 * framework, e.g. doesn't increment configure_request_count,
3212 * doesn't set info->last, etc.; that's because
3213 * we don't save the info needed to arrive at this same request
3216 * To gtk_window_move_resize(), this will end up looking exactly
3217 * the same as the position being changed by the window
3221 /* FIXME are we handling gravity properly for framed windows? */
3223 gdk_window_move (window->frame,
3224 x - window->frame_left,
3225 y - window->frame_top);
3227 gdk_window_move (GTK_WIDGET (window)->window,
3232 /* Save this position to apply on mapping */
3233 info->initial_x = x;
3234 info->initial_y = y;
3235 info->initial_pos_set = TRUE;
3240 * gtk_window_get_position:
3241 * @window: a #GtkWindow
3242 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3243 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3245 * This function returns the position you need to pass to
3246 * gtk_window_move() to keep @window in its current position. This
3247 * means that the meaning of the returned value varies with window
3248 * gravity. See gtk_window_move() for more details.
3250 * If you haven't changed the window gravity, its gravity will be
3251 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3252 * gets the position of the top-left corner of the window manager
3253 * frame for the window. gtk_window_move() sets the position of this
3254 * same top-left corner.
3256 * gtk_window_get_position() is not 100% reliable because the X Window System
3257 * does not specify a way to obtain the geometry of the
3258 * decorations placed on a window by the window manager.
3259 * Thus GTK+ is using a "best guess" that works with most
3262 * Moreover, nearly all window managers are historically broken with
3263 * respect to their handling of window gravity. So moving a window to
3264 * its current position as returned by gtk_window_get_position() tends
3265 * to result in moving the window slightly. Window managers are
3266 * slowly getting better over time.
3268 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3269 * frame is not relevant, and thus gtk_window_get_position() will
3270 * always produce accurate results. However you can't use static
3271 * gravity to do things like place a window in a corner of the screen,
3272 * because static gravity ignores the window manager decorations.
3274 * If you are saving and restoring your application's window
3275 * positions, you should know that it's impossible for applications to
3276 * do this without getting it somewhat wrong because applications do
3277 * not have sufficient knowledge of window manager state. The Correct
3278 * Mechanism is to support the session management protocol (see the
3279 * "GnomeClient" object in the GNOME libraries for example) and allow
3280 * the window manager to save your window sizes and positions.
3285 gtk_window_get_position (GtkWindow *window,
3291 g_return_if_fail (GTK_IS_WINDOW (window));
3293 widget = GTK_WIDGET (window);
3295 if (window->gravity == GDK_GRAVITY_STATIC)
3297 if (GTK_WIDGET_MAPPED (widget))
3299 /* This does a server round-trip, which is sort of wrong;
3300 * but a server round-trip is inevitable for
3301 * gdk_window_get_frame_extents() in the usual
3302 * NorthWestGravity case below, so not sure what else to
3303 * do. We should likely be consistent about whether we get
3304 * the client-side info or the server-side info.
3306 gdk_window_get_origin (widget->window, root_x, root_y);
3310 GdkRectangle configure_request;
3312 gtk_window_compute_configure_request (window,
3316 *root_x = configure_request.x;
3317 *root_y = configure_request.y;
3322 GdkRectangle frame_extents;
3327 if (GTK_WIDGET_MAPPED (widget))
3330 gdk_window_get_frame_extents (window->frame, &frame_extents);
3332 gdk_window_get_frame_extents (widget->window, &frame_extents);
3333 x = frame_extents.x;
3334 y = frame_extents.y;
3335 gtk_window_get_size (window, &w, &h);
3339 /* We just say the frame has 0 size on all sides.
3340 * Not sure what else to do.
3342 gtk_window_compute_configure_request (window,
3345 x = frame_extents.x;
3346 y = frame_extents.y;
3347 w = frame_extents.width;
3348 h = frame_extents.height;
3351 switch (window->gravity)
3353 case GDK_GRAVITY_NORTH:
3354 case GDK_GRAVITY_CENTER:
3355 case GDK_GRAVITY_SOUTH:
3356 /* Find center of frame. */
3357 x += frame_extents.width / 2;
3358 /* Center client window on that point. */
3362 case GDK_GRAVITY_SOUTH_EAST:
3363 case GDK_GRAVITY_EAST:
3364 case GDK_GRAVITY_NORTH_EAST:
3365 /* Find right edge of frame */
3366 x += frame_extents.width;
3367 /* Align left edge of client at that point. */
3374 switch (window->gravity)
3376 case GDK_GRAVITY_WEST:
3377 case GDK_GRAVITY_CENTER:
3378 case GDK_GRAVITY_EAST:
3379 /* Find center of frame. */
3380 y += frame_extents.height / 2;
3381 /* Center client window there. */
3384 case GDK_GRAVITY_SOUTH_WEST:
3385 case GDK_GRAVITY_SOUTH:
3386 case GDK_GRAVITY_SOUTH_EAST:
3387 /* Find south edge of frame */
3388 y += frame_extents.height;
3389 /* Place bottom edge of client there */
3404 * gtk_window_reshow_with_initial_size:
3405 * @window: a #GtkWindow
3407 * Hides @window, then reshows it, resetting the
3408 * default size and position of the window. Used
3409 * by GUI builders only.
3412 gtk_window_reshow_with_initial_size (GtkWindow *window)
3416 g_return_if_fail (GTK_IS_WINDOW (window));
3418 widget = GTK_WIDGET (window);
3420 gtk_widget_hide (widget);
3421 gtk_widget_unrealize (widget);
3422 gtk_widget_show (widget);
3426 gtk_window_destroy (GtkObject *object)
3428 GtkWindow *window = GTK_WINDOW (object);
3430 if (window->transient_parent)
3431 gtk_window_set_transient_for (window, NULL);
3433 /* frees the icons */
3434 gtk_window_set_icon_list (window, NULL);
3436 if (window->has_user_ref_count)
3438 window->has_user_ref_count = FALSE;
3439 g_object_unref (window);
3443 gtk_window_group_remove_window (window->group, window);
3445 gtk_window_free_key_hash (window);
3447 GTK_OBJECT_CLASS (parent_class)->destroy (object);
3451 gtk_window_mnemonic_hash_remove (gpointer key,
3455 GtkWindowMnemonic *mnemonic = key;
3456 GtkWindow *window = user;
3458 if (mnemonic->window == window)
3460 if (mnemonic->targets)
3462 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
3464 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
3465 name, mnemonic->targets->data);
3468 g_slist_free (mnemonic->targets);
3477 gtk_window_finalize (GObject *object)
3479 GtkWindow *window = GTK_WINDOW (object);
3481 toplevel_list = g_slist_remove (toplevel_list, window);
3483 g_free (window->title);
3484 g_free (window->wmclass_name);
3485 g_free (window->wmclass_class);
3486 g_free (window->wm_role);
3488 g_hash_table_foreach_remove (mnemonic_hash_table,
3489 gtk_window_mnemonic_hash_remove,
3491 if (window->geometry_info)
3493 if (window->geometry_info->widget)
3494 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3495 gtk_widget_destroyed,
3496 &window->geometry_info->widget);
3497 g_free (window->geometry_info);
3500 if (window->keys_changed_handler)
3502 g_source_remove (window->keys_changed_handler);
3503 window->keys_changed_handler = 0;
3506 G_OBJECT_CLASS (parent_class)->finalize (object);
3510 gtk_window_show (GtkWidget *widget)
3512 GtkWindow *window = GTK_WINDOW (widget);
3513 GtkContainer *container = GTK_CONTAINER (window);
3514 gboolean need_resize;
3516 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3518 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3519 container->need_resize = FALSE;
3523 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3524 GtkAllocation allocation = { 0, 0 };
3525 GdkRectangle configure_request;
3526 GdkGeometry new_geometry;
3528 gboolean was_realized;
3530 /* We are going to go ahead and perform this configure request
3531 * and then emulate a configure notify by going ahead and
3532 * doing a size allocate. Sort of a synchronous
3533 * mini-copy of gtk_window_move_resize() here.
3535 gtk_window_compute_configure_request (window,
3540 /* We update this because we are going to go ahead
3541 * and gdk_window_resize() below, rather than
3544 info->last.configure_request.width = configure_request.width;
3545 info->last.configure_request.height = configure_request.height;
3547 /* and allocate the window - this is normally done
3548 * in move_resize in response to configure notify
3550 allocation.width = configure_request.width;
3551 allocation.height = configure_request.height;
3552 gtk_widget_size_allocate (widget, &allocation);
3554 /* Then we guarantee we have a realize */
3555 was_realized = FALSE;
3556 if (!GTK_WIDGET_REALIZED (widget))
3558 gtk_widget_realize (widget);
3559 was_realized = TRUE;
3562 /* Must be done after the windows are realized,
3563 * so that the decorations can be read
3565 gtk_decorated_window_calculate_frame_size (window);
3567 /* We only send configure request if we didn't just finish
3568 * creating the window; if we just created the window
3569 * then we created it with widget->allocation anyhow.
3572 gdk_window_resize (widget->window,
3573 configure_request.width,
3574 configure_request.height);
3577 gtk_container_check_resize (container);
3579 gtk_widget_map (widget);
3581 /* Try to make sure that we have some focused widget
3583 #ifdef GDK_WINDOWING_X11
3584 if (!window->focus_widget && !GTK_IS_PLUG (window))
3586 if (!window->focus_widget)
3588 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
3591 gtk_grab_add (widget);
3595 gtk_window_hide (GtkWidget *widget)
3597 GtkWindow *window = GTK_WINDOW (widget);
3599 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3600 gtk_widget_unmap (widget);
3603 gtk_grab_remove (widget);
3607 gtk_window_map (GtkWidget *widget)
3609 GtkWindow *window = GTK_WINDOW (widget);
3610 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
3611 GdkWindow *toplevel;
3613 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3615 if (window->bin.child &&
3616 GTK_WIDGET_VISIBLE (window->bin.child) &&
3617 !GTK_WIDGET_MAPPED (window->bin.child))
3618 gtk_widget_map (window->bin.child);
3621 toplevel = window->frame;
3623 toplevel = widget->window;
3625 if (window->maximize_initially)
3626 gdk_window_maximize (toplevel);
3628 gdk_window_unmaximize (toplevel);
3630 if (window->stick_initially)
3631 gdk_window_stick (toplevel);
3633 gdk_window_unstick (toplevel);
3635 if (window->iconify_initially)
3636 gdk_window_iconify (toplevel);
3638 gdk_window_deiconify (toplevel);
3640 if (priv->fullscreen_initially)
3641 gdk_window_fullscreen (toplevel);
3643 gdk_window_unfullscreen (toplevel);
3645 gdk_window_set_keep_above (toplevel, priv->above_initially);
3647 gdk_window_set_keep_below (toplevel, priv->below_initially);
3649 /* No longer use the default settings */
3650 window->need_default_size = FALSE;
3651 window->need_default_position = FALSE;
3653 gdk_window_show (widget->window);
3656 gdk_window_show (window->frame);
3658 if (!disable_startup_notification &&
3659 !sent_startup_notification)
3661 sent_startup_notification = TRUE;
3662 gdk_notify_startup_complete ();
3667 gtk_window_unmap (GtkWidget *widget)
3669 GtkWindow *window = GTK_WINDOW (widget);
3670 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
3671 GtkWindowGeometryInfo *info;
3672 GdkWindowState state;
3674 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3676 gdk_window_withdraw (window->frame);
3678 gdk_window_withdraw (widget->window);
3680 window->configure_request_count = 0;
3681 window->configure_notify_received = FALSE;
3683 /* on unmap, we reset the default positioning of the window,
3684 * so it's placed again, but we don't reset the default
3685 * size of the window, so it's remembered.
3687 window->need_default_position = TRUE;
3689 info = gtk_window_get_geometry_info (window, FALSE);
3692 info->initial_pos_set = FALSE;
3693 info->position_constraints_changed = FALSE;
3696 state = gdk_window_get_state (widget->window);
3697 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
3698 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
3699 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
3700 priv->above_initially = state & GDK_WINDOW_STATE_ABOVE;
3701 priv->below_initially = state & GDK_WINDOW_STATE_BELOW;
3705 gtk_window_realize (GtkWidget *widget)
3708 GdkWindow *parent_window;
3709 GdkWindowAttr attributes;
3710 gint attributes_mask;
3712 window = GTK_WINDOW (widget);
3714 /* ensure widget tree is properly size allocated */
3715 if (widget->allocation.x == -1 &&
3716 widget->allocation.y == -1 &&
3717 widget->allocation.width == 1 &&
3718 widget->allocation.height == 1)
3720 GtkRequisition requisition;
3721 GtkAllocation allocation = { 0, 0, 200, 200 };
3723 gtk_widget_size_request (widget, &requisition);
3724 if (requisition.width || requisition.height)
3726 /* non-empty window */
3727 allocation.width = requisition.width;
3728 allocation.height = requisition.height;
3730 gtk_widget_size_allocate (widget, &allocation);
3732 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3734 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3737 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3739 switch (window->type)
3741 case GTK_WINDOW_TOPLEVEL:
3742 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3744 case GTK_WINDOW_POPUP:
3745 attributes.window_type = GDK_WINDOW_TEMP;
3748 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3752 attributes.title = window->title;
3753 attributes.wmclass_name = window->wmclass_name;
3754 attributes.wmclass_class = window->wmclass_class;
3755 attributes.wclass = GDK_INPUT_OUTPUT;
3756 attributes.visual = gtk_widget_get_visual (widget);
3757 attributes.colormap = gtk_widget_get_colormap (widget);
3759 if (window->has_frame)
3761 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3762 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3763 attributes.event_mask = (GDK_EXPOSURE_MASK |
3764 GDK_KEY_PRESS_MASK |
3765 GDK_ENTER_NOTIFY_MASK |
3766 GDK_LEAVE_NOTIFY_MASK |
3767 GDK_FOCUS_CHANGE_MASK |
3768 GDK_STRUCTURE_MASK |
3769 GDK_BUTTON_MOTION_MASK |
3770 GDK_POINTER_MOTION_HINT_MASK |
3771 GDK_BUTTON_PRESS_MASK |
3772 GDK_BUTTON_RELEASE_MASK);
3774 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3776 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
3777 &attributes, attributes_mask);
3779 gdk_window_set_user_data (window->frame, widget);
3781 attributes.window_type = GDK_WINDOW_CHILD;
3782 attributes.x = window->frame_left;
3783 attributes.y = window->frame_top;
3785 attributes_mask = GDK_WA_X | GDK_WA_Y;
3787 parent_window = window->frame;
3791 attributes_mask = 0;
3792 parent_window = gtk_widget_get_root_window (widget);
3795 attributes.width = widget->allocation.width;
3796 attributes.height = widget->allocation.height;
3797 attributes.event_mask = gtk_widget_get_events (widget);
3798 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3799 GDK_KEY_PRESS_MASK |
3800 GDK_KEY_RELEASE_MASK |
3801 GDK_ENTER_NOTIFY_MASK |
3802 GDK_LEAVE_NOTIFY_MASK |
3803 GDK_FOCUS_CHANGE_MASK |
3804 GDK_STRUCTURE_MASK);
3806 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3807 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3808 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3810 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3812 gdk_window_set_user_data (widget->window, window);
3814 widget->style = gtk_style_attach (widget->style, widget->window);
3815 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3817 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3819 /* This is a bad hack to set the window background. */
3820 gtk_window_paint (widget, NULL);
3822 if (window->transient_parent &&
3823 GTK_WIDGET_REALIZED (window->transient_parent))
3824 gdk_window_set_transient_for (widget->window,
3825 GTK_WIDGET (window->transient_parent)->window);
3827 if (window->wm_role)
3828 gdk_window_set_role (widget->window, window->wm_role);
3830 if (!window->decorated)
3831 gdk_window_set_decorations (widget->window, 0);
3833 gdk_window_set_type_hint (widget->window, window->type_hint);
3835 if (gtk_window_get_skip_pager_hint (window))
3837 g_print ("setting skip pager when realizing\n");
3838 gdk_window_set_skip_pager_hint (widget->window, TRUE);
3841 if (gtk_window_get_skip_taskbar_hint (window))
3842 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
3845 gdk_window_set_modal_hint (widget->window, TRUE);
3847 gdk_window_set_modal_hint (widget->window, FALSE);
3850 gtk_window_realize_icon (window);
3854 gtk_window_unrealize (GtkWidget *widget)
3857 GtkWindowGeometryInfo *info;
3859 window = GTK_WINDOW (widget);
3861 /* On unrealize, we reset the size of the window such
3862 * that we will re-apply the default sizing stuff
3863 * next time we show the window.
3865 * Default positioning is reset on unmap, instead of unrealize.
3867 window->need_default_size = TRUE;
3868 info = gtk_window_get_geometry_info (window, FALSE);
3871 info->resize_width = -1;
3872 info->resize_height = -1;
3873 info->last.configure_request.x = 0;
3874 info->last.configure_request.y = 0;
3875 info->last.configure_request.width = -1;
3876 info->last.configure_request.height = -1;
3877 /* be sure we reset geom hints on re-realize */
3878 info->last.flags = 0;
3883 gdk_window_set_user_data (window->frame, NULL);
3884 gdk_window_destroy (window->frame);
3885 window->frame = NULL;
3889 gtk_window_unrealize_icon (window);
3891 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3895 gtk_window_size_request (GtkWidget *widget,
3896 GtkRequisition *requisition)
3901 window = GTK_WINDOW (widget);
3902 bin = GTK_BIN (window);
3904 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3905 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3907 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3909 GtkRequisition child_requisition;
3911 gtk_widget_size_request (bin->child, &child_requisition);
3913 requisition->width += child_requisition.width;
3914 requisition->height += child_requisition.height;
3919 gtk_window_size_allocate (GtkWidget *widget,
3920 GtkAllocation *allocation)
3923 GtkAllocation child_allocation;
3925 window = GTK_WINDOW (widget);
3926 widget->allocation = *allocation;
3928 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3930 child_allocation.x = GTK_CONTAINER (window)->border_width;
3931 child_allocation.y = GTK_CONTAINER (window)->border_width;
3932 child_allocation.width =
3933 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3934 child_allocation.height =
3935 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3937 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3940 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3942 gdk_window_resize (window->frame,
3943 allocation->width + window->frame_left + window->frame_right,
3944 allocation->height + window->frame_top + window->frame_bottom);
3949 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3952 gboolean return_val;
3954 window = GTK_WINDOW (widget);
3956 if (window->frame && (event->any.window == window->frame))
3958 if ((event->type != GDK_KEY_PRESS) &&
3959 (event->type != GDK_KEY_RELEASE) &&
3960 (event->type != GDK_FOCUS_CHANGE))
3962 g_signal_stop_emission_by_name (widget, "event");
3964 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
3969 g_object_unref (event->any.window);
3970 event->any.window = g_object_ref (widget->window);
3978 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3980 GdkEventConfigure *configure_event;
3983 switch (event->type)
3986 configure_event = (GdkEventConfigure *)event;
3988 /* Invalidate the decorations */
3991 rect.width = configure_event->width;
3992 rect.height = configure_event->height;
3994 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3996 /* Pass on the (modified) configure event */
3997 configure_event->width -= window->frame_left + window->frame_right;
3998 configure_event->height -= window->frame_top + window->frame_bottom;
3999 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
4008 gtk_window_configure_event (GtkWidget *widget,
4009 GdkEventConfigure *event)
4011 GtkWindow *window = GTK_WINDOW (widget);
4012 gboolean expected_reply = window->configure_request_count > 0;
4014 /* window->configure_request_count incremented for each
4015 * configure request, and decremented to a min of 0 for
4016 * each configure notify.
4018 * All it means is that we know we will get at least
4019 * window->configure_request_count more configure notifies.
4020 * We could get more configure notifies than that; some
4021 * of the configure notifies we get may be unrelated to
4022 * the configure requests. But we will get at least
4023 * window->configure_request_count notifies.
4026 if (window->configure_request_count > 0)
4027 window->configure_request_count -= 1;
4029 /* As an optimization, we avoid a resize when possible.
4031 * The only times we can avoid a resize are:
4032 * - we know only the position changed, not the size
4033 * - we know we have made more requests and so will get more
4034 * notifies and can wait to resize when we get them
4037 if (!expected_reply &&
4038 (widget->allocation.width == event->width &&
4039 widget->allocation.height == event->height))
4043 * If we do need to resize, we do that by:
4044 * - filling in widget->allocation with the new size
4045 * - setting configure_notify_received to TRUE
4046 * for use in gtk_window_move_resize()
4047 * - queueing a resize, leading to invocation of
4048 * gtk_window_move_resize() in an idle handler
4052 window->configure_notify_received = TRUE;
4054 widget->allocation.width = event->width;
4055 widget->allocation.height = event->height;
4057 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4062 /* the accel_key and accel_mods fields of the key have to be setup
4063 * upon calling this function. it'll then return whether that key
4064 * is at all used as accelerator, and if so will OR in the
4065 * accel_flags member of the key.
4068 _gtk_window_query_nonaccels (GtkWindow *window,
4070 GdkModifierType accel_mods)
4072 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4074 /* movement keys are considered locked accels */
4077 static const guint bindings[] = {
4078 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
4079 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
4083 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
4084 if (bindings[i] == accel_key)
4088 /* mnemonics are considered locked accels */
4089 if (accel_mods == window->mnemonic_modifier)
4091 GtkWindowMnemonic mkey;
4093 mkey.window = window;
4094 mkey.keyval = accel_key;
4095 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
4103 gtk_window_key_press_event (GtkWidget *widget,
4110 window = GTK_WINDOW (widget);
4114 /* Check for mnemonics and accelerators
4117 handled = _gtk_window_activate_key (window, event);
4121 focus = window->focus_widget;
4123 g_object_ref (focus);
4126 focus && focus != widget &&
4127 gtk_widget_get_toplevel (focus) == widget)
4131 if (GTK_WIDGET_IS_SENSITIVE (focus))
4132 handled = gtk_widget_event (focus, (GdkEvent*) event);
4134 parent = focus->parent;
4136 g_object_ref (parent);
4138 g_object_unref (focus);
4144 g_object_unref (focus);
4147 /* Chain up, invokes binding set */
4148 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
4149 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4155 gtk_window_key_release_event (GtkWidget *widget,
4161 window = GTK_WINDOW (widget);
4163 if (window->focus_widget &&
4164 window->focus_widget != widget &&
4165 GTK_WIDGET_SENSITIVE (window->focus_widget))
4167 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
4170 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
4171 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
4177 gtk_window_real_activate_default (GtkWindow *window)
4179 gtk_window_activate_default (window);
4183 gtk_window_real_activate_focus (GtkWindow *window)
4185 gtk_window_activate_focus (window);
4189 gtk_window_move_focus (GtkWindow *window,
4190 GtkDirectionType dir)
4192 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4194 if (!GTK_CONTAINER (window)->focus_child)
4195 gtk_window_set_focus (window, NULL);
4199 gtk_window_enter_notify_event (GtkWidget *widget,
4200 GdkEventCrossing *event)
4206 gtk_window_leave_notify_event (GtkWidget *widget,
4207 GdkEventCrossing *event)
4213 do_focus_change (GtkWidget *widget,
4216 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4218 g_object_ref (widget);
4221 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4223 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4225 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4226 fevent->focus_change.window = widget->window;
4228 g_object_ref (widget->window);
4229 fevent->focus_change.in = in;
4231 gtk_widget_event (widget, fevent);
4233 g_object_notify (G_OBJECT (widget), "has_focus");
4235 g_object_unref (widget);
4236 gdk_event_free (fevent);
4240 gtk_window_focus_in_event (GtkWidget *widget,
4241 GdkEventFocus *event)
4243 GtkWindow *window = GTK_WINDOW (widget);
4245 /* It appears spurious focus in events can occur when
4246 * the window is hidden. So we'll just check to see if
4247 * the window is visible before actually handling the
4250 if (GTK_WIDGET_VISIBLE (widget))
4252 _gtk_window_set_has_toplevel_focus (window, TRUE);
4253 _gtk_window_set_is_active (window, TRUE);
4260 gtk_window_focus_out_event (GtkWidget *widget,
4261 GdkEventFocus *event)
4263 GtkWindow *window = GTK_WINDOW (widget);
4265 _gtk_window_set_has_toplevel_focus (window, FALSE);
4266 _gtk_window_set_is_active (window, FALSE);
4271 static GdkAtom atom_rcfiles = GDK_NONE;
4274 gtk_window_read_rcfiles (GtkWidget *widget,
4275 GdkEventClient *event)
4277 GList *embedded_windows;
4279 embedded_windows = g_object_get_data (G_OBJECT (widget), "gtk-embedded");
4280 if (embedded_windows)
4282 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4285 for (i = 0; i < 5; i++)
4286 send_event->client.data.l[i] = 0;
4287 send_event->client.data_format = 32;
4288 send_event->client.message_type = atom_rcfiles;
4290 while (embedded_windows)
4292 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4293 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4294 embedded_windows = embedded_windows->next;
4297 gdk_event_free (send_event);
4300 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4304 gtk_window_client_event (GtkWidget *widget,
4305 GdkEventClient *event)
4308 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
4310 if (event->message_type == atom_rcfiles)
4311 gtk_window_read_rcfiles (widget, event);
4317 gtk_window_check_resize (GtkContainer *container)
4319 GtkWindow *window = GTK_WINDOW (container);
4321 if (GTK_WIDGET_VISIBLE (container))
4322 gtk_window_move_resize (window);
4326 gtk_window_focus (GtkWidget *widget,
4327 GtkDirectionType direction)
4331 GtkContainer *container;
4332 GtkWidget *old_focus_child;
4335 container = GTK_CONTAINER (widget);
4336 window = GTK_WINDOW (widget);
4337 bin = GTK_BIN (widget);
4339 old_focus_child = container->focus_child;
4341 /* We need a special implementation here to deal properly with wrapping
4342 * around in the tab chain without the danger of going into an
4345 if (old_focus_child)
4347 if (gtk_widget_child_focus (old_focus_child, direction))
4351 if (window->focus_widget)
4353 if (direction == GTK_DIR_LEFT ||
4354 direction == GTK_DIR_RIGHT ||
4355 direction == GTK_DIR_UP ||
4356 direction == GTK_DIR_DOWN)
4361 /* Wrapped off the end, clear the focus setting for the toplpevel */
4362 parent = window->focus_widget->parent;
4365 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4366 parent = GTK_WIDGET (parent)->parent;
4369 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4372 /* Now try to focus the first widget in the window */
4375 if (gtk_widget_child_focus (bin->child, direction))
4383 gtk_window_real_set_focus (GtkWindow *window,
4386 GtkWidget *old_focus = window->focus_widget;
4387 gboolean def_flags = 0;
4391 g_object_ref (old_focus);
4392 g_object_freeze_notify (G_OBJECT (old_focus));
4396 g_object_ref (focus);
4397 g_object_freeze_notify (G_OBJECT (focus));
4400 if (window->default_widget)
4401 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4403 if (window->focus_widget)
4405 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4406 (window->focus_widget != window->default_widget))
4408 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4410 if (window->default_widget)
4411 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4414 window->focus_widget = NULL;
4416 if (window->has_focus)
4417 do_focus_change (old_focus, FALSE);
4419 g_object_notify (G_OBJECT (old_focus), "is_focus");
4422 /* The above notifications may have set a new focus widget,
4423 * if so, we don't want to override it.
4425 if (focus && !window->focus_widget)
4427 window->focus_widget = focus;
4429 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4430 (window->focus_widget != window->default_widget))
4432 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4433 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4435 if (window->default_widget)
4436 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4439 if (window->has_focus)
4440 do_focus_change (window->focus_widget, TRUE);
4442 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4445 /* If the default widget changed, a redraw will have been queued
4446 * on the old and new default widgets by gtk_window_set_default(), so
4447 * we only have to worry about the case where it didn't change.
4448 * We'll sometimes queue a draw twice on the new widget but that
4451 if (window->default_widget &&
4452 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
4453 gtk_widget_queue_draw (window->default_widget);
4457 g_object_thaw_notify (G_OBJECT (old_focus));
4458 g_object_unref (old_focus);
4462 g_object_thaw_notify (G_OBJECT (focus));
4463 g_object_unref (focus);
4468 * _gtk_window_unset_focus_and_default:
4469 * @window: a #GtkWindow
4470 * @widget: a widget inside of @window
4472 * Checks whether the focus and default widgets of @window are
4473 * @widget or a descendent of @widget, and if so, unset them.
4476 _gtk_window_unset_focus_and_default (GtkWindow *window,
4482 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
4484 child = window->focus_widget;
4486 while (child && child != widget)
4487 child = child->parent;
4489 if (child == widget)
4490 gtk_window_set_focus (GTK_WINDOW (window), NULL);
4493 child = window->default_widget;
4495 while (child && child != widget)
4496 child = child->parent;
4498 if (child == widget)
4499 gtk_window_set_default (window, NULL);
4502 /*********************************
4503 * Functions related to resizing *
4504 *********************************/
4506 /* This function doesn't constrain to geometry hints */
4508 gtk_window_compute_configure_request_size (GtkWindow *window,
4512 GtkRequisition requisition;
4513 GtkWindowGeometryInfo *info;
4517 * - we've done a size request
4520 widget = GTK_WIDGET (window);
4522 info = gtk_window_get_geometry_info (window, FALSE);
4524 if (window->need_default_size)
4526 gtk_widget_get_child_requisition (widget, &requisition);
4528 /* Default to requisition */
4529 *width = requisition.width;
4530 *height = requisition.height;
4532 /* If window is empty so requests 0, default to random nonzero size */
4533 if (*width == 0 && *height == 0)
4539 /* Override requisition with default size */
4543 gint base_width = 0;
4544 gint base_height = 0;
4546 gint height_inc = 1;
4548 if (info->default_is_geometry &&
4549 (info->default_width > 0 || info->default_height > 0))
4551 GdkGeometry geometry;
4554 gtk_window_compute_hints (window, &geometry, &flags);
4556 if (flags & GDK_HINT_BASE_SIZE)
4558 base_width = geometry.base_width;
4559 base_height = geometry.base_height;
4561 else if (flags & GDK_HINT_MIN_SIZE)
4563 base_width = geometry.min_width;
4564 base_height = geometry.min_height;
4566 if (flags & GDK_HINT_RESIZE_INC)
4568 width_inc = geometry.width_inc;
4569 height_inc = geometry.height_inc;
4573 if (info->default_width > 0)
4574 *width = info->default_width * width_inc + base_width;
4576 if (info->default_height > 0)
4577 *height = info->default_height * height_inc + base_height;
4582 /* Default to keeping current size */
4583 *width = widget->allocation.width;
4584 *height = widget->allocation.height;
4587 /* Override any size with gtk_window_resize() values */
4590 if (info->resize_width > 0)
4591 *width = info->resize_width;
4593 if (info->resize_height > 0)
4594 *height = info->resize_height;
4598 static GtkWindowPosition
4599 get_effective_position (GtkWindow *window)
4601 GtkWindowPosition pos = window->position;
4602 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
4603 (window->transient_parent == NULL ||
4604 !GTK_WIDGET_MAPPED (window->transient_parent)))
4605 pos = GTK_WIN_POS_NONE;
4611 get_center_monitor_of_window (GtkWindow *window)
4613 /* We could try to sort out the relative positions of the monitors and
4614 * stuff, or we could just be losers and assume you have a row
4615 * or column of monitors.
4617 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
4621 get_monitor_containing_pointer (GtkWindow *window)
4625 GdkScreen *window_screen;
4626 GdkScreen *pointer_screen;
4628 window_screen = gtk_window_check_screen (window);
4629 gdk_display_get_pointer (gdk_screen_get_display (window_screen),
4633 if (pointer_screen == window_screen)
4634 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
4642 center_window_on_monitor (GtkWindow *window,
4648 GdkRectangle monitor;
4651 monitor_num = get_monitor_containing_pointer (window);
4653 if (monitor_num == -1)
4654 monitor_num = get_center_monitor_of_window (window);
4656 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
4657 monitor_num, &monitor);
4659 *x = (monitor.width - w) / 2 + monitor.x;
4660 *y = (monitor.height - h) / 2 + monitor.y;
4662 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
4663 * and WM decorations.
4672 clamp_window_to_rectangle (gint *x,
4676 const GdkRectangle *rect)
4678 gint outside_w, outside_h;
4680 outside_w = (*x + w) - (rect->x + rect->width);
4684 outside_h = (*y + h) - (rect->y + rect->height);
4688 /* if larger than the screen, center on the screen. */
4690 *x += (rect->x - *x) / 2;
4692 *y += (rect->y - *y) / 2;
4697 gtk_window_compute_configure_request (GtkWindow *window,
4698 GdkRectangle *request,
4699 GdkGeometry *geometry,
4702 GdkGeometry new_geometry;
4706 GtkWindowPosition pos;
4707 GtkWidget *parent_widget;
4708 GtkWindowGeometryInfo *info;
4712 widget = GTK_WIDGET (window);
4714 screen = gtk_window_check_screen (window);
4716 gtk_widget_size_request (widget, NULL);
4717 gtk_window_compute_configure_request_size (window, &w, &h);
4719 gtk_window_compute_hints (window, &new_geometry, &new_flags);
4720 gtk_window_constrain_size (window,
4721 &new_geometry, new_flags,
4725 parent_widget = (GtkWidget*) window->transient_parent;
4727 pos = get_effective_position (window);
4728 info = gtk_window_get_geometry_info (window, TRUE);
4730 /* by default, don't change position requested */
4731 x = info->last.configure_request.x;
4732 y = info->last.configure_request.y;
4734 if (window->need_default_position)
4737 /* FIXME this all interrelates with window gravity.
4738 * For most of them I think we want to set GRAVITY_CENTER.
4740 * Not sure how to go about that.
4745 /* here we are only handling CENTER_ALWAYS
4746 * as it relates to default positioning,
4747 * where it's equivalent to simply CENTER
4749 case GTK_WIN_POS_CENTER_ALWAYS:
4750 case GTK_WIN_POS_CENTER:
4751 center_window_on_monitor (window, w, h, &x, &y);
4754 case GTK_WIN_POS_CENTER_ON_PARENT:
4757 GdkRectangle monitor;
4760 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
4762 if (parent_widget->window != NULL)
4763 monitor_num = gdk_screen_get_monitor_at_window (screen,
4764 parent_widget->window);
4768 gdk_window_get_origin (parent_widget->window,
4771 x = ox + (parent_widget->allocation.width - w) / 2;
4772 y = oy + (parent_widget->allocation.height - h) / 2;
4774 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4775 * WM decorations. If parent wasn't on a monitor, just
4778 if (monitor_num >= 0)
4780 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
4781 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4786 case GTK_WIN_POS_MOUSE:
4788 gint screen_width = gdk_screen_get_width (screen);
4789 gint screen_height = gdk_screen_get_height (screen);
4791 GdkRectangle monitor;
4792 GdkScreen *pointer_screen;
4795 gdk_display_get_pointer (gdk_screen_get_display (screen),
4799 if (pointer_screen == screen)
4800 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
4806 x = CLAMP (x, 0, screen_width - w);
4807 y = CLAMP (y, 0, screen_height - h);
4809 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4810 * WM decorations. Don't try to figure out what's going
4811 * on if the mouse wasn't inside a monitor.
4813 if (monitor_num >= 0)
4815 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
4816 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4824 } /* if (window->need_default_position) */
4826 if (window->need_default_position &&
4827 info->initial_pos_set)
4829 x = info->initial_x;
4830 y = info->initial_y;
4831 gtk_window_constrain_position (window, w, h, &x, &y);
4837 request->height = h;
4840 *geometry = new_geometry;
4846 gtk_window_constrain_position (GtkWindow *window,
4852 /* See long comments in gtk_window_move_resize()
4853 * on when it's safe to call this function.
4855 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4857 gint center_x, center_y;
4859 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
4867 gtk_window_move_resize (GtkWindow *window)
4871 * First we determine whether any information has changed that would
4872 * cause us to revise our last configure request. If we would send
4873 * a different configure request from last time, then
4874 * configure_request_size_changed = TRUE or
4875 * configure_request_pos_changed = TRUE. configure_request_size_changed
4876 * may be true due to new hints, a gtk_window_resize(), or whatever.
4877 * configure_request_pos_changed may be true due to gtk_window_set_position()
4878 * or gtk_window_move().
4880 * If the configure request has changed, we send off a new one. To
4881 * ensure GTK+ invariants are maintained (resize queue does what it
4882 * should), we go ahead and size_allocate the requested size in this
4885 * If the configure request has not changed, we don't ever resend
4886 * it, because it could mean fighting the user or window manager.
4889 * To prepare the configure request, we come up with a base size/pos:
4890 * - the one from gtk_window_move()/gtk_window_resize()
4891 * - else default_width, default_height if we haven't ever
4893 * - else the size request if we haven't ever been mapped,
4894 * as a substitute default size
4895 * - else the current size of the window, as received from
4896 * configure notifies (i.e. the current allocation)
4898 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4899 * the position request to be centered.
4902 GtkContainer *container;
4903 GtkWindowGeometryInfo *info;
4904 GdkGeometry new_geometry;
4906 GdkRectangle new_request;
4907 gboolean configure_request_size_changed;
4908 gboolean configure_request_pos_changed;
4909 gboolean hints_changed; /* do we need to send these again */
4910 GtkWindowLastGeometryInfo saved_last_info;
4912 widget = GTK_WIDGET (window);
4913 container = GTK_CONTAINER (widget);
4914 info = gtk_window_get_geometry_info (window, TRUE);
4916 configure_request_size_changed = FALSE;
4917 configure_request_pos_changed = FALSE;
4919 gtk_window_compute_configure_request (window, &new_request,
4920 &new_geometry, &new_flags);
4922 /* This check implies the invariant that we never set info->last
4923 * without setting the hints and sending off a configure request.
4925 * If we change info->last without sending the request, we may
4928 if (info->last.configure_request.x != new_request.x ||
4929 info->last.configure_request.y != new_request.y)
4930 configure_request_pos_changed = TRUE;
4932 if ((info->last.configure_request.width != new_request.width ||
4933 info->last.configure_request.height != new_request.height))
4934 configure_request_size_changed = TRUE;
4936 hints_changed = FALSE;
4938 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4939 &new_geometry, new_flags))
4941 hints_changed = TRUE;
4944 /* Position Constraints
4945 * ====================
4947 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4948 * a default. The other POS_ values are used only when the
4949 * window is shown, not after that.
4951 * However, we can't implement a position constraint as
4952 * "anytime the window size changes, center the window"
4953 * because this may well end up fighting the WM or user. In
4954 * fact it gets in an infinite loop with at least one WM.
4956 * Basically, applications are in no way in a position to
4957 * constrain the position of a window, with one exception:
4958 * override redirect windows. (Really the intended purpose
4959 * of CENTER_ALWAYS anyhow, I would think.)
4961 * So the way we implement this "constraint" is to say that when WE
4962 * cause a move or resize, i.e. we make a configure request changing
4963 * window size, we recompute the CENTER_ALWAYS position to reflect
4964 * the new window size, and include it in our request. Also, if we
4965 * just turned on CENTER_ALWAYS we snap to center with a new
4966 * request. Otherwise, if we are just NOTIFIED of a move or resize
4967 * done by someone else e.g. the window manager, we do NOT send a
4968 * new configure request.
4970 * For override redirect windows, this works fine; all window
4971 * sizes are from our configure requests. For managed windows,
4972 * it is at least semi-sane, though who knows what the
4973 * app author is thinking.
4976 /* This condition should be kept in sync with the condition later on
4977 * that determines whether we send a configure request. i.e. we
4978 * should do this position constraining anytime we were going to
4979 * send a configure request anyhow, plus when constraints have
4982 if (configure_request_pos_changed ||
4983 configure_request_size_changed ||
4985 info->position_constraints_changed)
4987 /* We request the constrained position if:
4988 * - we were changing position, and need to clamp
4989 * the change to the constraint
4990 * - we're changing the size anyway
4991 * - set_position() was called to toggle CENTER_ALWAYS on
4994 gtk_window_constrain_position (window,
5000 /* Update whether we need to request a move */
5001 if (info->last.configure_request.x != new_request.x ||
5002 info->last.configure_request.y != new_request.y)
5003 configure_request_pos_changed = TRUE;
5005 configure_request_pos_changed = FALSE;
5009 if (window->type == GTK_WINDOW_TOPLEVEL)
5011 int notify_x, notify_y;
5013 /* this is the position from the last configure notify */
5014 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
5016 g_message ("--- %s ---\n"
5017 "last : %d,%d\t%d x %d\n"
5018 "this : %d,%d\t%d x %d\n"
5019 "alloc : %d,%d\t%d x %d\n"
5021 "resize: \t%d x %d\n"
5022 "size_changed: %d pos_changed: %d hints_changed: %d\n"
5023 "configure_notify_received: %d\n"
5024 "configure_request_count: %d\n"
5025 "position_constraints_changed: %d\n",
5026 window->title ? window->title : "(no title)",
5027 info->last.configure_request.x,
5028 info->last.configure_request.y,
5029 info->last.configure_request.width,
5030 info->last.configure_request.height,
5036 widget->allocation.width,
5037 widget->allocation.height,
5038 widget->requisition.width,
5039 widget->requisition.height,
5041 info->resize_height,
5042 configure_request_pos_changed,
5043 configure_request_size_changed,
5045 window->configure_notify_received,
5046 window->configure_request_count,
5047 info->position_constraints_changed);
5051 saved_last_info = info->last;
5052 info->last.geometry = new_geometry;
5053 info->last.flags = new_flags;
5054 info->last.configure_request = new_request;
5056 /* need to set PPosition so the WM will look at our position,
5057 * but we don't want to count PPosition coming and going as a hints
5058 * change for future iterations. So we saved info->last prior to
5062 /* Also, if the initial position was explicitly set, then we always
5063 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
5067 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
5068 * this is an initial map
5071 if ((configure_request_pos_changed ||
5072 info->initial_pos_set ||
5073 (window->need_default_position &&
5074 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
5075 (new_flags & GDK_HINT_POS) == 0)
5077 new_flags |= GDK_HINT_POS;
5078 hints_changed = TRUE;
5081 /* Set hints if necessary
5084 gdk_window_set_geometry_hints (widget->window,
5088 /* handle resizing/moving and widget tree allocation
5090 if (window->configure_notify_received)
5092 GtkAllocation allocation;
5094 /* If we have received a configure event since
5095 * the last time in this function, we need to
5096 * accept our new size and size_allocate child widgets.
5097 * (see gtk_window_configure_event() for more details).
5099 * 1 or more configure notifies may have been received.
5100 * Also, configure_notify_received will only be TRUE
5101 * if all expected configure notifies have been received
5102 * (one per configure request), as an optimization.
5105 window->configure_notify_received = FALSE;
5107 /* gtk_window_configure_event() filled in widget->allocation */
5108 allocation = widget->allocation;
5109 gtk_widget_size_allocate (widget, &allocation);
5111 /* If the configure request changed, it means that
5113 * 1) coincidentally changed hints or widget properties
5114 * impacting the configure request before getting
5115 * a configure notify, or
5116 * 2) some broken widget is changing its size request
5117 * during size allocation, resulting in
5118 * a false appearance of changed configure request.
5120 * For 1), we could just go ahead and ask for the
5121 * new size right now, but doing that for 2)
5122 * might well be fighting the user (and can even
5123 * trigger a loop). Since we really don't want to
5124 * do that, we requeue a resize in hopes that
5125 * by the time it gets handled, the child has seen
5126 * the light and is willing to go along with the
5127 * new size. (this happens for the zvt widget, since
5128 * the size_allocate() above will have stored the
5129 * requisition corresponding to the new size in the
5132 * This doesn't buy us anything for 1), but it shouldn't
5133 * hurt us too badly, since it is what would have
5134 * happened if we had gotten the configure event before
5135 * the new size had been set.
5138 if (configure_request_size_changed ||
5139 configure_request_pos_changed)
5141 /* Don't change the recorded last info after all, because we
5142 * haven't actually updated to the new info yet - we decided
5143 * to postpone our configure request until later.
5145 info->last = saved_last_info;
5147 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
5150 return; /* Bail out, we didn't really process the move/resize */
5152 else if ((configure_request_size_changed || hints_changed) &&
5153 (widget->allocation.width != new_request.width ||
5154 widget->allocation.height != new_request.height))
5157 /* We are in one of the following situations:
5158 * A. configure_request_size_changed
5159 * our requisition has changed and we need a different window size,
5160 * so we request it from the window manager.
5161 * B. !configure_request_size_changed && hints_changed
5162 * the window manager rejects our size, but we have just changed the
5163 * window manager hints, so there's a chance our request will
5164 * be honoured this time, so we try again.
5166 * However, if the new requisition is the same as the current allocation,
5167 * we don't request it again, since we won't get a ConfigureNotify back from
5168 * the window manager unless it decides to change our requisition. If
5169 * we don't get the ConfigureNotify back, the resize queue will never be run.
5172 /* Now send the configure request */
5173 if (configure_request_pos_changed)
5177 gdk_window_move_resize (window->frame,
5178 new_request.x - window->frame_left,
5179 new_request.y - window->frame_top,
5180 new_request.width + window->frame_left + window->frame_right,
5181 new_request.height + window->frame_top + window->frame_bottom);
5182 gdk_window_resize (widget->window,
5183 new_request.width, new_request.height);
5186 gdk_window_move_resize (widget->window,
5187 new_request.x, new_request.y,
5188 new_request.width, new_request.height);
5190 else /* only size changed */
5193 gdk_window_resize (window->frame,
5194 new_request.width + window->frame_left + window->frame_right,
5195 new_request.height + window->frame_top + window->frame_bottom);
5196 gdk_window_resize (widget->window,
5197 new_request.width, new_request.height);
5200 /* Increment the number of have-not-yet-received-notify requests */
5201 window->configure_request_count += 1;
5203 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5204 * configure event in response to our resizing request.
5205 * the configure event will cause a new resize with
5206 * ->configure_notify_received=TRUE.
5207 * until then, we want to
5208 * - discard expose events
5209 * - coalesce resizes for our children
5210 * - defer any window resizes until the configure event arrived
5211 * to achieve this, we queue a resize for the window, but remove its
5212 * resizing handler, so resizing will not be handled from the next
5213 * idle handler but when the configure event arrives.
5215 * FIXME: we should also dequeue the pending redraws here, since
5216 * we handle those ourselves upon ->configure_notify_received==TRUE.
5218 if (container->resize_mode == GTK_RESIZE_QUEUE)
5220 gtk_widget_queue_resize (widget);
5221 _gtk_container_dequeue_resize_handler (container);
5226 /* Handle any position changes.
5228 if (configure_request_pos_changed)
5232 gdk_window_move (window->frame,
5233 new_request.x - window->frame_left,
5234 new_request.y - window->frame_top);
5237 gdk_window_move (widget->window,
5238 new_request.x, new_request.y);
5241 /* And run the resize queue.
5243 gtk_container_resize_children (container);
5246 /* We have now processed a move/resize since the last position
5247 * constraint change, setting of the initial position, or resize.
5248 * (Not resetting these flags here can lead to infinite loops for
5249 * GTK_RESIZE_IMMEDIATE containers)
5251 info->position_constraints_changed = FALSE;
5252 info->initial_pos_set = FALSE;
5253 info->resize_width = -1;
5254 info->resize_height = -1;
5257 /* Compare two sets of Geometry hints for equality.
5260 gtk_window_compare_hints (GdkGeometry *geometry_a,
5262 GdkGeometry *geometry_b,
5265 if (flags_a != flags_b)
5268 if ((flags_a & GDK_HINT_MIN_SIZE) &&
5269 (geometry_a->min_width != geometry_b->min_width ||
5270 geometry_a->min_height != geometry_b->min_height))
5273 if ((flags_a & GDK_HINT_MAX_SIZE) &&
5274 (geometry_a->max_width != geometry_b->max_width ||
5275 geometry_a->max_height != geometry_b->max_height))
5278 if ((flags_a & GDK_HINT_BASE_SIZE) &&
5279 (geometry_a->base_width != geometry_b->base_width ||
5280 geometry_a->base_height != geometry_b->base_height))
5283 if ((flags_a & GDK_HINT_ASPECT) &&
5284 (geometry_a->min_aspect != geometry_b->min_aspect ||
5285 geometry_a->max_aspect != geometry_b->max_aspect))
5288 if ((flags_a & GDK_HINT_RESIZE_INC) &&
5289 (geometry_a->width_inc != geometry_b->width_inc ||
5290 geometry_a->height_inc != geometry_b->height_inc))
5293 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5294 geometry_a->win_gravity != geometry_b->win_gravity)
5301 _gtk_window_constrain_size (GtkWindow *window,
5307 GtkWindowGeometryInfo *info;
5309 g_return_if_fail (GTK_IS_WINDOW (window));
5311 info = window->geometry_info;
5314 GdkWindowHints flags = info->last.flags;
5315 GdkGeometry *geometry = &info->last.geometry;
5317 gtk_window_constrain_size (window,
5328 gtk_window_constrain_size (GtkWindow *window,
5329 GdkGeometry *geometry,
5336 gdk_window_constrain_size (geometry, flags, width, height,
5337 new_width, new_height);
5340 /* Compute the set of geometry hints and flags for a window
5341 * based on the application set geometry, and requisiition
5342 * of the window. gtk_widget_size_request() must have been
5346 gtk_window_compute_hints (GtkWindow *window,
5347 GdkGeometry *new_geometry,
5351 gint extra_width = 0;
5352 gint extra_height = 0;
5353 GtkWindowGeometryInfo *geometry_info;
5354 GtkRequisition requisition;
5356 widget = GTK_WIDGET (window);
5358 gtk_widget_get_child_requisition (widget, &requisition);
5359 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5363 *new_flags = geometry_info->mask;
5364 *new_geometry = geometry_info->geometry;
5371 if (geometry_info && geometry_info->widget)
5373 GtkRequisition child_requisition;
5375 /* FIXME: This really isn't right. It gets the min size wrong and forces
5376 * callers to do horrible hacks like set a huge usize on the child requisition
5377 * to get the base size right. We really want to find the answers to:
5379 * - If the geometry widget was infinitely big, how much extra space
5380 * would be needed for the stuff around it.
5382 * - If the geometry widget was infinitely small, how big would the
5383 * window still have to be.
5385 * Finding these answers would be a bit of a mess here. (Bug #68668)
5387 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5389 extra_width = widget->requisition.width - child_requisition.width;
5390 extra_height = widget->requisition.height - child_requisition.height;
5393 /* We don't want to set GDK_HINT_POS in here, we just set it
5394 * in gtk_window_move_resize() when we want the position
5398 if (*new_flags & GDK_HINT_BASE_SIZE)
5400 new_geometry->base_width += extra_width;
5401 new_geometry->base_height += extra_height;
5403 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5404 (*new_flags & GDK_HINT_RESIZE_INC) &&
5405 ((extra_width != 0) || (extra_height != 0)))
5407 *new_flags |= GDK_HINT_BASE_SIZE;
5409 new_geometry->base_width = extra_width;
5410 new_geometry->base_height = extra_height;
5413 if (*new_flags & GDK_HINT_MIN_SIZE)
5415 if (new_geometry->min_width < 0)
5416 new_geometry->min_width = requisition.width;
5418 new_geometry->min_width += extra_width;
5420 if (new_geometry->min_height < 0)
5421 new_geometry->min_height = requisition.height;
5423 new_geometry->min_height += extra_height;
5425 else if (!window->allow_shrink)
5427 *new_flags |= GDK_HINT_MIN_SIZE;
5429 new_geometry->min_width = requisition.width;
5430 new_geometry->min_height = requisition.height;
5433 if (*new_flags & GDK_HINT_MAX_SIZE)
5435 if (new_geometry->max_width < 0)
5436 new_geometry->max_width = requisition.width;
5438 new_geometry->max_width += extra_width;
5440 if (new_geometry->max_height < 0)
5441 new_geometry->max_height = requisition.height;
5443 new_geometry->max_height += extra_height;
5445 else if (!window->allow_grow)
5447 *new_flags |= GDK_HINT_MAX_SIZE;
5449 new_geometry->max_width = requisition.width;
5450 new_geometry->max_height = requisition.height;
5453 *new_flags |= GDK_HINT_WIN_GRAVITY;
5454 new_geometry->win_gravity = window->gravity;
5457 /***********************
5458 * Redrawing functions *
5459 ***********************/
5462 gtk_window_paint (GtkWidget *widget,
5465 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
5466 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
5470 gtk_window_expose (GtkWidget *widget,
5471 GdkEventExpose *event)
5473 if (!GTK_WIDGET_APP_PAINTABLE (widget))
5474 gtk_window_paint (widget, &event->area);
5476 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
5477 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
5483 * gtk_window_set_has_frame:
5484 * @window: a #GtkWindow
5485 * @setting: a boolean
5487 * (Note: this is a special-purpose function for the framebuffer port,
5488 * that causes GTK+ to draw its own window border. For most applications,
5489 * you want gtk_window_set_decorated() instead, which tells the window
5490 * manager whether to draw the window border.)
5492 * If this function is called on a window with setting of %TRUE, before
5493 * it is realized or showed, it will have a "frame" window around
5494 * @window->window, accessible in @window->frame. Using the signal
5495 * frame_event you can receive all events targeted at the frame.
5497 * This function is used by the linux-fb port to implement managed
5498 * windows, but it could concievably be used by X-programs that
5499 * want to do their own window decorations.
5503 gtk_window_set_has_frame (GtkWindow *window,
5506 g_return_if_fail (GTK_IS_WINDOW (window));
5507 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
5509 window->has_frame = setting != FALSE;
5513 * gtk_window_get_has_frame:
5514 * @window: a #GtkWindow
5516 * Accessor for whether the window has a frame window exterior to
5517 * @window->window. Gets the value set by gtk_window_set_has_frame ().
5519 * Return value: %TRUE if a frame has been added to the window
5520 * via gtk_window_set_has_frame().
5523 gtk_window_get_has_frame (GtkWindow *window)
5525 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5527 return window->has_frame;
5531 * gtk_window_set_frame_dimensions:
5532 * @window: a #GtkWindow that has a frame
5533 * @left: The width of the left border
5534 * @top: The height of the top border
5535 * @right: The width of the right border
5536 * @bottom: The height of the bottom border
5538 * (Note: this is a special-purpose function intended for the framebuffer
5539 * port; see gtk_window_set_has_frame(). It will have no effect on the
5540 * window border drawn by the window manager, which is the normal
5541 * case when using the X Window system.)
5543 * For windows with frames (see gtk_window_set_has_frame()) this function
5544 * can be used to change the size of the frame border.
5547 gtk_window_set_frame_dimensions (GtkWindow *window,
5555 g_return_if_fail (GTK_IS_WINDOW (window));
5557 widget = GTK_WIDGET (window);
5559 if (window->frame_left == left &&
5560 window->frame_top == top &&
5561 window->frame_right == right &&
5562 window->frame_bottom == bottom)
5565 window->frame_left = left;
5566 window->frame_top = top;
5567 window->frame_right = right;
5568 window->frame_bottom = bottom;
5570 if (GTK_WIDGET_REALIZED (widget) && window->frame)
5572 gint width = widget->allocation.width + left + right;
5573 gint height = widget->allocation.height + top + bottom;
5574 gdk_window_resize (window->frame, width, height);
5575 gtk_decorated_window_move_resize_window (window,
5577 widget->allocation.width,
5578 widget->allocation.height);
5583 * gtk_window_present:
5584 * @window: a #GtkWindow
5586 * Presents a window to the user. This may mean raising the window
5587 * in the stacking order, deiconifying it, moving it to the current
5588 * desktop, and/or giving it the keyboard focus, possibly dependent
5589 * on the user's platform, window manager, and preferences.
5591 * If @window is hidden, this function calls gtk_widget_show()
5594 * This function should be used when the user tries to open a window
5595 * that's already open. Say for example the preferences dialog is
5596 * currently open, and the user chooses Preferences from the menu
5597 * a second time; use gtk_window_present() to move the already-open dialog
5598 * where the user can see it.
5602 gtk_window_present (GtkWindow *window)
5606 g_return_if_fail (GTK_IS_WINDOW (window));
5608 widget = GTK_WIDGET (window);
5610 if (GTK_WIDGET_VISIBLE (window))
5612 g_assert (widget->window != NULL);
5614 gdk_window_show (widget->window);
5616 /* note that gdk_window_focus() will also move the window to
5617 * the current desktop, for WM spec compliant window managers.
5619 gdk_window_focus (widget->window,
5620 gtk_get_current_event_time ());
5624 gtk_widget_show (widget);
5629 * gtk_window_iconify:
5630 * @window: a #GtkWindow
5632 * Asks to iconify (i.e. minimize) the specified @window. Note that
5633 * you shouldn't assume the window is definitely iconified afterward,
5634 * because other entities (e.g. the user or <link
5635 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
5636 * again, or there may not be a window manager in which case
5637 * iconification isn't possible, etc. But normally the window will end
5638 * up iconified. Just don't write code that crashes if not.
5640 * It's permitted to call this function before showing a window,
5641 * in which case the window will be iconified before it ever appears
5644 * You can track iconification via the "window_state_event" signal
5649 gtk_window_iconify (GtkWindow *window)
5652 GdkWindow *toplevel;
5654 g_return_if_fail (GTK_IS_WINDOW (window));
5656 widget = GTK_WIDGET (window);
5658 window->iconify_initially = TRUE;
5661 toplevel = window->frame;
5663 toplevel = widget->window;
5665 if (toplevel != NULL)
5666 gdk_window_iconify (toplevel);
5670 * gtk_window_deiconify:
5671 * @window: a #GtkWindow
5673 * Asks to deiconify (i.e. unminimize) the specified @window. Note
5674 * that you shouldn't assume the window is definitely deiconified
5675 * afterward, because other entities (e.g. the user or <link
5676 * linkend="gtk-X11-arch">window manager</link>) could iconify it
5677 * again before your code which assumes deiconification gets to run.
5679 * You can track iconification via the "window_state_event" signal
5683 gtk_window_deiconify (GtkWindow *window)
5686 GdkWindow *toplevel;
5688 g_return_if_fail (GTK_IS_WINDOW (window));
5690 widget = GTK_WIDGET (window);
5692 window->iconify_initially = FALSE;
5695 toplevel = window->frame;
5697 toplevel = widget->window;
5699 if (toplevel != NULL)
5700 gdk_window_deiconify (toplevel);
5705 * @window: a #GtkWindow
5707 * Asks to stick @window, which means that it will appear on all user
5708 * desktops. Note that you shouldn't assume the window is definitely
5709 * stuck afterward, because other entities (e.g. the user or <link
5710 * linkend="gtk-X11-arch">window manager</link>) could unstick it
5711 * again, and some window managers do not support sticking
5712 * windows. But normally the window will end up stuck. Just don't
5713 * write code that crashes if not.
5715 * It's permitted to call this function before showing a window.
5717 * You can track stickiness via the "window_state_event" signal
5722 gtk_window_stick (GtkWindow *window)
5725 GdkWindow *toplevel;
5727 g_return_if_fail (GTK_IS_WINDOW (window));
5729 widget = GTK_WIDGET (window);
5731 window->stick_initially = TRUE;
5734 toplevel = window->frame;
5736 toplevel = widget->window;
5738 if (toplevel != NULL)
5739 gdk_window_stick (toplevel);
5743 * gtk_window_unstick:
5744 * @window: a #GtkWindow
5746 * Asks to unstick @window, which means that it will appear on only
5747 * one of the user's desktops. Note that you shouldn't assume the
5748 * window is definitely unstuck afterward, because other entities
5749 * (e.g. the user or <link linkend="gtk-X11-arch">window
5750 * manager</link>) could stick it again. But normally the window will
5751 * end up stuck. Just don't write code that crashes if not.
5753 * You can track stickiness via the "window_state_event" signal
5758 gtk_window_unstick (GtkWindow *window)
5761 GdkWindow *toplevel;
5763 g_return_if_fail (GTK_IS_WINDOW (window));
5765 widget = GTK_WIDGET (window);
5767 window->stick_initially = FALSE;
5770 toplevel = window->frame;
5772 toplevel = widget->window;
5774 if (toplevel != NULL)
5775 gdk_window_unstick (toplevel);
5779 * gtk_window_maximize:
5780 * @window: a #GtkWindow
5782 * Asks to maximize @window, so that it becomes full-screen. Note that
5783 * you shouldn't assume the window is definitely maximized afterward,
5784 * because other entities (e.g. the user or <link
5785 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
5786 * again, and not all window managers support maximization. But
5787 * normally the window will end up maximized. Just don't write code
5788 * that crashes if not.
5790 * It's permitted to call this function before showing a window,
5791 * in which case the window will be maximized when it appears onscreen
5794 * You can track maximization via the "window_state_event" signal
5799 gtk_window_maximize (GtkWindow *window)
5802 GdkWindow *toplevel;
5804 g_return_if_fail (GTK_IS_WINDOW (window));
5806 widget = GTK_WIDGET (window);
5808 window->maximize_initially = TRUE;
5811 toplevel = window->frame;
5813 toplevel = widget->window;
5815 if (toplevel != NULL)
5816 gdk_window_maximize (toplevel);
5820 * gtk_window_unmaximize:
5821 * @window: a #GtkWindow
5823 * Asks to unmaximize @window. Note that you shouldn't assume the
5824 * window is definitely unmaximized afterward, because other entities
5825 * (e.g. the user or <link linkend="gtk-X11-arch">window
5826 * manager</link>) could maximize it again, and not all window
5827 * managers honor requests to unmaximize. But normally the window will
5828 * end up unmaximized. Just don't write code that crashes if not.
5830 * You can track maximization via the "window_state_event" signal
5835 gtk_window_unmaximize (GtkWindow *window)
5838 GdkWindow *toplevel;
5840 g_return_if_fail (GTK_IS_WINDOW (window));
5842 widget = GTK_WIDGET (window);
5844 window->maximize_initially = FALSE;
5847 toplevel = window->frame;
5849 toplevel = widget->window;
5851 if (toplevel != NULL)
5852 gdk_window_unmaximize (toplevel);
5856 * gtk_window_fullscreen:
5857 * @window: a #GtkWindow
5859 * Asks to place @window in the fullscreen state. Note that you
5860 * shouldn't assume the window is definitely full screen afterward,
5861 * because other entities (e.g. the user or <link
5862 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
5863 * again, and not all window managers honor requests to fullscreen
5864 * windows. But normally the window will end up fullscreen. Just
5865 * don't write code that crashes if not.
5867 * You can track the fullscreen state via the "window_state_event" signal
5873 gtk_window_fullscreen (GtkWindow *window)
5876 GdkWindow *toplevel;
5877 GtkWindowPrivate *priv;
5879 g_return_if_fail (GTK_IS_WINDOW (window));
5881 widget = GTK_WIDGET (window);
5882 priv = GTK_WINDOW_GET_PRIVATE (window);
5884 priv->fullscreen_initially = TRUE;
5887 toplevel = window->frame;
5889 toplevel = widget->window;
5891 if (toplevel != NULL)
5892 gdk_window_fullscreen (toplevel);
5896 * gtk_window_unfullscreen:
5897 * @window: a #GtkWindow
5899 * Asks to toggle off the fullscreen state for @window. Note that you
5900 * shouldn't assume the window is definitely not full screen
5901 * afterward, because other entities (e.g. the user or <link
5902 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
5903 * again, and not all window managers honor requests to unfullscreen
5904 * windows. But normally the window will end up restored to its normal
5905 * state. Just don't write code that crashes if not.
5907 * You can track the fullscreen state via the "window_state_event" signal
5913 gtk_window_unfullscreen (GtkWindow *window)
5916 GdkWindow *toplevel;
5917 GtkWindowPrivate *priv;
5919 g_return_if_fail (GTK_IS_WINDOW (window));
5921 widget = GTK_WIDGET (window);
5922 priv = GTK_WINDOW_GET_PRIVATE (window);
5924 priv->fullscreen_initially = FALSE;
5927 toplevel = window->frame;
5929 toplevel = widget->window;
5931 if (toplevel != NULL)
5932 gdk_window_unfullscreen (toplevel);
5936 * gtk_window_set_keep_above:
5937 * @window: a #GtkWindow
5938 * @setting: whether to keep @window above other windows
5940 * Asks to keep @window above, so that it stays on top. Note that
5941 * you shouldn't assume the window is definitely above afterward,
5942 * because other entities (e.g. the user or <link
5943 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
5944 * and not all window managers support keeping windows above. But
5945 * normally the window will end kept above. Just don't write code
5946 * that crashes if not.
5948 * It's permitted to call this function before showing a window,
5949 * in which case the window will be kept above when it appears onscreen
5952 * You can track the above state via the "window_state_event" signal
5955 * Note that, according to the <ulink
5956 * url="http://www.freedesktop.org/standards/wm-spec.html">Extended Window Manager Hints</ulink>
5957 * specification, the above state is mainly meant for user preferences and should not be used
5958 * by applications e.g. for drawing attention to their dialogs.
5963 gtk_window_set_keep_above (GtkWindow *window,
5967 GtkWindowPrivate *priv;
5968 GdkWindow *toplevel;
5970 g_return_if_fail (GTK_IS_WINDOW (window));
5972 widget = GTK_WIDGET (window);
5973 priv = GTK_WINDOW_GET_PRIVATE (window);
5975 priv->above_initially = setting;
5977 priv->below_initially = FALSE;
5980 toplevel = window->frame;
5982 toplevel = widget->window;
5984 if (toplevel != NULL)
5985 gdk_window_set_keep_above (toplevel, setting);
5989 * gtk_window_set_keep_below:
5990 * @window: a #GtkWindow
5991 * @setting: whether to keep @window below other windows
5993 * Asks to keep @window below, so that it stays in bottom. Note that
5994 * you shouldn't assume the window is definitely below afterward,
5995 * because other entities (e.g. the user or <link
5996 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
5997 * and not all window managers support putting windows below. But
5998 * normally the window will be kept below. Just don't write code
5999 * that crashes if not.
6001 * It's permitted to call this function before showing a window,
6002 * in which case the window will be kept below when it appears onscreen
6005 * You can track the below state via the "window_state_event" signal
6008 * Note that, according to the <ulink
6009 * url="http://www.freedesktop.org/standards/wm-spec.html">Extended Window Manager Hints</ulink>
6010 * specification, the above state is mainly meant for user preferences and should not be used
6011 * by applications e.g. for drawing attention to their dialogs.
6016 gtk_window_set_keep_below (GtkWindow *window,
6020 GtkWindowPrivate *priv;
6021 GdkWindow *toplevel;
6023 g_return_if_fail (GTK_IS_WINDOW (window));
6025 widget = GTK_WIDGET (window);
6026 priv = GTK_WINDOW_GET_PRIVATE (window);
6028 priv->below_initially = setting;
6030 priv->above_initially = FALSE;
6033 toplevel = window->frame;
6035 toplevel = widget->window;
6037 if (toplevel != NULL)
6038 gdk_window_set_keep_below (toplevel, setting);
6042 * gtk_window_set_resizable:
6043 * @window: a #GtkWindow
6044 * @resizable: %TRUE if the user can resize this window
6046 * Sets whether the user can resize a window. Windows are user resizable
6050 gtk_window_set_resizable (GtkWindow *window,
6053 g_return_if_fail (GTK_IS_WINDOW (window));
6055 gtk_window_set_policy (window, FALSE, resizable, FALSE);
6059 * gtk_window_get_resizable:
6060 * @window: a #GtkWindow
6062 * Gets the value set by gtk_window_set_resizable().
6064 * Return value: %TRUE if the user can resize the window
6067 gtk_window_get_resizable (GtkWindow *window)
6069 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6071 /* allow_grow is most likely to indicate the semantic concept we
6072 * mean by "resizable" (and will be a reliable indicator if
6073 * set_policy() hasn't been called)
6075 return window->allow_grow;
6079 * gtk_window_set_gravity:
6080 * @window: a #GtkWindow
6081 * @gravity: window gravity
6083 * Window gravity defines the meaning of coordinates passed to
6084 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
6087 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
6088 * typically "do what you mean."
6092 gtk_window_set_gravity (GtkWindow *window,
6095 g_return_if_fail (GTK_IS_WINDOW (window));
6097 if (gravity != window->gravity)
6099 window->gravity = gravity;
6101 /* gtk_window_move_resize() will adapt gravity
6103 gtk_widget_queue_resize (GTK_WIDGET (window));
6105 g_object_notify (G_OBJECT (window), "gravity");
6110 * gtk_window_get_gravity:
6111 * @window: a #GtkWindow
6113 * Gets the value set by gtk_window_set_gravity().
6115 * Return value: window gravity
6118 gtk_window_get_gravity (GtkWindow *window)
6120 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
6122 return window->gravity;
6126 * gtk_window_begin_resize_drag:
6127 * @window: a #GtkWindow
6128 * @button: mouse button that initiated the drag
6129 * @edge: position of the resize control
6130 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6131 * @root_y: Y position where the user clicked to initiate the drag
6132 * @timestamp: timestamp from the click event that initiated the drag
6134 * Starts resizing a window. This function is used if an application
6135 * has window resizing controls. When GDK can support it, the resize
6136 * will be done using the standard mechanism for the <link
6137 * linkend="gtk-X11-arch">window manager</link> or windowing
6138 * system. Otherwise, GDK will try to emulate window resizing,
6139 * potentially not all that well, depending on the windowing system.
6143 gtk_window_begin_resize_drag (GtkWindow *window,
6151 GdkWindow *toplevel;
6153 g_return_if_fail (GTK_IS_WINDOW (window));
6154 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6156 widget = GTK_WIDGET (window);
6159 toplevel = window->frame;
6161 toplevel = widget->window;
6163 gdk_window_begin_resize_drag (toplevel,
6170 * gtk_window_get_frame_dimensions:
6171 * @window: a #GtkWindow
6172 * @left: location to store the width of the frame at the left, or %NULL
6173 * @top: location to store the height of the frame at the top, or %NULL
6174 * @right: location to store the width of the frame at the returns, or %NULL
6175 * @bottom: location to store the height of the frame at the bottom, or %NULL
6177 * (Note: this is a special-purpose function intended for the
6178 * framebuffer port; see gtk_window_set_has_frame(). It will not
6179 * return the size of the window border drawn by the <link
6180 * linkend="gtk-X11-arch">window manager</link>, which is the normal
6181 * case when using a windowing system. See
6182 * gdk_window_get_frame_extents() to get the standard window border
6185 * Retrieves the dimensions of the frame window for this toplevel.
6186 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
6189 gtk_window_get_frame_dimensions (GtkWindow *window,
6195 g_return_if_fail (GTK_IS_WINDOW (window));
6198 *left = window->frame_left;
6200 *top = window->frame_top;
6202 *right = window->frame_right;
6204 *bottom = window->frame_bottom;
6208 * gtk_window_begin_move_drag:
6209 * @window: a #GtkWindow
6210 * @button: mouse button that initiated the drag
6211 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6212 * @root_y: Y position where the user clicked to initiate the drag
6213 * @timestamp: timestamp from the click event that initiated the drag
6215 * Starts moving a window. This function is used if an application has
6216 * window movement grips. When GDK can support it, the window movement
6217 * will be done using the standard mechanism for the <link
6218 * linkend="gtk-X11-arch">window manager</link> or windowing
6219 * system. Otherwise, GDK will try to emulate window movement,
6220 * potentially not all that well, depending on the windowing system.
6224 gtk_window_begin_move_drag (GtkWindow *window,
6231 GdkWindow *toplevel;
6233 g_return_if_fail (GTK_IS_WINDOW (window));
6234 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6236 widget = GTK_WIDGET (window);
6239 toplevel = window->frame;
6241 toplevel = widget->window;
6243 gdk_window_begin_move_drag (toplevel,
6250 * gtk_window_set_screen:
6251 * @window: a #GtkWindow.
6252 * @screen: a #GdkScreen.
6254 * Sets the #GdkScreen where the @window is displayed; if
6255 * the window is already mapped, it will be unmapped, and
6256 * then remapped on the new screen.
6261 gtk_window_set_screen (GtkWindow *window,
6265 GdkScreen *previous_screen;
6266 gboolean was_mapped;
6268 g_return_if_fail (GTK_IS_WINDOW (window));
6269 g_return_if_fail (GDK_IS_SCREEN (screen));
6271 if (screen == window->screen)
6274 widget = GTK_WIDGET (window);
6276 previous_screen = window->screen;
6277 was_mapped = GTK_WIDGET_MAPPED (widget);
6280 gtk_widget_unmap (widget);
6281 if (GTK_WIDGET_REALIZED (widget))
6282 gtk_widget_unrealize (widget);
6284 gtk_window_free_key_hash (window);
6285 window->screen = screen;
6286 gtk_widget_reset_rc_styles (widget);
6287 if (screen != previous_screen)
6288 _gtk_widget_propagate_screen_changed (widget, previous_screen);
6289 g_object_notify (G_OBJECT (window), "screen");
6292 gtk_widget_map (widget);
6296 gtk_window_check_screen (GtkWindow *window)
6299 return window->screen;
6302 g_warning ("Screen for GtkWindow not set; you must always set\n"
6303 "a screen for a GtkWindow before using the window");
6309 * gtk_window_get_screen:
6310 * @window: a #GtkWindow.
6312 * Returns the #GdkScreen associated with @window.
6314 * Return value: a #GdkScreen.
6319 gtk_window_get_screen (GtkWindow *window)
6321 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6323 return window->screen;
6327 * gtk_window_is_active:
6328 * @window: a #GtkWindow
6330 * Returns whether the window is part of the current active toplevel.
6331 * (That is, the toplevel window receiving keystrokes.)
6332 * The return value is %TRUE if the window is active toplevel
6333 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
6334 * You might use this function if you wanted to draw a widget
6335 * differently in an active window from a widget in an inactive window.
6336 * See gtk_window_has_toplevel_focus()
6338 * Return value: %TRUE if the window part of the current active window.
6343 gtk_window_is_active (GtkWindow *window)
6345 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6347 return window->is_active;
6351 * gtk_window_has_toplevel_focus:
6352 * @window: a #GtkWindow
6354 * Returns whether the input focus is within this GtkWindow.
6355 * For real toplevel windows, this is identical to gtk_window_is_active(),
6356 * but for embedded windows, like #GtkPlug, the results will differ.
6358 * Return value: %TRUE if the the input focus is within this GtkWindow
6363 gtk_window_has_toplevel_focus (GtkWindow *window)
6365 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6367 return window->has_toplevel_focus;
6371 gtk_window_group_class_init (GtkWindowGroupClass *klass)
6376 gtk_window_group_get_type (void)
6378 static GType window_group_type = 0;
6380 if (!window_group_type)
6382 static const GTypeInfo window_group_info =
6384 sizeof (GtkWindowGroupClass),
6385 NULL, /* base_init */
6386 NULL, /* base_finalize */
6387 (GClassInitFunc) gtk_window_group_class_init,
6388 NULL, /* class_finalize */
6389 NULL, /* class_data */
6390 sizeof (GtkWindowGroup),
6391 16, /* n_preallocs */
6392 (GInstanceInitFunc) NULL,
6395 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
6398 return window_group_type;
6402 * gtk_window_group_new:
6404 * Creates a new #GtkWindowGroup object. Grabs added with
6405 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
6407 * Return value: a new #GtkWindowGroup.
6410 gtk_window_group_new (void)
6412 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
6416 window_group_cleanup_grabs (GtkWindowGroup *group,
6420 GSList *to_remove = NULL;
6422 tmp_list = group->grabs;
6425 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
6426 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
6427 tmp_list = tmp_list->next;
6432 gtk_grab_remove (to_remove->data);
6433 g_object_unref (to_remove->data);
6434 to_remove = g_slist_delete_link (to_remove, to_remove);
6439 * gtk_window_group_add_window:
6440 * @window_group: a #GtkWindowGroup
6441 * @window: the #GtkWindow to add
6443 * Adds a window to a #GtkWindowGroup.
6446 gtk_window_group_add_window (GtkWindowGroup *window_group,
6449 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6450 g_return_if_fail (GTK_IS_WINDOW (window));
6452 if (window->group != window_group)
6454 g_object_ref (window);
6455 g_object_ref (window_group);
6458 gtk_window_group_remove_window (window->group, window);
6460 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
6462 window->group = window_group;
6464 g_object_unref (window);
6469 * gtk_window_group_remove_window:
6470 * @window_group: a #GtkWindowGroup
6471 * @window: the #GtkWindow to remove
6473 * Removes a window from a #GtkWindowGroup.
6476 gtk_window_group_remove_window (GtkWindowGroup *window_group,
6479 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6480 g_return_if_fail (GTK_IS_WIDGET (window));
6481 g_return_if_fail (window->group == window_group);
6483 g_object_ref (window);
6485 window_group_cleanup_grabs (window_group, window);
6486 window->group = NULL;
6488 g_object_unref (window_group);
6489 g_object_unref (window);
6492 /* Return the group for the window or the default group
6495 _gtk_window_get_group (GtkWindow *window)
6497 if (window && window->group)
6498 return window->group;
6501 static GtkWindowGroup *default_group = NULL;
6504 default_group = gtk_window_group_new ();
6506 return default_group;
6512 Derived from XParseGeometry() in XFree86
6514 Copyright 1985, 1986, 1987,1998 The Open Group
6516 All Rights Reserved.
6518 The above copyright notice and this permission notice shall be included
6519 in all copies or substantial portions of the Software.
6521 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
6522 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6523 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6524 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
6525 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
6526 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
6527 OTHER DEALINGS IN THE SOFTWARE.
6529 Except as contained in this notice, the name of The Open Group shall
6530 not be used in advertising or otherwise to promote the sale, use or
6531 other dealings in this Software without prior written authorization
6532 from The Open Group.
6537 * XParseGeometry parses strings of the form
6538 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
6539 * width, height, xoffset, and yoffset are unsigned integers.
6540 * Example: "=80x24+300-49"
6541 * The equal sign is optional.
6542 * It returns a bitmask that indicates which of the four values
6543 * were actually found in the string. For each value found,
6544 * the corresponding argument is updated; for each value
6545 * not found, the corresponding argument is left unchanged.
6548 /* The following code is from Xlib, and is minimally modified, so we
6549 * can track any upstream changes if required. Don't change this
6550 * code. Or if you do, put in a huge comment marking which thing
6555 read_int (gchar *string,
6563 else if (*string == '-')
6569 for (; (*string >= '0') && (*string <= '9'); string++)
6571 result = (result * 10) + (*string - '0');
6583 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
6584 * value (x, y, width, height) was found in the parsed string.
6586 #define NoValue 0x0000
6587 #define XValue 0x0001
6588 #define YValue 0x0002
6589 #define WidthValue 0x0004
6590 #define HeightValue 0x0008
6591 #define AllValues 0x000F
6592 #define XNegative 0x0010
6593 #define YNegative 0x0020
6595 /* Try not to reformat/modify, so we can compare/sync with X sources */
6597 gtk_XParseGeometry (const char *string,
6600 unsigned int *width,
6601 unsigned int *height)
6605 unsigned int tempWidth, tempHeight;
6607 char *nextCharacter;
6609 /* These initializations are just to silence gcc */
6615 if ( (string == NULL) || (*string == '\0')) return(mask);
6617 string++; /* ignore possible '=' at beg of geometry spec */
6619 strind = (char *)string;
6620 if (*strind != '+' && *strind != '-' && *strind != 'x') {
6621 tempWidth = read_int(strind, &nextCharacter);
6622 if (strind == nextCharacter)
6624 strind = nextCharacter;
6628 if (*strind == 'x' || *strind == 'X') {
6630 tempHeight = read_int(strind, &nextCharacter);
6631 if (strind == nextCharacter)
6633 strind = nextCharacter;
6634 mask |= HeightValue;
6637 if ((*strind == '+') || (*strind == '-')) {
6638 if (*strind == '-') {
6640 tempX = -read_int(strind, &nextCharacter);
6641 if (strind == nextCharacter)
6643 strind = nextCharacter;
6649 tempX = read_int(strind, &nextCharacter);
6650 if (strind == nextCharacter)
6652 strind = nextCharacter;
6655 if ((*strind == '+') || (*strind == '-')) {
6656 if (*strind == '-') {
6658 tempY = -read_int(strind, &nextCharacter);
6659 if (strind == nextCharacter)
6661 strind = nextCharacter;
6668 tempY = read_int(strind, &nextCharacter);
6669 if (strind == nextCharacter)
6671 strind = nextCharacter;
6677 /* If strind isn't at the end of the string the it's an invalid
6678 geometry specification. */
6680 if (*strind != '\0') return (0);
6686 if (mask & WidthValue)
6688 if (mask & HeightValue)
6689 *height = tempHeight;
6694 * gtk_window_parse_geometry:
6695 * @window: a #GtkWindow
6696 * @geometry: geometry string
6698 * Parses a standard X Window System geometry string - see the
6699 * manual page for X (type 'man X') for details on this.
6700 * gtk_window_parse_geometry() does work on all GTK+ ports
6701 * including Win32 but is primarily intended for an X environment.
6703 * If either a size or a position can be extracted from the
6704 * geometry string, gtk_window_parse_geometry() returns %TRUE
6705 * and calls gtk_window_set_default_size() and/or gtk_window_move()
6706 * to resize/move the window.
6708 * If gtk_window_parse_geometry() returns %TRUE, it will also
6709 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
6710 * indicating to the window manager that the size/position of
6711 * the window was user-specified. This causes most window
6712 * managers to honor the geometry.
6714 * Note that for gtk_window_parse_geometry() to work as expected, it has
6715 * to be called when the window has its "final" size, i.e. after calling
6716 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
6719 * <informalexample><programlisting>
6721 * main (int argc, char *argv[])
6723 * GtkWidget *window, vbox;
6724 * GdkGeometry size_hints;
6726 * gtk_init (&argc, &argv);
6728 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6729 * vbox = gtk_vbox_new (FALSE, 0);
6731 * gtk_container_add (GTK_CONTAINER (window), vbox);
6732 * fill_with_content (vbox);
6733 * gtk_widget_show_all (vbox);
6736 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
6739 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
6742 * GDK_HINT_MIN_SIZE |
6743 * GDK_HINT_BASE_SIZE |
6744 * GDK_HINT_RESIZE_INC);
6748 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
6749 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
6752 * gtk_widget_show_all (window);
6757 * </programlisting></informalexample>
6759 * Return value: %TRUE if string was parsed successfully
6762 gtk_window_parse_geometry (GtkWindow *window,
6763 const gchar *geometry)
6768 gboolean size_set, pos_set;
6771 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6772 g_return_val_if_fail (geometry != NULL, FALSE);
6774 screen = gtk_window_check_screen (window);
6776 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
6778 if ((result & WidthValue) == 0 ||
6781 if ((result & HeightValue) == 0 ||
6786 if ((result & WidthValue) || (result & HeightValue))
6788 gtk_window_set_default_size_internal (window, TRUE, w, TRUE, h, TRUE);
6792 gtk_window_get_size (window, &w, &h);
6794 grav = GDK_GRAVITY_NORTH_WEST;
6796 if ((result & XNegative) && (result & YNegative))
6797 grav = GDK_GRAVITY_SOUTH_EAST;
6798 else if (result & XNegative)
6799 grav = GDK_GRAVITY_NORTH_EAST;
6800 else if (result & YNegative)
6801 grav = GDK_GRAVITY_SOUTH_WEST;
6803 if ((result & XValue) == 0)
6806 if ((result & YValue) == 0)
6809 if (grav == GDK_GRAVITY_SOUTH_WEST ||
6810 grav == GDK_GRAVITY_SOUTH_EAST)
6811 y = gdk_screen_get_height (screen) - h + y;
6813 if (grav == GDK_GRAVITY_SOUTH_EAST ||
6814 grav == GDK_GRAVITY_NORTH_EAST)
6815 x = gdk_screen_get_width (screen) - w + x;
6817 /* we don't let you put a window offscreen; maybe some people would
6818 * prefer to be able to, but it's kind of a bogus thing to do.
6827 if ((result & XValue) || (result & YValue))
6829 gtk_window_set_gravity (window, grav);
6830 gtk_window_move (window, x, y);
6834 if (size_set || pos_set)
6836 /* Set USSize, USPosition hints */
6837 GtkWindowGeometryInfo *info;
6839 info = gtk_window_get_geometry_info (window, TRUE);
6842 info->mask |= GDK_HINT_USER_POS;
6844 info->mask |= GDK_HINT_USER_SIZE;
6851 gtk_window_mnemonic_hash_foreach (gpointer key,
6857 GtkWindowKeysForeachFunc func;
6861 GtkWindowMnemonic *mnemonic = value;
6863 if (mnemonic->window == info->window)
6864 (*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
6868 _gtk_window_keys_foreach (GtkWindow *window,
6869 GtkWindowKeysForeachFunc func,
6876 GtkWindowKeysForeachFunc func;
6880 info.window = window;
6882 info.func_data = func_data;
6884 g_hash_table_foreach (mnemonic_hash_table,
6885 gtk_window_mnemonic_hash_foreach,
6888 groups = gtk_accel_groups_from_object (G_OBJECT (window));
6891 GtkAccelGroup *group = groups->data;
6894 for (i = 0; i < group->n_accels; i++)
6896 GtkAccelKey *key = &group->priv_accels[i].key;
6899 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
6902 groups = groups->next;
6907 gtk_window_keys_changed (GtkWindow *window)
6909 gtk_window_free_key_hash (window);
6910 gtk_window_get_key_hash (window);
6913 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
6915 struct _GtkWindowKeyEntry
6919 gboolean is_mnemonic;
6923 add_to_key_hash (GtkWindow *window,
6925 GdkModifierType modifiers,
6926 gboolean is_mnemonic,
6929 GtkKeyHash *key_hash = data;
6931 GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
6933 entry->keyval = keyval;
6934 entry->modifiers = modifiers;
6935 entry->is_mnemonic = is_mnemonic;
6937 /* GtkAccelGroup stores lowercased accelerators. To deal
6938 * with this, if <Shift> was specified, uppercase.
6940 if (modifiers & GDK_SHIFT_MASK)
6942 if (keyval == GDK_Tab)
6943 keyval = GDK_ISO_Left_Tab;
6945 keyval = gdk_keyval_to_upper (keyval);
6948 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
6952 gtk_window_get_key_hash (GtkWindow *window)
6954 GdkScreen *screen = gtk_window_check_screen (window);
6955 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6960 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
6961 (GDestroyNotify)g_free);
6962 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
6963 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
6969 gtk_window_free_key_hash (GtkWindow *window)
6971 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6974 _gtk_key_hash_free (key_hash);
6975 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
6980 * _gtk_window_activate_key:
6981 * @window: a #GtkWindow
6982 * @event: a #GdkEventKey
6984 * Activates mnemonics and accelerators for this #GtKWindow
6986 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
6989 _gtk_window_activate_key (GtkWindow *window,
6992 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6993 GtkWindowKeyEntry *found_entry = NULL;
6997 gtk_window_keys_changed (window);
6998 key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
7003 GSList *entries = _gtk_key_hash_lookup (key_hash,
7004 event->hardware_keycode,
7006 gtk_accelerator_get_default_mod_mask (),
7010 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
7012 GtkWindowKeyEntry *entry = tmp_list->data;
7013 if (entry->is_mnemonic)
7015 found_entry = entry;
7020 if (!found_entry && entries)
7021 found_entry = entries->data;
7023 g_slist_free (entries);
7028 if (found_entry->is_mnemonic)
7029 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
7031 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
7038 window_update_has_focus (GtkWindow *window)
7040 GtkWidget *widget = GTK_WIDGET (window);
7041 gboolean has_focus = window->has_toplevel_focus && window->is_active;
7043 if (has_focus != window->has_focus)
7045 window->has_focus = has_focus;
7049 if (window->focus_widget &&
7050 window->focus_widget != widget &&
7051 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7052 do_focus_change (window->focus_widget, TRUE);
7056 if (window->focus_widget &&
7057 window->focus_widget != widget &&
7058 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7059 do_focus_change (window->focus_widget, FALSE);
7065 * _gtk_window_set_is_active:
7066 * @window: a #GtkWindow
7067 * @is_active: %TRUE if the window is in the currently active toplevel
7069 * Internal function that sets whether the #GtkWindow is part
7070 * of the currently active toplevel window (taking into account inter-process
7074 _gtk_window_set_is_active (GtkWindow *window,
7077 g_return_if_fail (GTK_IS_WINDOW (window));
7079 is_active = is_active != FALSE;
7081 if (is_active != window->is_active)
7083 window->is_active = is_active;
7084 window_update_has_focus (window);
7086 g_object_notify (G_OBJECT (window), "is_active");
7091 * _gtk_window_set_has_toplevel_focus:
7092 * @window: a #GtkWindow
7093 * @has_toplevel_focus: %TRUE if the in
7095 * Internal function that sets whether the keyboard focus for the
7096 * toplevel window (taking into account inter-process embedding.)
7099 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
7100 gboolean has_toplevel_focus)
7102 g_return_if_fail (GTK_IS_WINDOW (window));
7104 has_toplevel_focus = has_toplevel_focus != FALSE;
7106 if (has_toplevel_focus != window->has_toplevel_focus)
7108 window->has_toplevel_focus = has_toplevel_focus;
7109 window_update_has_focus (window);
7111 g_object_notify (G_OBJECT (window), "has_toplevel_focus");
7116 * gtk_window_set_auto_startup_notification:
7117 * @setting: %TRUE to automatically do startup notification
7119 * By default, after showing the first #GtkWindow for each #GdkScreen,
7120 * GTK+ calls gdk_screen_notify_startup_complete(). Call this
7121 * function to disable the automatic startup notification. You might
7122 * do this if your first window is a splash screen, and you want to
7123 * delay notification until after your real main window has been
7124 * shown, for example.
7126 * In that example, you would disable startup notification
7127 * temporarily, show your splash screen, then re-enable it so that
7128 * showing the main window would automatically result in notification.
7133 gtk_window_set_auto_startup_notification (gboolean setting)
7135 disable_startup_notification = !setting;