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_unset_transient_for (GtkWindow *window)
1730 if (window->transient_parent)
1732 g_signal_handlers_disconnect_by_func (window->transient_parent,
1733 gtk_window_transient_parent_realized,
1735 g_signal_handlers_disconnect_by_func (window->transient_parent,
1736 gtk_window_transient_parent_unrealized,
1738 g_signal_handlers_disconnect_by_func (window->transient_parent,
1739 gtk_widget_destroyed,
1740 &window->transient_parent);
1742 if (window->destroy_with_parent)
1743 disconnect_parent_destroyed (window);
1745 window->transient_parent = NULL;
1750 * gtk_window_set_transient_for:
1751 * @window: a #GtkWindow
1752 * @parent: parent window
1754 * Dialog windows should be set transient for the main application
1755 * window they were spawned from. This allows <link
1756 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1757 * dialog on top of the main window, or center the dialog over the
1758 * main window. gtk_dialog_new_with_buttons() and other convenience
1759 * functions in GTK+ will sometimes call
1760 * gtk_window_set_transient_for() on your behalf.
1762 * On Windows, this function will and put the child window
1763 * on top of the parent, much as the window manager would have
1768 gtk_window_set_transient_for (GtkWindow *window,
1771 g_return_if_fail (GTK_IS_WINDOW (window));
1772 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1773 g_return_if_fail (window != parent);
1776 if (window->transient_parent)
1778 if (GTK_WIDGET_REALIZED (window) &&
1779 GTK_WIDGET_REALIZED (window->transient_parent) &&
1780 (!parent || !GTK_WIDGET_REALIZED (parent)))
1781 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1782 GTK_WIDGET (window));
1784 gtk_window_unset_transient_for (window);
1787 window->transient_parent = parent;
1791 g_signal_connect (parent, "destroy",
1792 G_CALLBACK (gtk_widget_destroyed),
1793 &window->transient_parent);
1794 g_signal_connect (parent, "realize",
1795 G_CALLBACK (gtk_window_transient_parent_realized),
1797 g_signal_connect (parent, "unrealize",
1798 G_CALLBACK (gtk_window_transient_parent_unrealized),
1801 window->screen = parent->screen;
1803 if (window->destroy_with_parent)
1804 connect_parent_destroyed (window);
1806 if (GTK_WIDGET_REALIZED (window) &&
1807 GTK_WIDGET_REALIZED (parent))
1808 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1809 GTK_WIDGET (window));
1814 * gtk_window_get_transient_for:
1815 * @window: a #GtkWindow
1817 * Fetches the transient parent for this window. See
1818 * gtk_window_set_transient_for().
1820 * Return value: the transient parent for this window, or %NULL
1821 * if no transient parent has been set.
1824 gtk_window_get_transient_for (GtkWindow *window)
1826 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1828 return window->transient_parent;
1832 * gtk_window_set_type_hint:
1833 * @window: a #GtkWindow
1834 * @hint: the window type
1836 * By setting the type hint for the window, you allow the window
1837 * manager to decorate and handle the window in a way which is
1838 * suitable to the function of the window in your application.
1840 * This function should be called before the window becomes visible.
1842 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1843 * will sometimes call gtk_window_set_type_hint() on your behalf.
1847 gtk_window_set_type_hint (GtkWindow *window,
1848 GdkWindowTypeHint hint)
1850 g_return_if_fail (GTK_IS_WINDOW (window));
1851 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1852 window->type_hint = hint;
1856 * gtk_window_get_type_hint:
1857 * @window: a #GtkWindow
1859 * Gets the type hint for this window. See gtk_window_set_type_hint().
1861 * Return value: the type hint for @window.
1864 gtk_window_get_type_hint (GtkWindow *window)
1866 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1868 return window->type_hint;
1872 * gtk_window_set_skip_taskbar_hint:
1873 * @window: a #GtkWindow
1874 * @setting: %TRUE to keep this window from appearing in the task bar
1876 * Windows may set a hint asking the desktop environment not to display
1877 * the window in the task bar. This function toggles this hint.
1881 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
1884 GtkWindowPrivate *priv;
1886 g_return_if_fail (GTK_IS_WINDOW (window));
1888 priv = gtk_window_get_private (window);
1890 setting = setting != FALSE;
1892 if (priv->skips_taskbar != setting)
1894 priv->skips_taskbar = setting;
1895 if (GTK_WIDGET_REALIZED (window))
1896 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
1897 priv->skips_taskbar);
1898 g_object_notify (G_OBJECT (window), "skip_taskbar_hint");
1903 * gtk_window_get_skip_taskbar_hint:
1904 * @window: a #GtkWindow
1906 * Gets the value set by gtk_window_set_skip_taskbar_hint()
1908 * Return value: %TRUE if window shouldn't be in taskbar
1911 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
1913 GtkWindowPrivate *priv;
1915 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1917 priv = gtk_window_get_private (window);
1919 return priv->skips_taskbar;
1923 * gtk_window_set_skip_pager_hint:
1924 * @window: a #GtkWindow
1925 * @setting: %TRUE to keep this window from appearing in the pager
1927 * Windows may set a hint asking the desktop environment not to display
1928 * the window in the pager. This function toggles this hint.
1929 * (A "pager" is any desktop navigation tool such as a workspace
1930 * switcher that displays a thumbnail representation of the windows
1935 gtk_window_set_skip_pager_hint (GtkWindow *window,
1938 GtkWindowPrivate *priv;
1940 g_return_if_fail (GTK_IS_WINDOW (window));
1942 priv = gtk_window_get_private (window);
1944 setting = setting != FALSE;
1946 if (priv->skips_pager != setting)
1948 priv->skips_pager = setting;
1949 if (GTK_WIDGET_REALIZED (window))
1950 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
1952 g_object_notify (G_OBJECT (window), "skip_pager_hint");
1957 * gtk_window_get_skip_pager_hint:
1958 * @window: a #GtkWindow
1960 * Gets the value set by gtk_window_set_skip_pager_hint().
1962 * Return value: %TRUE if window shouldn't be in pager
1965 gtk_window_get_skip_pager_hint (GtkWindow *window)
1967 GtkWindowPrivate *priv;
1969 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1971 priv = gtk_window_get_private (window);
1973 return priv->skips_pager;
1977 * gtk_window_set_destroy_with_parent:
1978 * @window: a #GtkWindow
1979 * @setting: whether to destroy @window with its transient parent
1981 * If @setting is %TRUE, then destroying the transient parent of @window
1982 * will also destroy @window itself. This is useful for dialogs that
1983 * shouldn't persist beyond the lifetime of the main window they're
1984 * associated with, for example.
1987 gtk_window_set_destroy_with_parent (GtkWindow *window,
1990 g_return_if_fail (GTK_IS_WINDOW (window));
1992 if (window->destroy_with_parent == (setting != FALSE))
1995 if (window->destroy_with_parent)
1997 disconnect_parent_destroyed (window);
2001 connect_parent_destroyed (window);
2004 window->destroy_with_parent = setting;
2006 g_object_notify (G_OBJECT (window), "destroy_with_parent");
2010 * gtk_window_get_destroy_with_parent:
2011 * @window: a #GtkWindow
2013 * Returns whether the window will be destroyed with its transient parent. See
2014 * gtk_window_set_destroy_with_parent ().
2016 * Return value: %TRUE if the window will be destroyed with its transient parent.
2019 gtk_window_get_destroy_with_parent (GtkWindow *window)
2021 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2023 return window->destroy_with_parent;
2026 static GtkWindowGeometryInfo*
2027 gtk_window_get_geometry_info (GtkWindow *window,
2030 GtkWindowGeometryInfo *info;
2032 info = window->geometry_info;
2033 if (!info && create)
2035 info = g_new0 (GtkWindowGeometryInfo, 1);
2037 info->default_width = -1;
2038 info->default_height = -1;
2039 info->resize_width = -1;
2040 info->resize_height = -1;
2041 info->initial_x = 0;
2042 info->initial_y = 0;
2043 info->initial_pos_set = FALSE;
2044 info->default_is_geometry = FALSE;
2045 info->position_constraints_changed = FALSE;
2046 info->last.configure_request.x = 0;
2047 info->last.configure_request.y = 0;
2048 info->last.configure_request.width = -1;
2049 info->last.configure_request.height = -1;
2050 info->widget = NULL;
2052 window->geometry_info = info;
2059 * gtk_window_set_geometry_hints:
2060 * @window: a #GtkWindow
2061 * @geometry_widget: widget the geometry hints will be applied to
2062 * @geometry: struct containing geometry information
2063 * @geom_mask: mask indicating which struct fields should be paid attention to
2065 * This function sets up hints about how a window can be resized by
2066 * the user. You can set a minimum and maximum size; allowed resize
2067 * increments (e.g. for xterm, you can only resize by the size of a
2068 * character); aspect ratios; and more. See the #GdkGeometry struct.
2072 gtk_window_set_geometry_hints (GtkWindow *window,
2073 GtkWidget *geometry_widget,
2074 GdkGeometry *geometry,
2075 GdkWindowHints geom_mask)
2077 GtkWindowGeometryInfo *info;
2079 g_return_if_fail (GTK_IS_WINDOW (window));
2080 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2082 info = gtk_window_get_geometry_info (window, TRUE);
2085 g_signal_handlers_disconnect_by_func (info->widget,
2086 gtk_widget_destroyed,
2089 info->widget = geometry_widget;
2091 g_signal_connect (geometry_widget, "destroy",
2092 G_CALLBACK (gtk_widget_destroyed),
2096 info->geometry = *geometry;
2098 /* We store gravity in window->gravity not in the hints. */
2099 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2101 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2103 gtk_window_set_gravity (window, geometry->win_gravity);
2106 gtk_widget_queue_resize (GTK_WIDGET (window));
2110 * gtk_window_set_decorated:
2111 * @window: a #GtkWindow
2112 * @setting: %TRUE to decorate the window
2114 * By default, windows are decorated with a title bar, resize
2115 * controls, etc. Some <link linkend="gtk-X11-arch">window
2116 * managers</link> allow GTK+ to disable these decorations, creating a
2117 * borderless window. If you set the decorated property to %FALSE
2118 * using this function, GTK+ will do its best to convince the window
2119 * manager not to decorate the window. Depending on the system, this
2120 * function may not have any effect when called on a window that is
2121 * already visible, so you should call it before calling gtk_window_show().
2123 * On Windows, this function always works, since there's no window manager
2128 gtk_window_set_decorated (GtkWindow *window,
2131 g_return_if_fail (GTK_IS_WINDOW (window));
2133 setting = setting != FALSE;
2135 if (setting == window->decorated)
2138 window->decorated = setting;
2140 if (GTK_WIDGET (window)->window)
2142 if (window->decorated)
2143 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2146 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2152 * gtk_window_get_decorated:
2153 * @window: a #GtkWindow
2155 * Returns whether the window has been set to have decorations
2156 * such as a title bar via gtk_window_set_decorated().
2158 * Return value: %TRUE if the window has been set to have decorations
2161 gtk_window_get_decorated (GtkWindow *window)
2163 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2165 return window->decorated;
2168 static GtkWindowIconInfo*
2169 get_icon_info (GtkWindow *window)
2171 return g_object_get_data (G_OBJECT (window),
2172 "gtk-window-icon-info");
2175 static GtkWindowIconInfo*
2176 ensure_icon_info (GtkWindow *window)
2178 GtkWindowIconInfo *info;
2180 info = get_icon_info (window);
2184 info = g_new0 (GtkWindowIconInfo, 1);
2185 g_object_set_data_full (G_OBJECT (window),
2186 "gtk-window-icon-info",
2201 get_screen_icon_info (GdkScreen *screen)
2203 ScreenIconInfo *info = g_object_get_data (G_OBJECT (screen),
2204 "gtk-window-default-icon-pixmap");
2207 info = g_new0 (ScreenIconInfo, 1);
2208 g_object_set_data (G_OBJECT (screen), "gtk-window-default-icon-pixmap", info);
2211 if (info->serial != default_icon_serial)
2215 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2216 info->pixmap = NULL;
2221 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2225 info->serial = default_icon_serial;
2232 get_pixmap_and_mask (GdkWindow *window,
2233 GtkWindowIconInfo *parent_info,
2234 gboolean is_default_list,
2236 GdkPixmap **pmap_return,
2237 GdkBitmap **mask_return)
2239 GdkScreen *screen = gdk_drawable_get_screen (window);
2240 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2241 GdkPixbuf *best_icon;
2245 *pmap_return = NULL;
2246 *mask_return = NULL;
2248 if (is_default_list &&
2249 default_icon_info->pixmap != NULL)
2251 /* Use shared icon pixmap for all windows on this screen.
2253 if (default_icon_info->pixmap)
2254 g_object_ref (default_icon_info->pixmap);
2255 if (default_icon_info->mask)
2256 g_object_ref (default_icon_info->mask);
2258 *pmap_return = default_icon_info->pixmap;
2259 *mask_return = default_icon_info->mask;
2261 else if (parent_info && parent_info->icon_pixmap)
2263 if (parent_info->icon_pixmap)
2264 g_object_ref (parent_info->icon_pixmap);
2265 if (parent_info->icon_mask)
2266 g_object_ref (parent_info->icon_mask);
2268 *pmap_return = parent_info->icon_pixmap;
2269 *mask_return = parent_info->icon_mask;
2273 #define IDEAL_SIZE 48
2275 best_size = G_MAXINT;
2277 tmp_list = icon_list;
2278 while (tmp_list != NULL)
2280 GdkPixbuf *pixbuf = tmp_list->data;
2283 /* average width and height - if someone passes in a rectangular
2284 * icon they deserve what they get.
2286 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2289 if (best_icon == NULL)
2296 /* icon is better if it's 32 pixels or larger, and closer to
2297 * the ideal size than the current best.
2300 (ABS (best_size - IDEAL_SIZE) <
2301 ABS (this - IDEAL_SIZE)))
2308 tmp_list = tmp_list->next;
2312 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2313 gdk_screen_get_system_colormap (screen),
2318 /* Save pmap/mask for others to use if appropriate */
2321 parent_info->icon_pixmap = *pmap_return;
2322 parent_info->icon_mask = *mask_return;
2324 if (parent_info->icon_pixmap)
2325 g_object_ref (parent_info->icon_pixmap);
2326 if (parent_info->icon_mask)
2327 g_object_ref (parent_info->icon_mask);
2329 else if (is_default_list)
2331 default_icon_info->pixmap = *pmap_return;
2332 default_icon_info->mask = *mask_return;
2334 if (default_icon_info->pixmap)
2335 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2336 (gpointer*)&default_icon_info->pixmap);
2337 if (default_icon_info->mask)
2338 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2339 (gpointer*)&default_icon_info->mask);
2345 gtk_window_realize_icon (GtkWindow *window)
2348 GtkWindowIconInfo *info;
2351 widget = GTK_WIDGET (window);
2353 g_return_if_fail (widget->window != NULL);
2355 /* no point setting an icon on override-redirect */
2356 if (window->type == GTK_WINDOW_POPUP)
2361 info = ensure_icon_info (window);
2366 g_return_if_fail (info->icon_pixmap == NULL);
2367 g_return_if_fail (info->icon_mask == NULL);
2369 info->using_default_icon = FALSE;
2370 info->using_parent_icon = FALSE;
2372 icon_list = info->icon_list;
2374 /* Inherit from transient parent */
2375 if (icon_list == NULL && window->transient_parent)
2377 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2379 info->using_parent_icon = TRUE;
2382 /* Inherit from default */
2383 if (icon_list == NULL)
2385 icon_list = default_icon_list;
2387 info->using_default_icon = TRUE;
2390 gdk_window_set_icon_list (widget->window, icon_list);
2392 get_pixmap_and_mask (widget->window,
2393 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2394 info->using_default_icon,
2399 /* This is a slight ICCCM violation since it's a color pixmap not
2400 * a bitmap, but everyone does it.
2402 gdk_window_set_icon (widget->window,
2407 info->realized = TRUE;
2411 gtk_window_unrealize_icon (GtkWindow *window)
2413 GtkWindowIconInfo *info;
2416 widget = GTK_WIDGET (window);
2418 info = get_icon_info (window);
2423 if (info->icon_pixmap)
2424 g_object_unref (info->icon_pixmap);
2426 if (info->icon_mask)
2427 g_object_unref (info->icon_mask);
2429 info->icon_pixmap = NULL;
2430 info->icon_mask = NULL;
2432 /* We don't clear the properties on the window, just figure the
2433 * window is going away.
2436 info->realized = FALSE;
2440 * gtk_window_set_icon_list:
2441 * @window: a #GtkWindow
2442 * @list: list of #GdkPixbuf
2444 * Sets up the icon representing a #GtkWindow. The icon is used when
2445 * the window is minimized (also known as iconified). Some window
2446 * managers or desktop environments may also place it in the window
2447 * frame, or display it in other contexts.
2449 * gtk_window_set_icon_list() allows you to pass in the same icon in
2450 * several hand-drawn sizes. The list should contain the natural sizes
2451 * your icon is available in; that is, don't scale the image before
2452 * passing it to GTK+. Scaling is postponed until the last minute,
2453 * when the desired final size is known, to allow best quality.
2455 * By passing several sizes, you may improve the final image quality
2456 * of the icon, by reducing or eliminating automatic image scaling.
2458 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2459 * larger images (64x64, 128x128) if you have them.
2461 * See also gtk_window_set_default_icon_list() to set the icon
2462 * for all windows in your application in one go.
2464 * Note that transient windows (those who have been set transient for another
2465 * window using gtk_window_set_transient_for()) will inherit their
2466 * icon from their transient parent. So there's no need to explicitly
2467 * set the icon on transient windows.
2470 gtk_window_set_icon_list (GtkWindow *window,
2473 GtkWindowIconInfo *info;
2475 g_return_if_fail (GTK_IS_WINDOW (window));
2477 info = ensure_icon_info (window);
2479 if (info->icon_list == list) /* check for NULL mostly */
2482 g_list_foreach (info->icon_list,
2483 (GFunc) g_object_unref, NULL);
2485 g_list_free (info->icon_list);
2487 info->icon_list = g_list_copy (list);
2488 g_list_foreach (info->icon_list,
2489 (GFunc) g_object_ref, NULL);
2491 g_object_notify (G_OBJECT (window), "icon");
2493 gtk_window_unrealize_icon (window);
2495 if (GTK_WIDGET_REALIZED (window))
2496 gtk_window_realize_icon (window);
2498 /* We could try to update our transient children, but I don't think
2499 * it's really worth it. If we did it, the best way would probably
2500 * be to have children connect to notify::icon_list
2505 * gtk_window_get_icon_list:
2506 * @window: a #GtkWindow
2508 * Retrieves the list of icons set by gtk_window_set_icon_list().
2509 * The list is copied, but the reference count on each
2510 * member won't be incremented.
2512 * Return value: copy of window's icon list
2515 gtk_window_get_icon_list (GtkWindow *window)
2517 GtkWindowIconInfo *info;
2519 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2521 info = get_icon_info (window);
2524 return g_list_copy (info->icon_list);
2530 * gtk_window_set_icon:
2531 * @window: a #GtkWindow
2532 * @icon: icon image, or %NULL
2534 * Sets up the icon representing a #GtkWindow. This icon is used when
2535 * the window is minimized (also known as iconified). Some window
2536 * managers or desktop environments may also place it in the window
2537 * frame, or display it in other contexts.
2539 * The icon should be provided in whatever size it was naturally
2540 * drawn; that is, don't scale the image before passing it to
2541 * GTK+. Scaling is postponed until the last minute, when the desired
2542 * final size is known, to allow best quality.
2544 * If you have your icon hand-drawn in multiple sizes, use
2545 * gtk_window_set_icon_list(). Then the best size will be used.
2547 * This function is equivalent to calling gtk_window_set_icon_list()
2548 * with a 1-element list.
2550 * See also gtk_window_set_default_icon_list() to set the icon
2551 * for all windows in your application in one go.
2554 gtk_window_set_icon (GtkWindow *window,
2559 g_return_if_fail (GTK_IS_WINDOW (window));
2560 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2565 list = g_list_append (list, icon);
2567 gtk_window_set_icon_list (window, list);
2572 * gtk_window_get_icon:
2573 * @window: a #GtkWindow
2575 * Gets the value set by gtk_window_set_icon() (or if you've
2576 * called gtk_window_set_icon_list(), gets the first icon in
2579 * Return value: icon for window
2582 gtk_window_get_icon (GtkWindow *window)
2584 GtkWindowIconInfo *info;
2586 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2588 info = get_icon_info (window);
2589 if (info && info->icon_list)
2590 return GDK_PIXBUF (info->icon_list->data);
2595 /* Load pixbuf, printing warning on failure if error == NULL
2598 load_pixbuf_verbosely (const char *filename,
2601 GError *local_err = NULL;
2604 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
2612 g_warning ("Error loading icon from file '%s':\n\t%s",
2613 filename, local_err->message);
2614 g_error_free (local_err);
2622 * gtk_window_set_icon_from_file:
2623 * @window: a #GtkWindow
2624 * @filename: location of icon file
2625 * @err: location to store error, or %NULL.
2627 * Sets the icon for @window.
2628 * Warns on failure if @err is %NULL.
2630 * This function is equivalent to calling gtk_window_set_icon()
2631 * with a pixbuf created by loading the image from @filename.
2633 * Returns: %TRUE if setting the icon succeeded.
2636 gtk_window_set_icon_from_file (GtkWindow *window,
2637 const gchar *filename,
2640 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2644 gtk_window_set_icon (window, pixbuf);
2645 g_object_unref (pixbuf);
2654 * gtk_window_set_default_icon_list:
2655 * @list: a list of #GdkPixbuf
2657 * Sets an icon list to be used as fallback for windows that haven't
2658 * had gtk_window_set_icon_list() called on them to set up a
2659 * window-specific icon list. This function allows you to set up the
2660 * icon for all windows in your app at once.
2662 * See gtk_window_set_icon_list() for more details.
2666 gtk_window_set_default_icon_list (GList *list)
2670 if (list == default_icon_list)
2673 /* Update serial so we don't used cached pixmaps/masks
2675 default_icon_serial++;
2677 g_list_foreach (default_icon_list,
2678 (GFunc) g_object_unref, NULL);
2680 g_list_free (default_icon_list);
2682 default_icon_list = g_list_copy (list);
2683 g_list_foreach (default_icon_list,
2684 (GFunc) g_object_ref, NULL);
2686 /* Update all toplevels */
2687 toplevels = gtk_window_list_toplevels ();
2688 tmp_list = toplevels;
2689 while (tmp_list != NULL)
2691 GtkWindowIconInfo *info;
2692 GtkWindow *w = tmp_list->data;
2694 info = get_icon_info (w);
2695 if (info && info->using_default_icon)
2697 gtk_window_unrealize_icon (w);
2698 if (GTK_WIDGET_REALIZED (w))
2699 gtk_window_realize_icon (w);
2702 tmp_list = tmp_list->next;
2704 g_list_free (toplevels);
2708 * gtk_window_set_default_icon_from_file:
2709 * @filename: location of icon file
2710 * @err: location to store error, or %NULL.
2712 * Sets an icon to be used as fallback for windows that haven't
2713 * had gtk_window_set_icon_list() called on them from a file
2714 * on disk. Warns on failure if @error is %NULL.
2716 * Returns: %TRUE if setting the icon succeeded.
2719 gtk_window_set_default_icon_from_file (const gchar *filename,
2722 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2726 GList *list = g_list_prepend (NULL, pixbuf);
2727 gtk_window_set_default_icon_list (list);
2730 g_object_unref (pixbuf);
2739 * gtk_window_get_default_icon_list:
2741 * Gets the value set by gtk_window_set_default_icon_list().
2742 * The list is a copy and should be freed with g_list_free(),
2743 * but the pixbufs in the list have not had their reference count
2746 * Return value: copy of default icon list
2749 gtk_window_get_default_icon_list (void)
2751 return g_list_copy (default_icon_list);
2755 gtk_window_set_default_size_internal (GtkWindow *window,
2756 gboolean change_width,
2758 gboolean change_height,
2760 gboolean is_geometry)
2762 GtkWindowGeometryInfo *info;
2764 g_return_if_fail (change_width == FALSE || width >= -1);
2765 g_return_if_fail (change_height == FALSE || height >= -1);
2767 info = gtk_window_get_geometry_info (window, TRUE);
2769 g_object_freeze_notify (G_OBJECT (window));
2771 info->default_is_geometry = is_geometry != FALSE;
2781 info->default_width = width;
2783 g_object_notify (G_OBJECT (window), "default_width");
2794 info->default_height = height;
2796 g_object_notify (G_OBJECT (window), "default_height");
2799 g_object_thaw_notify (G_OBJECT (window));
2801 gtk_widget_queue_resize (GTK_WIDGET (window));
2805 * gtk_window_set_default_size:
2806 * @window: a #GtkWindow
2807 * @width: width in pixels, or -1 to unset the default width
2808 * @height: height in pixels, or -1 to unset the default height
2810 * Sets the default size of a window. If the window's "natural" size
2811 * (its size request) is larger than the default, the default will be
2812 * ignored. More generally, if the default size does not obey the
2813 * geometry hints for the window (gtk_window_set_geometry_hints() can
2814 * be used to set these explicitly), the default size will be clamped
2815 * to the nearest permitted size.
2817 * Unlike gtk_widget_set_size_request(), which sets a size request for
2818 * a widget and thus would keep users from shrinking the window, this
2819 * function only sets the initial size, just as if the user had
2820 * resized the window themselves. Users can still shrink the window
2821 * again as they normally would. Setting a default size of -1 means to
2822 * use the "natural" default size (the size request of the window).
2824 * For more control over a window's initial size and how resizing works,
2825 * investigate gtk_window_set_geometry_hints().
2827 * For some uses, gtk_window_resize() is a more appropriate function.
2828 * gtk_window_resize() changes the current size of the window, rather
2829 * than the size to be used on initial display. gtk_window_resize() always
2830 * affects the window itself, not the geometry widget.
2832 * The default size of a window only affects the first time a window is
2833 * shown; if a window is hidden and re-shown, it will remember the size
2834 * it had prior to hiding, rather than using the default size.
2836 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2837 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2840 gtk_window_set_default_size (GtkWindow *window,
2844 g_return_if_fail (GTK_IS_WINDOW (window));
2845 g_return_if_fail (width >= -1);
2846 g_return_if_fail (height >= -1);
2848 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
2852 * gtk_window_get_default_size:
2853 * @window: a #GtkWindow
2854 * @width: location to store the default width, or %NULL
2855 * @height: location to store the default height, or %NULL
2857 * Gets the default size of the window. A value of -1 for the width or
2858 * height indicates that a default size has not been explicitly set
2859 * for that dimension, so the "natural" size of the window will be
2864 gtk_window_get_default_size (GtkWindow *window,
2868 GtkWindowGeometryInfo *info;
2870 g_return_if_fail (GTK_IS_WINDOW (window));
2872 info = gtk_window_get_geometry_info (window, FALSE);
2875 *width = info->default_width;
2878 *height = info->default_height;
2882 * gtk_window_resize:
2883 * @window: a #GtkWindow
2884 * @width: width in pixels to resize the window to
2885 * @height: height in pixels to resize the window to
2887 * Resizes the window as if the user had done so, obeying geometry
2888 * constraints. The default geometry constraint is that windows may
2889 * not be smaller than their size request; to override this
2890 * constraint, call gtk_widget_set_size_request() to set the window's
2891 * request to a smaller value.
2893 * If gtk_window_resize() is called before showing a window for the
2894 * first time, it overrides any default size set with
2895 * gtk_window_set_default_size().
2897 * Windows may not be resized smaller than 1 by 1 pixels.
2901 gtk_window_resize (GtkWindow *window,
2905 GtkWindowGeometryInfo *info;
2907 g_return_if_fail (GTK_IS_WINDOW (window));
2908 g_return_if_fail (width > 0);
2909 g_return_if_fail (height > 0);
2911 info = gtk_window_get_geometry_info (window, TRUE);
2913 info->resize_width = width;
2914 info->resize_height = height;
2916 gtk_widget_queue_resize (GTK_WIDGET (window));
2920 * gtk_window_get_size:
2921 * @window: a #GtkWindow
2922 * @width: return location for width, or %NULL
2923 * @height: return location for height, or %NULL
2925 * Obtains the current size of @window. If @window is not onscreen,
2926 * it returns the size GTK+ will suggest to the <link
2927 * linkend="gtk-X11-arch">window manager</link> for the initial window
2928 * size (but this is not reliably the same as the size the window
2929 * manager will actually select). The size obtained by
2930 * gtk_window_get_size() is the last size received in a
2931 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2932 * rather than querying the X server for the size. As a result, if you
2933 * call gtk_window_resize() then immediately call
2934 * gtk_window_get_size(), the size won't have taken effect yet. After
2935 * the window manager processes the resize request, GTK+ receives
2936 * notification that the size has changed via a configure event, and
2937 * the size of the window gets updated.
2939 * Note 1: Nearly any use of this function creates a race condition,
2940 * because the size of the window may change between the time that you
2941 * get the size and the time that you perform some action assuming
2942 * that size is the current size. To avoid race conditions, connect to
2943 * "configure_event" on the window and adjust your size-dependent
2944 * state to match the size delivered in the #GdkEventConfigure.
2946 * Note 2: The returned size does <emphasis>not</emphasis> include the
2947 * size of the window manager decorations (aka the window frame or
2948 * border). Those are not drawn by GTK+ and GTK+ has no reliable
2949 * method of determining their size.
2951 * Note 3: If you are getting a window size in order to position
2952 * the window onscreen, there may be a better way. The preferred
2953 * way is to simply set the window's semantic type with
2954 * gtk_window_set_type_hint(), which allows the window manager to
2955 * e.g. center dialogs. Also, if you set the transient parent of
2956 * dialogs with gtk_window_set_transient_for() window managers
2957 * will often center the dialog over its parent window. It's
2958 * much preferred to let the window manager handle these
2959 * things rather than doing it yourself, because all apps will
2960 * behave consistently and according to user prefs if the window
2961 * manager handles it. Also, the window manager can take the size
2962 * of the window decorations/border into account, while your
2963 * application cannot.
2965 * In any case, if you insist on application-specified window
2966 * positioning, there's <emphasis>still</emphasis> a better way than
2967 * doing it yourself - gtk_window_set_position() will frequently
2968 * handle the details for you.
2972 gtk_window_get_size (GtkWindow *window,
2979 g_return_if_fail (GTK_IS_WINDOW (window));
2981 widget = GTK_WIDGET (window);
2983 if (width == NULL && height == NULL)
2986 if (GTK_WIDGET_MAPPED (window))
2988 gdk_drawable_get_size (GTK_WIDGET (window)->window,
2993 GdkRectangle configure_request;
2995 gtk_window_compute_configure_request (window,
2999 w = configure_request.width;
3000 h = configure_request.height;
3011 * @window: a #GtkWindow
3012 * @x: X coordinate to move window to
3013 * @y: Y coordinate to move window to
3015 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3016 * @window to the given position. Window managers are free to ignore
3017 * this; most window managers ignore requests for initial window
3018 * positions (instead using a user-defined placement algorithm) and
3019 * honor requests after the window has already been shown.
3021 * Note: the position is the position of the gravity-determined
3022 * reference point for the window. The gravity determines two things:
3023 * first, the location of the reference point in root window
3024 * coordinates; and second, which point on the window is positioned at
3025 * the reference point.
3027 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3028 * point is simply the @x, @y supplied to gtk_window_move(). The
3029 * top-left corner of the window decorations (aka window frame or
3030 * border) will be placed at @x, @y. Therefore, to position a window
3031 * at the top left of the screen, you want to use the default gravity
3032 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3034 * To position a window at the bottom right corner of the screen, you
3035 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3036 * point is at @x + the window width and @y + the window height, and
3037 * the bottom-right corner of the window border will be placed at that
3038 * reference point. So, to place a window in the bottom right corner
3039 * you would first set gravity to south east, then write:
3040 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3041 * gdk_screen_height () - window_height)</literal>.
3043 * The extended window manager hints specification at <ulink
3044 * url="http://www.freedesktop.org/standards/wm-spec.html">
3045 * http://www.freedesktop.org/standards/wm-spec.html</ulink> has a
3046 * nice table of gravities in the "implementation notes" section.
3048 * The gtk_window_get_position() documentation may also be relevant.
3052 gtk_window_move (GtkWindow *window,
3056 GtkWindowGeometryInfo *info;
3059 g_return_if_fail (GTK_IS_WINDOW (window));
3061 widget = GTK_WIDGET (window);
3063 info = gtk_window_get_geometry_info (window, TRUE);
3065 if (GTK_WIDGET_MAPPED (window))
3067 /* we have now sent a request with this position
3068 * with currently-active constraints, so toggle flag.
3070 info->position_constraints_changed = FALSE;
3072 /* we only constrain if mapped - if not mapped,
3073 * then gtk_window_compute_configure_request()
3074 * will apply the constraints later, and we
3075 * don't want to lose information about
3076 * what position the user set before then.
3077 * i.e. if you do a move() then turn off POS_CENTER
3078 * then show the window, your move() will work.
3080 gtk_window_constrain_position (window,
3081 widget->allocation.width,
3082 widget->allocation.height,
3085 /* Note that this request doesn't go through our standard request
3086 * framework, e.g. doesn't increment configure_request_count,
3087 * doesn't set info->last, etc.; that's because
3088 * we don't save the info needed to arrive at this same request
3091 * To gtk_window_move_resize(), this will end up looking exactly
3092 * the same as the position being changed by the window
3096 /* FIXME are we handling gravity properly for framed windows? */
3098 gdk_window_move (window->frame,
3099 x - window->frame_left,
3100 y - window->frame_top);
3102 gdk_window_move (GTK_WIDGET (window)->window,
3107 /* Save this position to apply on mapping */
3108 info->initial_x = x;
3109 info->initial_y = y;
3110 info->initial_pos_set = TRUE;
3115 * gtk_window_get_position:
3116 * @window: a #GtkWindow
3117 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3118 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3120 * This function returns the position you need to pass to
3121 * gtk_window_move() to keep @window in its current position. This
3122 * means that the meaning of the returned value varies with window
3123 * gravity. See gtk_window_move() for more details.
3125 * If you haven't changed the window gravity, its gravity will be
3126 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3127 * gets the position of the top-left corner of the window manager
3128 * frame for the window. gtk_window_move() sets the position of this
3129 * same top-left corner.
3131 * gtk_window_get_position() is not 100% reliable because the X Window System
3132 * does not specify a way to obtain the geometry of the
3133 * decorations placed on a window by the window manager.
3134 * Thus GTK+ is using a "best guess" that works with most
3137 * Moreover, nearly all window managers are historically broken with
3138 * respect to their handling of window gravity. So moving a window to
3139 * its current position as returned by gtk_window_get_position() tends
3140 * to result in moving the window slightly. Window managers are
3141 * slowly getting better over time.
3143 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3144 * frame is not relevant, and thus gtk_window_get_position() will
3145 * always produce accurate results. However you can't use static
3146 * gravity to do things like place a window in a corner of the screen,
3147 * because static gravity ignores the window manager decorations.
3149 * If you are saving and restoring your application's window
3150 * positions, you should know that it's impossible for applications to
3151 * do this without getting it somewhat wrong because applications do
3152 * not have sufficient knowledge of window manager state. The Correct
3153 * Mechanism is to support the session management protocol (see the
3154 * "GnomeClient" object in the GNOME libraries for example) and allow
3155 * the window manager to save your window sizes and positions.
3160 gtk_window_get_position (GtkWindow *window,
3166 g_return_if_fail (GTK_IS_WINDOW (window));
3168 widget = GTK_WIDGET (window);
3170 if (window->gravity == GDK_GRAVITY_STATIC)
3172 if (GTK_WIDGET_MAPPED (widget))
3174 /* This does a server round-trip, which is sort of wrong;
3175 * but a server round-trip is inevitable for
3176 * gdk_window_get_frame_extents() in the usual
3177 * NorthWestGravity case below, so not sure what else to
3178 * do. We should likely be consistent about whether we get
3179 * the client-side info or the server-side info.
3181 gdk_window_get_origin (widget->window, root_x, root_y);
3185 GdkRectangle configure_request;
3187 gtk_window_compute_configure_request (window,
3191 *root_x = configure_request.x;
3192 *root_y = configure_request.y;
3197 GdkRectangle frame_extents;
3202 if (GTK_WIDGET_MAPPED (widget))
3205 gdk_window_get_frame_extents (window->frame, &frame_extents);
3207 gdk_window_get_frame_extents (widget->window, &frame_extents);
3208 x = frame_extents.x;
3209 y = frame_extents.y;
3210 gtk_window_get_size (window, &w, &h);
3214 /* We just say the frame has 0 size on all sides.
3215 * Not sure what else to do.
3217 gtk_window_compute_configure_request (window,
3220 x = frame_extents.x;
3221 y = frame_extents.y;
3222 w = frame_extents.width;
3223 h = frame_extents.height;
3226 switch (window->gravity)
3228 case GDK_GRAVITY_NORTH:
3229 case GDK_GRAVITY_CENTER:
3230 case GDK_GRAVITY_SOUTH:
3231 /* Find center of frame. */
3232 x += frame_extents.width / 2;
3233 /* Center client window on that point. */
3237 case GDK_GRAVITY_SOUTH_EAST:
3238 case GDK_GRAVITY_EAST:
3239 case GDK_GRAVITY_NORTH_EAST:
3240 /* Find right edge of frame */
3241 x += frame_extents.width;
3242 /* Align left edge of client at that point. */
3249 switch (window->gravity)
3251 case GDK_GRAVITY_WEST:
3252 case GDK_GRAVITY_CENTER:
3253 case GDK_GRAVITY_EAST:
3254 /* Find center of frame. */
3255 y += frame_extents.height / 2;
3256 /* Center client window there. */
3259 case GDK_GRAVITY_SOUTH_WEST:
3260 case GDK_GRAVITY_SOUTH:
3261 case GDK_GRAVITY_SOUTH_EAST:
3262 /* Find south edge of frame */
3263 y += frame_extents.height;
3264 /* Place bottom edge of client there */
3279 * gtk_window_reshow_with_initial_size:
3280 * @window: a #GtkWindow
3282 * Hides @window, then reshows it, resetting the
3283 * default size and position of the window. Used
3284 * by GUI builders only.
3287 gtk_window_reshow_with_initial_size (GtkWindow *window)
3291 g_return_if_fail (GTK_IS_WINDOW (window));
3293 widget = GTK_WIDGET (window);
3295 gtk_widget_hide (widget);
3296 gtk_widget_unrealize (widget);
3297 gtk_widget_show (widget);
3301 gtk_window_destroy (GtkObject *object)
3303 GtkWindow *window = GTK_WINDOW (object);
3305 if (window->transient_parent)
3306 gtk_window_set_transient_for (window, NULL);
3308 /* frees the icons */
3309 gtk_window_set_icon_list (window, NULL);
3311 if (window->has_user_ref_count)
3313 window->has_user_ref_count = FALSE;
3314 g_object_unref (window);
3318 gtk_window_group_remove_window (window->group, window);
3320 gtk_window_free_key_hash (window);
3322 GTK_OBJECT_CLASS (parent_class)->destroy (object);
3326 gtk_window_mnemonic_hash_remove (gpointer key,
3330 GtkWindowMnemonic *mnemonic = key;
3331 GtkWindow *window = user;
3333 if (mnemonic->window == window)
3335 if (mnemonic->targets)
3337 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
3339 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
3340 name, mnemonic->targets->data);
3343 g_slist_free (mnemonic->targets);
3352 gtk_window_private_finalize (GtkWindowPrivate *priv)
3359 gtk_window_finalize (GObject *object)
3361 GtkWindow *window = GTK_WINDOW (object);
3363 toplevel_list = g_slist_remove (toplevel_list, window);
3365 g_free (window->title);
3366 g_free (window->wmclass_name);
3367 g_free (window->wmclass_class);
3368 g_free (window->wm_role);
3370 g_hash_table_foreach_remove (mnemonic_hash_table,
3371 gtk_window_mnemonic_hash_remove,
3373 if (window->geometry_info)
3375 if (window->geometry_info->widget)
3376 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3377 gtk_widget_destroyed,
3378 &window->geometry_info->widget);
3379 g_free (window->geometry_info);
3382 if (window->keys_changed_handler)
3384 gtk_idle_remove (window->keys_changed_handler);
3385 window->keys_changed_handler = 0;
3388 G_OBJECT_CLASS (parent_class)->finalize (object);
3392 gtk_window_show (GtkWidget *widget)
3394 GtkWindow *window = GTK_WINDOW (widget);
3395 GtkContainer *container = GTK_CONTAINER (window);
3396 gboolean need_resize;
3398 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3400 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3401 container->need_resize = FALSE;
3405 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3406 GtkAllocation allocation = { 0, 0 };
3407 GdkRectangle configure_request;
3408 GdkGeometry new_geometry;
3410 gboolean was_realized;
3412 /* We are going to go ahead and perform this configure request
3413 * and then emulate a configure notify by going ahead and
3414 * doing a size allocate. Sort of a synchronous
3415 * mini-copy of gtk_window_move_resize() here.
3417 gtk_window_compute_configure_request (window,
3422 /* We update this because we are going to go ahead
3423 * and gdk_window_resize() below, rather than
3426 info->last.configure_request.width = configure_request.width;
3427 info->last.configure_request.height = configure_request.height;
3429 /* and allocate the window - this is normally done
3430 * in move_resize in response to configure notify
3432 allocation.width = configure_request.width;
3433 allocation.height = configure_request.height;
3434 gtk_widget_size_allocate (widget, &allocation);
3436 /* Then we guarantee we have a realize */
3437 was_realized = FALSE;
3438 if (!GTK_WIDGET_REALIZED (widget))
3440 gtk_widget_realize (widget);
3441 was_realized = TRUE;
3444 /* Must be done after the windows are realized,
3445 * so that the decorations can be read
3447 gtk_decorated_window_calculate_frame_size (window);
3449 /* We only send configure request if we didn't just finish
3450 * creating the window; if we just created the window
3451 * then we created it with widget->allocation anyhow.
3454 gdk_window_resize (widget->window,
3455 configure_request.width,
3456 configure_request.height);
3459 gtk_container_check_resize (container);
3461 gtk_widget_map (widget);
3463 /* Try to make sure that we have some focused widget
3465 #ifdef GDK_WINDOWING_X11
3466 if (!window->focus_widget && !GTK_IS_PLUG (window))
3468 if (!window->focus_widget)
3470 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
3473 gtk_grab_add (widget);
3477 gtk_window_hide (GtkWidget *widget)
3479 GtkWindow *window = GTK_WINDOW (widget);
3481 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3482 gtk_widget_unmap (widget);
3485 gtk_grab_remove (widget);
3489 gtk_window_map (GtkWidget *widget)
3491 GtkWindow *window = GTK_WINDOW (widget);
3492 GdkWindow *toplevel;
3493 GtkWindowPrivate *priv;
3495 priv = gtk_window_get_private (window);
3497 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3499 if (window->bin.child &&
3500 GTK_WIDGET_VISIBLE (window->bin.child) &&
3501 !GTK_WIDGET_MAPPED (window->bin.child))
3502 gtk_widget_map (window->bin.child);
3505 toplevel = window->frame;
3507 toplevel = widget->window;
3509 if (window->maximize_initially)
3510 gdk_window_maximize (toplevel);
3512 gdk_window_unmaximize (toplevel);
3514 if (window->stick_initially)
3515 gdk_window_stick (toplevel);
3517 gdk_window_unstick (toplevel);
3519 if (window->iconify_initially)
3520 gdk_window_iconify (toplevel);
3522 gdk_window_deiconify (toplevel);
3524 if (priv->fullscreen_initially)
3525 gdk_window_fullscreen (toplevel);
3527 gdk_window_unfullscreen (toplevel);
3529 /* No longer use the default settings */
3530 window->need_default_size = FALSE;
3531 window->need_default_position = FALSE;
3533 gdk_window_show (widget->window);
3536 gdk_window_show (window->frame);
3540 gtk_window_unmap (GtkWidget *widget)
3542 GtkWindow *window = GTK_WINDOW (widget);
3543 GtkWindowGeometryInfo *info;
3544 GdkWindowState state;
3546 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3548 gdk_window_withdraw (window->frame);
3550 gdk_window_withdraw (widget->window);
3552 window->configure_request_count = 0;
3553 window->configure_notify_received = FALSE;
3555 /* on unmap, we reset the default positioning of the window,
3556 * so it's placed again, but we don't reset the default
3557 * size of the window, so it's remembered.
3559 window->need_default_position = TRUE;
3561 info = gtk_window_get_geometry_info (window, FALSE);
3564 info->initial_pos_set = FALSE;
3565 info->position_constraints_changed = FALSE;
3568 state = gdk_window_get_state (widget->window);
3569 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
3570 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
3571 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
3575 gtk_window_realize (GtkWidget *widget)
3578 GdkWindow *parent_window;
3579 GdkWindowAttr attributes;
3580 gint attributes_mask;
3582 window = GTK_WINDOW (widget);
3584 /* ensure widget tree is properly size allocated */
3585 if (widget->allocation.x == -1 &&
3586 widget->allocation.y == -1 &&
3587 widget->allocation.width == 1 &&
3588 widget->allocation.height == 1)
3590 GtkRequisition requisition;
3591 GtkAllocation allocation = { 0, 0, 200, 200 };
3593 gtk_widget_size_request (widget, &requisition);
3594 if (requisition.width || requisition.height)
3596 /* non-empty window */
3597 allocation.width = requisition.width;
3598 allocation.height = requisition.height;
3600 gtk_widget_size_allocate (widget, &allocation);
3602 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3604 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3607 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3609 switch (window->type)
3611 case GTK_WINDOW_TOPLEVEL:
3612 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3614 case GTK_WINDOW_POPUP:
3615 attributes.window_type = GDK_WINDOW_TEMP;
3618 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3622 attributes.title = window->title;
3623 attributes.wmclass_name = window->wmclass_name;
3624 attributes.wmclass_class = window->wmclass_class;
3625 attributes.wclass = GDK_INPUT_OUTPUT;
3626 attributes.visual = gtk_widget_get_visual (widget);
3627 attributes.colormap = gtk_widget_get_colormap (widget);
3629 if (window->has_frame)
3631 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3632 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3633 attributes.event_mask = (GDK_EXPOSURE_MASK |
3634 GDK_KEY_PRESS_MASK |
3635 GDK_ENTER_NOTIFY_MASK |
3636 GDK_LEAVE_NOTIFY_MASK |
3637 GDK_FOCUS_CHANGE_MASK |
3638 GDK_STRUCTURE_MASK |
3639 GDK_BUTTON_MOTION_MASK |
3640 GDK_POINTER_MOTION_HINT_MASK |
3641 GDK_BUTTON_PRESS_MASK |
3642 GDK_BUTTON_RELEASE_MASK);
3644 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3646 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
3647 &attributes, attributes_mask);
3649 gdk_window_set_user_data (window->frame, widget);
3651 attributes.window_type = GDK_WINDOW_CHILD;
3652 attributes.x = window->frame_left;
3653 attributes.y = window->frame_top;
3655 attributes_mask = GDK_WA_X | GDK_WA_Y;
3657 parent_window = window->frame;
3661 attributes_mask = 0;
3662 parent_window = gtk_widget_get_root_window (widget);
3665 attributes.width = widget->allocation.width;
3666 attributes.height = widget->allocation.height;
3667 attributes.event_mask = gtk_widget_get_events (widget);
3668 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3669 GDK_KEY_PRESS_MASK |
3670 GDK_KEY_RELEASE_MASK |
3671 GDK_ENTER_NOTIFY_MASK |
3672 GDK_LEAVE_NOTIFY_MASK |
3673 GDK_FOCUS_CHANGE_MASK |
3674 GDK_STRUCTURE_MASK);
3676 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3677 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3678 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3680 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3682 gdk_window_set_user_data (widget->window, window);
3684 widget->style = gtk_style_attach (widget->style, widget->window);
3685 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3687 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3689 /* This is a bad hack to set the window background. */
3690 gtk_window_paint (widget, NULL);
3692 if (window->transient_parent &&
3693 GTK_WIDGET_REALIZED (window->transient_parent))
3694 gdk_window_set_transient_for (widget->window,
3695 GTK_WIDGET (window->transient_parent)->window);
3697 if (window->wm_role)
3698 gdk_window_set_role (widget->window, window->wm_role);
3700 if (!window->decorated)
3701 gdk_window_set_decorations (widget->window, 0);
3703 gdk_window_set_type_hint (widget->window, window->type_hint);
3705 if (gtk_window_get_skip_pager_hint (window))
3706 gdk_window_set_skip_pager_hint (widget->window, TRUE);
3708 if (gtk_window_get_skip_taskbar_hint (window))
3709 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
3711 /* transient_for must be set to allow the modal hint */
3712 if (window->transient_parent && window->modal)
3713 gdk_window_set_modal_hint (widget->window, TRUE);
3715 gdk_window_set_modal_hint (widget->window, FALSE);
3718 gtk_window_realize_icon (window);
3722 gtk_window_unrealize (GtkWidget *widget)
3725 GtkWindowGeometryInfo *info;
3727 window = GTK_WINDOW (widget);
3729 /* On unrealize, we reset the size of the window such
3730 * that we will re-apply the default sizing stuff
3731 * next time we show the window.
3733 * Default positioning is reset on unmap, instead of unrealize.
3735 window->need_default_size = TRUE;
3736 info = gtk_window_get_geometry_info (window, FALSE);
3739 info->resize_width = -1;
3740 info->resize_height = -1;
3741 info->last.configure_request.x = 0;
3742 info->last.configure_request.y = 0;
3743 info->last.configure_request.width = -1;
3744 info->last.configure_request.height = -1;
3745 /* be sure we reset geom hints on re-realize */
3746 info->last.flags = 0;
3751 gdk_window_set_user_data (window->frame, NULL);
3752 gdk_window_destroy (window->frame);
3753 window->frame = NULL;
3757 gtk_window_unrealize_icon (window);
3759 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3763 gtk_window_size_request (GtkWidget *widget,
3764 GtkRequisition *requisition)
3769 window = GTK_WINDOW (widget);
3770 bin = GTK_BIN (window);
3772 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3773 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3775 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3777 GtkRequisition child_requisition;
3779 gtk_widget_size_request (bin->child, &child_requisition);
3781 requisition->width += child_requisition.width;
3782 requisition->height += child_requisition.height;
3787 gtk_window_size_allocate (GtkWidget *widget,
3788 GtkAllocation *allocation)
3791 GtkAllocation child_allocation;
3793 window = GTK_WINDOW (widget);
3794 widget->allocation = *allocation;
3796 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3798 child_allocation.x = GTK_CONTAINER (window)->border_width;
3799 child_allocation.y = GTK_CONTAINER (window)->border_width;
3800 child_allocation.width =
3801 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3802 child_allocation.height =
3803 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3805 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3808 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3810 gdk_window_resize (window->frame,
3811 allocation->width + window->frame_left + window->frame_right,
3812 allocation->height + window->frame_top + window->frame_bottom);
3817 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3820 gboolean return_val;
3822 window = GTK_WINDOW (widget);
3824 if (window->frame && (event->any.window == window->frame))
3826 if ((event->type != GDK_KEY_PRESS) &&
3827 (event->type != GDK_KEY_RELEASE) &&
3828 (event->type != GDK_FOCUS_CHANGE))
3830 g_signal_stop_emission_by_name (widget, "event");
3832 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
3837 g_object_unref (event->any.window);
3838 event->any.window = g_object_ref (widget->window);
3846 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3848 GdkEventConfigure *configure_event;
3851 switch (event->type)
3854 configure_event = (GdkEventConfigure *)event;
3856 /* Invalidate the decorations */
3859 rect.width = configure_event->width;
3860 rect.height = configure_event->height;
3862 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3864 /* Pass on the (modified) configure event */
3865 configure_event->width -= window->frame_left + window->frame_right;
3866 configure_event->height -= window->frame_top + window->frame_bottom;
3867 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3876 gtk_window_configure_event (GtkWidget *widget,
3877 GdkEventConfigure *event)
3879 GtkWindow *window = GTK_WINDOW (widget);
3880 gboolean expected_reply = window->configure_request_count > 0;
3882 /* window->configure_request_count incremented for each
3883 * configure request, and decremented to a min of 0 for
3884 * each configure notify.
3886 * All it means is that we know we will get at least
3887 * window->configure_request_count more configure notifies.
3888 * We could get more configure notifies than that; some
3889 * of the configure notifies we get may be unrelated to
3890 * the configure requests. But we will get at least
3891 * window->configure_request_count notifies.
3894 if (window->configure_request_count > 0)
3895 window->configure_request_count -= 1;
3897 /* As an optimization, we avoid a resize when possible.
3899 * The only times we can avoid a resize are:
3900 * - we know only the position changed, not the size
3901 * - we know we have made more requests and so will get more
3902 * notifies and can wait to resize when we get them
3905 if (!expected_reply &&
3906 (widget->allocation.width == event->width &&
3907 widget->allocation.height == event->height))
3911 * If we do need to resize, we do that by:
3912 * - filling in widget->allocation with the new size
3913 * - setting configure_notify_received to TRUE
3914 * for use in gtk_window_move_resize()
3915 * - queueing a resize, leading to invocation of
3916 * gtk_window_move_resize() in an idle handler
3920 window->configure_notify_received = TRUE;
3922 widget->allocation.width = event->width;
3923 widget->allocation.height = event->height;
3925 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3930 /* the accel_key and accel_mods fields of the key have to be setup
3931 * upon calling this function. it'll then return whether that key
3932 * is at all used as accelerator, and if so will OR in the
3933 * accel_flags member of the key.
3936 _gtk_window_query_nonaccels (GtkWindow *window,
3938 GdkModifierType accel_mods)
3940 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3942 /* movement keys are considered locked accels */
3945 static const guint bindings[] = {
3946 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
3947 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
3951 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
3952 if (bindings[i] == accel_key)
3956 /* mnemonics are considered locked accels */
3957 if (accel_mods == window->mnemonic_modifier)
3959 GtkWindowMnemonic mkey;
3961 mkey.window = window;
3962 mkey.keyval = accel_key;
3963 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
3971 gtk_window_key_press_event (GtkWidget *widget,
3978 window = GTK_WINDOW (widget);
3982 /* Check for mnemonics and accelerators
3985 handled = _gtk_window_activate_key (window, event);
3989 focus = window->focus_widget;
3991 g_object_ref (focus);
3994 focus && focus != widget &&
3995 gtk_widget_get_toplevel (focus) == widget)
3999 if (GTK_WIDGET_IS_SENSITIVE (focus))
4000 handled = gtk_widget_event (focus, (GdkEvent*) event);
4002 parent = focus->parent;
4004 g_object_ref (parent);
4006 g_object_unref (focus);
4012 g_object_unref (focus);
4015 /* Chain up, invokes binding set */
4016 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
4017 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4023 gtk_window_key_release_event (GtkWidget *widget,
4029 window = GTK_WINDOW (widget);
4031 if (window->focus_widget &&
4032 window->focus_widget != widget &&
4033 GTK_WIDGET_SENSITIVE (window->focus_widget))
4035 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
4038 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
4039 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
4045 gtk_window_real_activate_default (GtkWindow *window)
4047 gtk_window_activate_default (window);
4051 gtk_window_real_activate_focus (GtkWindow *window)
4053 gtk_window_activate_focus (window);
4057 gtk_window_move_focus (GtkWindow *window,
4058 GtkDirectionType dir)
4060 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4062 if (!GTK_CONTAINER (window)->focus_child)
4063 gtk_window_set_focus (window, NULL);
4067 gtk_window_enter_notify_event (GtkWidget *widget,
4068 GdkEventCrossing *event)
4074 gtk_window_leave_notify_event (GtkWidget *widget,
4075 GdkEventCrossing *event)
4081 do_focus_change (GtkWidget *widget,
4084 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4086 g_object_ref (widget);
4089 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4091 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4093 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4094 fevent->focus_change.window = g_object_ref (widget->window);
4095 fevent->focus_change.in = in;
4097 gtk_widget_event (widget, fevent);
4099 g_object_notify (G_OBJECT (widget), "has_focus");
4101 g_object_unref (widget);
4102 gdk_event_free (fevent);
4106 gtk_window_focus_in_event (GtkWidget *widget,
4107 GdkEventFocus *event)
4109 GtkWindow *window = GTK_WINDOW (widget);
4111 /* It appears spurious focus in events can occur when
4112 * the window is hidden. So we'll just check to see if
4113 * the window is visible before actually handling the
4116 if (GTK_WIDGET_VISIBLE (widget))
4118 _gtk_window_set_has_toplevel_focus (window, TRUE);
4119 _gtk_window_set_is_active (window, TRUE);
4126 gtk_window_focus_out_event (GtkWidget *widget,
4127 GdkEventFocus *event)
4129 GtkWindow *window = GTK_WINDOW (widget);
4131 _gtk_window_set_has_toplevel_focus (window, FALSE);
4132 _gtk_window_set_is_active (window, FALSE);
4137 static GdkAtom atom_rcfiles = GDK_NONE;
4140 gtk_window_read_rcfiles (GtkWidget *widget,
4141 GdkEventClient *event)
4143 GList *embedded_windows;
4145 embedded_windows = g_object_get_data (G_OBJECT (widget), "gtk-embedded");
4146 if (embedded_windows)
4148 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4151 for (i = 0; i < 5; i++)
4152 send_event->client.data.l[i] = 0;
4153 send_event->client.data_format = 32;
4154 send_event->client.message_type = atom_rcfiles;
4156 while (embedded_windows)
4158 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4159 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4160 embedded_windows = embedded_windows->next;
4163 gdk_event_free (send_event);
4166 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4170 gtk_window_client_event (GtkWidget *widget,
4171 GdkEventClient *event)
4174 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
4176 if (event->message_type == atom_rcfiles)
4177 gtk_window_read_rcfiles (widget, event);
4183 gtk_window_check_resize (GtkContainer *container)
4185 GtkWindow *window = GTK_WINDOW (container);
4187 if (GTK_WIDGET_VISIBLE (container))
4188 gtk_window_move_resize (window);
4192 gtk_window_focus (GtkWidget *widget,
4193 GtkDirectionType direction)
4197 GtkContainer *container;
4198 GtkWidget *old_focus_child;
4201 container = GTK_CONTAINER (widget);
4202 window = GTK_WINDOW (widget);
4203 bin = GTK_BIN (widget);
4205 old_focus_child = container->focus_child;
4207 /* We need a special implementation here to deal properly with wrapping
4208 * around in the tab chain without the danger of going into an
4211 if (old_focus_child)
4213 if (gtk_widget_child_focus (old_focus_child, direction))
4217 if (window->focus_widget)
4219 /* Wrapped off the end, clear the focus setting for the toplpevel */
4220 parent = window->focus_widget->parent;
4223 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4224 parent = GTK_WIDGET (parent)->parent;
4227 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4230 /* Now try to focus the first widget in the window */
4233 if (gtk_widget_child_focus (bin->child, direction))
4241 gtk_window_real_set_focus (GtkWindow *window,
4244 GtkWidget *old_focus = window->focus_widget;
4245 gboolean def_flags = 0;
4249 g_object_ref (old_focus);
4250 g_object_freeze_notify (G_OBJECT (old_focus));
4254 g_object_ref (focus);
4255 g_object_freeze_notify (G_OBJECT (focus));
4258 if (window->default_widget)
4259 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4261 if (window->focus_widget)
4263 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4264 (window->focus_widget != window->default_widget))
4266 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4268 if (window->default_widget)
4269 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4272 if (window->has_focus)
4273 do_focus_change (window->focus_widget, FALSE);
4275 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4278 window->focus_widget = focus;
4280 if (window->focus_widget)
4282 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4283 (window->focus_widget != window->default_widget))
4285 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4286 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4288 if (window->default_widget)
4289 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4292 if (window->has_focus)
4293 do_focus_change (window->focus_widget, TRUE);
4295 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4298 if (window->default_widget &&
4299 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
4300 gtk_widget_queue_draw (window->default_widget);
4304 g_object_thaw_notify (G_OBJECT (old_focus));
4305 g_object_unref (old_focus);
4309 g_object_thaw_notify (G_OBJECT (focus));
4310 g_object_unref (focus);
4314 /*********************************
4315 * Functions related to resizing *
4316 *********************************/
4318 /* This function doesn't constrain to geometry hints */
4320 gtk_window_compute_configure_request_size (GtkWindow *window,
4324 GtkRequisition requisition;
4325 GtkWindowGeometryInfo *info;
4329 * - we've done a size request
4332 widget = GTK_WIDGET (window);
4334 info = gtk_window_get_geometry_info (window, FALSE);
4336 if (window->need_default_size)
4338 gtk_widget_get_child_requisition (widget, &requisition);
4340 /* Default to requisition */
4341 *width = requisition.width;
4342 *height = requisition.height;
4344 /* If window is empty so requests 0, default to random nonzero size */
4345 if (*width == 0 && *height == 0)
4351 /* Override requisition with default size */
4355 gint base_width = 0;
4356 gint base_height = 0;
4358 gint height_inc = 1;
4360 if (info->default_is_geometry &&
4361 (info->default_width > 0 || info->default_height > 0))
4363 GdkGeometry geometry;
4366 gtk_window_compute_hints (window, &geometry, &flags);
4368 if (flags & GDK_HINT_BASE_SIZE)
4370 base_width = geometry.base_width;
4371 base_height = geometry.base_height;
4373 else if (flags & GDK_HINT_MIN_SIZE)
4375 base_width = geometry.min_width;
4376 base_height = geometry.min_height;
4378 if (flags & GDK_HINT_RESIZE_INC)
4380 width_inc = geometry.width_inc;
4381 height_inc = geometry.height_inc;
4385 if (info->default_width > 0)
4386 *width = info->default_width * width_inc + base_width;
4388 if (info->default_height > 0)
4389 *height = info->default_height * height_inc + base_height;
4394 /* Default to keeping current size */
4395 *width = widget->allocation.width;
4396 *height = widget->allocation.height;
4399 /* Override any size with gtk_window_resize() values */
4402 if (info->resize_width > 0)
4403 *width = info->resize_width;
4405 if (info->resize_height > 0)
4406 *height = info->resize_height;
4410 static GtkWindowPosition
4411 get_effective_position (GtkWindow *window)
4413 GtkWindowPosition pos = window->position;
4414 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
4415 (window->transient_parent == NULL ||
4416 !GTK_WIDGET_MAPPED (window->transient_parent)))
4417 pos = GTK_WIN_POS_NONE;
4423 gtk_window_compute_configure_request (GtkWindow *window,
4424 GdkRectangle *request,
4425 GdkGeometry *geometry,
4428 GdkGeometry new_geometry;
4432 GtkWindowPosition pos;
4433 GtkWidget *parent_widget;
4434 GtkWindowGeometryInfo *info;
4437 widget = GTK_WIDGET (window);
4439 gtk_widget_size_request (widget, NULL);
4440 gtk_window_compute_configure_request_size (window, &w, &h);
4442 gtk_window_compute_hints (window, &new_geometry, &new_flags);
4443 gtk_window_constrain_size (window,
4444 &new_geometry, new_flags,
4448 parent_widget = (GtkWidget*) window->transient_parent;
4450 pos = get_effective_position (window);
4451 info = gtk_window_get_geometry_info (window, TRUE);
4453 /* by default, don't change position requested */
4454 x = info->last.configure_request.x;
4455 y = info->last.configure_request.y;
4457 if (window->need_default_position)
4460 /* FIXME this all interrelates with window gravity.
4461 * For most of them I think we want to set GRAVITY_CENTER.
4463 * Not sure how to go about that.
4468 /* here we are only handling CENTER_ALWAYS
4469 * as it relates to default positioning,
4470 * where it's equivalent to simply CENTER
4472 case GTK_WIN_POS_CENTER_ALWAYS:
4473 case GTK_WIN_POS_CENTER:
4475 gint px, py, monitor_num;
4476 GdkRectangle monitor;
4478 gdk_window_get_pointer (gdk_screen_get_root_window (window->screen),
4481 monitor_num = gdk_screen_get_monitor_at_point (window->screen, px, py);
4482 if (monitor_num == -1)
4485 gdk_screen_get_monitor_geometry (window->screen, monitor_num, &monitor);
4487 x = (monitor.width - w) / 2 + monitor.x;
4488 y = (monitor.height - h) / 2 + monitor.y;
4492 case GTK_WIN_POS_CENTER_ON_PARENT:
4496 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
4498 gdk_window_get_origin (parent_widget->window,
4501 x = ox + (parent_widget->allocation.width - w) / 2;
4502 y = oy + (parent_widget->allocation.height - h) / 2;
4506 case GTK_WIN_POS_MOUSE:
4508 gint screen_width = gdk_screen_get_width (window->screen);
4509 gint screen_height = gdk_screen_get_height (window->screen);
4512 gdk_window_get_pointer (gdk_screen_get_root_window (window->screen),
4516 x = CLAMP (x, 0, screen_width - w);
4517 y = CLAMP (y, 0, screen_height - h);
4524 } /* if (window->need_default_position) */
4526 if (window->need_default_position &&
4527 info->initial_pos_set)
4529 x = info->initial_x;
4530 y = info->initial_y;
4531 gtk_window_constrain_position (window, w, h, &x, &y);
4537 request->height = h;
4540 *geometry = new_geometry;
4546 gtk_window_constrain_position (GtkWindow *window,
4552 /* See long comments in gtk_window_move_resize()
4553 * on when it's safe to call this function.
4555 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4557 gint center_x, center_y;
4558 gint screen_width = gdk_screen_get_width (window->screen);
4559 gint screen_height = gdk_screen_get_height (window->screen);
4561 center_x = (screen_width - new_width) / 2;
4562 center_y = (screen_height - new_height) / 2;
4570 gtk_window_move_resize (GtkWindow *window)
4574 * First we determine whether any information has changed that would
4575 * cause us to revise our last configure request. If we would send
4576 * a different configure request from last time, then
4577 * configure_request_size_changed = TRUE or
4578 * configure_request_pos_changed = TRUE. configure_request_size_changed
4579 * may be true due to new hints, a gtk_window_resize(), or whatever.
4580 * configure_request_pos_changed may be true due to gtk_window_set_position()
4581 * or gtk_window_move().
4583 * If the configure request has changed, we send off a new one. To
4584 * ensure GTK+ invariants are maintained (resize queue does what it
4585 * should), we go ahead and size_allocate the requested size in this
4588 * If the configure request has not changed, we don't ever resend
4589 * it, because it could mean fighting the user or window manager.
4592 * To prepare the configure request, we come up with a base size/pos:
4593 * - the one from gtk_window_move()/gtk_window_resize()
4594 * - else default_width, default_height if we haven't ever
4596 * - else the size request if we haven't ever been mapped,
4597 * as a substitute default size
4598 * - else the current size of the window, as received from
4599 * configure notifies (i.e. the current allocation)
4601 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4602 * the position request to be centered.
4605 GtkContainer *container;
4606 GtkWindowGeometryInfo *info;
4607 GdkGeometry new_geometry;
4609 GdkRectangle new_request;
4610 gboolean configure_request_size_changed;
4611 gboolean configure_request_pos_changed;
4612 gboolean hints_changed; /* do we need to send these again */
4613 GtkWindowLastGeometryInfo saved_last_info;
4615 widget = GTK_WIDGET (window);
4616 container = GTK_CONTAINER (widget);
4617 info = gtk_window_get_geometry_info (window, TRUE);
4619 configure_request_size_changed = FALSE;
4620 configure_request_pos_changed = FALSE;
4622 gtk_window_compute_configure_request (window, &new_request,
4623 &new_geometry, &new_flags);
4625 /* This check implies the invariant that we never set info->last
4626 * without setting the hints and sending off a configure request.
4628 * If we change info->last without sending the request, we may
4631 if (info->last.configure_request.x != new_request.x ||
4632 info->last.configure_request.y != new_request.y)
4633 configure_request_pos_changed = TRUE;
4635 if ((info->last.configure_request.width != new_request.width ||
4636 info->last.configure_request.height != new_request.height))
4637 configure_request_size_changed = TRUE;
4639 hints_changed = FALSE;
4641 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4642 &new_geometry, new_flags))
4644 hints_changed = TRUE;
4647 /* Position Constraints
4648 * ====================
4650 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4651 * a default. The other POS_ values are used only when the
4652 * window is shown, not after that.
4654 * However, we can't implement a position constraint as
4655 * "anytime the window size changes, center the window"
4656 * because this may well end up fighting the WM or user. In
4657 * fact it gets in an infinite loop with at least one WM.
4659 * Basically, applications are in no way in a position to
4660 * constrain the position of a window, with one exception:
4661 * override redirect windows. (Really the intended purpose
4662 * of CENTER_ALWAYS anyhow, I would think.)
4664 * So the way we implement this "constraint" is to say that when WE
4665 * cause a move or resize, i.e. we make a configure request changing
4666 * window size, we recompute the CENTER_ALWAYS position to reflect
4667 * the new window size, and include it in our request. Also, if we
4668 * just turned on CENTER_ALWAYS we snap to center with a new
4669 * request. Otherwise, if we are just NOTIFIED of a move or resize
4670 * done by someone else e.g. the window manager, we do NOT send a
4671 * new configure request.
4673 * For override redirect windows, this works fine; all window
4674 * sizes are from our configure requests. For managed windows,
4675 * it is at least semi-sane, though who knows what the
4676 * app author is thinking.
4679 /* This condition should be kept in sync with the condition later on
4680 * that determines whether we send a configure request. i.e. we
4681 * should do this position constraining anytime we were going to
4682 * send a configure request anyhow, plus when constraints have
4685 if (configure_request_pos_changed ||
4686 configure_request_size_changed ||
4688 info->position_constraints_changed)
4690 /* We request the constrained position if:
4691 * - we were changing position, and need to clamp
4692 * the change to the constraint
4693 * - we're changing the size anyway
4694 * - set_position() was called to toggle CENTER_ALWAYS on
4697 gtk_window_constrain_position (window,
4703 /* Update whether we need to request a move */
4704 if (info->last.configure_request.x != new_request.x ||
4705 info->last.configure_request.y != new_request.y)
4706 configure_request_pos_changed = TRUE;
4708 configure_request_pos_changed = FALSE;
4712 if (window->type == GTK_WINDOW_TOPLEVEL)
4714 int notify_x, notify_y;
4716 /* this is the position from the last configure notify */
4717 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4719 g_message ("--- %s ---\n"
4720 "last : %d,%d\t%d x %d\n"
4721 "this : %d,%d\t%d x %d\n"
4722 "alloc : %d,%d\t%d x %d\n"
4724 "resize: \t%d x %d\n"
4725 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4726 "configure_notify_received: %d\n"
4727 "configure_request_count: %d\n"
4728 "position_constraints_changed: %d\n",
4729 window->title ? window->title : "(no title)",
4730 info->last.configure_request.x,
4731 info->last.configure_request.y,
4732 info->last.configure_request.width,
4733 info->last.configure_request.height,
4739 widget->allocation.width,
4740 widget->allocation.height,
4741 widget->requisition.width,
4742 widget->requisition.height,
4744 info->resize_height,
4745 configure_request_pos_changed,
4746 configure_request_size_changed,
4748 window->configure_notify_received,
4749 window->configure_request_count,
4750 info->position_constraints_changed);
4754 saved_last_info = info->last;
4755 info->last.geometry = new_geometry;
4756 info->last.flags = new_flags;
4757 info->last.configure_request = new_request;
4759 /* need to set PPosition so the WM will look at our position,
4760 * but we don't want to count PPosition coming and going as a hints
4761 * change for future iterations. So we saved info->last prior to
4765 /* Also, if the initial position was explicitly set, then we always
4766 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4770 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4771 * this is an initial map
4774 if ((configure_request_pos_changed ||
4775 info->initial_pos_set ||
4776 (window->need_default_position &&
4777 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
4778 (new_flags & GDK_HINT_POS) == 0)
4780 new_flags |= GDK_HINT_POS;
4781 hints_changed = TRUE;
4784 /* Set hints if necessary
4787 gdk_window_set_geometry_hints (widget->window,
4791 /* handle resizing/moving and widget tree allocation
4793 if (window->configure_notify_received)
4795 GtkAllocation allocation;
4797 /* If we have received a configure event since
4798 * the last time in this function, we need to
4799 * accept our new size and size_allocate child widgets.
4800 * (see gtk_window_configure_event() for more details).
4802 * 1 or more configure notifies may have been received.
4803 * Also, configure_notify_received will only be TRUE
4804 * if all expected configure notifies have been received
4805 * (one per configure request), as an optimization.
4808 window->configure_notify_received = FALSE;
4810 /* gtk_window_configure_event() filled in widget->allocation */
4811 allocation = widget->allocation;
4812 gtk_widget_size_allocate (widget, &allocation);
4814 /* If the configure request changed, it means that
4816 * 1) coincidentally changed hints or widget properties
4817 * impacting the configure request before getting
4818 * a configure notify, or
4819 * 2) some broken widget is changing its size request
4820 * during size allocation, resulting in
4821 * a false appearance of changed configure request.
4823 * For 1), we could just go ahead and ask for the
4824 * new size right now, but doing that for 2)
4825 * might well be fighting the user (and can even
4826 * trigger a loop). Since we really don't want to
4827 * do that, we requeue a resize in hopes that
4828 * by the time it gets handled, the child has seen
4829 * the light and is willing to go along with the
4830 * new size. (this happens for the zvt widget, since
4831 * the size_allocate() above will have stored the
4832 * requisition corresponding to the new size in the
4835 * This doesn't buy us anything for 1), but it shouldn't
4836 * hurt us too badly, since it is what would have
4837 * happened if we had gotten the configure event before
4838 * the new size had been set.
4841 if (configure_request_size_changed ||
4842 configure_request_pos_changed)
4844 /* Don't change the recorded last info after all, because we
4845 * haven't actually updated to the new info yet - we decided
4846 * to postpone our configure request until later.
4848 info->last = saved_last_info;
4850 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
4853 return; /* Bail out, we didn't really process the move/resize */
4855 else if ((configure_request_size_changed || hints_changed) &&
4856 (widget->allocation.width != new_request.width ||
4857 widget->allocation.height != new_request.height))
4860 /* We are in one of the following situations:
4861 * A. configure_request_size_changed
4862 * our requisition has changed and we need a different window size,
4863 * so we request it from the window manager.
4864 * B. !configure_request_size_changed && hints_changed
4865 * the window manager rejects our size, but we have just changed the
4866 * window manager hints, so there's a chance our request will
4867 * be honoured this time, so we try again.
4869 * However, if the new requisition is the same as the current allocation,
4870 * we don't request it again, since we won't get a ConfigureNotify back from
4871 * the window manager unless it decides to change our requisition. If
4872 * we don't get the ConfigureNotify back, the resize queue will never be run.
4875 /* Now send the configure request */
4876 if (configure_request_pos_changed)
4880 gdk_window_move_resize (window->frame,
4881 new_request.x - window->frame_left,
4882 new_request.y - window->frame_top,
4883 new_request.width + window->frame_left + window->frame_right,
4884 new_request.height + window->frame_top + window->frame_bottom);
4885 gdk_window_resize (widget->window,
4886 new_request.width, new_request.height);
4890 gdk_window_move_resize (widget->window,
4891 new_request.x, new_request.y,
4892 new_request.width, new_request.height);
4894 else /* only size changed */
4897 gdk_window_resize (window->frame,
4898 new_request.width + window->frame_left + window->frame_right,
4899 new_request.height + window->frame_top + window->frame_bottom);
4901 gdk_window_resize (widget->window,
4902 new_request.width, new_request.height);
4905 /* Increment the number of have-not-yet-received-notify requests */
4906 window->configure_request_count += 1;
4908 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
4909 * configure event in response to our resizing request.
4910 * the configure event will cause a new resize with
4911 * ->configure_notify_received=TRUE.
4912 * until then, we want to
4913 * - discard expose events
4914 * - coalesce resizes for our children
4915 * - defer any window resizes until the configure event arrived
4916 * to achieve this, we queue a resize for the window, but remove its
4917 * resizing handler, so resizing will not be handled from the next
4918 * idle handler but when the configure event arrives.
4920 * FIXME: we should also dequeue the pending redraws here, since
4921 * we handle those ourselves upon ->configure_notify_received==TRUE.
4923 if (container->resize_mode == GTK_RESIZE_QUEUE)
4925 gtk_widget_queue_resize (widget);
4926 _gtk_container_dequeue_resize_handler (container);
4931 /* Handle any position changes.
4933 if (configure_request_pos_changed)
4937 gdk_window_move (window->frame,
4938 new_request.x - window->frame_left,
4939 new_request.y - window->frame_top);
4942 gdk_window_move (widget->window,
4943 new_request.x, new_request.y);
4946 /* And run the resize queue.
4948 gtk_container_resize_children (container);
4951 /* We have now processed a move/resize since the last position
4952 * constraint change, setting of the initial position, or resize.
4953 * (Not resetting these flags here can lead to infinite loops for
4954 * GTK_RESIZE_IMMEDIATE containers)
4956 info->position_constraints_changed = FALSE;
4957 info->initial_pos_set = FALSE;
4958 info->resize_width = -1;
4959 info->resize_height = -1;
4962 /* Compare two sets of Geometry hints for equality.
4965 gtk_window_compare_hints (GdkGeometry *geometry_a,
4967 GdkGeometry *geometry_b,
4970 if (flags_a != flags_b)
4973 if ((flags_a & GDK_HINT_MIN_SIZE) &&
4974 (geometry_a->min_width != geometry_b->min_width ||
4975 geometry_a->min_height != geometry_b->min_height))
4978 if ((flags_a & GDK_HINT_MAX_SIZE) &&
4979 (geometry_a->max_width != geometry_b->max_width ||
4980 geometry_a->max_height != geometry_b->max_height))
4983 if ((flags_a & GDK_HINT_BASE_SIZE) &&
4984 (geometry_a->base_width != geometry_b->base_width ||
4985 geometry_a->base_height != geometry_b->base_height))
4988 if ((flags_a & GDK_HINT_ASPECT) &&
4989 (geometry_a->min_aspect != geometry_b->min_aspect ||
4990 geometry_a->max_aspect != geometry_b->max_aspect))
4993 if ((flags_a & GDK_HINT_RESIZE_INC) &&
4994 (geometry_a->width_inc != geometry_b->width_inc ||
4995 geometry_a->height_inc != geometry_b->height_inc))
4998 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
4999 geometry_a->win_gravity != geometry_b->win_gravity)
5006 _gtk_window_constrain_size (GtkWindow *window,
5012 GtkWindowGeometryInfo *info;
5014 g_return_if_fail (GTK_IS_WINDOW (window));
5016 info = window->geometry_info;
5019 GdkWindowHints flags = info->last.flags;
5020 GdkGeometry *geometry = &info->last.geometry;
5022 gtk_window_constrain_size (window,
5033 gtk_window_constrain_size (GtkWindow *window,
5034 GdkGeometry *geometry,
5041 gdk_window_constrain_size (geometry, flags, width, height,
5042 new_width, new_height);
5045 /* Compute the set of geometry hints and flags for a window
5046 * based on the application set geometry, and requisiition
5047 * of the window. gtk_widget_size_request() must have been
5051 gtk_window_compute_hints (GtkWindow *window,
5052 GdkGeometry *new_geometry,
5056 gint extra_width = 0;
5057 gint extra_height = 0;
5058 GtkWindowGeometryInfo *geometry_info;
5059 GtkRequisition requisition;
5061 widget = GTK_WIDGET (window);
5063 gtk_widget_get_child_requisition (widget, &requisition);
5064 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5068 *new_flags = geometry_info->mask;
5069 *new_geometry = geometry_info->geometry;
5076 if (geometry_info && geometry_info->widget)
5078 GtkRequisition child_requisition;
5080 /* FIXME: This really isn't right. It gets the min size wrong and forces
5081 * callers to do horrible hacks like set a huge usize on the child requisition
5082 * to get the base size right. We really want to find the answers to:
5084 * - If the geometry widget was infinitely big, how much extra space
5085 * would be needed for the stuff around it.
5087 * - If the geometry widget was infinitely small, how big would the
5088 * window still have to be.
5090 * Finding these answers would be a bit of a mess here. (Bug #68668)
5092 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5094 extra_width = widget->requisition.width - child_requisition.width;
5095 extra_height = widget->requisition.height - child_requisition.height;
5098 /* We don't want to set GDK_HINT_POS in here, we just set it
5099 * in gtk_window_move_resize() when we want the position
5103 if (*new_flags & GDK_HINT_BASE_SIZE)
5105 new_geometry->base_width += extra_width;
5106 new_geometry->base_height += extra_height;
5108 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5109 (*new_flags & GDK_HINT_RESIZE_INC) &&
5110 ((extra_width != 0) || (extra_height != 0)))
5112 *new_flags |= GDK_HINT_BASE_SIZE;
5114 new_geometry->base_width = extra_width;
5115 new_geometry->base_height = extra_height;
5118 if (*new_flags & GDK_HINT_MIN_SIZE)
5120 if (new_geometry->min_width < 0)
5121 new_geometry->min_width = requisition.width;
5123 new_geometry->min_width += extra_width;
5125 if (new_geometry->min_height < 0)
5126 new_geometry->min_height = requisition.height;
5128 new_geometry->min_height += extra_height;
5130 else if (!window->allow_shrink)
5132 *new_flags |= GDK_HINT_MIN_SIZE;
5134 new_geometry->min_width = requisition.width;
5135 new_geometry->min_height = requisition.height;
5138 if (*new_flags & GDK_HINT_MAX_SIZE)
5140 if (new_geometry->max_width < 0)
5141 new_geometry->max_width = requisition.width;
5143 new_geometry->max_width += extra_width;
5145 if (new_geometry->max_height < 0)
5146 new_geometry->max_width = requisition.height;
5148 new_geometry->max_height += extra_height;
5150 else if (!window->allow_grow)
5152 *new_flags |= GDK_HINT_MAX_SIZE;
5154 new_geometry->max_width = requisition.width;
5155 new_geometry->max_height = requisition.height;
5158 *new_flags |= GDK_HINT_WIN_GRAVITY;
5159 new_geometry->win_gravity = window->gravity;
5162 /***********************
5163 * Redrawing functions *
5164 ***********************/
5167 gtk_window_paint (GtkWidget *widget,
5170 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
5171 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
5175 gtk_window_expose (GtkWidget *widget,
5176 GdkEventExpose *event)
5178 if (!GTK_WIDGET_APP_PAINTABLE (widget))
5179 gtk_window_paint (widget, &event->area);
5181 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
5182 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
5188 * gtk_window_set_has_frame:
5189 * @window: a #GtkWindow
5190 * @setting: a boolean
5192 * (Note: this is a special-purpose function for the framebuffer port,
5193 * that causes GTK+ to draw its own window border. For most applications,
5194 * you want gtk_window_set_decorated() instead, which tells the window
5195 * manager whether to draw the window border.)
5197 * If this function is called on a window with setting of %TRUE, before
5198 * it is realized or showed, it will have a "frame" window around
5199 * @window->window, accessible in @window->frame. Using the signal
5200 * frame_event you can recieve all events targeted at the frame.
5202 * This function is used by the linux-fb port to implement managed
5203 * windows, but it could concievably be used by X-programs that
5204 * want to do their own window decorations.
5208 gtk_window_set_has_frame (GtkWindow *window,
5211 g_return_if_fail (GTK_IS_WINDOW (window));
5212 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
5214 window->has_frame = setting != FALSE;
5218 * gtk_window_get_has_frame:
5219 * @window: a #GtkWindow
5221 * Accessor for whether the window has a frame window exterior to
5222 * @window->window. Gets the value set by gtk_window_set_has_frame ().
5224 * Return value: %TRUE if a frame has been added to the window
5225 * via gtk_window_set_has_frame().
5228 gtk_window_get_has_frame (GtkWindow *window)
5230 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5232 return window->has_frame;
5236 * gtk_window_set_frame_dimensions:
5237 * @window: a #GtkWindow that has a frame
5238 * @left: The width of the left border
5239 * @top: The height of the top border
5240 * @right: The width of the right border
5241 * @bottom: The height of the bottom border
5243 * (Note: this is a special-purpose function intended for the framebuffer
5244 * port; see gtk_window_set_has_frame(). It will have no effect on the
5245 * window border drawn by the window manager, which is the normal
5246 * case when using the X Window system.)
5248 * For windows with frames (see gtk_window_set_has_frame()) this function
5249 * can be used to change the size of the frame border.
5252 gtk_window_set_frame_dimensions (GtkWindow *window,
5260 g_return_if_fail (GTK_IS_WINDOW (window));
5262 widget = GTK_WIDGET (window);
5264 if (window->frame_left == left &&
5265 window->frame_top == top &&
5266 window->frame_right == right &&
5267 window->frame_bottom == bottom)
5270 window->frame_left = left;
5271 window->frame_top = top;
5272 window->frame_right = right;
5273 window->frame_bottom = bottom;
5275 if (GTK_WIDGET_REALIZED (widget) && window->frame)
5277 gint width = widget->allocation.width + left + right;
5278 gint height = widget->allocation.height + top + bottom;
5279 gdk_window_resize (window->frame, width, height);
5280 gtk_decorated_window_move_resize_window (window,
5282 widget->allocation.width,
5283 widget->allocation.height);
5288 * gtk_window_present:
5289 * @window: a #GtkWindow
5291 * Presents a window to the user. This may mean raising the window
5292 * in the stacking order, deiconifying it, moving it to the current
5293 * desktop, and/or giving it the keyboard focus, possibly dependent
5294 * on the user's platform, window manager, and preferences.
5296 * If @window is hidden, this function calls gtk_widget_show()
5299 * This function should be used when the user tries to open a window
5300 * that's already open. Say for example the preferences dialog is
5301 * currently open, and the user chooses Preferences from the menu
5302 * a second time; use gtk_window_present() to move the already-open dialog
5303 * where the user can see it.
5307 gtk_window_present (GtkWindow *window)
5311 g_return_if_fail (GTK_IS_WINDOW (window));
5313 widget = GTK_WIDGET (window);
5315 if (GTK_WIDGET_VISIBLE (window))
5317 g_assert (widget->window != NULL);
5319 gdk_window_show (widget->window);
5321 /* note that gdk_window_focus() will also move the window to
5322 * the current desktop, for WM spec compliant window managers.
5324 gdk_window_focus (widget->window,
5325 gtk_get_current_event_time ());
5329 gtk_widget_show (widget);
5334 * gtk_window_iconify:
5335 * @window: a #GtkWindow
5337 * Asks to iconify (i.e. minimize) the specified @window. Note that
5338 * you shouldn't assume the window is definitely iconified afterward,
5339 * because other entities (e.g. the user or <link
5340 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
5341 * again, or there may not be a window manager in which case
5342 * iconification isn't possible, etc. But normally the window will end
5343 * up iconified. Just don't write code that crashes if not.
5345 * It's permitted to call this function before showing a window,
5346 * in which case the window will be iconified before it ever appears
5349 * You can track iconification via the "window_state_event" signal
5354 gtk_window_iconify (GtkWindow *window)
5357 GdkWindow *toplevel;
5359 g_return_if_fail (GTK_IS_WINDOW (window));
5361 widget = GTK_WIDGET (window);
5363 window->iconify_initially = TRUE;
5366 toplevel = window->frame;
5368 toplevel = widget->window;
5370 if (toplevel != NULL)
5371 gdk_window_iconify (toplevel);
5375 * gtk_window_deiconify:
5376 * @window: a #GtkWindow
5378 * Asks to deiconify (i.e. unminimize) the specified @window. Note
5379 * that you shouldn't assume the window is definitely deiconified
5380 * afterward, because other entities (e.g. the user or <link
5381 * linkend="gtk-X11-arch">window manager</link>) could iconify it
5382 * again before your code which assumes deiconification gets to run.
5384 * You can track iconification via the "window_state_event" signal
5388 gtk_window_deiconify (GtkWindow *window)
5391 GdkWindow *toplevel;
5393 g_return_if_fail (GTK_IS_WINDOW (window));
5395 widget = GTK_WIDGET (window);
5397 window->iconify_initially = FALSE;
5400 toplevel = window->frame;
5402 toplevel = widget->window;
5404 if (toplevel != NULL)
5405 gdk_window_deiconify (toplevel);
5410 * @window: a #GtkWindow
5412 * Asks to stick @window, which means that it will appear on all user
5413 * desktops. Note that you shouldn't assume the window is definitely
5414 * stuck afterward, because other entities (e.g. the user or <link
5415 * linkend="gtk-X11-arch">window manager</link>) could unstick it
5416 * again, and some window managers do not support sticking
5417 * windows. But normally the window will end up stuck. Just don't
5418 * write code that crashes if not.
5420 * It's permitted to call this function before showing a window.
5422 * You can track stickiness via the "window_state_event" signal
5427 gtk_window_stick (GtkWindow *window)
5430 GdkWindow *toplevel;
5432 g_return_if_fail (GTK_IS_WINDOW (window));
5434 widget = GTK_WIDGET (window);
5436 window->stick_initially = TRUE;
5439 toplevel = window->frame;
5441 toplevel = widget->window;
5443 if (toplevel != NULL)
5444 gdk_window_stick (toplevel);
5448 * gtk_window_unstick:
5449 * @window: a #GtkWindow
5451 * Asks to unstick @window, which means that it will appear on only
5452 * one of the user's desktops. Note that you shouldn't assume the
5453 * window is definitely unstuck afterward, because other entities
5454 * (e.g. the user or <link linkend="gtk-X11-arch">window
5455 * manager</link>) could stick it again. But normally the window will
5456 * end up stuck. Just don't write code that crashes if not.
5458 * You can track stickiness via the "window_state_event" signal
5463 gtk_window_unstick (GtkWindow *window)
5466 GdkWindow *toplevel;
5468 g_return_if_fail (GTK_IS_WINDOW (window));
5470 widget = GTK_WIDGET (window);
5472 window->stick_initially = FALSE;
5475 toplevel = window->frame;
5477 toplevel = widget->window;
5479 if (toplevel != NULL)
5480 gdk_window_unstick (toplevel);
5484 * gtk_window_maximize:
5485 * @window: a #GtkWindow
5487 * Asks to maximize @window, so that it becomes full-screen. Note that
5488 * you shouldn't assume the window is definitely maximized afterward,
5489 * because other entities (e.g. the user or <link
5490 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
5491 * again, and not all window managers support maximization. But
5492 * normally the window will end up maximized. Just don't write code
5493 * that crashes if not.
5495 * It's permitted to call this function before showing a window,
5496 * in which case the window will be maximized when it appears onscreen
5499 * You can track maximization via the "window_state_event" signal
5504 gtk_window_maximize (GtkWindow *window)
5507 GdkWindow *toplevel;
5509 g_return_if_fail (GTK_IS_WINDOW (window));
5511 widget = GTK_WIDGET (window);
5513 window->maximize_initially = TRUE;
5516 toplevel = window->frame;
5518 toplevel = widget->window;
5520 if (toplevel != NULL)
5521 gdk_window_maximize (toplevel);
5525 * gtk_window_unmaximize:
5526 * @window: a #GtkWindow
5528 * Asks to unmaximize @window. Note that you shouldn't assume the
5529 * window is definitely unmaximized afterward, because other entities
5530 * (e.g. the user or <link linkend="gtk-X11-arch">window
5531 * manager</link>) could maximize it again, and not all window
5532 * managers honor requests to unmaximize. But normally the window will
5533 * end up unmaximized. Just don't write code that crashes if not.
5535 * You can track maximization via the "window_state_event" signal
5540 gtk_window_unmaximize (GtkWindow *window)
5543 GdkWindow *toplevel;
5545 g_return_if_fail (GTK_IS_WINDOW (window));
5547 widget = GTK_WIDGET (window);
5549 window->maximize_initially = FALSE;
5552 toplevel = window->frame;
5554 toplevel = widget->window;
5556 if (toplevel != NULL)
5557 gdk_window_unmaximize (toplevel);
5561 * gtk_window_fullscreen:
5562 * @window: a #GtkWindow
5564 * Asks to place @window in the fullscreen state. Note that you
5565 * shouldn't assume the window is definitely full screen afterward,
5566 * because other entities (e.g. the user or <link
5567 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
5568 * again, and not all window managers honor requests to fullscreen
5569 * windows. But normally the window will end up fullscreen. Just
5570 * don't write code that crashes if not.
5572 * You can track the fullscreen state via the "window_state_event" signal
5577 gtk_window_fullscreen (GtkWindow *window)
5580 GdkWindow *toplevel;
5581 GtkWindowPrivate *priv;
5583 g_return_if_fail (GTK_IS_WINDOW (window));
5585 widget = GTK_WIDGET (window);
5586 priv = gtk_window_get_private (window);
5588 priv->fullscreen_initially = TRUE;
5591 toplevel = window->frame;
5593 toplevel = widget->window;
5595 if (toplevel != NULL)
5596 gdk_window_fullscreen (toplevel);
5600 * gtk_window_unfullscreen:
5601 * @window: a #GtkWindow
5603 * Asks to toggle off the fullscreen state for @window. Note that you
5604 * shouldn't assume the window is definitely not full screen
5605 * afterward, because other entities (e.g. the user or <link
5606 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
5607 * again, and not all window managers honor requests to unfullscreen
5608 * windows. But normally the window will end up restored to its normal
5609 * state. Just don't write code that crashes if not.
5611 * You can track the fullscreen state via the "window_state_event" signal
5616 gtk_window_unfullscreen (GtkWindow *window)
5619 GdkWindow *toplevel;
5620 GtkWindowPrivate *priv;
5622 g_return_if_fail (GTK_IS_WINDOW (window));
5624 widget = GTK_WIDGET (window);
5625 priv = gtk_window_get_private (window);
5627 priv->fullscreen_initially = FALSE;
5630 toplevel = window->frame;
5632 toplevel = widget->window;
5634 if (toplevel != NULL)
5635 gdk_window_unfullscreen (toplevel);
5640 * gtk_window_set_resizable:
5641 * @window: a #GtkWindow
5642 * @resizable: %TRUE if the user can resize this window
5644 * Sets whether the user can resize a window. Windows are user resizable
5648 gtk_window_set_resizable (GtkWindow *window,
5651 g_return_if_fail (GTK_IS_WINDOW (window));
5653 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5657 * gtk_window_get_resizable:
5658 * @window: a #GtkWindow
5660 * Gets the value set by gtk_window_set_resizable().
5662 * Return value: %TRUE if the user can resize the window
5665 gtk_window_get_resizable (GtkWindow *window)
5667 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5669 /* allow_grow is most likely to indicate the semantic concept we
5670 * mean by "resizable" (and will be a reliable indicator if
5671 * set_policy() hasn't been called)
5673 return window->allow_grow;
5677 * gtk_window_set_gravity:
5678 * @window: a #GtkWindow
5679 * @gravity: window gravity
5681 * Window gravity defines the meaning of coordinates passed to
5682 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5685 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5686 * typically "do what you mean."
5690 gtk_window_set_gravity (GtkWindow *window,
5693 g_return_if_fail (GTK_IS_WINDOW (window));
5695 if (gravity != window->gravity)
5697 window->gravity = gravity;
5699 /* gtk_window_move_resize() will adapt gravity
5701 gtk_widget_queue_resize (GTK_WIDGET (window));
5706 * gtk_window_get_gravity:
5707 * @window: a #GtkWindow
5709 * Gets the value set by gtk_window_set_gravity().
5711 * Return value: window gravity
5714 gtk_window_get_gravity (GtkWindow *window)
5716 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5718 return window->gravity;
5722 * gtk_window_begin_resize_drag:
5723 * @window: a #GtkWindow
5724 * @button: mouse button that initiated the drag
5725 * @edge: position of the resize control
5726 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5727 * @root_y: Y position where the user clicked to initiate the drag
5728 * @timestamp: timestamp from the click event that initiated the drag
5730 * Starts resizing a window. This function is used if an application
5731 * has window resizing controls. When GDK can support it, the resize
5732 * will be done using the standard mechanism for the <link
5733 * linkend="gtk-X11-arch">window manager</link> or windowing
5734 * system. Otherwise, GDK will try to emulate window resizing,
5735 * potentially not all that well, depending on the windowing system.
5739 gtk_window_begin_resize_drag (GtkWindow *window,
5747 GdkWindow *toplevel;
5749 g_return_if_fail (GTK_IS_WINDOW (window));
5750 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5752 widget = GTK_WIDGET (window);
5755 toplevel = window->frame;
5757 toplevel = widget->window;
5759 gdk_window_begin_resize_drag (toplevel,
5766 * gtk_window_get_frame_dimensions:
5767 * @window: a #GtkWindow
5768 * @left: location to store the width of the frame at the left, or %NULL
5769 * @top: location to store the height of the frame at the top, or %NULL
5770 * @right: location to store the width of the frame at the returns, or %NULL
5771 * @bottom: location to store the height of the frame at the bottom, or %NULL
5773 * (Note: this is a special-purpose function intended for the
5774 * framebuffer port; see gtk_window_set_has_frame(). It will not
5775 * return the size of the window border drawn by the <link
5776 * linkend="gtk-X11-arch">window manager</link>, which is the normal
5777 * case when using a windowing system. See
5778 * gdk_window_get_frame_extents() to get the standard window border
5781 * Retrieves the dimensions of the frame window for this toplevel.
5782 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5785 gtk_window_get_frame_dimensions (GtkWindow *window,
5791 g_return_if_fail (GTK_IS_WINDOW (window));
5794 *left = window->frame_left;
5796 *top = window->frame_top;
5798 *right = window->frame_right;
5800 *bottom = window->frame_bottom;
5804 * gtk_window_begin_move_drag:
5805 * @window: a #GtkWindow
5806 * @button: mouse button that initiated the drag
5807 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5808 * @root_y: Y position where the user clicked to initiate the drag
5809 * @timestamp: timestamp from the click event that initiated the drag
5811 * Starts moving a window. This function is used if an application has
5812 * window movement grips. When GDK can support it, the window movement
5813 * will be done using the standard mechanism for the <link
5814 * linkend="gtk-X11-arch">window manager</link> or windowing
5815 * system. Otherwise, GDK will try to emulate window movement,
5816 * potentially not all that well, depending on the windowing system.
5820 gtk_window_begin_move_drag (GtkWindow *window,
5827 GdkWindow *toplevel;
5829 g_return_if_fail (GTK_IS_WINDOW (window));
5830 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5832 widget = GTK_WIDGET (window);
5835 toplevel = window->frame;
5837 toplevel = widget->window;
5839 gdk_window_begin_move_drag (toplevel,
5846 * gtk_window_set_screen:
5847 * @window: a #GtkWindow.
5848 * @screen: a #GdkScreen.
5850 * Sets the #GdkScreen where the @window is displayed; if
5851 * the window is already mapped, it will be unmapped, and
5852 * then remapped on the new screen.
5855 gtk_window_set_screen (GtkWindow *window,
5859 gboolean was_mapped;
5861 g_return_if_fail (GTK_IS_WINDOW (window));
5862 g_return_if_fail (GDK_IS_SCREEN (screen));
5864 if (screen == window->screen)
5867 widget = GTK_WIDGET (window);
5869 was_mapped = GTK_WIDGET_MAPPED (widget);
5872 gtk_widget_unmap (widget);
5873 if (GTK_WIDGET_REALIZED (widget))
5874 gtk_widget_unrealize (widget);
5876 gtk_window_free_key_hash (window);
5877 window->screen = screen;
5878 gtk_widget_reset_rc_styles (widget);
5879 g_object_notify (G_OBJECT (window), "screen");
5882 gtk_widget_map (widget);
5886 * gtk_window_get_screen:
5887 * @window: a #GtkWindow.
5889 * Returns the #GdkScreen associated with @window.
5891 * Return value: a #GdkScreen.
5894 gtk_window_get_screen (GtkWindow *window)
5896 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
5898 return window->screen;
5903 gtk_window_group_class_init (GtkWindowGroupClass *klass)
5908 gtk_window_group_get_type (void)
5910 static GType window_group_type = 0;
5912 if (!window_group_type)
5914 static const GTypeInfo window_group_info =
5916 sizeof (GtkWindowGroupClass),
5917 NULL, /* base_init */
5918 NULL, /* base_finalize */
5919 (GClassInitFunc) gtk_window_group_class_init,
5920 NULL, /* class_finalize */
5921 NULL, /* class_data */
5922 sizeof (GtkWindowGroup),
5923 16, /* n_preallocs */
5924 (GInstanceInitFunc) NULL,
5927 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
5930 return window_group_type;
5934 * gtk_window_group_new:
5936 * Creates a new #GtkWindowGroup object. Grabs added with
5937 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
5939 * Return value: a new #GtkWindowGroup.
5942 gtk_window_group_new (void)
5944 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
5948 window_group_cleanup_grabs (GtkWindowGroup *group,
5952 GSList *to_remove = NULL;
5954 tmp_list = group->grabs;
5957 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
5958 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
5959 tmp_list = tmp_list->next;
5964 gtk_grab_remove (to_remove->data);
5965 g_object_unref (to_remove->data);
5966 to_remove = g_slist_delete_link (to_remove, to_remove);
5971 * gtk_window_group_add_window:
5972 * @window_group: a #GtkWindowGroup
5973 * @window: the #GtkWindow to add
5975 * Adds a window to a #GtkWindowGroup.
5978 gtk_window_group_add_window (GtkWindowGroup *window_group,
5981 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5982 g_return_if_fail (GTK_IS_WINDOW (window));
5984 if (window->group != window_group)
5986 g_object_ref (window);
5987 g_object_ref (window_group);
5990 gtk_window_group_remove_window (window->group, window);
5992 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
5994 window->group = window_group;
5996 g_object_unref (window);
6001 * gtk_window_group_remove_window:
6002 * @window_group: a #GtkWindowGroup
6003 * @window: the #GtkWindow to remove
6005 * Removes a window from a #GtkWindowGroup.
6008 gtk_window_group_remove_window (GtkWindowGroup *window_group,
6011 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6012 g_return_if_fail (GTK_IS_WIDGET (window));
6013 g_return_if_fail (window->group == window_group);
6015 g_object_ref (window);
6017 window_group_cleanup_grabs (window_group, window);
6018 window->group = NULL;
6020 g_object_unref (window_group);
6021 g_object_unref (window);
6024 /* Return the group for the window or the default group
6027 _gtk_window_get_group (GtkWindow *window)
6029 if (window && window->group)
6030 return window->group;
6033 static GtkWindowGroup *default_group = NULL;
6036 default_group = gtk_window_group_new ();
6038 return default_group;
6044 Derived from XParseGeometry() in XFree86
6046 Copyright 1985, 1986, 1987,1998 The Open Group
6048 All Rights Reserved.
6050 The above copyright notice and this permission notice shall be included
6051 in all copies or substantial portions of the Software.
6053 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
6054 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6055 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6056 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
6057 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
6058 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
6059 OTHER DEALINGS IN THE SOFTWARE.
6061 Except as contained in this notice, the name of The Open Group shall
6062 not be used in advertising or otherwise to promote the sale, use or
6063 other dealings in this Software without prior written authorization
6064 from The Open Group.
6069 * XParseGeometry parses strings of the form
6070 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
6071 * width, height, xoffset, and yoffset are unsigned integers.
6072 * Example: "=80x24+300-49"
6073 * The equal sign is optional.
6074 * It returns a bitmask that indicates which of the four values
6075 * were actually found in the string. For each value found,
6076 * the corresponding argument is updated; for each value
6077 * not found, the corresponding argument is left unchanged.
6080 /* The following code is from Xlib, and is minimally modified, so we
6081 * can track any upstream changes if required. Don't change this
6082 * code. Or if you do, put in a huge comment marking which thing
6087 read_int (gchar *string,
6095 else if (*string == '-')
6101 for (; (*string >= '0') && (*string <= '9'); string++)
6103 result = (result * 10) + (*string - '0');
6115 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
6116 * value (x, y, width, height) was found in the parsed string.
6118 #define NoValue 0x0000
6119 #define XValue 0x0001
6120 #define YValue 0x0002
6121 #define WidthValue 0x0004
6122 #define HeightValue 0x0008
6123 #define AllValues 0x000F
6124 #define XNegative 0x0010
6125 #define YNegative 0x0020
6127 /* Try not to reformat/modify, so we can compare/sync with X sources */
6129 gtk_XParseGeometry (const char *string,
6132 unsigned int *width,
6133 unsigned int *height)
6137 unsigned int tempWidth, tempHeight;
6139 char *nextCharacter;
6141 /* These initializations are just to silence gcc */
6147 if ( (string == NULL) || (*string == '\0')) return(mask);
6149 string++; /* ignore possible '=' at beg of geometry spec */
6151 strind = (char *)string;
6152 if (*strind != '+' && *strind != '-' && *strind != 'x') {
6153 tempWidth = read_int(strind, &nextCharacter);
6154 if (strind == nextCharacter)
6156 strind = nextCharacter;
6160 if (*strind == 'x' || *strind == 'X') {
6162 tempHeight = read_int(strind, &nextCharacter);
6163 if (strind == nextCharacter)
6165 strind = nextCharacter;
6166 mask |= HeightValue;
6169 if ((*strind == '+') || (*strind == '-')) {
6170 if (*strind == '-') {
6172 tempX = -read_int(strind, &nextCharacter);
6173 if (strind == nextCharacter)
6175 strind = nextCharacter;
6181 tempX = read_int(strind, &nextCharacter);
6182 if (strind == nextCharacter)
6184 strind = nextCharacter;
6187 if ((*strind == '+') || (*strind == '-')) {
6188 if (*strind == '-') {
6190 tempY = -read_int(strind, &nextCharacter);
6191 if (strind == nextCharacter)
6193 strind = nextCharacter;
6200 tempY = read_int(strind, &nextCharacter);
6201 if (strind == nextCharacter)
6203 strind = nextCharacter;
6209 /* If strind isn't at the end of the string the it's an invalid
6210 geometry specification. */
6212 if (*strind != '\0') return (0);
6218 if (mask & WidthValue)
6220 if (mask & HeightValue)
6221 *height = tempHeight;
6226 * gtk_window_parse_geometry:
6227 * @window: a #GtkWindow
6228 * @geometry: geometry string
6230 * Parses a standard X Window System geometry string - see the
6231 * manual page for X (type 'man X') for details on this.
6232 * gtk_window_parse_geometry() does work on all GTK+ ports
6233 * including Win32 but is primarily intended for an X environment.
6235 * If either a size or a position can be extracted from the
6236 * geometry string, gtk_window_parse_geometry() returns %TRUE
6237 * and calls gtk_window_set_default_size() and/or gtk_window_move()
6238 * to resize/move the window.
6240 * If gtk_window_parse_geometry() returns %TRUE, it will also
6241 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
6242 * indicating to the window manager that the size/position of
6243 * the window was user-specified. This causes most window
6244 * managers to honor the geometry.
6246 * Return value: %TRUE if string was parsed successfully
6249 gtk_window_parse_geometry (GtkWindow *window,
6250 const gchar *geometry)
6255 gboolean size_set, pos_set;
6257 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6258 g_return_val_if_fail (geometry != NULL, FALSE);
6260 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
6262 if ((result & WidthValue) == 0 ||
6265 if ((result & HeightValue) == 0 ||
6270 if ((result & WidthValue) || (result & HeightValue))
6272 gtk_window_set_default_size_internal (window, TRUE, w, TRUE, h, TRUE);
6276 gtk_window_get_size (window, &w, &h);
6278 grav = GDK_GRAVITY_NORTH_WEST;
6280 if ((result & XNegative) && (result & YNegative))
6281 grav = GDK_GRAVITY_SOUTH_EAST;
6282 else if (result & XNegative)
6283 grav = GDK_GRAVITY_NORTH_EAST;
6284 else if (result & YNegative)
6285 grav = GDK_GRAVITY_SOUTH_WEST;
6287 if ((result & XValue) == 0)
6290 if ((result & YValue) == 0)
6293 if (grav == GDK_GRAVITY_SOUTH_WEST ||
6294 grav == GDK_GRAVITY_SOUTH_EAST)
6295 y = gdk_screen_get_height (window->screen) - h + y;
6297 if (grav == GDK_GRAVITY_SOUTH_EAST ||
6298 grav == GDK_GRAVITY_NORTH_EAST)
6299 x = gdk_screen_get_width (window->screen) - w + x;
6301 /* we don't let you put a window offscreen; maybe some people would
6302 * prefer to be able to, but it's kind of a bogus thing to do.
6311 if ((result & XValue) || (result & YValue))
6313 gtk_window_set_gravity (window, grav);
6314 gtk_window_move (window, x, y);
6318 if (size_set || pos_set)
6320 /* Set USSize, USPosition hints */
6321 GtkWindowGeometryInfo *info;
6323 info = gtk_window_get_geometry_info (window, TRUE);
6326 info->mask |= GDK_HINT_USER_POS;
6328 info->mask |= GDK_HINT_USER_SIZE;
6335 gtk_window_mnemonic_hash_foreach (gpointer key,
6341 GtkWindowKeysForeachFunc func;
6345 GtkWindowMnemonic *mnemonic = value;
6347 if (mnemonic->window == info->window)
6348 (*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
6352 _gtk_window_keys_foreach (GtkWindow *window,
6353 GtkWindowKeysForeachFunc func,
6360 GtkWindowKeysForeachFunc func;
6364 info.window = window;
6366 info.func_data = func_data;
6368 g_hash_table_foreach (mnemonic_hash_table,
6369 gtk_window_mnemonic_hash_foreach,
6372 groups = gtk_accel_groups_from_object (G_OBJECT (window));
6375 GtkAccelGroup *group = groups->data;
6378 for (i = 0; i < group->n_accels; i++)
6380 GtkAccelKey *key = &group->priv_accels[i].key;
6383 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
6386 groups = groups->next;
6391 gtk_window_keys_changed (GtkWindow *window)
6393 gtk_window_free_key_hash (window);
6394 gtk_window_get_key_hash (window);
6397 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
6399 struct _GtkWindowKeyEntry
6403 gboolean is_mnemonic;
6407 add_to_key_hash (GtkWindow *window,
6409 GdkModifierType modifiers,
6410 gboolean is_mnemonic,
6413 GtkKeyHash *key_hash = data;
6415 GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
6417 entry->keyval = keyval;
6418 entry->modifiers = modifiers;
6419 entry->is_mnemonic = is_mnemonic;
6421 /* GtkAccelGroup stores lowercased accelerators. To deal
6422 * with this, if <Shift> was specified, uppercase.
6424 if (modifiers & GDK_SHIFT_MASK)
6426 if (keyval == GDK_Tab)
6427 keyval = GDK_ISO_Left_Tab;
6429 keyval = gdk_keyval_to_upper (keyval);
6432 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
6436 gtk_window_get_key_hash (GtkWindow *window)
6438 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6442 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (window->screen)),
6443 (GDestroyNotify)g_free);
6444 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
6445 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
6451 gtk_window_free_key_hash (GtkWindow *window)
6453 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6456 _gtk_key_hash_free (key_hash);
6457 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
6462 * _gtk_window_activate_key:
6463 * @window: a #GtkWindow
6464 * @event: a #GdkEventKey
6466 * Activates mnemonics and accelerators for this #GtKWindow
6468 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
6471 _gtk_window_activate_key (GtkWindow *window,
6474 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6475 GtkWindowKeyEntry *found_entry = NULL;
6479 gtk_window_keys_changed (window);
6480 key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6485 GSList *entries = _gtk_key_hash_lookup (key_hash,
6486 event->hardware_keycode,
6487 event->state & gtk_accelerator_get_default_mod_mask (),
6491 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
6493 GtkWindowKeyEntry *entry = tmp_list->data;
6494 if (entry->is_mnemonic)
6496 found_entry = entry;
6501 if (!found_entry && entries)
6502 found_entry = entries->data;
6504 g_slist_free (entries);
6509 if (found_entry->is_mnemonic)
6510 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
6512 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
6519 window_update_has_focus (GtkWindow *window)
6521 GtkWidget *widget = GTK_WIDGET (window);
6522 gboolean has_focus = window->has_toplevel_focus && window->is_active;
6524 if (has_focus != window->has_focus)
6526 window->has_focus = has_focus;
6530 if (window->focus_widget &&
6531 window->focus_widget != widget &&
6532 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6533 do_focus_change (window->focus_widget, TRUE);
6537 if (window->focus_widget &&
6538 window->focus_widget != widget &&
6539 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6540 do_focus_change (window->focus_widget, FALSE);
6546 * _gtk_window_set_is_active:
6547 * @window: a #GtkWindow
6548 * @is_active: %TRUE if the window is in the currently active toplevel
6550 * Internal function that sets whether the #GtkWindow is part
6551 * of the currently active toplevel window (taking into account inter-process
6555 _gtk_window_set_is_active (GtkWindow *window,
6558 g_return_if_fail (GTK_IS_WINDOW (window));
6560 is_active = is_active != FALSE;
6562 if (is_active != window->is_active)
6564 window->is_active = is_active;
6565 window_update_has_focus (window);
6567 g_object_notify (G_OBJECT (window), "is_active");
6572 * _gtk_window_set_has_toplevel_focus:
6573 * @window: a #GtkWindow
6574 * @has_toplevel_focus: %TRUE if the in
6576 * Internal function that sets whether the keyboard focus for the
6577 * toplevel window (taking into account inter-process embedding.)
6580 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
6581 gboolean has_toplevel_focus)
6583 g_return_if_fail (GTK_IS_WINDOW (window));
6585 has_toplevel_focus = has_toplevel_focus != FALSE;
6587 if (has_toplevel_focus != window->has_toplevel_focus)
6589 window->has_toplevel_focus = has_toplevel_focus;
6590 window_update_has_focus (window);
6592 g_object_notify (G_OBJECT (window), "has_toplevel_focus");