1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
30 #include "gdk/gdkkeysyms.h"
32 #include "gtkprivate.h"
34 #include "gtkwindow.h"
35 #include "gtkwindow-decorate.h"
36 #include "gtkbindings.h"
37 #include "gtkkeyhash.h"
39 #include "gtkiconfactory.h"
41 #include "gtkmarshalers.h"
69 PROP_DESTROY_WITH_PARENT,
73 PROP_SKIP_TASKBAR_HINT,
76 /* Readonly properties */
78 PROP_HAS_TOPLEVEL_FOCUS,
86 GdkPixmap *icon_pixmap;
89 guint using_default_icon : 1;
90 guint using_parent_icon : 1;
94 GdkGeometry geometry; /* Last set of geometry hints we set */
96 GdkRectangle configure_request;
97 } GtkWindowLastGeometryInfo;
99 struct _GtkWindowGeometryInfo
101 /* Properties that the app has set on the window
103 GdkGeometry geometry; /* Geometry hints */
105 GtkWidget *widget; /* subwidget to which hints apply */
106 /* from last gtk_window_resize () - if > 0, indicates that
107 * we should resize to this size.
112 /* From last gtk_window_move () prior to mapping -
113 * only used if initial_pos_set
118 /* Default size - used only the FIRST time we map a window,
123 /* whether to use initial_x, initial_y */
124 guint initial_pos_set : 1;
125 /* CENTER_ALWAYS or other position constraint changed since
126 * we sent the last configure request.
128 guint position_constraints_changed : 1;
130 /* if true, default_width, height come from gtk_window_parse_geometry,
131 * and thus should be multiplied by the increments and affect the
132 * geometry widget only
134 guint default_is_geometry : 1;
136 GtkWindowLastGeometryInfo last;
139 typedef struct _GtkWindowMnemonic GtkWindowMnemonic;
141 struct _GtkWindowMnemonic {
148 typedef struct _GtkWindowPrivate GtkWindowPrivate;
150 struct _GtkWindowPrivate
152 guint fullscreen_initially : 1;
153 guint skips_taskbar : 1;
154 guint skips_pager : 1;
157 static void gtk_window_class_init (GtkWindowClass *klass);
158 static void gtk_window_init (GtkWindow *window);
159 static void gtk_window_dispose (GObject *object);
160 static void gtk_window_destroy (GtkObject *object);
161 static void gtk_window_finalize (GObject *object);
162 static void gtk_window_private_finalize (GtkWindowPrivate *priv);
163 static void gtk_window_show (GtkWidget *widget);
164 static void gtk_window_hide (GtkWidget *widget);
165 static void gtk_window_map (GtkWidget *widget);
166 static void gtk_window_unmap (GtkWidget *widget);
167 static void gtk_window_realize (GtkWidget *widget);
168 static void gtk_window_unrealize (GtkWidget *widget);
169 static void gtk_window_size_request (GtkWidget *widget,
170 GtkRequisition *requisition);
171 static void gtk_window_size_allocate (GtkWidget *widget,
172 GtkAllocation *allocation);
173 static gint gtk_window_event (GtkWidget *widget,
175 static gboolean gtk_window_frame_event (GtkWindow *window,
177 static gint gtk_window_configure_event (GtkWidget *widget,
178 GdkEventConfigure *event);
179 static gint gtk_window_key_press_event (GtkWidget *widget,
181 static gint gtk_window_key_release_event (GtkWidget *widget,
183 static gint gtk_window_enter_notify_event (GtkWidget *widget,
184 GdkEventCrossing *event);
185 static gint gtk_window_leave_notify_event (GtkWidget *widget,
186 GdkEventCrossing *event);
187 static gint gtk_window_focus_in_event (GtkWidget *widget,
188 GdkEventFocus *event);
189 static gint gtk_window_focus_out_event (GtkWidget *widget,
190 GdkEventFocus *event);
191 static gint gtk_window_client_event (GtkWidget *widget,
192 GdkEventClient *event);
193 static void gtk_window_check_resize (GtkContainer *container);
194 static gint gtk_window_focus (GtkWidget *widget,
195 GtkDirectionType direction);
196 static void gtk_window_real_set_focus (GtkWindow *window,
199 static void gtk_window_real_activate_default (GtkWindow *window);
200 static void gtk_window_real_activate_focus (GtkWindow *window);
201 static void gtk_window_move_focus (GtkWindow *window,
202 GtkDirectionType dir);
203 static void gtk_window_keys_changed (GtkWindow *window);
204 static void gtk_window_read_rcfiles (GtkWidget *widget,
205 GdkEventClient *event);
206 static void gtk_window_paint (GtkWidget *widget,
208 static gint gtk_window_expose (GtkWidget *widget,
209 GdkEventExpose *event);
210 static void gtk_window_unset_transient_for (GtkWindow *window);
211 static void gtk_window_transient_parent_realized (GtkWidget *parent,
213 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
216 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
219 static void gtk_window_move_resize (GtkWindow *window);
220 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
222 GdkGeometry *geometry_b,
224 static void gtk_window_constrain_size (GtkWindow *window,
225 GdkGeometry *geometry,
231 static void gtk_window_constrain_position (GtkWindow *window,
236 static void gtk_window_compute_hints (GtkWindow *window,
237 GdkGeometry *new_geometry,
239 static void gtk_window_compute_configure_request (GtkWindow *window,
240 GdkRectangle *request,
241 GdkGeometry *geometry,
244 static void gtk_window_set_default_size_internal (GtkWindow *window,
245 gboolean change_width,
247 gboolean change_height,
249 gboolean is_geometry);
251 static void gtk_window_realize_icon (GtkWindow *window);
252 static void gtk_window_unrealize_icon (GtkWindow *window);
254 static void gtk_window_notify_keys_changed (GtkWindow *window);
255 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
256 static void gtk_window_free_key_hash (GtkWindow *window);
258 static GSList *toplevel_list = NULL;
259 static GHashTable *mnemonic_hash_table = NULL;
260 static GtkBinClass *parent_class = NULL;
261 static guint window_signals[LAST_SIGNAL] = { 0 };
262 static GList *default_icon_list = NULL;
263 static guint default_icon_serial = 0;
265 static void gtk_window_set_property (GObject *object,
269 static void gtk_window_get_property (GObject *object,
276 mnemonic_hash (gconstpointer key)
278 const GtkWindowMnemonic *k;
281 k = (GtkWindowMnemonic *)key;
283 h = (gulong) k->window;
284 h ^= k->keyval << 16;
285 h ^= k->keyval >> 16;
291 mnemonic_equal (gconstpointer a, gconstpointer b)
293 const GtkWindowMnemonic *ka;
294 const GtkWindowMnemonic *kb;
296 ka = (GtkWindowMnemonic *)a;
297 kb = (GtkWindowMnemonic *)b;
300 (ka->window == kb->window) &&
301 (ka->keyval == kb->keyval);
305 gtk_window_get_private (GtkWindow *window)
307 GtkWindowPrivate *private;
308 static GQuark private_quark = 0;
311 private_quark = g_quark_from_static_string ("gtk-window-private");
313 private = g_object_get_qdata (G_OBJECT (window), private_quark);
317 private = g_new0 (GtkWindowPrivate, 1);
319 private->fullscreen_initially = FALSE;
320 private->skips_pager = FALSE;
321 private->skips_taskbar = FALSE;
323 g_object_set_qdata_full (G_OBJECT (window), private_quark,
325 (GDestroyNotify) gtk_window_private_finalize);
332 gtk_window_get_type (void)
334 static GType window_type = 0;
338 static const GTypeInfo window_info =
340 sizeof (GtkWindowClass),
341 NULL, /* base_init */
342 NULL, /* base_finalize */
343 (GClassInitFunc) gtk_window_class_init,
344 NULL, /* class_finalize */
345 NULL, /* class_data */
348 (GInstanceInitFunc) gtk_window_init,
351 window_type = g_type_register_static (GTK_TYPE_BIN, "GtkWindow",
359 add_tab_bindings (GtkBindingSet *binding_set,
360 GdkModifierType modifiers,
361 GtkDirectionType direction)
363 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
365 GTK_TYPE_DIRECTION_TYPE, direction);
366 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
368 GTK_TYPE_DIRECTION_TYPE, direction);
372 add_arrow_bindings (GtkBindingSet *binding_set,
374 GtkDirectionType direction)
376 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
378 gtk_binding_entry_add_signal (binding_set, keysym, 0,
380 GTK_TYPE_DIRECTION_TYPE, direction);
381 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
383 GTK_TYPE_DIRECTION_TYPE, direction);
384 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
386 GTK_TYPE_DIRECTION_TYPE, direction);
387 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
389 GTK_TYPE_DIRECTION_TYPE, direction);
394 gtk_window_class_init (GtkWindowClass *klass)
396 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
397 GtkObjectClass *object_class;
398 GtkWidgetClass *widget_class;
399 GtkContainerClass *container_class;
400 GtkBindingSet *binding_set;
402 object_class = (GtkObjectClass*) klass;
403 widget_class = (GtkWidgetClass*) klass;
404 container_class = (GtkContainerClass*) klass;
406 parent_class = g_type_class_peek_parent (klass);
408 mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
410 gobject_class->dispose = gtk_window_dispose;
411 gobject_class->finalize = gtk_window_finalize;
413 gobject_class->set_property = gtk_window_set_property;
414 gobject_class->get_property = gtk_window_get_property;
416 object_class->destroy = gtk_window_destroy;
418 widget_class->show = gtk_window_show;
419 widget_class->hide = gtk_window_hide;
420 widget_class->map = gtk_window_map;
421 widget_class->unmap = gtk_window_unmap;
422 widget_class->realize = gtk_window_realize;
423 widget_class->unrealize = gtk_window_unrealize;
424 widget_class->size_request = gtk_window_size_request;
425 widget_class->size_allocate = gtk_window_size_allocate;
426 widget_class->configure_event = gtk_window_configure_event;
427 widget_class->key_press_event = gtk_window_key_press_event;
428 widget_class->key_release_event = gtk_window_key_release_event;
429 widget_class->enter_notify_event = gtk_window_enter_notify_event;
430 widget_class->leave_notify_event = gtk_window_leave_notify_event;
431 widget_class->focus_in_event = gtk_window_focus_in_event;
432 widget_class->focus_out_event = gtk_window_focus_out_event;
433 widget_class->client_event = gtk_window_client_event;
434 widget_class->focus = gtk_window_focus;
436 widget_class->expose_event = gtk_window_expose;
438 container_class->check_resize = gtk_window_check_resize;
440 klass->set_focus = gtk_window_real_set_focus;
441 klass->frame_event = gtk_window_frame_event;
443 klass->activate_default = gtk_window_real_activate_default;
444 klass->activate_focus = gtk_window_real_activate_focus;
445 klass->move_focus = gtk_window_move_focus;
446 klass->keys_changed = gtk_window_keys_changed;
449 g_object_class_install_property (gobject_class,
451 g_param_spec_enum ("type",
453 _("The type of the window"),
454 GTK_TYPE_WINDOW_TYPE,
456 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
459 g_object_class_install_property (gobject_class,
461 g_param_spec_string ("title",
463 _("The title of the window"),
467 g_object_class_install_property (gobject_class,
469 g_param_spec_boolean ("allow_shrink",
471 /* xgettext:no-c-format */
472 _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
476 g_object_class_install_property (gobject_class,
478 g_param_spec_boolean ("allow_grow",
480 _("If TRUE, users can expand the window beyond its minimum size"),
484 g_object_class_install_property (gobject_class,
486 g_param_spec_boolean ("resizable",
488 _("If TRUE, users can resize the window"),
492 g_object_class_install_property (gobject_class,
494 g_param_spec_boolean ("modal",
496 _("If TRUE, the window is modal (other windows are not usable while this one is up)"),
500 g_object_class_install_property (gobject_class,
502 g_param_spec_enum ("window_position",
503 _("Window Position"),
504 _("The initial position of the window"),
505 GTK_TYPE_WINDOW_POSITION,
509 g_object_class_install_property (gobject_class,
511 g_param_spec_int ("default_width",
513 _("The default width of the window, used when initially showing the window"),
519 g_object_class_install_property (gobject_class,
521 g_param_spec_int ("default_height",
523 _("The default height of the window, used when initially showing the window"),
529 g_object_class_install_property (gobject_class,
530 PROP_DESTROY_WITH_PARENT,
531 g_param_spec_boolean ("destroy_with_parent",
532 _("Destroy with Parent"),
533 _("If this window should be destroyed when the parent is destroyed"),
537 g_object_class_install_property (gobject_class,
539 g_param_spec_object ("icon",
541 _("Icon for this window"),
545 g_object_class_install_property (gobject_class,
547 g_param_spec_object ("screen",
549 _("The screen where this window will be displayed"),
553 g_object_class_install_property (gobject_class,
555 g_param_spec_boolean ("is_active",
557 _("Whether the toplevel is the current active window"),
561 g_object_class_install_property (gobject_class,
562 PROP_HAS_TOPLEVEL_FOCUS,
563 g_param_spec_boolean ("has_toplevel_focus",
564 _("Focus in Toplevel"),
565 _("Whether the input focus is within this GtkWindow"),
569 g_object_class_install_property (gobject_class,
571 g_param_spec_enum ("type_hint",
573 _("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
574 GDK_TYPE_WINDOW_TYPE_HINT,
575 GDK_WINDOW_TYPE_HINT_NORMAL,
578 g_object_class_install_property (gobject_class,
579 PROP_SKIP_TASKBAR_HINT,
580 g_param_spec_boolean ("skip_taskbar_hint",
582 _("TRUE if the window should not be in the task bar."),
586 g_object_class_install_property (gobject_class,
587 PROP_SKIP_PAGER_HINT,
588 g_param_spec_boolean ("skip_pager_hint",
590 _("TRUE if the window should not be in the pager."),
594 window_signals[SET_FOCUS] =
595 g_signal_new ("set_focus",
596 G_TYPE_FROM_CLASS (gobject_class),
598 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
600 _gtk_marshal_VOID__OBJECT,
604 window_signals[FRAME_EVENT] =
605 g_signal_new ("frame_event",
606 G_TYPE_FROM_CLASS (gobject_class),
608 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
609 _gtk_boolean_handled_accumulator, NULL,
610 _gtk_marshal_BOOLEAN__BOXED,
614 window_signals[ACTIVATE_FOCUS] =
615 g_signal_new ("activate_focus",
616 G_TYPE_FROM_CLASS (gobject_class),
617 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
618 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
620 _gtk_marshal_VOID__VOID,
624 window_signals[ACTIVATE_DEFAULT] =
625 g_signal_new ("activate_default",
626 G_TYPE_FROM_CLASS (gobject_class),
627 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
628 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
630 _gtk_marshal_VOID__VOID,
634 window_signals[MOVE_FOCUS] =
635 g_signal_new ("move_focus",
636 G_TYPE_FROM_CLASS (gobject_class),
637 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
638 G_STRUCT_OFFSET (GtkWindowClass, move_focus),
640 _gtk_marshal_VOID__ENUM,
643 GTK_TYPE_DIRECTION_TYPE);
645 window_signals[KEYS_CHANGED] =
646 g_signal_new ("keys_changed",
647 G_TYPE_FROM_CLASS (gobject_class),
649 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
651 _gtk_marshal_VOID__VOID,
659 binding_set = gtk_binding_set_by_class (klass);
661 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
662 "activate_focus", 0);
663 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
664 "activate_focus", 0);
666 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
667 "activate_default", 0);
669 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
670 "activate_default", 0);
672 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
673 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
674 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
675 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
677 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
678 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
679 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
680 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
684 gtk_window_init (GtkWindow *window)
686 GdkColormap *colormap;
688 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
689 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
691 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
693 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
695 window->title = NULL;
696 window->wmclass_name = g_strdup (g_get_prgname ());
697 window->wmclass_class = g_strdup (gdk_get_program_class ());
698 window->wm_role = NULL;
699 window->geometry_info = NULL;
700 window->type = GTK_WINDOW_TOPLEVEL;
701 window->focus_widget = NULL;
702 window->default_widget = NULL;
703 window->configure_request_count = 0;
704 window->allow_shrink = FALSE;
705 window->allow_grow = TRUE;
706 window->configure_notify_received = FALSE;
707 window->position = GTK_WIN_POS_NONE;
708 window->need_default_size = TRUE;
709 window->need_default_position = TRUE;
710 window->modal = FALSE;
711 window->frame = NULL;
712 window->has_frame = FALSE;
713 window->frame_left = 0;
714 window->frame_right = 0;
715 window->frame_top = 0;
716 window->frame_bottom = 0;
717 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
718 window->gravity = GDK_GRAVITY_NORTH_WEST;
719 window->decorated = TRUE;
720 window->mnemonic_modifier = GDK_MOD1_MASK;
721 window->screen = gdk_screen_get_default ();
723 colormap = _gtk_widget_peek_colormap ();
725 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
727 g_object_ref (window);
728 gtk_object_sink (GTK_OBJECT (window));
729 window->has_user_ref_count = TRUE;
730 toplevel_list = g_slist_prepend (toplevel_list, window);
732 gtk_decorated_window_init (window);
734 g_signal_connect (window,
736 G_CALLBACK (gtk_window_event),
741 gtk_window_set_property (GObject *object,
748 window = GTK_WINDOW (object);
753 window->type = g_value_get_enum (value);
756 gtk_window_set_title (window, g_value_get_string (value));
758 case PROP_ALLOW_SHRINK:
759 window->allow_shrink = g_value_get_boolean (value);
760 gtk_widget_queue_resize (GTK_WIDGET (window));
762 case PROP_ALLOW_GROW:
763 window->allow_grow = g_value_get_boolean (value);
764 gtk_widget_queue_resize (GTK_WIDGET (window));
765 g_object_notify (G_OBJECT (window), "resizable");
768 window->allow_grow = g_value_get_boolean (value);
769 gtk_widget_queue_resize (GTK_WIDGET (window));
770 g_object_notify (G_OBJECT (window), "allow_grow");
773 gtk_window_set_modal (window, g_value_get_boolean (value));
776 gtk_window_set_position (window, g_value_get_enum (value));
778 case PROP_DEFAULT_WIDTH:
779 gtk_window_set_default_size_internal (window,
780 TRUE, g_value_get_int (value),
783 case PROP_DEFAULT_HEIGHT:
784 gtk_window_set_default_size_internal (window,
786 TRUE, g_value_get_int (value), FALSE);
788 case PROP_DESTROY_WITH_PARENT:
789 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
792 gtk_window_set_icon (window,
793 g_value_get_object (value));
796 gtk_window_set_screen (window, g_value_get_object (value));
799 gtk_window_set_type_hint (window,
800 g_value_get_enum (value));
802 case PROP_SKIP_TASKBAR_HINT:
803 gtk_window_set_skip_taskbar_hint (window,
804 g_value_get_boolean (value));
806 case PROP_SKIP_PAGER_HINT:
807 gtk_window_set_skip_pager_hint (window,
808 g_value_get_boolean (value));
817 gtk_window_get_property (GObject *object,
824 window = GTK_WINDOW (object);
828 GtkWindowGeometryInfo *info;
830 g_value_set_enum (value, window->type);
833 g_value_set_string (value, window->title);
835 case PROP_ALLOW_SHRINK:
836 g_value_set_boolean (value, window->allow_shrink);
838 case PROP_ALLOW_GROW:
839 g_value_set_boolean (value, window->allow_grow);
842 g_value_set_boolean (value, window->allow_grow);
845 g_value_set_boolean (value, window->modal);
848 g_value_set_enum (value, window->position);
850 case PROP_DEFAULT_WIDTH:
851 info = gtk_window_get_geometry_info (window, FALSE);
853 g_value_set_int (value, -1);
855 g_value_set_int (value, info->default_width);
857 case PROP_DEFAULT_HEIGHT:
858 info = gtk_window_get_geometry_info (window, FALSE);
860 g_value_set_int (value, -1);
862 g_value_set_int (value, info->default_height);
864 case PROP_DESTROY_WITH_PARENT:
865 g_value_set_boolean (value, window->destroy_with_parent);
868 g_value_set_object (value, gtk_window_get_icon (window));
871 g_value_set_object (value, window->screen);
874 g_value_set_boolean (value, window->is_active);
876 case PROP_HAS_TOPLEVEL_FOCUS:
877 g_value_set_boolean (value, window->has_toplevel_focus);
880 g_value_set_enum (value,
883 case PROP_SKIP_TASKBAR_HINT:
884 g_value_set_boolean (value,
885 gtk_window_get_skip_taskbar_hint (window));
887 case PROP_SKIP_PAGER_HINT:
888 g_value_set_boolean (value,
889 gtk_window_get_skip_pager_hint (window));
892 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
899 * @type: type of window
901 * Creates a new #GtkWindow, which is a toplevel window that can
902 * contain other widgets. Nearly always, the type of the window should
903 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
904 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
905 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
906 * dialogs, though in some other toolkits dialogs are called "popups".
907 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
908 * On X11, popup windows are not controlled by the <link
909 * linkend="gtk-X11-arch">window manager</link>.
911 * If you simply want an undecorated window (no window borders), use
912 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
914 * Return value: a new #GtkWindow.
917 gtk_window_new (GtkWindowType type)
921 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
923 window = g_object_new (GTK_TYPE_WINDOW, NULL);
927 return GTK_WIDGET (window);
931 * gtk_window_set_title:
932 * @window: a #GtkWindow
933 * @title: title of the window
935 * Sets the title of the #GtkWindow. The title of a window will be
936 * displayed in its title bar; on the X Window System, the title bar
937 * is rendered by the <link linkend="gtk-X11-arch">window
938 * manager</link>, so exactly how the title appears to users may vary
939 * according to a user's exact configuration. The title should help a
940 * user distinguish this window from other windows they may have
941 * open. A good title might include the application name and current
942 * document filename, for example.
946 gtk_window_set_title (GtkWindow *window,
949 g_return_if_fail (GTK_IS_WINDOW (window));
952 g_free (window->title);
953 window->title = g_strdup (title);
955 if (GTK_WIDGET_REALIZED (window))
957 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
959 gtk_decorated_window_set_title (window, title);
962 g_object_notify (G_OBJECT (window), "title");
966 * gtk_window_get_title:
967 * @window: a #GtkWindow
969 * Retrieves the title of the window. See gtk_window_set_title().
971 * Return value: the title of the window, or %NULL if none has
972 * been set explicitely. The returned string is owned by the widget
973 * and must not be modified or freed.
975 G_CONST_RETURN gchar *
976 gtk_window_get_title (GtkWindow *window)
978 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
980 return window->title;
984 * gtk_window_set_wmclass:
985 * @window: a #GtkWindow
986 * @wmclass_name: window name hint
987 * @wmclass_class: window class hint
989 * Don't use this function. It sets the X Window System "class" and
990 * "name" hints for a window. According to the ICCCM, you should
991 * always set these to the same value for all windows in an
992 * application, and GTK+ sets them to that value by default, so calling
993 * this function is sort of pointless. However, you may want to call
994 * gtk_window_set_role() on each window in your application, for the
995 * benefit of the session manager. Setting the role allows the window
996 * manager to restore window positions when loading a saved session.
1000 gtk_window_set_wmclass (GtkWindow *window,
1001 const gchar *wmclass_name,
1002 const gchar *wmclass_class)
1004 g_return_if_fail (GTK_IS_WINDOW (window));
1006 g_free (window->wmclass_name);
1007 window->wmclass_name = g_strdup (wmclass_name);
1009 g_free (window->wmclass_class);
1010 window->wmclass_class = g_strdup (wmclass_class);
1012 if (GTK_WIDGET_REALIZED (window))
1013 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1017 * gtk_window_set_role:
1018 * @window: a #GtkWindow
1019 * @role: unique identifier for the window to be used when restoring a session
1021 * This function is only useful on X11, not with other GTK+ targets.
1023 * In combination with the window title, the window role allows a
1024 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1025 * same" window when an application is restarted. So for example you
1026 * might set the "toolbox" role on your app's toolbox window, so that
1027 * when the user restarts their session, the window manager can put
1028 * the toolbox back in the same place.
1030 * If a window already has a unique title, you don't need to set the
1031 * role, since the WM can use the title to identify the window when
1032 * restoring the session.
1036 gtk_window_set_role (GtkWindow *window,
1039 g_return_if_fail (GTK_IS_WINDOW (window));
1041 if (role == window->wm_role)
1044 g_free (window->wm_role);
1045 window->wm_role = g_strdup (role);
1047 if (GTK_WIDGET_REALIZED (window))
1048 g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
1052 * gtk_window_get_role:
1053 * @window: a #GtkWindow
1055 * Returns the role of the window. See gtk_window_set_role() for
1056 * further explanation.
1058 * Return value: the role of the window if set, or %NULL. The
1059 * returned is owned by the widget and must not be modified
1062 G_CONST_RETURN gchar *
1063 gtk_window_get_role (GtkWindow *window)
1065 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1067 return window->wm_role;
1071 * gtk_window_set_focus:
1072 * @window: a #GtkWindow
1073 * @focus: widget to be the new focus widget, or %NULL to unset
1074 * any focus widget for the toplevel window.
1076 * If @focus is not the current focus widget, and is focusable, sets
1077 * it as the focus widget for the window. If @focus is %NULL, unsets
1078 * the focus widget for this window. To set the focus to a particular
1079 * widget in the toplevel, it is usually more convenient to use
1080 * gtk_widget_grab_focus() instead of this function.
1083 gtk_window_set_focus (GtkWindow *window,
1086 g_return_if_fail (GTK_IS_WINDOW (window));
1089 g_return_if_fail (GTK_IS_WIDGET (focus));
1090 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1094 gtk_widget_grab_focus (focus);
1097 /* Clear the existing focus chain, so that when we focus into
1098 * the window again, we start at the beginnning.
1100 GtkWidget *widget = window->focus_widget;
1103 while (widget->parent)
1105 widget = widget->parent;
1106 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1110 _gtk_window_internal_set_focus (window, NULL);
1115 _gtk_window_internal_set_focus (GtkWindow *window,
1118 g_return_if_fail (GTK_IS_WINDOW (window));
1120 if ((window->focus_widget != focus) ||
1121 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1122 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1126 * gtk_window_set_default:
1127 * @window: a #GtkWindow
1128 * @default_widget: widget to be the default, or %NULL to unset the
1129 * default widget for the toplevel.
1131 * The default widget is the widget that's activated when the user
1132 * presses Enter in a dialog (for example). This function sets or
1133 * unsets the default widget for a #GtkWindow about. When setting
1134 * (rather than unsetting) the default widget it's generally easier to
1135 * call gtk_widget_grab_focus() on the widget. Before making a widget
1136 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1137 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1140 gtk_window_set_default (GtkWindow *window,
1141 GtkWidget *default_widget)
1143 g_return_if_fail (GTK_IS_WINDOW (window));
1146 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1148 if (window->default_widget != default_widget)
1150 GtkWidget *old_default_widget = NULL;
1153 g_object_ref (default_widget);
1155 if (window->default_widget)
1157 old_default_widget = window->default_widget;
1159 if (window->focus_widget != window->default_widget ||
1160 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1161 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1162 gtk_widget_queue_draw (window->default_widget);
1165 window->default_widget = default_widget;
1167 if (window->default_widget)
1169 if (window->focus_widget == NULL ||
1170 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1171 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1172 gtk_widget_queue_draw (window->default_widget);
1175 if (old_default_widget)
1176 g_object_notify (G_OBJECT (old_default_widget), "has_default");
1180 g_object_notify (G_OBJECT (default_widget), "has_default");
1181 g_object_unref (default_widget);
1187 gtk_window_set_policy (GtkWindow *window,
1188 gboolean allow_shrink,
1189 gboolean allow_grow,
1190 gboolean auto_shrink)
1192 g_return_if_fail (GTK_IS_WINDOW (window));
1194 window->allow_shrink = (allow_shrink != FALSE);
1195 window->allow_grow = (allow_grow != FALSE);
1197 g_object_freeze_notify (G_OBJECT (window));
1198 g_object_notify (G_OBJECT (window), "allow_shrink");
1199 g_object_notify (G_OBJECT (window), "allow_grow");
1200 g_object_notify (G_OBJECT (window), "resizable");
1201 g_object_thaw_notify (G_OBJECT (window));
1203 gtk_widget_queue_resize (GTK_WIDGET (window));
1207 handle_keys_changed (gpointer data)
1211 GDK_THREADS_ENTER ();
1212 window = GTK_WINDOW (data);
1214 if (window->keys_changed_handler)
1216 gtk_idle_remove (window->keys_changed_handler);
1217 window->keys_changed_handler = 0;
1220 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1221 GDK_THREADS_LEAVE ();
1227 gtk_window_notify_keys_changed (GtkWindow *window)
1229 if (!window->keys_changed_handler)
1230 window->keys_changed_handler = gtk_idle_add (handle_keys_changed, window);
1234 * gtk_window_add_accel_group:
1235 * @window: window to attach accelerator group to
1236 * @accel_group: a #GtkAccelGroup
1238 * Associate @accel_group with @window, such that calling
1239 * gtk_accel_groups_activate() on @window will activate accelerators
1243 gtk_window_add_accel_group (GtkWindow *window,
1244 GtkAccelGroup *accel_group)
1246 g_return_if_fail (GTK_IS_WINDOW (window));
1247 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1249 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1250 g_signal_connect_object (accel_group, "accel_changed",
1251 G_CALLBACK (gtk_window_notify_keys_changed),
1252 window, G_CONNECT_SWAPPED);
1256 * gtk_window_remove_accel_group:
1257 * @window: a #GtkWindow
1258 * @accel_group: a #GtkAccelGroup
1260 * Reverses the effects of gtk_window_add_accel_group().
1263 gtk_window_remove_accel_group (GtkWindow *window,
1264 GtkAccelGroup *accel_group)
1266 g_return_if_fail (GTK_IS_WINDOW (window));
1267 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1269 g_signal_handlers_disconnect_by_func (accel_group,
1270 gtk_window_notify_keys_changed,
1272 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1276 * gtk_window_add_mnemonic:
1277 * @window: a #GtkWindow
1278 * @keyval: the mnemonic
1279 * @target: the widget that gets activated by the mnemonic
1281 * Adds a mnemonic to this window.
1284 gtk_window_add_mnemonic (GtkWindow *window,
1288 GtkWindowMnemonic key;
1289 GtkWindowMnemonic *mnemonic;
1291 g_return_if_fail (GTK_IS_WINDOW (window));
1292 g_return_if_fail (GTK_IS_WIDGET (target));
1294 key.window = window;
1295 key.keyval = keyval;
1296 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1300 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1301 mnemonic->targets = g_slist_append (mnemonic->targets, target);
1305 mnemonic = g_new (GtkWindowMnemonic, 1);
1307 mnemonic->targets = g_slist_prepend (NULL, target);
1308 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1310 gtk_window_notify_keys_changed (window);
1314 * gtk_window_remove_mnemonic:
1315 * @window: a #GtkWindow
1316 * @keyval: the mnemonic
1317 * @target: the widget that gets activated by the mnemonic
1319 * Removes a mnemonic from this window.
1322 gtk_window_remove_mnemonic (GtkWindow *window,
1326 GtkWindowMnemonic key;
1327 GtkWindowMnemonic *mnemonic;
1329 g_return_if_fail (GTK_IS_WINDOW (window));
1330 g_return_if_fail (GTK_IS_WIDGET (target));
1332 key.window = window;
1333 key.keyval = keyval;
1334 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1336 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1338 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1339 if (mnemonic->targets == NULL)
1341 g_hash_table_remove (mnemonic_hash_table, mnemonic);
1344 gtk_window_notify_keys_changed (window);
1348 * gtk_window_mnemonic_activate:
1349 * @window: a #GtkWindow
1350 * @keyval: the mnemonic
1351 * @modifier: the modifiers
1352 * @returns: %TRUE if the activation is done.
1354 * Activates the targets associated with the mnemonic.
1357 gtk_window_mnemonic_activate (GtkWindow *window,
1359 GdkModifierType modifier)
1361 GtkWindowMnemonic key;
1362 GtkWindowMnemonic *mnemonic;
1364 GtkWidget *widget, *chosen_widget;
1365 gboolean overloaded;
1367 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1369 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1372 key.window = window;
1373 key.keyval = keyval;
1374 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1380 chosen_widget = NULL;
1381 list = mnemonic->targets;
1384 widget = GTK_WIDGET (list->data);
1386 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1387 GTK_WIDGET_MAPPED (widget))
1395 chosen_widget = widget;
1397 list = g_slist_next (list);
1402 /* For round robin we put the activated entry on
1403 * the end of the list after activation
1405 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1406 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1408 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1414 * gtk_window_set_mnemonic_modifier:
1415 * @window: a #GtkWindow
1416 * @modifier: the modifier mask used to activate
1417 * mnemonics on this window.
1419 * Sets the mnemonic modifier for this window.
1422 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1423 GdkModifierType modifier)
1425 g_return_if_fail (GTK_IS_WINDOW (window));
1426 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1428 window->mnemonic_modifier = modifier;
1429 gtk_window_notify_keys_changed (window);
1433 * gtk_window_get_mnemonic_modifier:
1434 * @window: a #GtkWindow
1436 * Returns the mnemonic modifier for this window. See
1437 * gtk_window_set_mnemonic_modifier().
1439 * Return value: the modifier mask used to activate
1440 * mnemonics on this window.
1443 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1445 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1447 return window->mnemonic_modifier;
1451 * gtk_window_set_position:
1452 * @window: a #GtkWindow.
1453 * @position: a position constraint.
1455 * Sets a position constraint for this window. If the old or new
1456 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1457 * the window to be repositioned to satisfy the new constraint.
1460 gtk_window_set_position (GtkWindow *window,
1461 GtkWindowPosition position)
1463 g_return_if_fail (GTK_IS_WINDOW (window));
1465 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1466 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1468 GtkWindowGeometryInfo *info;
1470 info = gtk_window_get_geometry_info (window, TRUE);
1472 /* this flag causes us to re-request the CENTER_ALWAYS
1473 * constraint in gtk_window_move_resize(), see
1474 * comment in that function.
1476 info->position_constraints_changed = TRUE;
1478 gtk_widget_queue_resize (GTK_WIDGET (window));
1481 window->position = position;
1483 g_object_notify (G_OBJECT (window), "window_position");
1487 gtk_window_activate_focus (GtkWindow *window)
1489 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1491 if (window->focus_widget)
1493 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1494 gtk_widget_activate (window->focus_widget);
1502 * gtk_window_get_focus:
1503 * @window: a #GtkWindow
1505 * Retrieves the current focused widget within the window.
1506 * Note that this is the widget that would have the focus
1507 * if the toplevel window focused; if the toplevel window
1508 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1509 * not be %TRUE for the widget.
1511 * Return value: the currently focused widget.
1514 gtk_window_get_focus (GtkWindow *window)
1516 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1518 return window->focus_widget;
1522 gtk_window_activate_default (GtkWindow *window)
1524 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1526 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1527 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1529 gtk_widget_activate (window->default_widget);
1532 else if (window->focus_widget)
1534 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1535 gtk_widget_activate (window->focus_widget);
1543 * gtk_window_set_modal:
1544 * @window: a #GtkWindow
1545 * @modal: whether the window is modal
1547 * Sets a window modal or non-modal. Modal windows prevent interaction
1548 * with other windows in the same application. To keep modal dialogs
1549 * on top of main application windows, use
1550 * gtk_window_set_transient_for() to make the dialog transient for the
1551 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1552 * will then disallow lowering the dialog below the parent.
1557 gtk_window_set_modal (GtkWindow *window,
1560 g_return_if_fail (GTK_IS_WINDOW (window));
1562 window->modal = modal != FALSE;
1564 /* adjust desired modality state */
1565 if (GTK_WIDGET_VISIBLE (window) && window->modal)
1566 gtk_grab_add (GTK_WIDGET (window));
1568 gtk_grab_remove (GTK_WIDGET (window));
1570 g_object_notify (G_OBJECT (window), "modal");
1574 * gtk_window_get_modal:
1575 * @window: a #GtkWindow
1577 * Returns whether the window is modal. See gtk_window_set_modal().
1579 * Return value: %TRUE if the window is set to be modal and
1580 * establishes a grab when shown
1583 gtk_window_get_modal (GtkWindow *window)
1585 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1587 return window->modal;
1591 * gtk_window_list_toplevels:
1593 * Returns a list of all existing toplevel windows. The widgets
1594 * in the list are not individually referenced. If you want
1595 * to iterate through the list and perform actions involving
1596 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1597 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1598 * then unref all the widgets afterwards.
1600 * Return value: list of toplevel widgets
1603 gtk_window_list_toplevels (void)
1608 for (slist = toplevel_list; slist; slist = slist->next)
1609 list = g_list_prepend (list, slist->data);
1615 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1617 GList *embedded_windows;
1619 g_return_if_fail (GTK_IS_WINDOW (window));
1621 embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1622 if (embedded_windows)
1623 g_object_steal_qdata (G_OBJECT (window),
1624 g_quark_from_static_string ("gtk-embedded"));
1625 embedded_windows = g_list_prepend (embedded_windows,
1626 GUINT_TO_POINTER (xid));
1628 g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
1631 (GDestroyNotify) g_list_free : NULL);
1635 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1637 GList *embedded_windows;
1640 g_return_if_fail (GTK_IS_WINDOW (window));
1642 embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1643 if (embedded_windows)
1644 g_object_steal_qdata (G_OBJECT (window),
1645 g_quark_from_static_string ("gtk-embedded"));
1647 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1650 embedded_windows = g_list_remove_link (embedded_windows, node);
1651 g_list_free_1 (node);
1654 g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
1657 (GDestroyNotify) g_list_free : NULL);
1661 _gtk_window_reposition (GtkWindow *window,
1665 g_return_if_fail (GTK_IS_WINDOW (window));
1667 gtk_window_move (window, x, y);
1671 gtk_window_dispose (GObject *object)
1673 GtkWindow *window = GTK_WINDOW (object);
1675 gtk_window_set_focus (window, NULL);
1676 gtk_window_set_default (window, NULL);
1678 G_OBJECT_CLASS (parent_class)->dispose (object);
1682 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1684 gtk_widget_destroy (GTK_WIDGET (child));
1688 connect_parent_destroyed (GtkWindow *window)
1690 if (window->transient_parent)
1692 g_signal_connect (window->transient_parent,
1694 G_CALLBACK (parent_destroyed_callback),
1700 disconnect_parent_destroyed (GtkWindow *window)
1702 if (window->transient_parent)
1704 g_signal_handlers_disconnect_by_func (window->transient_parent,
1705 parent_destroyed_callback,
1711 gtk_window_transient_parent_realized (GtkWidget *parent,
1714 if (GTK_WIDGET_REALIZED (window))
1715 gdk_window_set_transient_for (window->window, parent->window);
1719 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1722 if (GTK_WIDGET_REALIZED (window))
1723 gdk_property_delete (window->window,
1724 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1728 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
1732 gtk_window_set_screen (window, parent->screen);
1736 gtk_window_unset_transient_for (GtkWindow *window)
1738 if (window->transient_parent)
1740 g_signal_handlers_disconnect_by_func (window->transient_parent,
1741 gtk_window_transient_parent_realized,
1743 g_signal_handlers_disconnect_by_func (window->transient_parent,
1744 gtk_window_transient_parent_unrealized,
1746 g_signal_handlers_disconnect_by_func (window->transient_parent,
1747 gtk_window_transient_parent_screen_changed,
1749 g_signal_handlers_disconnect_by_func (window->transient_parent,
1750 gtk_widget_destroyed,
1751 &window->transient_parent);
1753 if (window->destroy_with_parent)
1754 disconnect_parent_destroyed (window);
1756 window->transient_parent = NULL;
1761 * gtk_window_set_transient_for:
1762 * @window: a #GtkWindow
1763 * @parent: parent window
1765 * Dialog windows should be set transient for the main application
1766 * window they were spawned from. This allows <link
1767 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1768 * dialog on top of the main window, or center the dialog over the
1769 * main window. gtk_dialog_new_with_buttons() and other convenience
1770 * functions in GTK+ will sometimes call
1771 * gtk_window_set_transient_for() on your behalf.
1773 * On Windows, this function will and put the child window
1774 * on top of the parent, much as the window manager would have
1779 gtk_window_set_transient_for (GtkWindow *window,
1782 g_return_if_fail (GTK_IS_WINDOW (window));
1783 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1784 g_return_if_fail (window != parent);
1787 if (window->transient_parent)
1789 if (GTK_WIDGET_REALIZED (window) &&
1790 GTK_WIDGET_REALIZED (window->transient_parent) &&
1791 (!parent || !GTK_WIDGET_REALIZED (parent)))
1792 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1793 GTK_WIDGET (window));
1795 gtk_window_unset_transient_for (window);
1798 window->transient_parent = parent;
1802 g_signal_connect (parent, "destroy",
1803 G_CALLBACK (gtk_widget_destroyed),
1804 &window->transient_parent);
1805 g_signal_connect (parent, "realize",
1806 G_CALLBACK (gtk_window_transient_parent_realized),
1808 g_signal_connect (parent, "unrealize",
1809 G_CALLBACK (gtk_window_transient_parent_unrealized),
1811 g_signal_connect (parent, "notify::screen",
1812 G_CALLBACK (gtk_window_transient_parent_screen_changed),
1815 gtk_window_set_screen (window, parent->screen);
1817 if (window->destroy_with_parent)
1818 connect_parent_destroyed (window);
1820 if (GTK_WIDGET_REALIZED (window) &&
1821 GTK_WIDGET_REALIZED (parent))
1822 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1823 GTK_WIDGET (window));
1828 * gtk_window_get_transient_for:
1829 * @window: a #GtkWindow
1831 * Fetches the transient parent for this window. See
1832 * gtk_window_set_transient_for().
1834 * Return value: the transient parent for this window, or %NULL
1835 * if no transient parent has been set.
1838 gtk_window_get_transient_for (GtkWindow *window)
1840 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1842 return window->transient_parent;
1846 * gtk_window_set_type_hint:
1847 * @window: a #GtkWindow
1848 * @hint: the window type
1850 * By setting the type hint for the window, you allow the window
1851 * manager to decorate and handle the window in a way which is
1852 * suitable to the function of the window in your application.
1854 * This function should be called before the window becomes visible.
1856 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1857 * will sometimes call gtk_window_set_type_hint() on your behalf.
1861 gtk_window_set_type_hint (GtkWindow *window,
1862 GdkWindowTypeHint hint)
1864 g_return_if_fail (GTK_IS_WINDOW (window));
1865 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1866 window->type_hint = hint;
1870 * gtk_window_get_type_hint:
1871 * @window: a #GtkWindow
1873 * Gets the type hint for this window. See gtk_window_set_type_hint().
1875 * Return value: the type hint for @window.
1878 gtk_window_get_type_hint (GtkWindow *window)
1880 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1882 return window->type_hint;
1886 * gtk_window_set_skip_taskbar_hint:
1887 * @window: a #GtkWindow
1888 * @setting: %TRUE to keep this window from appearing in the task bar
1890 * Windows may set a hint asking the desktop environment not to display
1891 * the window in the task bar. This function toggles this hint.
1895 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
1898 GtkWindowPrivate *priv;
1900 g_return_if_fail (GTK_IS_WINDOW (window));
1902 priv = gtk_window_get_private (window);
1904 setting = setting != FALSE;
1906 if (priv->skips_taskbar != setting)
1908 priv->skips_taskbar = setting;
1909 if (GTK_WIDGET_REALIZED (window))
1910 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
1911 priv->skips_taskbar);
1912 g_object_notify (G_OBJECT (window), "skip_taskbar_hint");
1917 * gtk_window_get_skip_taskbar_hint:
1918 * @window: a #GtkWindow
1920 * Gets the value set by gtk_window_set_skip_taskbar_hint()
1922 * Return value: %TRUE if window shouldn't be in taskbar
1925 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
1927 GtkWindowPrivate *priv;
1929 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1931 priv = gtk_window_get_private (window);
1933 return priv->skips_taskbar;
1937 * gtk_window_set_skip_pager_hint:
1938 * @window: a #GtkWindow
1939 * @setting: %TRUE to keep this window from appearing in the pager
1941 * Windows may set a hint asking the desktop environment not to display
1942 * the window in the pager. This function toggles this hint.
1943 * (A "pager" is any desktop navigation tool such as a workspace
1944 * switcher that displays a thumbnail representation of the windows
1949 gtk_window_set_skip_pager_hint (GtkWindow *window,
1952 GtkWindowPrivate *priv;
1954 g_return_if_fail (GTK_IS_WINDOW (window));
1956 priv = gtk_window_get_private (window);
1958 setting = setting != FALSE;
1960 if (priv->skips_pager != setting)
1962 priv->skips_pager = setting;
1963 if (GTK_WIDGET_REALIZED (window))
1964 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
1966 g_object_notify (G_OBJECT (window), "skip_pager_hint");
1971 * gtk_window_get_skip_pager_hint:
1972 * @window: a #GtkWindow
1974 * Gets the value set by gtk_window_set_skip_pager_hint().
1976 * Return value: %TRUE if window shouldn't be in pager
1979 gtk_window_get_skip_pager_hint (GtkWindow *window)
1981 GtkWindowPrivate *priv;
1983 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1985 priv = gtk_window_get_private (window);
1987 return priv->skips_pager;
1991 * gtk_window_set_destroy_with_parent:
1992 * @window: a #GtkWindow
1993 * @setting: whether to destroy @window with its transient parent
1995 * If @setting is %TRUE, then destroying the transient parent of @window
1996 * will also destroy @window itself. This is useful for dialogs that
1997 * shouldn't persist beyond the lifetime of the main window they're
1998 * associated with, for example.
2001 gtk_window_set_destroy_with_parent (GtkWindow *window,
2004 g_return_if_fail (GTK_IS_WINDOW (window));
2006 if (window->destroy_with_parent == (setting != FALSE))
2009 if (window->destroy_with_parent)
2011 disconnect_parent_destroyed (window);
2015 connect_parent_destroyed (window);
2018 window->destroy_with_parent = setting;
2020 g_object_notify (G_OBJECT (window), "destroy_with_parent");
2024 * gtk_window_get_destroy_with_parent:
2025 * @window: a #GtkWindow
2027 * Returns whether the window will be destroyed with its transient parent. See
2028 * gtk_window_set_destroy_with_parent ().
2030 * Return value: %TRUE if the window will be destroyed with its transient parent.
2033 gtk_window_get_destroy_with_parent (GtkWindow *window)
2035 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2037 return window->destroy_with_parent;
2040 static GtkWindowGeometryInfo*
2041 gtk_window_get_geometry_info (GtkWindow *window,
2044 GtkWindowGeometryInfo *info;
2046 info = window->geometry_info;
2047 if (!info && create)
2049 info = g_new0 (GtkWindowGeometryInfo, 1);
2051 info->default_width = -1;
2052 info->default_height = -1;
2053 info->resize_width = -1;
2054 info->resize_height = -1;
2055 info->initial_x = 0;
2056 info->initial_y = 0;
2057 info->initial_pos_set = FALSE;
2058 info->default_is_geometry = FALSE;
2059 info->position_constraints_changed = FALSE;
2060 info->last.configure_request.x = 0;
2061 info->last.configure_request.y = 0;
2062 info->last.configure_request.width = -1;
2063 info->last.configure_request.height = -1;
2064 info->widget = NULL;
2066 window->geometry_info = info;
2073 * gtk_window_set_geometry_hints:
2074 * @window: a #GtkWindow
2075 * @geometry_widget: widget the geometry hints will be applied to
2076 * @geometry: struct containing geometry information
2077 * @geom_mask: mask indicating which struct fields should be paid attention to
2079 * This function sets up hints about how a window can be resized by
2080 * the user. You can set a minimum and maximum size; allowed resize
2081 * increments (e.g. for xterm, you can only resize by the size of a
2082 * character); aspect ratios; and more. See the #GdkGeometry struct.
2086 gtk_window_set_geometry_hints (GtkWindow *window,
2087 GtkWidget *geometry_widget,
2088 GdkGeometry *geometry,
2089 GdkWindowHints geom_mask)
2091 GtkWindowGeometryInfo *info;
2093 g_return_if_fail (GTK_IS_WINDOW (window));
2094 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2096 info = gtk_window_get_geometry_info (window, TRUE);
2099 g_signal_handlers_disconnect_by_func (info->widget,
2100 gtk_widget_destroyed,
2103 info->widget = geometry_widget;
2105 g_signal_connect (geometry_widget, "destroy",
2106 G_CALLBACK (gtk_widget_destroyed),
2110 info->geometry = *geometry;
2112 /* We store gravity in window->gravity not in the hints. */
2113 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2115 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2117 gtk_window_set_gravity (window, geometry->win_gravity);
2120 gtk_widget_queue_resize (GTK_WIDGET (window));
2124 * gtk_window_set_decorated:
2125 * @window: a #GtkWindow
2126 * @setting: %TRUE to decorate the window
2128 * By default, windows are decorated with a title bar, resize
2129 * controls, etc. Some <link linkend="gtk-X11-arch">window
2130 * managers</link> allow GTK+ to disable these decorations, creating a
2131 * borderless window. If you set the decorated property to %FALSE
2132 * using this function, GTK+ will do its best to convince the window
2133 * manager not to decorate the window. Depending on the system, this
2134 * function may not have any effect when called on a window that is
2135 * already visible, so you should call it before calling gtk_window_show().
2137 * On Windows, this function always works, since there's no window manager
2142 gtk_window_set_decorated (GtkWindow *window,
2145 g_return_if_fail (GTK_IS_WINDOW (window));
2147 setting = setting != FALSE;
2149 if (setting == window->decorated)
2152 window->decorated = setting;
2154 if (GTK_WIDGET (window)->window)
2156 if (window->decorated)
2157 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2160 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2166 * gtk_window_get_decorated:
2167 * @window: a #GtkWindow
2169 * Returns whether the window has been set to have decorations
2170 * such as a title bar via gtk_window_set_decorated().
2172 * Return value: %TRUE if the window has been set to have decorations
2175 gtk_window_get_decorated (GtkWindow *window)
2177 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2179 return window->decorated;
2182 static GtkWindowIconInfo*
2183 get_icon_info (GtkWindow *window)
2185 return g_object_get_data (G_OBJECT (window),
2186 "gtk-window-icon-info");
2189 static GtkWindowIconInfo*
2190 ensure_icon_info (GtkWindow *window)
2192 GtkWindowIconInfo *info;
2194 info = get_icon_info (window);
2198 info = g_new0 (GtkWindowIconInfo, 1);
2199 g_object_set_data_full (G_OBJECT (window),
2200 "gtk-window-icon-info",
2215 get_screen_icon_info (GdkScreen *screen)
2217 ScreenIconInfo *info = g_object_get_data (G_OBJECT (screen),
2218 "gtk-window-default-icon-pixmap");
2221 info = g_new0 (ScreenIconInfo, 1);
2222 g_object_set_data (G_OBJECT (screen), "gtk-window-default-icon-pixmap", info);
2225 if (info->serial != default_icon_serial)
2229 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2230 info->pixmap = NULL;
2235 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2239 info->serial = default_icon_serial;
2246 get_pixmap_and_mask (GdkWindow *window,
2247 GtkWindowIconInfo *parent_info,
2248 gboolean is_default_list,
2250 GdkPixmap **pmap_return,
2251 GdkBitmap **mask_return)
2253 GdkScreen *screen = gdk_drawable_get_screen (window);
2254 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2255 GdkPixbuf *best_icon;
2259 *pmap_return = NULL;
2260 *mask_return = NULL;
2262 if (is_default_list &&
2263 default_icon_info->pixmap != NULL)
2265 /* Use shared icon pixmap for all windows on this screen.
2267 if (default_icon_info->pixmap)
2268 g_object_ref (default_icon_info->pixmap);
2269 if (default_icon_info->mask)
2270 g_object_ref (default_icon_info->mask);
2272 *pmap_return = default_icon_info->pixmap;
2273 *mask_return = default_icon_info->mask;
2275 else if (parent_info && parent_info->icon_pixmap)
2277 if (parent_info->icon_pixmap)
2278 g_object_ref (parent_info->icon_pixmap);
2279 if (parent_info->icon_mask)
2280 g_object_ref (parent_info->icon_mask);
2282 *pmap_return = parent_info->icon_pixmap;
2283 *mask_return = parent_info->icon_mask;
2287 #define IDEAL_SIZE 48
2289 best_size = G_MAXINT;
2291 tmp_list = icon_list;
2292 while (tmp_list != NULL)
2294 GdkPixbuf *pixbuf = tmp_list->data;
2297 /* average width and height - if someone passes in a rectangular
2298 * icon they deserve what they get.
2300 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2303 if (best_icon == NULL)
2310 /* icon is better if it's 32 pixels or larger, and closer to
2311 * the ideal size than the current best.
2314 (ABS (best_size - IDEAL_SIZE) <
2315 ABS (this - IDEAL_SIZE)))
2322 tmp_list = tmp_list->next;
2326 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2327 gdk_screen_get_system_colormap (screen),
2332 /* Save pmap/mask for others to use if appropriate */
2335 parent_info->icon_pixmap = *pmap_return;
2336 parent_info->icon_mask = *mask_return;
2338 if (parent_info->icon_pixmap)
2339 g_object_ref (parent_info->icon_pixmap);
2340 if (parent_info->icon_mask)
2341 g_object_ref (parent_info->icon_mask);
2343 else if (is_default_list)
2345 default_icon_info->pixmap = *pmap_return;
2346 default_icon_info->mask = *mask_return;
2348 if (default_icon_info->pixmap)
2349 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2350 (gpointer*)&default_icon_info->pixmap);
2351 if (default_icon_info->mask)
2352 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2353 (gpointer*)&default_icon_info->mask);
2359 gtk_window_realize_icon (GtkWindow *window)
2362 GtkWindowIconInfo *info;
2365 widget = GTK_WIDGET (window);
2367 g_return_if_fail (widget->window != NULL);
2369 /* no point setting an icon on override-redirect */
2370 if (window->type == GTK_WINDOW_POPUP)
2375 info = ensure_icon_info (window);
2380 g_return_if_fail (info->icon_pixmap == NULL);
2381 g_return_if_fail (info->icon_mask == NULL);
2383 info->using_default_icon = FALSE;
2384 info->using_parent_icon = FALSE;
2386 icon_list = info->icon_list;
2388 /* Inherit from transient parent */
2389 if (icon_list == NULL && window->transient_parent)
2391 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2393 info->using_parent_icon = TRUE;
2396 /* Inherit from default */
2397 if (icon_list == NULL)
2399 icon_list = default_icon_list;
2401 info->using_default_icon = TRUE;
2404 gdk_window_set_icon_list (widget->window, icon_list);
2406 get_pixmap_and_mask (widget->window,
2407 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2408 info->using_default_icon,
2413 /* This is a slight ICCCM violation since it's a color pixmap not
2414 * a bitmap, but everyone does it.
2416 gdk_window_set_icon (widget->window,
2421 info->realized = TRUE;
2425 gtk_window_unrealize_icon (GtkWindow *window)
2427 GtkWindowIconInfo *info;
2430 widget = GTK_WIDGET (window);
2432 info = get_icon_info (window);
2437 if (info->icon_pixmap)
2438 g_object_unref (info->icon_pixmap);
2440 if (info->icon_mask)
2441 g_object_unref (info->icon_mask);
2443 info->icon_pixmap = NULL;
2444 info->icon_mask = NULL;
2446 /* We don't clear the properties on the window, just figure the
2447 * window is going away.
2450 info->realized = FALSE;
2454 * gtk_window_set_icon_list:
2455 * @window: a #GtkWindow
2456 * @list: list of #GdkPixbuf
2458 * Sets up the icon representing a #GtkWindow. The icon is used when
2459 * the window is minimized (also known as iconified). Some window
2460 * managers or desktop environments may also place it in the window
2461 * frame, or display it in other contexts.
2463 * gtk_window_set_icon_list() allows you to pass in the same icon in
2464 * several hand-drawn sizes. The list should contain the natural sizes
2465 * your icon is available in; that is, don't scale the image before
2466 * passing it to GTK+. Scaling is postponed until the last minute,
2467 * when the desired final size is known, to allow best quality.
2469 * By passing several sizes, you may improve the final image quality
2470 * of the icon, by reducing or eliminating automatic image scaling.
2472 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2473 * larger images (64x64, 128x128) if you have them.
2475 * See also gtk_window_set_default_icon_list() to set the icon
2476 * for all windows in your application in one go.
2478 * Note that transient windows (those who have been set transient for another
2479 * window using gtk_window_set_transient_for()) will inherit their
2480 * icon from their transient parent. So there's no need to explicitly
2481 * set the icon on transient windows.
2484 gtk_window_set_icon_list (GtkWindow *window,
2487 GtkWindowIconInfo *info;
2489 g_return_if_fail (GTK_IS_WINDOW (window));
2491 info = ensure_icon_info (window);
2493 if (info->icon_list == list) /* check for NULL mostly */
2496 g_list_foreach (info->icon_list,
2497 (GFunc) g_object_unref, NULL);
2499 g_list_free (info->icon_list);
2501 info->icon_list = g_list_copy (list);
2502 g_list_foreach (info->icon_list,
2503 (GFunc) g_object_ref, NULL);
2505 g_object_notify (G_OBJECT (window), "icon");
2507 gtk_window_unrealize_icon (window);
2509 if (GTK_WIDGET_REALIZED (window))
2510 gtk_window_realize_icon (window);
2512 /* We could try to update our transient children, but I don't think
2513 * it's really worth it. If we did it, the best way would probably
2514 * be to have children connect to notify::icon_list
2519 * gtk_window_get_icon_list:
2520 * @window: a #GtkWindow
2522 * Retrieves the list of icons set by gtk_window_set_icon_list().
2523 * The list is copied, but the reference count on each
2524 * member won't be incremented.
2526 * Return value: copy of window's icon list
2529 gtk_window_get_icon_list (GtkWindow *window)
2531 GtkWindowIconInfo *info;
2533 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2535 info = get_icon_info (window);
2538 return g_list_copy (info->icon_list);
2544 * gtk_window_set_icon:
2545 * @window: a #GtkWindow
2546 * @icon: icon image, or %NULL
2548 * Sets up the icon representing a #GtkWindow. This icon is used when
2549 * the window is minimized (also known as iconified). Some window
2550 * managers or desktop environments may also place it in the window
2551 * frame, or display it in other contexts.
2553 * The icon should be provided in whatever size it was naturally
2554 * drawn; that is, don't scale the image before passing it to
2555 * GTK+. Scaling is postponed until the last minute, when the desired
2556 * final size is known, to allow best quality.
2558 * If you have your icon hand-drawn in multiple sizes, use
2559 * gtk_window_set_icon_list(). Then the best size will be used.
2561 * This function is equivalent to calling gtk_window_set_icon_list()
2562 * with a 1-element list.
2564 * See also gtk_window_set_default_icon_list() to set the icon
2565 * for all windows in your application in one go.
2568 gtk_window_set_icon (GtkWindow *window,
2573 g_return_if_fail (GTK_IS_WINDOW (window));
2574 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2579 list = g_list_append (list, icon);
2581 gtk_window_set_icon_list (window, list);
2586 * gtk_window_get_icon:
2587 * @window: a #GtkWindow
2589 * Gets the value set by gtk_window_set_icon() (or if you've
2590 * called gtk_window_set_icon_list(), gets the first icon in
2593 * Return value: icon for window
2596 gtk_window_get_icon (GtkWindow *window)
2598 GtkWindowIconInfo *info;
2600 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2602 info = get_icon_info (window);
2603 if (info && info->icon_list)
2604 return GDK_PIXBUF (info->icon_list->data);
2609 /* Load pixbuf, printing warning on failure if error == NULL
2612 load_pixbuf_verbosely (const char *filename,
2615 GError *local_err = NULL;
2618 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
2626 g_warning ("Error loading icon from file '%s':\n\t%s",
2627 filename, local_err->message);
2628 g_error_free (local_err);
2636 * gtk_window_set_icon_from_file:
2637 * @window: a #GtkWindow
2638 * @filename: location of icon file
2639 * @err: location to store error, or %NULL.
2641 * Sets the icon for @window.
2642 * Warns on failure if @err is %NULL.
2644 * This function is equivalent to calling gtk_window_set_icon()
2645 * with a pixbuf created by loading the image from @filename.
2647 * Returns: %TRUE if setting the icon succeeded.
2650 gtk_window_set_icon_from_file (GtkWindow *window,
2651 const gchar *filename,
2654 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2658 gtk_window_set_icon (window, pixbuf);
2659 g_object_unref (pixbuf);
2668 * gtk_window_set_default_icon_list:
2669 * @list: a list of #GdkPixbuf
2671 * Sets an icon list to be used as fallback for windows that haven't
2672 * had gtk_window_set_icon_list() called on them to set up a
2673 * window-specific icon list. This function allows you to set up the
2674 * icon for all windows in your app at once.
2676 * See gtk_window_set_icon_list() for more details.
2680 gtk_window_set_default_icon_list (GList *list)
2684 if (list == default_icon_list)
2687 /* Update serial so we don't used cached pixmaps/masks
2689 default_icon_serial++;
2691 g_list_foreach (default_icon_list,
2692 (GFunc) g_object_unref, NULL);
2694 g_list_free (default_icon_list);
2696 default_icon_list = g_list_copy (list);
2697 g_list_foreach (default_icon_list,
2698 (GFunc) g_object_ref, NULL);
2700 /* Update all toplevels */
2701 toplevels = gtk_window_list_toplevels ();
2702 tmp_list = toplevels;
2703 while (tmp_list != NULL)
2705 GtkWindowIconInfo *info;
2706 GtkWindow *w = tmp_list->data;
2708 info = get_icon_info (w);
2709 if (info && info->using_default_icon)
2711 gtk_window_unrealize_icon (w);
2712 if (GTK_WIDGET_REALIZED (w))
2713 gtk_window_realize_icon (w);
2716 tmp_list = tmp_list->next;
2718 g_list_free (toplevels);
2722 * gtk_window_set_default_icon_from_file:
2723 * @filename: location of icon file
2724 * @err: location to store error, or %NULL.
2726 * Sets an icon to be used as fallback for windows that haven't
2727 * had gtk_window_set_icon_list() called on them from a file
2728 * on disk. Warns on failure if @err is %NULL.
2730 * Returns: %TRUE if setting the icon succeeded.
2733 gtk_window_set_default_icon_from_file (const gchar *filename,
2736 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2740 GList *list = g_list_prepend (NULL, pixbuf);
2741 gtk_window_set_default_icon_list (list);
2744 g_object_unref (pixbuf);
2753 * gtk_window_get_default_icon_list:
2755 * Gets the value set by gtk_window_set_default_icon_list().
2756 * The list is a copy and should be freed with g_list_free(),
2757 * but the pixbufs in the list have not had their reference count
2760 * Return value: copy of default icon list
2763 gtk_window_get_default_icon_list (void)
2765 return g_list_copy (default_icon_list);
2769 gtk_window_set_default_size_internal (GtkWindow *window,
2770 gboolean change_width,
2772 gboolean change_height,
2774 gboolean is_geometry)
2776 GtkWindowGeometryInfo *info;
2778 g_return_if_fail (change_width == FALSE || width >= -1);
2779 g_return_if_fail (change_height == FALSE || height >= -1);
2781 info = gtk_window_get_geometry_info (window, TRUE);
2783 g_object_freeze_notify (G_OBJECT (window));
2785 info->default_is_geometry = is_geometry != FALSE;
2795 info->default_width = width;
2797 g_object_notify (G_OBJECT (window), "default_width");
2808 info->default_height = height;
2810 g_object_notify (G_OBJECT (window), "default_height");
2813 g_object_thaw_notify (G_OBJECT (window));
2815 gtk_widget_queue_resize (GTK_WIDGET (window));
2819 * gtk_window_set_default_size:
2820 * @window: a #GtkWindow
2821 * @width: width in pixels, or -1 to unset the default width
2822 * @height: height in pixels, or -1 to unset the default height
2824 * Sets the default size of a window. If the window's "natural" size
2825 * (its size request) is larger than the default, the default will be
2826 * ignored. More generally, if the default size does not obey the
2827 * geometry hints for the window (gtk_window_set_geometry_hints() can
2828 * be used to set these explicitly), the default size will be clamped
2829 * to the nearest permitted size.
2831 * Unlike gtk_widget_set_size_request(), which sets a size request for
2832 * a widget and thus would keep users from shrinking the window, this
2833 * function only sets the initial size, just as if the user had
2834 * resized the window themselves. Users can still shrink the window
2835 * again as they normally would. Setting a default size of -1 means to
2836 * use the "natural" default size (the size request of the window).
2838 * For more control over a window's initial size and how resizing works,
2839 * investigate gtk_window_set_geometry_hints().
2841 * For some uses, gtk_window_resize() is a more appropriate function.
2842 * gtk_window_resize() changes the current size of the window, rather
2843 * than the size to be used on initial display. gtk_window_resize() always
2844 * affects the window itself, not the geometry widget.
2846 * The default size of a window only affects the first time a window is
2847 * shown; if a window is hidden and re-shown, it will remember the size
2848 * it had prior to hiding, rather than using the default size.
2850 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2851 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2854 gtk_window_set_default_size (GtkWindow *window,
2858 g_return_if_fail (GTK_IS_WINDOW (window));
2859 g_return_if_fail (width >= -1);
2860 g_return_if_fail (height >= -1);
2862 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
2866 * gtk_window_get_default_size:
2867 * @window: a #GtkWindow
2868 * @width: location to store the default width, or %NULL
2869 * @height: location to store the default height, or %NULL
2871 * Gets the default size of the window. A value of -1 for the width or
2872 * height indicates that a default size has not been explicitly set
2873 * for that dimension, so the "natural" size of the window will be
2878 gtk_window_get_default_size (GtkWindow *window,
2882 GtkWindowGeometryInfo *info;
2884 g_return_if_fail (GTK_IS_WINDOW (window));
2886 info = gtk_window_get_geometry_info (window, FALSE);
2889 *width = info->default_width;
2892 *height = info->default_height;
2896 * gtk_window_resize:
2897 * @window: a #GtkWindow
2898 * @width: width in pixels to resize the window to
2899 * @height: height in pixels to resize the window to
2901 * Resizes the window as if the user had done so, obeying geometry
2902 * constraints. The default geometry constraint is that windows may
2903 * not be smaller than their size request; to override this
2904 * constraint, call gtk_widget_set_size_request() to set the window's
2905 * request to a smaller value.
2907 * If gtk_window_resize() is called before showing a window for the
2908 * first time, it overrides any default size set with
2909 * gtk_window_set_default_size().
2911 * Windows may not be resized smaller than 1 by 1 pixels.
2915 gtk_window_resize (GtkWindow *window,
2919 GtkWindowGeometryInfo *info;
2921 g_return_if_fail (GTK_IS_WINDOW (window));
2922 g_return_if_fail (width > 0);
2923 g_return_if_fail (height > 0);
2925 info = gtk_window_get_geometry_info (window, TRUE);
2927 info->resize_width = width;
2928 info->resize_height = height;
2930 gtk_widget_queue_resize (GTK_WIDGET (window));
2934 * gtk_window_get_size:
2935 * @window: a #GtkWindow
2936 * @width: return location for width, or %NULL
2937 * @height: return location for height, or %NULL
2939 * Obtains the current size of @window. If @window is not onscreen,
2940 * it returns the size GTK+ will suggest to the <link
2941 * linkend="gtk-X11-arch">window manager</link> for the initial window
2942 * size (but this is not reliably the same as the size the window
2943 * manager will actually select). The size obtained by
2944 * gtk_window_get_size() is the last size received in a
2945 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2946 * rather than querying the X server for the size. As a result, if you
2947 * call gtk_window_resize() then immediately call
2948 * gtk_window_get_size(), the size won't have taken effect yet. After
2949 * the window manager processes the resize request, GTK+ receives
2950 * notification that the size has changed via a configure event, and
2951 * the size of the window gets updated.
2953 * Note 1: Nearly any use of this function creates a race condition,
2954 * because the size of the window may change between the time that you
2955 * get the size and the time that you perform some action assuming
2956 * that size is the current size. To avoid race conditions, connect to
2957 * "configure_event" on the window and adjust your size-dependent
2958 * state to match the size delivered in the #GdkEventConfigure.
2960 * Note 2: The returned size does <emphasis>not</emphasis> include the
2961 * size of the window manager decorations (aka the window frame or
2962 * border). Those are not drawn by GTK+ and GTK+ has no reliable
2963 * method of determining their size.
2965 * Note 3: If you are getting a window size in order to position
2966 * the window onscreen, there may be a better way. The preferred
2967 * way is to simply set the window's semantic type with
2968 * gtk_window_set_type_hint(), which allows the window manager to
2969 * e.g. center dialogs. Also, if you set the transient parent of
2970 * dialogs with gtk_window_set_transient_for() window managers
2971 * will often center the dialog over its parent window. It's
2972 * much preferred to let the window manager handle these
2973 * things rather than doing it yourself, because all apps will
2974 * behave consistently and according to user prefs if the window
2975 * manager handles it. Also, the window manager can take the size
2976 * of the window decorations/border into account, while your
2977 * application cannot.
2979 * In any case, if you insist on application-specified window
2980 * positioning, there's <emphasis>still</emphasis> a better way than
2981 * doing it yourself - gtk_window_set_position() will frequently
2982 * handle the details for you.
2986 gtk_window_get_size (GtkWindow *window,
2993 g_return_if_fail (GTK_IS_WINDOW (window));
2995 widget = GTK_WIDGET (window);
2997 if (width == NULL && height == NULL)
3000 if (GTK_WIDGET_MAPPED (window))
3002 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3007 GdkRectangle configure_request;
3009 gtk_window_compute_configure_request (window,
3013 w = configure_request.width;
3014 h = configure_request.height;
3025 * @window: a #GtkWindow
3026 * @x: X coordinate to move window to
3027 * @y: Y coordinate to move window to
3029 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3030 * @window to the given position. Window managers are free to ignore
3031 * this; most window managers ignore requests for initial window
3032 * positions (instead using a user-defined placement algorithm) and
3033 * honor requests after the window has already been shown.
3035 * Note: the position is the position of the gravity-determined
3036 * reference point for the window. The gravity determines two things:
3037 * first, the location of the reference point in root window
3038 * coordinates; and second, which point on the window is positioned at
3039 * the reference point.
3041 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3042 * point is simply the @x, @y supplied to gtk_window_move(). The
3043 * top-left corner of the window decorations (aka window frame or
3044 * border) will be placed at @x, @y. Therefore, to position a window
3045 * at the top left of the screen, you want to use the default gravity
3046 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3048 * To position a window at the bottom right corner of the screen, you
3049 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3050 * point is at @x + the window width and @y + the window height, and
3051 * the bottom-right corner of the window border will be placed at that
3052 * reference point. So, to place a window in the bottom right corner
3053 * you would first set gravity to south east, then write:
3054 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3055 * gdk_screen_height () - window_height)</literal>.
3057 * The extended window manager hints specification at <ulink
3058 * url="http://www.freedesktop.org/standards/wm-spec.html">
3059 * http://www.freedesktop.org/standards/wm-spec.html</ulink> has a
3060 * nice table of gravities in the "implementation notes" section.
3062 * The gtk_window_get_position() documentation may also be relevant.
3066 gtk_window_move (GtkWindow *window,
3070 GtkWindowGeometryInfo *info;
3073 g_return_if_fail (GTK_IS_WINDOW (window));
3075 widget = GTK_WIDGET (window);
3077 info = gtk_window_get_geometry_info (window, TRUE);
3079 if (GTK_WIDGET_MAPPED (window))
3081 /* we have now sent a request with this position
3082 * with currently-active constraints, so toggle flag.
3084 info->position_constraints_changed = FALSE;
3086 /* we only constrain if mapped - if not mapped,
3087 * then gtk_window_compute_configure_request()
3088 * will apply the constraints later, and we
3089 * don't want to lose information about
3090 * what position the user set before then.
3091 * i.e. if you do a move() then turn off POS_CENTER
3092 * then show the window, your move() will work.
3094 gtk_window_constrain_position (window,
3095 widget->allocation.width,
3096 widget->allocation.height,
3099 /* Note that this request doesn't go through our standard request
3100 * framework, e.g. doesn't increment configure_request_count,
3101 * doesn't set info->last, etc.; that's because
3102 * we don't save the info needed to arrive at this same request
3105 * To gtk_window_move_resize(), this will end up looking exactly
3106 * the same as the position being changed by the window
3110 /* FIXME are we handling gravity properly for framed windows? */
3112 gdk_window_move (window->frame,
3113 x - window->frame_left,
3114 y - window->frame_top);
3116 gdk_window_move (GTK_WIDGET (window)->window,
3121 /* Save this position to apply on mapping */
3122 info->initial_x = x;
3123 info->initial_y = y;
3124 info->initial_pos_set = TRUE;
3129 * gtk_window_get_position:
3130 * @window: a #GtkWindow
3131 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3132 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3134 * This function returns the position you need to pass to
3135 * gtk_window_move() to keep @window in its current position. This
3136 * means that the meaning of the returned value varies with window
3137 * gravity. See gtk_window_move() for more details.
3139 * If you haven't changed the window gravity, its gravity will be
3140 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3141 * gets the position of the top-left corner of the window manager
3142 * frame for the window. gtk_window_move() sets the position of this
3143 * same top-left corner.
3145 * gtk_window_get_position() is not 100% reliable because the X Window System
3146 * does not specify a way to obtain the geometry of the
3147 * decorations placed on a window by the window manager.
3148 * Thus GTK+ is using a "best guess" that works with most
3151 * Moreover, nearly all window managers are historically broken with
3152 * respect to their handling of window gravity. So moving a window to
3153 * its current position as returned by gtk_window_get_position() tends
3154 * to result in moving the window slightly. Window managers are
3155 * slowly getting better over time.
3157 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3158 * frame is not relevant, and thus gtk_window_get_position() will
3159 * always produce accurate results. However you can't use static
3160 * gravity to do things like place a window in a corner of the screen,
3161 * because static gravity ignores the window manager decorations.
3163 * If you are saving and restoring your application's window
3164 * positions, you should know that it's impossible for applications to
3165 * do this without getting it somewhat wrong because applications do
3166 * not have sufficient knowledge of window manager state. The Correct
3167 * Mechanism is to support the session management protocol (see the
3168 * "GnomeClient" object in the GNOME libraries for example) and allow
3169 * the window manager to save your window sizes and positions.
3174 gtk_window_get_position (GtkWindow *window,
3180 g_return_if_fail (GTK_IS_WINDOW (window));
3182 widget = GTK_WIDGET (window);
3184 if (window->gravity == GDK_GRAVITY_STATIC)
3186 if (GTK_WIDGET_MAPPED (widget))
3188 /* This does a server round-trip, which is sort of wrong;
3189 * but a server round-trip is inevitable for
3190 * gdk_window_get_frame_extents() in the usual
3191 * NorthWestGravity case below, so not sure what else to
3192 * do. We should likely be consistent about whether we get
3193 * the client-side info or the server-side info.
3195 gdk_window_get_origin (widget->window, root_x, root_y);
3199 GdkRectangle configure_request;
3201 gtk_window_compute_configure_request (window,
3205 *root_x = configure_request.x;
3206 *root_y = configure_request.y;
3211 GdkRectangle frame_extents;
3216 if (GTK_WIDGET_MAPPED (widget))
3219 gdk_window_get_frame_extents (window->frame, &frame_extents);
3221 gdk_window_get_frame_extents (widget->window, &frame_extents);
3222 x = frame_extents.x;
3223 y = frame_extents.y;
3224 gtk_window_get_size (window, &w, &h);
3228 /* We just say the frame has 0 size on all sides.
3229 * Not sure what else to do.
3231 gtk_window_compute_configure_request (window,
3234 x = frame_extents.x;
3235 y = frame_extents.y;
3236 w = frame_extents.width;
3237 h = frame_extents.height;
3240 switch (window->gravity)
3242 case GDK_GRAVITY_NORTH:
3243 case GDK_GRAVITY_CENTER:
3244 case GDK_GRAVITY_SOUTH:
3245 /* Find center of frame. */
3246 x += frame_extents.width / 2;
3247 /* Center client window on that point. */
3251 case GDK_GRAVITY_SOUTH_EAST:
3252 case GDK_GRAVITY_EAST:
3253 case GDK_GRAVITY_NORTH_EAST:
3254 /* Find right edge of frame */
3255 x += frame_extents.width;
3256 /* Align left edge of client at that point. */
3263 switch (window->gravity)
3265 case GDK_GRAVITY_WEST:
3266 case GDK_GRAVITY_CENTER:
3267 case GDK_GRAVITY_EAST:
3268 /* Find center of frame. */
3269 y += frame_extents.height / 2;
3270 /* Center client window there. */
3273 case GDK_GRAVITY_SOUTH_WEST:
3274 case GDK_GRAVITY_SOUTH:
3275 case GDK_GRAVITY_SOUTH_EAST:
3276 /* Find south edge of frame */
3277 y += frame_extents.height;
3278 /* Place bottom edge of client there */
3293 * gtk_window_reshow_with_initial_size:
3294 * @window: a #GtkWindow
3296 * Hides @window, then reshows it, resetting the
3297 * default size and position of the window. Used
3298 * by GUI builders only.
3301 gtk_window_reshow_with_initial_size (GtkWindow *window)
3305 g_return_if_fail (GTK_IS_WINDOW (window));
3307 widget = GTK_WIDGET (window);
3309 gtk_widget_hide (widget);
3310 gtk_widget_unrealize (widget);
3311 gtk_widget_show (widget);
3315 gtk_window_destroy (GtkObject *object)
3317 GtkWindow *window = GTK_WINDOW (object);
3319 if (window->transient_parent)
3320 gtk_window_set_transient_for (window, NULL);
3322 /* frees the icons */
3323 gtk_window_set_icon_list (window, NULL);
3325 if (window->has_user_ref_count)
3327 window->has_user_ref_count = FALSE;
3328 g_object_unref (window);
3332 gtk_window_group_remove_window (window->group, window);
3334 gtk_window_free_key_hash (window);
3336 GTK_OBJECT_CLASS (parent_class)->destroy (object);
3340 gtk_window_mnemonic_hash_remove (gpointer key,
3344 GtkWindowMnemonic *mnemonic = key;
3345 GtkWindow *window = user;
3347 if (mnemonic->window == window)
3349 if (mnemonic->targets)
3351 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
3353 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
3354 name, mnemonic->targets->data);
3357 g_slist_free (mnemonic->targets);
3366 gtk_window_private_finalize (GtkWindowPrivate *priv)
3373 gtk_window_finalize (GObject *object)
3375 GtkWindow *window = GTK_WINDOW (object);
3377 toplevel_list = g_slist_remove (toplevel_list, window);
3379 g_free (window->title);
3380 g_free (window->wmclass_name);
3381 g_free (window->wmclass_class);
3382 g_free (window->wm_role);
3384 g_hash_table_foreach_remove (mnemonic_hash_table,
3385 gtk_window_mnemonic_hash_remove,
3387 if (window->geometry_info)
3389 if (window->geometry_info->widget)
3390 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3391 gtk_widget_destroyed,
3392 &window->geometry_info->widget);
3393 g_free (window->geometry_info);
3396 if (window->keys_changed_handler)
3398 gtk_idle_remove (window->keys_changed_handler);
3399 window->keys_changed_handler = 0;
3402 G_OBJECT_CLASS (parent_class)->finalize (object);
3406 gtk_window_show (GtkWidget *widget)
3408 GtkWindow *window = GTK_WINDOW (widget);
3409 GtkContainer *container = GTK_CONTAINER (window);
3410 gboolean need_resize;
3412 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3414 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3415 container->need_resize = FALSE;
3419 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3420 GtkAllocation allocation = { 0, 0 };
3421 GdkRectangle configure_request;
3422 GdkGeometry new_geometry;
3424 gboolean was_realized;
3426 /* We are going to go ahead and perform this configure request
3427 * and then emulate a configure notify by going ahead and
3428 * doing a size allocate. Sort of a synchronous
3429 * mini-copy of gtk_window_move_resize() here.
3431 gtk_window_compute_configure_request (window,
3436 /* We update this because we are going to go ahead
3437 * and gdk_window_resize() below, rather than
3440 info->last.configure_request.width = configure_request.width;
3441 info->last.configure_request.height = configure_request.height;
3443 /* and allocate the window - this is normally done
3444 * in move_resize in response to configure notify
3446 allocation.width = configure_request.width;
3447 allocation.height = configure_request.height;
3448 gtk_widget_size_allocate (widget, &allocation);
3450 /* Then we guarantee we have a realize */
3451 was_realized = FALSE;
3452 if (!GTK_WIDGET_REALIZED (widget))
3454 gtk_widget_realize (widget);
3455 was_realized = TRUE;
3458 /* Must be done after the windows are realized,
3459 * so that the decorations can be read
3461 gtk_decorated_window_calculate_frame_size (window);
3463 /* We only send configure request if we didn't just finish
3464 * creating the window; if we just created the window
3465 * then we created it with widget->allocation anyhow.
3468 gdk_window_resize (widget->window,
3469 configure_request.width,
3470 configure_request.height);
3473 gtk_container_check_resize (container);
3475 gtk_widget_map (widget);
3477 /* Try to make sure that we have some focused widget
3479 #ifdef GDK_WINDOWING_X11
3480 if (!window->focus_widget && !GTK_IS_PLUG (window))
3482 if (!window->focus_widget)
3484 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
3487 gtk_grab_add (widget);
3491 gtk_window_hide (GtkWidget *widget)
3493 GtkWindow *window = GTK_WINDOW (widget);
3495 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3496 gtk_widget_unmap (widget);
3499 gtk_grab_remove (widget);
3503 gtk_window_map (GtkWidget *widget)
3505 GtkWindow *window = GTK_WINDOW (widget);
3506 GdkWindow *toplevel;
3507 GtkWindowPrivate *priv;
3509 priv = gtk_window_get_private (window);
3511 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3513 if (window->bin.child &&
3514 GTK_WIDGET_VISIBLE (window->bin.child) &&
3515 !GTK_WIDGET_MAPPED (window->bin.child))
3516 gtk_widget_map (window->bin.child);
3519 toplevel = window->frame;
3521 toplevel = widget->window;
3523 if (window->maximize_initially)
3524 gdk_window_maximize (toplevel);
3526 gdk_window_unmaximize (toplevel);
3528 if (window->stick_initially)
3529 gdk_window_stick (toplevel);
3531 gdk_window_unstick (toplevel);
3533 if (window->iconify_initially)
3534 gdk_window_iconify (toplevel);
3536 gdk_window_deiconify (toplevel);
3538 if (priv->fullscreen_initially)
3539 gdk_window_fullscreen (toplevel);
3541 gdk_window_unfullscreen (toplevel);
3543 /* No longer use the default settings */
3544 window->need_default_size = FALSE;
3545 window->need_default_position = FALSE;
3547 gdk_window_show (widget->window);
3550 gdk_window_show (window->frame);
3554 gtk_window_unmap (GtkWidget *widget)
3556 GtkWindow *window = GTK_WINDOW (widget);
3557 GtkWindowGeometryInfo *info;
3558 GdkWindowState state;
3560 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3562 gdk_window_withdraw (window->frame);
3564 gdk_window_withdraw (widget->window);
3566 window->configure_request_count = 0;
3567 window->configure_notify_received = FALSE;
3569 /* on unmap, we reset the default positioning of the window,
3570 * so it's placed again, but we don't reset the default
3571 * size of the window, so it's remembered.
3573 window->need_default_position = TRUE;
3575 info = gtk_window_get_geometry_info (window, FALSE);
3578 info->initial_pos_set = FALSE;
3579 info->position_constraints_changed = FALSE;
3582 state = gdk_window_get_state (widget->window);
3583 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
3584 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
3585 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
3589 gtk_window_realize (GtkWidget *widget)
3592 GdkWindow *parent_window;
3593 GdkWindowAttr attributes;
3594 gint attributes_mask;
3596 window = GTK_WINDOW (widget);
3598 /* ensure widget tree is properly size allocated */
3599 if (widget->allocation.x == -1 &&
3600 widget->allocation.y == -1 &&
3601 widget->allocation.width == 1 &&
3602 widget->allocation.height == 1)
3604 GtkRequisition requisition;
3605 GtkAllocation allocation = { 0, 0, 200, 200 };
3607 gtk_widget_size_request (widget, &requisition);
3608 if (requisition.width || requisition.height)
3610 /* non-empty window */
3611 allocation.width = requisition.width;
3612 allocation.height = requisition.height;
3614 gtk_widget_size_allocate (widget, &allocation);
3616 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3618 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3621 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3623 switch (window->type)
3625 case GTK_WINDOW_TOPLEVEL:
3626 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3628 case GTK_WINDOW_POPUP:
3629 attributes.window_type = GDK_WINDOW_TEMP;
3632 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3636 attributes.title = window->title;
3637 attributes.wmclass_name = window->wmclass_name;
3638 attributes.wmclass_class = window->wmclass_class;
3639 attributes.wclass = GDK_INPUT_OUTPUT;
3640 attributes.visual = gtk_widget_get_visual (widget);
3641 attributes.colormap = gtk_widget_get_colormap (widget);
3643 if (window->has_frame)
3645 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3646 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3647 attributes.event_mask = (GDK_EXPOSURE_MASK |
3648 GDK_KEY_PRESS_MASK |
3649 GDK_ENTER_NOTIFY_MASK |
3650 GDK_LEAVE_NOTIFY_MASK |
3651 GDK_FOCUS_CHANGE_MASK |
3652 GDK_STRUCTURE_MASK |
3653 GDK_BUTTON_MOTION_MASK |
3654 GDK_POINTER_MOTION_HINT_MASK |
3655 GDK_BUTTON_PRESS_MASK |
3656 GDK_BUTTON_RELEASE_MASK);
3658 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3660 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
3661 &attributes, attributes_mask);
3663 gdk_window_set_user_data (window->frame, widget);
3665 attributes.window_type = GDK_WINDOW_CHILD;
3666 attributes.x = window->frame_left;
3667 attributes.y = window->frame_top;
3669 attributes_mask = GDK_WA_X | GDK_WA_Y;
3671 parent_window = window->frame;
3675 attributes_mask = 0;
3676 parent_window = gtk_widget_get_root_window (widget);
3679 attributes.width = widget->allocation.width;
3680 attributes.height = widget->allocation.height;
3681 attributes.event_mask = gtk_widget_get_events (widget);
3682 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3683 GDK_KEY_PRESS_MASK |
3684 GDK_KEY_RELEASE_MASK |
3685 GDK_ENTER_NOTIFY_MASK |
3686 GDK_LEAVE_NOTIFY_MASK |
3687 GDK_FOCUS_CHANGE_MASK |
3688 GDK_STRUCTURE_MASK);
3690 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3691 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3692 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3694 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3696 gdk_window_set_user_data (widget->window, window);
3698 widget->style = gtk_style_attach (widget->style, widget->window);
3699 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3701 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3703 /* This is a bad hack to set the window background. */
3704 gtk_window_paint (widget, NULL);
3706 if (window->transient_parent &&
3707 GTK_WIDGET_REALIZED (window->transient_parent))
3708 gdk_window_set_transient_for (widget->window,
3709 GTK_WIDGET (window->transient_parent)->window);
3711 if (window->wm_role)
3712 gdk_window_set_role (widget->window, window->wm_role);
3714 if (!window->decorated)
3715 gdk_window_set_decorations (widget->window, 0);
3717 gdk_window_set_type_hint (widget->window, window->type_hint);
3719 if (gtk_window_get_skip_pager_hint (window))
3720 gdk_window_set_skip_pager_hint (widget->window, TRUE);
3722 if (gtk_window_get_skip_taskbar_hint (window))
3723 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
3725 /* transient_for must be set to allow the modal hint */
3726 if (window->transient_parent && window->modal)
3727 gdk_window_set_modal_hint (widget->window, TRUE);
3729 gdk_window_set_modal_hint (widget->window, FALSE);
3732 gtk_window_realize_icon (window);
3736 gtk_window_unrealize (GtkWidget *widget)
3739 GtkWindowGeometryInfo *info;
3741 window = GTK_WINDOW (widget);
3743 /* On unrealize, we reset the size of the window such
3744 * that we will re-apply the default sizing stuff
3745 * next time we show the window.
3747 * Default positioning is reset on unmap, instead of unrealize.
3749 window->need_default_size = TRUE;
3750 info = gtk_window_get_geometry_info (window, FALSE);
3753 info->resize_width = -1;
3754 info->resize_height = -1;
3755 info->last.configure_request.x = 0;
3756 info->last.configure_request.y = 0;
3757 info->last.configure_request.width = -1;
3758 info->last.configure_request.height = -1;
3759 /* be sure we reset geom hints on re-realize */
3760 info->last.flags = 0;
3765 gdk_window_set_user_data (window->frame, NULL);
3766 gdk_window_destroy (window->frame);
3767 window->frame = NULL;
3771 gtk_window_unrealize_icon (window);
3773 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3777 gtk_window_size_request (GtkWidget *widget,
3778 GtkRequisition *requisition)
3783 window = GTK_WINDOW (widget);
3784 bin = GTK_BIN (window);
3786 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3787 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3789 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3791 GtkRequisition child_requisition;
3793 gtk_widget_size_request (bin->child, &child_requisition);
3795 requisition->width += child_requisition.width;
3796 requisition->height += child_requisition.height;
3801 gtk_window_size_allocate (GtkWidget *widget,
3802 GtkAllocation *allocation)
3805 GtkAllocation child_allocation;
3807 window = GTK_WINDOW (widget);
3808 widget->allocation = *allocation;
3810 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3812 child_allocation.x = GTK_CONTAINER (window)->border_width;
3813 child_allocation.y = GTK_CONTAINER (window)->border_width;
3814 child_allocation.width =
3815 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3816 child_allocation.height =
3817 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3819 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3822 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3824 gdk_window_resize (window->frame,
3825 allocation->width + window->frame_left + window->frame_right,
3826 allocation->height + window->frame_top + window->frame_bottom);
3831 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3834 gboolean return_val;
3836 window = GTK_WINDOW (widget);
3838 if (window->frame && (event->any.window == window->frame))
3840 if ((event->type != GDK_KEY_PRESS) &&
3841 (event->type != GDK_KEY_RELEASE) &&
3842 (event->type != GDK_FOCUS_CHANGE))
3844 g_signal_stop_emission_by_name (widget, "event");
3846 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
3851 g_object_unref (event->any.window);
3852 event->any.window = g_object_ref (widget->window);
3860 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3862 GdkEventConfigure *configure_event;
3865 switch (event->type)
3868 configure_event = (GdkEventConfigure *)event;
3870 /* Invalidate the decorations */
3873 rect.width = configure_event->width;
3874 rect.height = configure_event->height;
3876 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3878 /* Pass on the (modified) configure event */
3879 configure_event->width -= window->frame_left + window->frame_right;
3880 configure_event->height -= window->frame_top + window->frame_bottom;
3881 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3890 gtk_window_configure_event (GtkWidget *widget,
3891 GdkEventConfigure *event)
3893 GtkWindow *window = GTK_WINDOW (widget);
3894 gboolean expected_reply = window->configure_request_count > 0;
3896 /* window->configure_request_count incremented for each
3897 * configure request, and decremented to a min of 0 for
3898 * each configure notify.
3900 * All it means is that we know we will get at least
3901 * window->configure_request_count more configure notifies.
3902 * We could get more configure notifies than that; some
3903 * of the configure notifies we get may be unrelated to
3904 * the configure requests. But we will get at least
3905 * window->configure_request_count notifies.
3908 if (window->configure_request_count > 0)
3909 window->configure_request_count -= 1;
3911 /* As an optimization, we avoid a resize when possible.
3913 * The only times we can avoid a resize are:
3914 * - we know only the position changed, not the size
3915 * - we know we have made more requests and so will get more
3916 * notifies and can wait to resize when we get them
3919 if (!expected_reply &&
3920 (widget->allocation.width == event->width &&
3921 widget->allocation.height == event->height))
3925 * If we do need to resize, we do that by:
3926 * - filling in widget->allocation with the new size
3927 * - setting configure_notify_received to TRUE
3928 * for use in gtk_window_move_resize()
3929 * - queueing a resize, leading to invocation of
3930 * gtk_window_move_resize() in an idle handler
3934 window->configure_notify_received = TRUE;
3936 widget->allocation.width = event->width;
3937 widget->allocation.height = event->height;
3939 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3944 /* the accel_key and accel_mods fields of the key have to be setup
3945 * upon calling this function. it'll then return whether that key
3946 * is at all used as accelerator, and if so will OR in the
3947 * accel_flags member of the key.
3950 _gtk_window_query_nonaccels (GtkWindow *window,
3952 GdkModifierType accel_mods)
3954 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3956 /* movement keys are considered locked accels */
3959 static const guint bindings[] = {
3960 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
3961 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
3965 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
3966 if (bindings[i] == accel_key)
3970 /* mnemonics are considered locked accels */
3971 if (accel_mods == window->mnemonic_modifier)
3973 GtkWindowMnemonic mkey;
3975 mkey.window = window;
3976 mkey.keyval = accel_key;
3977 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
3985 gtk_window_key_press_event (GtkWidget *widget,
3992 window = GTK_WINDOW (widget);
3996 /* Check for mnemonics and accelerators
3999 handled = _gtk_window_activate_key (window, event);
4003 focus = window->focus_widget;
4005 g_object_ref (focus);
4008 focus && focus != widget &&
4009 gtk_widget_get_toplevel (focus) == widget)
4013 if (GTK_WIDGET_IS_SENSITIVE (focus))
4014 handled = gtk_widget_event (focus, (GdkEvent*) event);
4016 parent = focus->parent;
4018 g_object_ref (parent);
4020 g_object_unref (focus);
4026 g_object_unref (focus);
4029 /* Chain up, invokes binding set */
4030 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
4031 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4037 gtk_window_key_release_event (GtkWidget *widget,
4043 window = GTK_WINDOW (widget);
4045 if (window->focus_widget &&
4046 window->focus_widget != widget &&
4047 GTK_WIDGET_SENSITIVE (window->focus_widget))
4049 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
4052 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
4053 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
4059 gtk_window_real_activate_default (GtkWindow *window)
4061 gtk_window_activate_default (window);
4065 gtk_window_real_activate_focus (GtkWindow *window)
4067 gtk_window_activate_focus (window);
4071 gtk_window_move_focus (GtkWindow *window,
4072 GtkDirectionType dir)
4074 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4076 if (!GTK_CONTAINER (window)->focus_child)
4077 gtk_window_set_focus (window, NULL);
4081 gtk_window_enter_notify_event (GtkWidget *widget,
4082 GdkEventCrossing *event)
4088 gtk_window_leave_notify_event (GtkWidget *widget,
4089 GdkEventCrossing *event)
4095 do_focus_change (GtkWidget *widget,
4098 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4100 g_object_ref (widget);
4103 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4105 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4107 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4108 fevent->focus_change.window = g_object_ref (widget->window);
4109 fevent->focus_change.in = in;
4111 gtk_widget_event (widget, fevent);
4113 g_object_notify (G_OBJECT (widget), "has_focus");
4115 g_object_unref (widget);
4116 gdk_event_free (fevent);
4120 gtk_window_focus_in_event (GtkWidget *widget,
4121 GdkEventFocus *event)
4123 GtkWindow *window = GTK_WINDOW (widget);
4125 /* It appears spurious focus in events can occur when
4126 * the window is hidden. So we'll just check to see if
4127 * the window is visible before actually handling the
4130 if (GTK_WIDGET_VISIBLE (widget))
4132 _gtk_window_set_has_toplevel_focus (window, TRUE);
4133 _gtk_window_set_is_active (window, TRUE);
4140 gtk_window_focus_out_event (GtkWidget *widget,
4141 GdkEventFocus *event)
4143 GtkWindow *window = GTK_WINDOW (widget);
4145 _gtk_window_set_has_toplevel_focus (window, FALSE);
4146 _gtk_window_set_is_active (window, FALSE);
4151 static GdkAtom atom_rcfiles = GDK_NONE;
4154 gtk_window_read_rcfiles (GtkWidget *widget,
4155 GdkEventClient *event)
4157 GList *embedded_windows;
4159 embedded_windows = g_object_get_data (G_OBJECT (widget), "gtk-embedded");
4160 if (embedded_windows)
4162 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4165 for (i = 0; i < 5; i++)
4166 send_event->client.data.l[i] = 0;
4167 send_event->client.data_format = 32;
4168 send_event->client.message_type = atom_rcfiles;
4170 while (embedded_windows)
4172 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4173 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4174 embedded_windows = embedded_windows->next;
4177 gdk_event_free (send_event);
4180 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4184 gtk_window_client_event (GtkWidget *widget,
4185 GdkEventClient *event)
4188 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
4190 if (event->message_type == atom_rcfiles)
4191 gtk_window_read_rcfiles (widget, event);
4197 gtk_window_check_resize (GtkContainer *container)
4199 GtkWindow *window = GTK_WINDOW (container);
4201 if (GTK_WIDGET_VISIBLE (container))
4202 gtk_window_move_resize (window);
4206 gtk_window_focus (GtkWidget *widget,
4207 GtkDirectionType direction)
4211 GtkContainer *container;
4212 GtkWidget *old_focus_child;
4215 container = GTK_CONTAINER (widget);
4216 window = GTK_WINDOW (widget);
4217 bin = GTK_BIN (widget);
4219 old_focus_child = container->focus_child;
4221 /* We need a special implementation here to deal properly with wrapping
4222 * around in the tab chain without the danger of going into an
4225 if (old_focus_child)
4227 if (gtk_widget_child_focus (old_focus_child, direction))
4231 if (window->focus_widget)
4233 /* Wrapped off the end, clear the focus setting for the toplpevel */
4234 parent = window->focus_widget->parent;
4237 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4238 parent = GTK_WIDGET (parent)->parent;
4241 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4244 /* Now try to focus the first widget in the window */
4247 if (gtk_widget_child_focus (bin->child, direction))
4255 gtk_window_real_set_focus (GtkWindow *window,
4258 GtkWidget *old_focus = window->focus_widget;
4259 gboolean def_flags = 0;
4263 g_object_ref (old_focus);
4264 g_object_freeze_notify (G_OBJECT (old_focus));
4268 g_object_ref (focus);
4269 g_object_freeze_notify (G_OBJECT (focus));
4272 if (window->default_widget)
4273 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4275 if (window->focus_widget)
4277 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4278 (window->focus_widget != window->default_widget))
4280 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4282 if (window->default_widget)
4283 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4286 if (window->has_focus)
4287 do_focus_change (window->focus_widget, FALSE);
4289 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4292 window->focus_widget = focus;
4294 if (window->focus_widget)
4296 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4297 (window->focus_widget != window->default_widget))
4299 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4300 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4302 if (window->default_widget)
4303 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4306 if (window->has_focus)
4307 do_focus_change (window->focus_widget, TRUE);
4309 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4312 if (window->default_widget &&
4313 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
4314 gtk_widget_queue_draw (window->default_widget);
4318 g_object_thaw_notify (G_OBJECT (old_focus));
4319 g_object_unref (old_focus);
4323 g_object_thaw_notify (G_OBJECT (focus));
4324 g_object_unref (focus);
4328 /*********************************
4329 * Functions related to resizing *
4330 *********************************/
4332 /* This function doesn't constrain to geometry hints */
4334 gtk_window_compute_configure_request_size (GtkWindow *window,
4338 GtkRequisition requisition;
4339 GtkWindowGeometryInfo *info;
4343 * - we've done a size request
4346 widget = GTK_WIDGET (window);
4348 info = gtk_window_get_geometry_info (window, FALSE);
4350 if (window->need_default_size)
4352 gtk_widget_get_child_requisition (widget, &requisition);
4354 /* Default to requisition */
4355 *width = requisition.width;
4356 *height = requisition.height;
4358 /* If window is empty so requests 0, default to random nonzero size */
4359 if (*width == 0 && *height == 0)
4365 /* Override requisition with default size */
4369 gint base_width = 0;
4370 gint base_height = 0;
4372 gint height_inc = 1;
4374 if (info->default_is_geometry &&
4375 (info->default_width > 0 || info->default_height > 0))
4377 GdkGeometry geometry;
4380 gtk_window_compute_hints (window, &geometry, &flags);
4382 if (flags & GDK_HINT_BASE_SIZE)
4384 base_width = geometry.base_width;
4385 base_height = geometry.base_height;
4387 else if (flags & GDK_HINT_MIN_SIZE)
4389 base_width = geometry.min_width;
4390 base_height = geometry.min_height;
4392 if (flags & GDK_HINT_RESIZE_INC)
4394 width_inc = geometry.width_inc;
4395 height_inc = geometry.height_inc;
4399 if (info->default_width > 0)
4400 *width = info->default_width * width_inc + base_width;
4402 if (info->default_height > 0)
4403 *height = info->default_height * height_inc + base_height;
4408 /* Default to keeping current size */
4409 *width = widget->allocation.width;
4410 *height = widget->allocation.height;
4413 /* Override any size with gtk_window_resize() values */
4416 if (info->resize_width > 0)
4417 *width = info->resize_width;
4419 if (info->resize_height > 0)
4420 *height = info->resize_height;
4424 static GtkWindowPosition
4425 get_effective_position (GtkWindow *window)
4427 GtkWindowPosition pos = window->position;
4428 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
4429 (window->transient_parent == NULL ||
4430 !GTK_WIDGET_MAPPED (window->transient_parent)))
4431 pos = GTK_WIN_POS_NONE;
4437 get_center_monitor_of_window (GtkWindow *window)
4439 /* We could try to sort out the relative positions of the monitors and
4440 * stuff, or we could just be losers and assume you have a row
4441 * or column of monitors.
4443 return gdk_screen_get_n_monitors (window->screen) / 2;
4447 get_monitor_containing_pointer (GtkWindow *window)
4451 GdkScreen *pointer_screen;
4453 gdk_display_get_pointer (gdk_screen_get_display (window->screen),
4457 if (pointer_screen == window->screen)
4458 monitor_num = gdk_screen_get_monitor_at_point (window->screen, px, py);
4466 center_window_on_monitor (GtkWindow *window,
4472 GdkRectangle monitor;
4475 monitor_num = get_monitor_containing_pointer (window);
4477 if (monitor_num == -1)
4478 monitor_num = get_center_monitor_of_window (window);
4480 gdk_screen_get_monitor_geometry (window->screen, monitor_num, &monitor);
4482 *x = (monitor.width - w) / 2 + monitor.x;
4483 *y = (monitor.height - h) / 2 + monitor.y;
4485 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
4486 * and WM decorations.
4495 clamp_window_to_rectangle (gint *x,
4499 const GdkRectangle *rect)
4501 gint outside_w, outside_h;
4503 outside_w = (*x + w) - (rect->x + rect->width);
4507 outside_h = (*y + h) - (rect->y + rect->height);
4511 /* if larger than the screen, center on the screen. */
4513 *x += (rect->x - *x) / 2;
4515 *y += (rect->y - *y) / 2;
4520 gtk_window_compute_configure_request (GtkWindow *window,
4521 GdkRectangle *request,
4522 GdkGeometry *geometry,
4525 GdkGeometry new_geometry;
4529 GtkWindowPosition pos;
4530 GtkWidget *parent_widget;
4531 GtkWindowGeometryInfo *info;
4534 widget = GTK_WIDGET (window);
4536 gtk_widget_size_request (widget, NULL);
4537 gtk_window_compute_configure_request_size (window, &w, &h);
4539 gtk_window_compute_hints (window, &new_geometry, &new_flags);
4540 gtk_window_constrain_size (window,
4541 &new_geometry, new_flags,
4545 parent_widget = (GtkWidget*) window->transient_parent;
4547 pos = get_effective_position (window);
4548 info = gtk_window_get_geometry_info (window, TRUE);
4550 /* by default, don't change position requested */
4551 x = info->last.configure_request.x;
4552 y = info->last.configure_request.y;
4554 if (window->need_default_position)
4557 /* FIXME this all interrelates with window gravity.
4558 * For most of them I think we want to set GRAVITY_CENTER.
4560 * Not sure how to go about that.
4565 /* here we are only handling CENTER_ALWAYS
4566 * as it relates to default positioning,
4567 * where it's equivalent to simply CENTER
4569 case GTK_WIN_POS_CENTER_ALWAYS:
4570 case GTK_WIN_POS_CENTER:
4571 center_window_on_monitor (window, w, h, &x, &y);
4574 case GTK_WIN_POS_CENTER_ON_PARENT:
4577 GdkRectangle monitor;
4580 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
4582 if (parent_widget->window != NULL)
4583 monitor_num = gdk_screen_get_monitor_at_window (window->screen,
4584 parent_widget->window);
4588 gdk_window_get_origin (parent_widget->window,
4591 x = ox + (parent_widget->allocation.width - w) / 2;
4592 y = oy + (parent_widget->allocation.height - h) / 2;
4594 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4595 * WM decorations. If parent wasn't on a monitor, just
4598 if (monitor_num >= 0)
4600 gdk_screen_get_monitor_geometry (window->screen, monitor_num, &monitor);
4601 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4606 case GTK_WIN_POS_MOUSE:
4608 gint screen_width = gdk_screen_get_width (window->screen);
4609 gint screen_height = gdk_screen_get_height (window->screen);
4611 GdkRectangle monitor;
4612 GdkScreen *pointer_screen;
4615 gdk_display_get_pointer (gdk_screen_get_display (window->screen),
4619 if (pointer_screen == window->screen)
4620 monitor_num = gdk_screen_get_monitor_at_point (window->screen, px, py);
4626 x = CLAMP (x, 0, screen_width - w);
4627 y = CLAMP (y, 0, screen_height - h);
4629 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4630 * WM decorations. Don't try to figure out what's going
4631 * on if the mouse wasn't inside a monitor.
4633 if (monitor_num >= 0)
4635 gdk_screen_get_monitor_geometry (window->screen, monitor_num, &monitor);
4636 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4644 } /* if (window->need_default_position) */
4646 if (window->need_default_position &&
4647 info->initial_pos_set)
4649 x = info->initial_x;
4650 y = info->initial_y;
4651 gtk_window_constrain_position (window, w, h, &x, &y);
4657 request->height = h;
4660 *geometry = new_geometry;
4666 gtk_window_constrain_position (GtkWindow *window,
4672 /* See long comments in gtk_window_move_resize()
4673 * on when it's safe to call this function.
4675 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4677 gint center_x, center_y;
4679 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
4687 gtk_window_move_resize (GtkWindow *window)
4691 * First we determine whether any information has changed that would
4692 * cause us to revise our last configure request. If we would send
4693 * a different configure request from last time, then
4694 * configure_request_size_changed = TRUE or
4695 * configure_request_pos_changed = TRUE. configure_request_size_changed
4696 * may be true due to new hints, a gtk_window_resize(), or whatever.
4697 * configure_request_pos_changed may be true due to gtk_window_set_position()
4698 * or gtk_window_move().
4700 * If the configure request has changed, we send off a new one. To
4701 * ensure GTK+ invariants are maintained (resize queue does what it
4702 * should), we go ahead and size_allocate the requested size in this
4705 * If the configure request has not changed, we don't ever resend
4706 * it, because it could mean fighting the user or window manager.
4709 * To prepare the configure request, we come up with a base size/pos:
4710 * - the one from gtk_window_move()/gtk_window_resize()
4711 * - else default_width, default_height if we haven't ever
4713 * - else the size request if we haven't ever been mapped,
4714 * as a substitute default size
4715 * - else the current size of the window, as received from
4716 * configure notifies (i.e. the current allocation)
4718 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4719 * the position request to be centered.
4722 GtkContainer *container;
4723 GtkWindowGeometryInfo *info;
4724 GdkGeometry new_geometry;
4726 GdkRectangle new_request;
4727 gboolean configure_request_size_changed;
4728 gboolean configure_request_pos_changed;
4729 gboolean hints_changed; /* do we need to send these again */
4730 GtkWindowLastGeometryInfo saved_last_info;
4732 widget = GTK_WIDGET (window);
4733 container = GTK_CONTAINER (widget);
4734 info = gtk_window_get_geometry_info (window, TRUE);
4736 configure_request_size_changed = FALSE;
4737 configure_request_pos_changed = FALSE;
4739 gtk_window_compute_configure_request (window, &new_request,
4740 &new_geometry, &new_flags);
4742 /* This check implies the invariant that we never set info->last
4743 * without setting the hints and sending off a configure request.
4745 * If we change info->last without sending the request, we may
4748 if (info->last.configure_request.x != new_request.x ||
4749 info->last.configure_request.y != new_request.y)
4750 configure_request_pos_changed = TRUE;
4752 if ((info->last.configure_request.width != new_request.width ||
4753 info->last.configure_request.height != new_request.height))
4754 configure_request_size_changed = TRUE;
4756 hints_changed = FALSE;
4758 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4759 &new_geometry, new_flags))
4761 hints_changed = TRUE;
4764 /* Position Constraints
4765 * ====================
4767 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4768 * a default. The other POS_ values are used only when the
4769 * window is shown, not after that.
4771 * However, we can't implement a position constraint as
4772 * "anytime the window size changes, center the window"
4773 * because this may well end up fighting the WM or user. In
4774 * fact it gets in an infinite loop with at least one WM.
4776 * Basically, applications are in no way in a position to
4777 * constrain the position of a window, with one exception:
4778 * override redirect windows. (Really the intended purpose
4779 * of CENTER_ALWAYS anyhow, I would think.)
4781 * So the way we implement this "constraint" is to say that when WE
4782 * cause a move or resize, i.e. we make a configure request changing
4783 * window size, we recompute the CENTER_ALWAYS position to reflect
4784 * the new window size, and include it in our request. Also, if we
4785 * just turned on CENTER_ALWAYS we snap to center with a new
4786 * request. Otherwise, if we are just NOTIFIED of a move or resize
4787 * done by someone else e.g. the window manager, we do NOT send a
4788 * new configure request.
4790 * For override redirect windows, this works fine; all window
4791 * sizes are from our configure requests. For managed windows,
4792 * it is at least semi-sane, though who knows what the
4793 * app author is thinking.
4796 /* This condition should be kept in sync with the condition later on
4797 * that determines whether we send a configure request. i.e. we
4798 * should do this position constraining anytime we were going to
4799 * send a configure request anyhow, plus when constraints have
4802 if (configure_request_pos_changed ||
4803 configure_request_size_changed ||
4805 info->position_constraints_changed)
4807 /* We request the constrained position if:
4808 * - we were changing position, and need to clamp
4809 * the change to the constraint
4810 * - we're changing the size anyway
4811 * - set_position() was called to toggle CENTER_ALWAYS on
4814 gtk_window_constrain_position (window,
4820 /* Update whether we need to request a move */
4821 if (info->last.configure_request.x != new_request.x ||
4822 info->last.configure_request.y != new_request.y)
4823 configure_request_pos_changed = TRUE;
4825 configure_request_pos_changed = FALSE;
4829 if (window->type == GTK_WINDOW_TOPLEVEL)
4831 int notify_x, notify_y;
4833 /* this is the position from the last configure notify */
4834 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4836 g_message ("--- %s ---\n"
4837 "last : %d,%d\t%d x %d\n"
4838 "this : %d,%d\t%d x %d\n"
4839 "alloc : %d,%d\t%d x %d\n"
4841 "resize: \t%d x %d\n"
4842 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4843 "configure_notify_received: %d\n"
4844 "configure_request_count: %d\n"
4845 "position_constraints_changed: %d\n",
4846 window->title ? window->title : "(no title)",
4847 info->last.configure_request.x,
4848 info->last.configure_request.y,
4849 info->last.configure_request.width,
4850 info->last.configure_request.height,
4856 widget->allocation.width,
4857 widget->allocation.height,
4858 widget->requisition.width,
4859 widget->requisition.height,
4861 info->resize_height,
4862 configure_request_pos_changed,
4863 configure_request_size_changed,
4865 window->configure_notify_received,
4866 window->configure_request_count,
4867 info->position_constraints_changed);
4871 saved_last_info = info->last;
4872 info->last.geometry = new_geometry;
4873 info->last.flags = new_flags;
4874 info->last.configure_request = new_request;
4876 /* need to set PPosition so the WM will look at our position,
4877 * but we don't want to count PPosition coming and going as a hints
4878 * change for future iterations. So we saved info->last prior to
4882 /* Also, if the initial position was explicitly set, then we always
4883 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4887 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4888 * this is an initial map
4891 if ((configure_request_pos_changed ||
4892 info->initial_pos_set ||
4893 (window->need_default_position &&
4894 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
4895 (new_flags & GDK_HINT_POS) == 0)
4897 new_flags |= GDK_HINT_POS;
4898 hints_changed = TRUE;
4901 /* Set hints if necessary
4904 gdk_window_set_geometry_hints (widget->window,
4908 /* handle resizing/moving and widget tree allocation
4910 if (window->configure_notify_received)
4912 GtkAllocation allocation;
4914 /* If we have received a configure event since
4915 * the last time in this function, we need to
4916 * accept our new size and size_allocate child widgets.
4917 * (see gtk_window_configure_event() for more details).
4919 * 1 or more configure notifies may have been received.
4920 * Also, configure_notify_received will only be TRUE
4921 * if all expected configure notifies have been received
4922 * (one per configure request), as an optimization.
4925 window->configure_notify_received = FALSE;
4927 /* gtk_window_configure_event() filled in widget->allocation */
4928 allocation = widget->allocation;
4929 gtk_widget_size_allocate (widget, &allocation);
4931 /* If the configure request changed, it means that
4933 * 1) coincidentally changed hints or widget properties
4934 * impacting the configure request before getting
4935 * a configure notify, or
4936 * 2) some broken widget is changing its size request
4937 * during size allocation, resulting in
4938 * a false appearance of changed configure request.
4940 * For 1), we could just go ahead and ask for the
4941 * new size right now, but doing that for 2)
4942 * might well be fighting the user (and can even
4943 * trigger a loop). Since we really don't want to
4944 * do that, we requeue a resize in hopes that
4945 * by the time it gets handled, the child has seen
4946 * the light and is willing to go along with the
4947 * new size. (this happens for the zvt widget, since
4948 * the size_allocate() above will have stored the
4949 * requisition corresponding to the new size in the
4952 * This doesn't buy us anything for 1), but it shouldn't
4953 * hurt us too badly, since it is what would have
4954 * happened if we had gotten the configure event before
4955 * the new size had been set.
4958 if (configure_request_size_changed ||
4959 configure_request_pos_changed)
4961 /* Don't change the recorded last info after all, because we
4962 * haven't actually updated to the new info yet - we decided
4963 * to postpone our configure request until later.
4965 info->last = saved_last_info;
4967 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
4970 return; /* Bail out, we didn't really process the move/resize */
4972 else if ((configure_request_size_changed || hints_changed) &&
4973 (widget->allocation.width != new_request.width ||
4974 widget->allocation.height != new_request.height))
4977 /* We are in one of the following situations:
4978 * A. configure_request_size_changed
4979 * our requisition has changed and we need a different window size,
4980 * so we request it from the window manager.
4981 * B. !configure_request_size_changed && hints_changed
4982 * the window manager rejects our size, but we have just changed the
4983 * window manager hints, so there's a chance our request will
4984 * be honoured this time, so we try again.
4986 * However, if the new requisition is the same as the current allocation,
4987 * we don't request it again, since we won't get a ConfigureNotify back from
4988 * the window manager unless it decides to change our requisition. If
4989 * we don't get the ConfigureNotify back, the resize queue will never be run.
4992 /* Now send the configure request */
4993 if (configure_request_pos_changed)
4997 gdk_window_move_resize (window->frame,
4998 new_request.x - window->frame_left,
4999 new_request.y - window->frame_top,
5000 new_request.width + window->frame_left + window->frame_right,
5001 new_request.height + window->frame_top + window->frame_bottom);
5002 gdk_window_resize (widget->window,
5003 new_request.width, new_request.height);
5007 gdk_window_move_resize (widget->window,
5008 new_request.x, new_request.y,
5009 new_request.width, new_request.height);
5011 else /* only size changed */
5014 gdk_window_resize (window->frame,
5015 new_request.width + window->frame_left + window->frame_right,
5016 new_request.height + window->frame_top + window->frame_bottom);
5018 gdk_window_resize (widget->window,
5019 new_request.width, new_request.height);
5022 /* Increment the number of have-not-yet-received-notify requests */
5023 window->configure_request_count += 1;
5025 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5026 * configure event in response to our resizing request.
5027 * the configure event will cause a new resize with
5028 * ->configure_notify_received=TRUE.
5029 * until then, we want to
5030 * - discard expose events
5031 * - coalesce resizes for our children
5032 * - defer any window resizes until the configure event arrived
5033 * to achieve this, we queue a resize for the window, but remove its
5034 * resizing handler, so resizing will not be handled from the next
5035 * idle handler but when the configure event arrives.
5037 * FIXME: we should also dequeue the pending redraws here, since
5038 * we handle those ourselves upon ->configure_notify_received==TRUE.
5040 if (container->resize_mode == GTK_RESIZE_QUEUE)
5042 gtk_widget_queue_resize (widget);
5043 _gtk_container_dequeue_resize_handler (container);
5048 /* Handle any position changes.
5050 if (configure_request_pos_changed)
5054 gdk_window_move (window->frame,
5055 new_request.x - window->frame_left,
5056 new_request.y - window->frame_top);
5059 gdk_window_move (widget->window,
5060 new_request.x, new_request.y);
5063 /* And run the resize queue.
5065 gtk_container_resize_children (container);
5068 /* We have now processed a move/resize since the last position
5069 * constraint change, setting of the initial position, or resize.
5070 * (Not resetting these flags here can lead to infinite loops for
5071 * GTK_RESIZE_IMMEDIATE containers)
5073 info->position_constraints_changed = FALSE;
5074 info->initial_pos_set = FALSE;
5075 info->resize_width = -1;
5076 info->resize_height = -1;
5079 /* Compare two sets of Geometry hints for equality.
5082 gtk_window_compare_hints (GdkGeometry *geometry_a,
5084 GdkGeometry *geometry_b,
5087 if (flags_a != flags_b)
5090 if ((flags_a & GDK_HINT_MIN_SIZE) &&
5091 (geometry_a->min_width != geometry_b->min_width ||
5092 geometry_a->min_height != geometry_b->min_height))
5095 if ((flags_a & GDK_HINT_MAX_SIZE) &&
5096 (geometry_a->max_width != geometry_b->max_width ||
5097 geometry_a->max_height != geometry_b->max_height))
5100 if ((flags_a & GDK_HINT_BASE_SIZE) &&
5101 (geometry_a->base_width != geometry_b->base_width ||
5102 geometry_a->base_height != geometry_b->base_height))
5105 if ((flags_a & GDK_HINT_ASPECT) &&
5106 (geometry_a->min_aspect != geometry_b->min_aspect ||
5107 geometry_a->max_aspect != geometry_b->max_aspect))
5110 if ((flags_a & GDK_HINT_RESIZE_INC) &&
5111 (geometry_a->width_inc != geometry_b->width_inc ||
5112 geometry_a->height_inc != geometry_b->height_inc))
5115 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5116 geometry_a->win_gravity != geometry_b->win_gravity)
5123 _gtk_window_constrain_size (GtkWindow *window,
5129 GtkWindowGeometryInfo *info;
5131 g_return_if_fail (GTK_IS_WINDOW (window));
5133 info = window->geometry_info;
5136 GdkWindowHints flags = info->last.flags;
5137 GdkGeometry *geometry = &info->last.geometry;
5139 gtk_window_constrain_size (window,
5150 gtk_window_constrain_size (GtkWindow *window,
5151 GdkGeometry *geometry,
5158 gdk_window_constrain_size (geometry, flags, width, height,
5159 new_width, new_height);
5162 /* Compute the set of geometry hints and flags for a window
5163 * based on the application set geometry, and requisiition
5164 * of the window. gtk_widget_size_request() must have been
5168 gtk_window_compute_hints (GtkWindow *window,
5169 GdkGeometry *new_geometry,
5173 gint extra_width = 0;
5174 gint extra_height = 0;
5175 GtkWindowGeometryInfo *geometry_info;
5176 GtkRequisition requisition;
5178 widget = GTK_WIDGET (window);
5180 gtk_widget_get_child_requisition (widget, &requisition);
5181 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5185 *new_flags = geometry_info->mask;
5186 *new_geometry = geometry_info->geometry;
5193 if (geometry_info && geometry_info->widget)
5195 GtkRequisition child_requisition;
5197 /* FIXME: This really isn't right. It gets the min size wrong and forces
5198 * callers to do horrible hacks like set a huge usize on the child requisition
5199 * to get the base size right. We really want to find the answers to:
5201 * - If the geometry widget was infinitely big, how much extra space
5202 * would be needed for the stuff around it.
5204 * - If the geometry widget was infinitely small, how big would the
5205 * window still have to be.
5207 * Finding these answers would be a bit of a mess here. (Bug #68668)
5209 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5211 extra_width = widget->requisition.width - child_requisition.width;
5212 extra_height = widget->requisition.height - child_requisition.height;
5215 /* We don't want to set GDK_HINT_POS in here, we just set it
5216 * in gtk_window_move_resize() when we want the position
5220 if (*new_flags & GDK_HINT_BASE_SIZE)
5222 new_geometry->base_width += extra_width;
5223 new_geometry->base_height += extra_height;
5225 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5226 (*new_flags & GDK_HINT_RESIZE_INC) &&
5227 ((extra_width != 0) || (extra_height != 0)))
5229 *new_flags |= GDK_HINT_BASE_SIZE;
5231 new_geometry->base_width = extra_width;
5232 new_geometry->base_height = extra_height;
5235 if (*new_flags & GDK_HINT_MIN_SIZE)
5237 if (new_geometry->min_width < 0)
5238 new_geometry->min_width = requisition.width;
5240 new_geometry->min_width += extra_width;
5242 if (new_geometry->min_height < 0)
5243 new_geometry->min_height = requisition.height;
5245 new_geometry->min_height += extra_height;
5247 else if (!window->allow_shrink)
5249 *new_flags |= GDK_HINT_MIN_SIZE;
5251 new_geometry->min_width = requisition.width;
5252 new_geometry->min_height = requisition.height;
5255 if (*new_flags & GDK_HINT_MAX_SIZE)
5257 if (new_geometry->max_width < 0)
5258 new_geometry->max_width = requisition.width;
5260 new_geometry->max_width += extra_width;
5262 if (new_geometry->max_height < 0)
5263 new_geometry->max_width = requisition.height;
5265 new_geometry->max_height += extra_height;
5267 else if (!window->allow_grow)
5269 *new_flags |= GDK_HINT_MAX_SIZE;
5271 new_geometry->max_width = requisition.width;
5272 new_geometry->max_height = requisition.height;
5275 *new_flags |= GDK_HINT_WIN_GRAVITY;
5276 new_geometry->win_gravity = window->gravity;
5279 /***********************
5280 * Redrawing functions *
5281 ***********************/
5284 gtk_window_paint (GtkWidget *widget,
5287 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
5288 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
5292 gtk_window_expose (GtkWidget *widget,
5293 GdkEventExpose *event)
5295 if (!GTK_WIDGET_APP_PAINTABLE (widget))
5296 gtk_window_paint (widget, &event->area);
5298 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
5299 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
5305 * gtk_window_set_has_frame:
5306 * @window: a #GtkWindow
5307 * @setting: a boolean
5309 * (Note: this is a special-purpose function for the framebuffer port,
5310 * that causes GTK+ to draw its own window border. For most applications,
5311 * you want gtk_window_set_decorated() instead, which tells the window
5312 * manager whether to draw the window border.)
5314 * If this function is called on a window with setting of %TRUE, before
5315 * it is realized or showed, it will have a "frame" window around
5316 * @window->window, accessible in @window->frame. Using the signal
5317 * frame_event you can recieve all events targeted at the frame.
5319 * This function is used by the linux-fb port to implement managed
5320 * windows, but it could concievably be used by X-programs that
5321 * want to do their own window decorations.
5325 gtk_window_set_has_frame (GtkWindow *window,
5328 g_return_if_fail (GTK_IS_WINDOW (window));
5329 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
5331 window->has_frame = setting != FALSE;
5335 * gtk_window_get_has_frame:
5336 * @window: a #GtkWindow
5338 * Accessor for whether the window has a frame window exterior to
5339 * @window->window. Gets the value set by gtk_window_set_has_frame ().
5341 * Return value: %TRUE if a frame has been added to the window
5342 * via gtk_window_set_has_frame().
5345 gtk_window_get_has_frame (GtkWindow *window)
5347 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5349 return window->has_frame;
5353 * gtk_window_set_frame_dimensions:
5354 * @window: a #GtkWindow that has a frame
5355 * @left: The width of the left border
5356 * @top: The height of the top border
5357 * @right: The width of the right border
5358 * @bottom: The height of the bottom border
5360 * (Note: this is a special-purpose function intended for the framebuffer
5361 * port; see gtk_window_set_has_frame(). It will have no effect on the
5362 * window border drawn by the window manager, which is the normal
5363 * case when using the X Window system.)
5365 * For windows with frames (see gtk_window_set_has_frame()) this function
5366 * can be used to change the size of the frame border.
5369 gtk_window_set_frame_dimensions (GtkWindow *window,
5377 g_return_if_fail (GTK_IS_WINDOW (window));
5379 widget = GTK_WIDGET (window);
5381 if (window->frame_left == left &&
5382 window->frame_top == top &&
5383 window->frame_right == right &&
5384 window->frame_bottom == bottom)
5387 window->frame_left = left;
5388 window->frame_top = top;
5389 window->frame_right = right;
5390 window->frame_bottom = bottom;
5392 if (GTK_WIDGET_REALIZED (widget) && window->frame)
5394 gint width = widget->allocation.width + left + right;
5395 gint height = widget->allocation.height + top + bottom;
5396 gdk_window_resize (window->frame, width, height);
5397 gtk_decorated_window_move_resize_window (window,
5399 widget->allocation.width,
5400 widget->allocation.height);
5405 * gtk_window_present:
5406 * @window: a #GtkWindow
5408 * Presents a window to the user. This may mean raising the window
5409 * in the stacking order, deiconifying it, moving it to the current
5410 * desktop, and/or giving it the keyboard focus, possibly dependent
5411 * on the user's platform, window manager, and preferences.
5413 * If @window is hidden, this function calls gtk_widget_show()
5416 * This function should be used when the user tries to open a window
5417 * that's already open. Say for example the preferences dialog is
5418 * currently open, and the user chooses Preferences from the menu
5419 * a second time; use gtk_window_present() to move the already-open dialog
5420 * where the user can see it.
5424 gtk_window_present (GtkWindow *window)
5428 g_return_if_fail (GTK_IS_WINDOW (window));
5430 widget = GTK_WIDGET (window);
5432 if (GTK_WIDGET_VISIBLE (window))
5434 g_assert (widget->window != NULL);
5436 gdk_window_show (widget->window);
5438 /* note that gdk_window_focus() will also move the window to
5439 * the current desktop, for WM spec compliant window managers.
5441 gdk_window_focus (widget->window,
5442 gtk_get_current_event_time ());
5446 gtk_widget_show (widget);
5451 * gtk_window_iconify:
5452 * @window: a #GtkWindow
5454 * Asks to iconify (i.e. minimize) the specified @window. Note that
5455 * you shouldn't assume the window is definitely iconified afterward,
5456 * because other entities (e.g. the user or <link
5457 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
5458 * again, or there may not be a window manager in which case
5459 * iconification isn't possible, etc. But normally the window will end
5460 * up iconified. Just don't write code that crashes if not.
5462 * It's permitted to call this function before showing a window,
5463 * in which case the window will be iconified before it ever appears
5466 * You can track iconification via the "window_state_event" signal
5471 gtk_window_iconify (GtkWindow *window)
5474 GdkWindow *toplevel;
5476 g_return_if_fail (GTK_IS_WINDOW (window));
5478 widget = GTK_WIDGET (window);
5480 window->iconify_initially = TRUE;
5483 toplevel = window->frame;
5485 toplevel = widget->window;
5487 if (toplevel != NULL)
5488 gdk_window_iconify (toplevel);
5492 * gtk_window_deiconify:
5493 * @window: a #GtkWindow
5495 * Asks to deiconify (i.e. unminimize) the specified @window. Note
5496 * that you shouldn't assume the window is definitely deiconified
5497 * afterward, because other entities (e.g. the user or <link
5498 * linkend="gtk-X11-arch">window manager</link>) could iconify it
5499 * again before your code which assumes deiconification gets to run.
5501 * You can track iconification via the "window_state_event" signal
5505 gtk_window_deiconify (GtkWindow *window)
5508 GdkWindow *toplevel;
5510 g_return_if_fail (GTK_IS_WINDOW (window));
5512 widget = GTK_WIDGET (window);
5514 window->iconify_initially = FALSE;
5517 toplevel = window->frame;
5519 toplevel = widget->window;
5521 if (toplevel != NULL)
5522 gdk_window_deiconify (toplevel);
5527 * @window: a #GtkWindow
5529 * Asks to stick @window, which means that it will appear on all user
5530 * desktops. Note that you shouldn't assume the window is definitely
5531 * stuck afterward, because other entities (e.g. the user or <link
5532 * linkend="gtk-X11-arch">window manager</link>) could unstick it
5533 * again, and some window managers do not support sticking
5534 * windows. But normally the window will end up stuck. Just don't
5535 * write code that crashes if not.
5537 * It's permitted to call this function before showing a window.
5539 * You can track stickiness via the "window_state_event" signal
5544 gtk_window_stick (GtkWindow *window)
5547 GdkWindow *toplevel;
5549 g_return_if_fail (GTK_IS_WINDOW (window));
5551 widget = GTK_WIDGET (window);
5553 window->stick_initially = TRUE;
5556 toplevel = window->frame;
5558 toplevel = widget->window;
5560 if (toplevel != NULL)
5561 gdk_window_stick (toplevel);
5565 * gtk_window_unstick:
5566 * @window: a #GtkWindow
5568 * Asks to unstick @window, which means that it will appear on only
5569 * one of the user's desktops. Note that you shouldn't assume the
5570 * window is definitely unstuck afterward, because other entities
5571 * (e.g. the user or <link linkend="gtk-X11-arch">window
5572 * manager</link>) could stick it again. But normally the window will
5573 * end up stuck. Just don't write code that crashes if not.
5575 * You can track stickiness via the "window_state_event" signal
5580 gtk_window_unstick (GtkWindow *window)
5583 GdkWindow *toplevel;
5585 g_return_if_fail (GTK_IS_WINDOW (window));
5587 widget = GTK_WIDGET (window);
5589 window->stick_initially = FALSE;
5592 toplevel = window->frame;
5594 toplevel = widget->window;
5596 if (toplevel != NULL)
5597 gdk_window_unstick (toplevel);
5601 * gtk_window_maximize:
5602 * @window: a #GtkWindow
5604 * Asks to maximize @window, so that it becomes full-screen. Note that
5605 * you shouldn't assume the window is definitely maximized afterward,
5606 * because other entities (e.g. the user or <link
5607 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
5608 * again, and not all window managers support maximization. But
5609 * normally the window will end up maximized. Just don't write code
5610 * that crashes if not.
5612 * It's permitted to call this function before showing a window,
5613 * in which case the window will be maximized when it appears onscreen
5616 * You can track maximization via the "window_state_event" signal
5621 gtk_window_maximize (GtkWindow *window)
5624 GdkWindow *toplevel;
5626 g_return_if_fail (GTK_IS_WINDOW (window));
5628 widget = GTK_WIDGET (window);
5630 window->maximize_initially = TRUE;
5633 toplevel = window->frame;
5635 toplevel = widget->window;
5637 if (toplevel != NULL)
5638 gdk_window_maximize (toplevel);
5642 * gtk_window_unmaximize:
5643 * @window: a #GtkWindow
5645 * Asks to unmaximize @window. Note that you shouldn't assume the
5646 * window is definitely unmaximized afterward, because other entities
5647 * (e.g. the user or <link linkend="gtk-X11-arch">window
5648 * manager</link>) could maximize it again, and not all window
5649 * managers honor requests to unmaximize. But normally the window will
5650 * end up unmaximized. Just don't write code that crashes if not.
5652 * You can track maximization via the "window_state_event" signal
5657 gtk_window_unmaximize (GtkWindow *window)
5660 GdkWindow *toplevel;
5662 g_return_if_fail (GTK_IS_WINDOW (window));
5664 widget = GTK_WIDGET (window);
5666 window->maximize_initially = FALSE;
5669 toplevel = window->frame;
5671 toplevel = widget->window;
5673 if (toplevel != NULL)
5674 gdk_window_unmaximize (toplevel);
5678 * gtk_window_fullscreen:
5679 * @window: a #GtkWindow
5681 * Asks to place @window in the fullscreen state. Note that you
5682 * shouldn't assume the window is definitely full screen afterward,
5683 * because other entities (e.g. the user or <link
5684 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
5685 * again, and not all window managers honor requests to fullscreen
5686 * windows. But normally the window will end up fullscreen. Just
5687 * don't write code that crashes if not.
5689 * You can track the fullscreen state via the "window_state_event" signal
5694 gtk_window_fullscreen (GtkWindow *window)
5697 GdkWindow *toplevel;
5698 GtkWindowPrivate *priv;
5700 g_return_if_fail (GTK_IS_WINDOW (window));
5702 widget = GTK_WIDGET (window);
5703 priv = gtk_window_get_private (window);
5705 priv->fullscreen_initially = TRUE;
5708 toplevel = window->frame;
5710 toplevel = widget->window;
5712 if (toplevel != NULL)
5713 gdk_window_fullscreen (toplevel);
5717 * gtk_window_unfullscreen:
5718 * @window: a #GtkWindow
5720 * Asks to toggle off the fullscreen state for @window. Note that you
5721 * shouldn't assume the window is definitely not full screen
5722 * afterward, because other entities (e.g. the user or <link
5723 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
5724 * again, and not all window managers honor requests to unfullscreen
5725 * windows. But normally the window will end up restored to its normal
5726 * state. Just don't write code that crashes if not.
5728 * You can track the fullscreen state via the "window_state_event" signal
5733 gtk_window_unfullscreen (GtkWindow *window)
5736 GdkWindow *toplevel;
5737 GtkWindowPrivate *priv;
5739 g_return_if_fail (GTK_IS_WINDOW (window));
5741 widget = GTK_WIDGET (window);
5742 priv = gtk_window_get_private (window);
5744 priv->fullscreen_initially = FALSE;
5747 toplevel = window->frame;
5749 toplevel = widget->window;
5751 if (toplevel != NULL)
5752 gdk_window_unfullscreen (toplevel);
5757 * gtk_window_set_resizable:
5758 * @window: a #GtkWindow
5759 * @resizable: %TRUE if the user can resize this window
5761 * Sets whether the user can resize a window. Windows are user resizable
5765 gtk_window_set_resizable (GtkWindow *window,
5768 g_return_if_fail (GTK_IS_WINDOW (window));
5770 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5774 * gtk_window_get_resizable:
5775 * @window: a #GtkWindow
5777 * Gets the value set by gtk_window_set_resizable().
5779 * Return value: %TRUE if the user can resize the window
5782 gtk_window_get_resizable (GtkWindow *window)
5784 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5786 /* allow_grow is most likely to indicate the semantic concept we
5787 * mean by "resizable" (and will be a reliable indicator if
5788 * set_policy() hasn't been called)
5790 return window->allow_grow;
5794 * gtk_window_set_gravity:
5795 * @window: a #GtkWindow
5796 * @gravity: window gravity
5798 * Window gravity defines the meaning of coordinates passed to
5799 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5802 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5803 * typically "do what you mean."
5807 gtk_window_set_gravity (GtkWindow *window,
5810 g_return_if_fail (GTK_IS_WINDOW (window));
5812 if (gravity != window->gravity)
5814 window->gravity = gravity;
5816 /* gtk_window_move_resize() will adapt gravity
5818 gtk_widget_queue_resize (GTK_WIDGET (window));
5823 * gtk_window_get_gravity:
5824 * @window: a #GtkWindow
5826 * Gets the value set by gtk_window_set_gravity().
5828 * Return value: window gravity
5831 gtk_window_get_gravity (GtkWindow *window)
5833 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5835 return window->gravity;
5839 * gtk_window_begin_resize_drag:
5840 * @window: a #GtkWindow
5841 * @button: mouse button that initiated the drag
5842 * @edge: position of the resize control
5843 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5844 * @root_y: Y position where the user clicked to initiate the drag
5845 * @timestamp: timestamp from the click event that initiated the drag
5847 * Starts resizing a window. This function is used if an application
5848 * has window resizing controls. When GDK can support it, the resize
5849 * will be done using the standard mechanism for the <link
5850 * linkend="gtk-X11-arch">window manager</link> or windowing
5851 * system. Otherwise, GDK will try to emulate window resizing,
5852 * potentially not all that well, depending on the windowing system.
5856 gtk_window_begin_resize_drag (GtkWindow *window,
5864 GdkWindow *toplevel;
5866 g_return_if_fail (GTK_IS_WINDOW (window));
5867 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5869 widget = GTK_WIDGET (window);
5872 toplevel = window->frame;
5874 toplevel = widget->window;
5876 gdk_window_begin_resize_drag (toplevel,
5883 * gtk_window_get_frame_dimensions:
5884 * @window: a #GtkWindow
5885 * @left: location to store the width of the frame at the left, or %NULL
5886 * @top: location to store the height of the frame at the top, or %NULL
5887 * @right: location to store the width of the frame at the returns, or %NULL
5888 * @bottom: location to store the height of the frame at the bottom, or %NULL
5890 * (Note: this is a special-purpose function intended for the
5891 * framebuffer port; see gtk_window_set_has_frame(). It will not
5892 * return the size of the window border drawn by the <link
5893 * linkend="gtk-X11-arch">window manager</link>, which is the normal
5894 * case when using a windowing system. See
5895 * gdk_window_get_frame_extents() to get the standard window border
5898 * Retrieves the dimensions of the frame window for this toplevel.
5899 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5902 gtk_window_get_frame_dimensions (GtkWindow *window,
5908 g_return_if_fail (GTK_IS_WINDOW (window));
5911 *left = window->frame_left;
5913 *top = window->frame_top;
5915 *right = window->frame_right;
5917 *bottom = window->frame_bottom;
5921 * gtk_window_begin_move_drag:
5922 * @window: a #GtkWindow
5923 * @button: mouse button that initiated the drag
5924 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5925 * @root_y: Y position where the user clicked to initiate the drag
5926 * @timestamp: timestamp from the click event that initiated the drag
5928 * Starts moving a window. This function is used if an application has
5929 * window movement grips. When GDK can support it, the window movement
5930 * will be done using the standard mechanism for the <link
5931 * linkend="gtk-X11-arch">window manager</link> or windowing
5932 * system. Otherwise, GDK will try to emulate window movement,
5933 * potentially not all that well, depending on the windowing system.
5937 gtk_window_begin_move_drag (GtkWindow *window,
5944 GdkWindow *toplevel;
5946 g_return_if_fail (GTK_IS_WINDOW (window));
5947 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5949 widget = GTK_WIDGET (window);
5952 toplevel = window->frame;
5954 toplevel = widget->window;
5956 gdk_window_begin_move_drag (toplevel,
5963 * gtk_window_set_screen:
5964 * @window: a #GtkWindow.
5965 * @screen: a #GdkScreen.
5967 * Sets the #GdkScreen where the @window is displayed; if
5968 * the window is already mapped, it will be unmapped, and
5969 * then remapped on the new screen.
5972 gtk_window_set_screen (GtkWindow *window,
5976 gboolean was_mapped;
5978 g_return_if_fail (GTK_IS_WINDOW (window));
5979 g_return_if_fail (GDK_IS_SCREEN (screen));
5981 if (screen == window->screen)
5984 widget = GTK_WIDGET (window);
5986 was_mapped = GTK_WIDGET_MAPPED (widget);
5989 gtk_widget_unmap (widget);
5990 if (GTK_WIDGET_REALIZED (widget))
5991 gtk_widget_unrealize (widget);
5993 gtk_window_free_key_hash (window);
5994 window->screen = screen;
5995 gtk_widget_reset_rc_styles (widget);
5996 g_object_notify (G_OBJECT (window), "screen");
5999 gtk_widget_map (widget);
6003 * gtk_window_get_screen:
6004 * @window: a #GtkWindow.
6006 * Returns the #GdkScreen associated with @window.
6008 * Return value: a #GdkScreen.
6011 gtk_window_get_screen (GtkWindow *window)
6013 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6015 return window->screen;
6020 gtk_window_group_class_init (GtkWindowGroupClass *klass)
6025 gtk_window_group_get_type (void)
6027 static GType window_group_type = 0;
6029 if (!window_group_type)
6031 static const GTypeInfo window_group_info =
6033 sizeof (GtkWindowGroupClass),
6034 NULL, /* base_init */
6035 NULL, /* base_finalize */
6036 (GClassInitFunc) gtk_window_group_class_init,
6037 NULL, /* class_finalize */
6038 NULL, /* class_data */
6039 sizeof (GtkWindowGroup),
6040 16, /* n_preallocs */
6041 (GInstanceInitFunc) NULL,
6044 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
6047 return window_group_type;
6051 * gtk_window_group_new:
6053 * Creates a new #GtkWindowGroup object. Grabs added with
6054 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
6056 * Return value: a new #GtkWindowGroup.
6059 gtk_window_group_new (void)
6061 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
6065 window_group_cleanup_grabs (GtkWindowGroup *group,
6069 GSList *to_remove = NULL;
6071 tmp_list = group->grabs;
6074 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
6075 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
6076 tmp_list = tmp_list->next;
6081 gtk_grab_remove (to_remove->data);
6082 g_object_unref (to_remove->data);
6083 to_remove = g_slist_delete_link (to_remove, to_remove);
6088 * gtk_window_group_add_window:
6089 * @window_group: a #GtkWindowGroup
6090 * @window: the #GtkWindow to add
6092 * Adds a window to a #GtkWindowGroup.
6095 gtk_window_group_add_window (GtkWindowGroup *window_group,
6098 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6099 g_return_if_fail (GTK_IS_WINDOW (window));
6101 if (window->group != window_group)
6103 g_object_ref (window);
6104 g_object_ref (window_group);
6107 gtk_window_group_remove_window (window->group, window);
6109 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
6111 window->group = window_group;
6113 g_object_unref (window);
6118 * gtk_window_group_remove_window:
6119 * @window_group: a #GtkWindowGroup
6120 * @window: the #GtkWindow to remove
6122 * Removes a window from a #GtkWindowGroup.
6125 gtk_window_group_remove_window (GtkWindowGroup *window_group,
6128 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6129 g_return_if_fail (GTK_IS_WIDGET (window));
6130 g_return_if_fail (window->group == window_group);
6132 g_object_ref (window);
6134 window_group_cleanup_grabs (window_group, window);
6135 window->group = NULL;
6137 g_object_unref (window_group);
6138 g_object_unref (window);
6141 /* Return the group for the window or the default group
6144 _gtk_window_get_group (GtkWindow *window)
6146 if (window && window->group)
6147 return window->group;
6150 static GtkWindowGroup *default_group = NULL;
6153 default_group = gtk_window_group_new ();
6155 return default_group;
6161 Derived from XParseGeometry() in XFree86
6163 Copyright 1985, 1986, 1987,1998 The Open Group
6165 All Rights Reserved.
6167 The above copyright notice and this permission notice shall be included
6168 in all copies or substantial portions of the Software.
6170 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
6171 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6172 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6173 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
6174 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
6175 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
6176 OTHER DEALINGS IN THE SOFTWARE.
6178 Except as contained in this notice, the name of The Open Group shall
6179 not be used in advertising or otherwise to promote the sale, use or
6180 other dealings in this Software without prior written authorization
6181 from The Open Group.
6186 * XParseGeometry parses strings of the form
6187 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
6188 * width, height, xoffset, and yoffset are unsigned integers.
6189 * Example: "=80x24+300-49"
6190 * The equal sign is optional.
6191 * It returns a bitmask that indicates which of the four values
6192 * were actually found in the string. For each value found,
6193 * the corresponding argument is updated; for each value
6194 * not found, the corresponding argument is left unchanged.
6197 /* The following code is from Xlib, and is minimally modified, so we
6198 * can track any upstream changes if required. Don't change this
6199 * code. Or if you do, put in a huge comment marking which thing
6204 read_int (gchar *string,
6212 else if (*string == '-')
6218 for (; (*string >= '0') && (*string <= '9'); string++)
6220 result = (result * 10) + (*string - '0');
6232 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
6233 * value (x, y, width, height) was found in the parsed string.
6235 #define NoValue 0x0000
6236 #define XValue 0x0001
6237 #define YValue 0x0002
6238 #define WidthValue 0x0004
6239 #define HeightValue 0x0008
6240 #define AllValues 0x000F
6241 #define XNegative 0x0010
6242 #define YNegative 0x0020
6244 /* Try not to reformat/modify, so we can compare/sync with X sources */
6246 gtk_XParseGeometry (const char *string,
6249 unsigned int *width,
6250 unsigned int *height)
6254 unsigned int tempWidth, tempHeight;
6256 char *nextCharacter;
6258 /* These initializations are just to silence gcc */
6264 if ( (string == NULL) || (*string == '\0')) return(mask);
6266 string++; /* ignore possible '=' at beg of geometry spec */
6268 strind = (char *)string;
6269 if (*strind != '+' && *strind != '-' && *strind != 'x') {
6270 tempWidth = read_int(strind, &nextCharacter);
6271 if (strind == nextCharacter)
6273 strind = nextCharacter;
6277 if (*strind == 'x' || *strind == 'X') {
6279 tempHeight = read_int(strind, &nextCharacter);
6280 if (strind == nextCharacter)
6282 strind = nextCharacter;
6283 mask |= HeightValue;
6286 if ((*strind == '+') || (*strind == '-')) {
6287 if (*strind == '-') {
6289 tempX = -read_int(strind, &nextCharacter);
6290 if (strind == nextCharacter)
6292 strind = nextCharacter;
6298 tempX = read_int(strind, &nextCharacter);
6299 if (strind == nextCharacter)
6301 strind = nextCharacter;
6304 if ((*strind == '+') || (*strind == '-')) {
6305 if (*strind == '-') {
6307 tempY = -read_int(strind, &nextCharacter);
6308 if (strind == nextCharacter)
6310 strind = nextCharacter;
6317 tempY = read_int(strind, &nextCharacter);
6318 if (strind == nextCharacter)
6320 strind = nextCharacter;
6326 /* If strind isn't at the end of the string the it's an invalid
6327 geometry specification. */
6329 if (*strind != '\0') return (0);
6335 if (mask & WidthValue)
6337 if (mask & HeightValue)
6338 *height = tempHeight;
6343 * gtk_window_parse_geometry:
6344 * @window: a #GtkWindow
6345 * @geometry: geometry string
6347 * Parses a standard X Window System geometry string - see the
6348 * manual page for X (type 'man X') for details on this.
6349 * gtk_window_parse_geometry() does work on all GTK+ ports
6350 * including Win32 but is primarily intended for an X environment.
6352 * If either a size or a position can be extracted from the
6353 * geometry string, gtk_window_parse_geometry() returns %TRUE
6354 * and calls gtk_window_set_default_size() and/or gtk_window_move()
6355 * to resize/move the window.
6357 * If gtk_window_parse_geometry() returns %TRUE, it will also
6358 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
6359 * indicating to the window manager that the size/position of
6360 * the window was user-specified. This causes most window
6361 * managers to honor the geometry.
6363 * Return value: %TRUE if string was parsed successfully
6366 gtk_window_parse_geometry (GtkWindow *window,
6367 const gchar *geometry)
6372 gboolean size_set, pos_set;
6374 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6375 g_return_val_if_fail (geometry != NULL, FALSE);
6377 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
6379 if ((result & WidthValue) == 0 ||
6382 if ((result & HeightValue) == 0 ||
6387 if ((result & WidthValue) || (result & HeightValue))
6389 gtk_window_set_default_size_internal (window, TRUE, w, TRUE, h, TRUE);
6393 gtk_window_get_size (window, &w, &h);
6395 grav = GDK_GRAVITY_NORTH_WEST;
6397 if ((result & XNegative) && (result & YNegative))
6398 grav = GDK_GRAVITY_SOUTH_EAST;
6399 else if (result & XNegative)
6400 grav = GDK_GRAVITY_NORTH_EAST;
6401 else if (result & YNegative)
6402 grav = GDK_GRAVITY_SOUTH_WEST;
6404 if ((result & XValue) == 0)
6407 if ((result & YValue) == 0)
6410 if (grav == GDK_GRAVITY_SOUTH_WEST ||
6411 grav == GDK_GRAVITY_SOUTH_EAST)
6412 y = gdk_screen_get_height (window->screen) - h + y;
6414 if (grav == GDK_GRAVITY_SOUTH_EAST ||
6415 grav == GDK_GRAVITY_NORTH_EAST)
6416 x = gdk_screen_get_width (window->screen) - w + x;
6418 /* we don't let you put a window offscreen; maybe some people would
6419 * prefer to be able to, but it's kind of a bogus thing to do.
6428 if ((result & XValue) || (result & YValue))
6430 gtk_window_set_gravity (window, grav);
6431 gtk_window_move (window, x, y);
6435 if (size_set || pos_set)
6437 /* Set USSize, USPosition hints */
6438 GtkWindowGeometryInfo *info;
6440 info = gtk_window_get_geometry_info (window, TRUE);
6443 info->mask |= GDK_HINT_USER_POS;
6445 info->mask |= GDK_HINT_USER_SIZE;
6452 gtk_window_mnemonic_hash_foreach (gpointer key,
6458 GtkWindowKeysForeachFunc func;
6462 GtkWindowMnemonic *mnemonic = value;
6464 if (mnemonic->window == info->window)
6465 (*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
6469 _gtk_window_keys_foreach (GtkWindow *window,
6470 GtkWindowKeysForeachFunc func,
6477 GtkWindowKeysForeachFunc func;
6481 info.window = window;
6483 info.func_data = func_data;
6485 g_hash_table_foreach (mnemonic_hash_table,
6486 gtk_window_mnemonic_hash_foreach,
6489 groups = gtk_accel_groups_from_object (G_OBJECT (window));
6492 GtkAccelGroup *group = groups->data;
6495 for (i = 0; i < group->n_accels; i++)
6497 GtkAccelKey *key = &group->priv_accels[i].key;
6500 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
6503 groups = groups->next;
6508 gtk_window_keys_changed (GtkWindow *window)
6510 gtk_window_free_key_hash (window);
6511 gtk_window_get_key_hash (window);
6514 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
6516 struct _GtkWindowKeyEntry
6520 gboolean is_mnemonic;
6524 add_to_key_hash (GtkWindow *window,
6526 GdkModifierType modifiers,
6527 gboolean is_mnemonic,
6530 GtkKeyHash *key_hash = data;
6532 GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
6534 entry->keyval = keyval;
6535 entry->modifiers = modifiers;
6536 entry->is_mnemonic = is_mnemonic;
6538 /* GtkAccelGroup stores lowercased accelerators. To deal
6539 * with this, if <Shift> was specified, uppercase.
6541 if (modifiers & GDK_SHIFT_MASK)
6543 if (keyval == GDK_Tab)
6544 keyval = GDK_ISO_Left_Tab;
6546 keyval = gdk_keyval_to_upper (keyval);
6549 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
6553 gtk_window_get_key_hash (GtkWindow *window)
6555 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6559 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (window->screen)),
6560 (GDestroyNotify)g_free);
6561 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
6562 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
6568 gtk_window_free_key_hash (GtkWindow *window)
6570 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6573 _gtk_key_hash_free (key_hash);
6574 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
6579 * _gtk_window_activate_key:
6580 * @window: a #GtkWindow
6581 * @event: a #GdkEventKey
6583 * Activates mnemonics and accelerators for this #GtKWindow
6585 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
6588 _gtk_window_activate_key (GtkWindow *window,
6591 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6592 GtkWindowKeyEntry *found_entry = NULL;
6596 gtk_window_keys_changed (window);
6597 key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6602 GSList *entries = _gtk_key_hash_lookup (key_hash,
6603 event->hardware_keycode,
6604 event->state & gtk_accelerator_get_default_mod_mask (),
6608 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
6610 GtkWindowKeyEntry *entry = tmp_list->data;
6611 if (entry->is_mnemonic)
6613 found_entry = entry;
6618 if (!found_entry && entries)
6619 found_entry = entries->data;
6621 g_slist_free (entries);
6626 if (found_entry->is_mnemonic)
6627 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
6629 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
6636 window_update_has_focus (GtkWindow *window)
6638 GtkWidget *widget = GTK_WIDGET (window);
6639 gboolean has_focus = window->has_toplevel_focus && window->is_active;
6641 if (has_focus != window->has_focus)
6643 window->has_focus = has_focus;
6647 if (window->focus_widget &&
6648 window->focus_widget != widget &&
6649 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6650 do_focus_change (window->focus_widget, TRUE);
6654 if (window->focus_widget &&
6655 window->focus_widget != widget &&
6656 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6657 do_focus_change (window->focus_widget, FALSE);
6663 * _gtk_window_set_is_active:
6664 * @window: a #GtkWindow
6665 * @is_active: %TRUE if the window is in the currently active toplevel
6667 * Internal function that sets whether the #GtkWindow is part
6668 * of the currently active toplevel window (taking into account inter-process
6672 _gtk_window_set_is_active (GtkWindow *window,
6675 g_return_if_fail (GTK_IS_WINDOW (window));
6677 is_active = is_active != FALSE;
6679 if (is_active != window->is_active)
6681 window->is_active = is_active;
6682 window_update_has_focus (window);
6684 g_object_notify (G_OBJECT (window), "is_active");
6689 * _gtk_window_set_has_toplevel_focus:
6690 * @window: a #GtkWindow
6691 * @has_toplevel_focus: %TRUE if the in
6693 * Internal function that sets whether the keyboard focus for the
6694 * toplevel window (taking into account inter-process embedding.)
6697 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
6698 gboolean has_toplevel_focus)
6700 g_return_if_fail (GTK_IS_WINDOW (window));
6702 has_toplevel_focus = has_toplevel_focus != FALSE;
6704 if (has_toplevel_focus != window->has_toplevel_focus)
6706 window->has_toplevel_focus = has_toplevel_focus;
6707 window_update_has_focus (window);
6709 g_object_notify (G_OBJECT (window), "has_toplevel_focus");