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 GdkScreen *gtk_window_check_screen (GtkWindow *window);
218 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
221 static void gtk_window_move_resize (GtkWindow *window);
222 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
224 GdkGeometry *geometry_b,
226 static void gtk_window_constrain_size (GtkWindow *window,
227 GdkGeometry *geometry,
233 static void gtk_window_constrain_position (GtkWindow *window,
238 static void gtk_window_compute_hints (GtkWindow *window,
239 GdkGeometry *new_geometry,
241 static void gtk_window_compute_configure_request (GtkWindow *window,
242 GdkRectangle *request,
243 GdkGeometry *geometry,
246 static void gtk_window_set_default_size_internal (GtkWindow *window,
247 gboolean change_width,
249 gboolean change_height,
251 gboolean is_geometry);
253 static void gtk_window_realize_icon (GtkWindow *window);
254 static void gtk_window_unrealize_icon (GtkWindow *window);
256 static void gtk_window_notify_keys_changed (GtkWindow *window);
257 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
258 static void gtk_window_free_key_hash (GtkWindow *window);
260 static GSList *toplevel_list = NULL;
261 static GHashTable *mnemonic_hash_table = NULL;
262 static GtkBinClass *parent_class = NULL;
263 static guint window_signals[LAST_SIGNAL] = { 0 };
264 static GList *default_icon_list = NULL;
265 static guint default_icon_serial = 0;
266 static gboolean disable_startup_notification = FALSE;
267 static gboolean sent_startup_notification = FALSE;
269 static void gtk_window_set_property (GObject *object,
273 static void gtk_window_get_property (GObject *object,
280 mnemonic_hash (gconstpointer key)
282 const GtkWindowMnemonic *k;
285 k = (GtkWindowMnemonic *)key;
287 h = (gulong) k->window;
288 h ^= k->keyval << 16;
289 h ^= k->keyval >> 16;
295 mnemonic_equal (gconstpointer a, gconstpointer b)
297 const GtkWindowMnemonic *ka;
298 const GtkWindowMnemonic *kb;
300 ka = (GtkWindowMnemonic *)a;
301 kb = (GtkWindowMnemonic *)b;
304 (ka->window == kb->window) &&
305 (ka->keyval == kb->keyval);
309 gtk_window_get_private (GtkWindow *window)
311 GtkWindowPrivate *private;
312 static GQuark private_quark = 0;
315 private_quark = g_quark_from_static_string ("gtk-window-private");
317 private = g_object_get_qdata (G_OBJECT (window), private_quark);
321 private = g_new0 (GtkWindowPrivate, 1);
323 private->fullscreen_initially = FALSE;
324 private->skips_pager = FALSE;
325 private->skips_taskbar = FALSE;
327 g_object_set_qdata_full (G_OBJECT (window), private_quark,
329 (GDestroyNotify) gtk_window_private_finalize);
336 gtk_window_get_type (void)
338 static GType window_type = 0;
342 static const GTypeInfo window_info =
344 sizeof (GtkWindowClass),
345 NULL, /* base_init */
346 NULL, /* base_finalize */
347 (GClassInitFunc) gtk_window_class_init,
348 NULL, /* class_finalize */
349 NULL, /* class_data */
352 (GInstanceInitFunc) gtk_window_init,
355 window_type = g_type_register_static (GTK_TYPE_BIN, "GtkWindow",
363 add_tab_bindings (GtkBindingSet *binding_set,
364 GdkModifierType modifiers,
365 GtkDirectionType direction)
367 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
369 GTK_TYPE_DIRECTION_TYPE, direction);
370 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
372 GTK_TYPE_DIRECTION_TYPE, direction);
376 add_arrow_bindings (GtkBindingSet *binding_set,
378 GtkDirectionType direction)
380 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
382 gtk_binding_entry_add_signal (binding_set, keysym, 0,
384 GTK_TYPE_DIRECTION_TYPE, direction);
385 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
387 GTK_TYPE_DIRECTION_TYPE, direction);
388 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
390 GTK_TYPE_DIRECTION_TYPE, direction);
391 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
393 GTK_TYPE_DIRECTION_TYPE, direction);
398 gtk_window_class_init (GtkWindowClass *klass)
400 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
401 GtkObjectClass *object_class;
402 GtkWidgetClass *widget_class;
403 GtkContainerClass *container_class;
404 GtkBindingSet *binding_set;
406 object_class = (GtkObjectClass*) klass;
407 widget_class = (GtkWidgetClass*) klass;
408 container_class = (GtkContainerClass*) klass;
410 parent_class = g_type_class_peek_parent (klass);
412 mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
414 gobject_class->dispose = gtk_window_dispose;
415 gobject_class->finalize = gtk_window_finalize;
417 gobject_class->set_property = gtk_window_set_property;
418 gobject_class->get_property = gtk_window_get_property;
420 object_class->destroy = gtk_window_destroy;
422 widget_class->show = gtk_window_show;
423 widget_class->hide = gtk_window_hide;
424 widget_class->map = gtk_window_map;
425 widget_class->unmap = gtk_window_unmap;
426 widget_class->realize = gtk_window_realize;
427 widget_class->unrealize = gtk_window_unrealize;
428 widget_class->size_request = gtk_window_size_request;
429 widget_class->size_allocate = gtk_window_size_allocate;
430 widget_class->configure_event = gtk_window_configure_event;
431 widget_class->key_press_event = gtk_window_key_press_event;
432 widget_class->key_release_event = gtk_window_key_release_event;
433 widget_class->enter_notify_event = gtk_window_enter_notify_event;
434 widget_class->leave_notify_event = gtk_window_leave_notify_event;
435 widget_class->focus_in_event = gtk_window_focus_in_event;
436 widget_class->focus_out_event = gtk_window_focus_out_event;
437 widget_class->client_event = gtk_window_client_event;
438 widget_class->focus = gtk_window_focus;
440 widget_class->expose_event = gtk_window_expose;
442 container_class->check_resize = gtk_window_check_resize;
444 klass->set_focus = gtk_window_real_set_focus;
445 klass->frame_event = gtk_window_frame_event;
447 klass->activate_default = gtk_window_real_activate_default;
448 klass->activate_focus = gtk_window_real_activate_focus;
449 klass->move_focus = gtk_window_move_focus;
450 klass->keys_changed = gtk_window_keys_changed;
453 g_object_class_install_property (gobject_class,
455 g_param_spec_enum ("type",
457 _("The type of the window"),
458 GTK_TYPE_WINDOW_TYPE,
460 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
463 g_object_class_install_property (gobject_class,
465 g_param_spec_string ("title",
467 _("The title of the window"),
471 g_object_class_install_property (gobject_class,
473 g_param_spec_boolean ("allow_shrink",
475 /* xgettext:no-c-format */
476 _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
480 g_object_class_install_property (gobject_class,
482 g_param_spec_boolean ("allow_grow",
484 _("If TRUE, users can expand the window beyond its minimum size"),
488 g_object_class_install_property (gobject_class,
490 g_param_spec_boolean ("resizable",
492 _("If TRUE, users can resize the window"),
496 g_object_class_install_property (gobject_class,
498 g_param_spec_boolean ("modal",
500 _("If TRUE, the window is modal (other windows are not usable while this one is up)"),
504 g_object_class_install_property (gobject_class,
506 g_param_spec_enum ("window_position",
507 _("Window Position"),
508 _("The initial position of the window"),
509 GTK_TYPE_WINDOW_POSITION,
513 g_object_class_install_property (gobject_class,
515 g_param_spec_int ("default_width",
517 _("The default width of the window, used when initially showing the window"),
523 g_object_class_install_property (gobject_class,
525 g_param_spec_int ("default_height",
527 _("The default height of the window, used when initially showing the window"),
533 g_object_class_install_property (gobject_class,
534 PROP_DESTROY_WITH_PARENT,
535 g_param_spec_boolean ("destroy_with_parent",
536 _("Destroy with Parent"),
537 _("If this window should be destroyed when the parent is destroyed"),
541 g_object_class_install_property (gobject_class,
543 g_param_spec_object ("icon",
545 _("Icon for this window"),
549 g_object_class_install_property (gobject_class,
551 g_param_spec_object ("screen",
553 _("The screen where this window will be displayed"),
557 g_object_class_install_property (gobject_class,
559 g_param_spec_boolean ("is_active",
561 _("Whether the toplevel is the current active window"),
565 g_object_class_install_property (gobject_class,
566 PROP_HAS_TOPLEVEL_FOCUS,
567 g_param_spec_boolean ("has_toplevel_focus",
568 _("Focus in Toplevel"),
569 _("Whether the input focus is within this GtkWindow"),
573 g_object_class_install_property (gobject_class,
575 g_param_spec_enum ("type_hint",
577 _("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
578 GDK_TYPE_WINDOW_TYPE_HINT,
579 GDK_WINDOW_TYPE_HINT_NORMAL,
582 g_object_class_install_property (gobject_class,
583 PROP_SKIP_TASKBAR_HINT,
584 g_param_spec_boolean ("skip_taskbar_hint",
586 _("TRUE if the window should not be in the task bar."),
590 g_object_class_install_property (gobject_class,
591 PROP_SKIP_PAGER_HINT,
592 g_param_spec_boolean ("skip_pager_hint",
594 _("TRUE if the window should not be in the pager."),
598 window_signals[SET_FOCUS] =
599 g_signal_new ("set_focus",
600 G_TYPE_FROM_CLASS (gobject_class),
602 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
604 _gtk_marshal_VOID__OBJECT,
608 window_signals[FRAME_EVENT] =
609 g_signal_new ("frame_event",
610 G_TYPE_FROM_CLASS (gobject_class),
612 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
613 _gtk_boolean_handled_accumulator, NULL,
614 _gtk_marshal_BOOLEAN__BOXED,
618 window_signals[ACTIVATE_FOCUS] =
619 g_signal_new ("activate_focus",
620 G_TYPE_FROM_CLASS (gobject_class),
621 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
622 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
624 _gtk_marshal_VOID__VOID,
628 window_signals[ACTIVATE_DEFAULT] =
629 g_signal_new ("activate_default",
630 G_TYPE_FROM_CLASS (gobject_class),
631 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
632 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
634 _gtk_marshal_VOID__VOID,
638 window_signals[MOVE_FOCUS] =
639 g_signal_new ("move_focus",
640 G_TYPE_FROM_CLASS (gobject_class),
641 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
642 G_STRUCT_OFFSET (GtkWindowClass, move_focus),
644 _gtk_marshal_VOID__ENUM,
647 GTK_TYPE_DIRECTION_TYPE);
649 window_signals[KEYS_CHANGED] =
650 g_signal_new ("keys_changed",
651 G_TYPE_FROM_CLASS (gobject_class),
653 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
655 _gtk_marshal_VOID__VOID,
663 binding_set = gtk_binding_set_by_class (klass);
665 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
666 "activate_focus", 0);
667 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
668 "activate_focus", 0);
670 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
671 "activate_default", 0);
673 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
674 "activate_default", 0);
676 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
677 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
678 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
679 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
681 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
682 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
683 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
684 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
688 gtk_window_init (GtkWindow *window)
690 GdkColormap *colormap;
692 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
693 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
695 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
697 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
699 window->title = NULL;
700 window->wmclass_name = g_strdup (g_get_prgname ());
701 window->wmclass_class = g_strdup (gdk_get_program_class ());
702 window->wm_role = NULL;
703 window->geometry_info = NULL;
704 window->type = GTK_WINDOW_TOPLEVEL;
705 window->focus_widget = NULL;
706 window->default_widget = NULL;
707 window->configure_request_count = 0;
708 window->allow_shrink = FALSE;
709 window->allow_grow = TRUE;
710 window->configure_notify_received = FALSE;
711 window->position = GTK_WIN_POS_NONE;
712 window->need_default_size = TRUE;
713 window->need_default_position = TRUE;
714 window->modal = FALSE;
715 window->frame = NULL;
716 window->has_frame = FALSE;
717 window->frame_left = 0;
718 window->frame_right = 0;
719 window->frame_top = 0;
720 window->frame_bottom = 0;
721 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
722 window->gravity = GDK_GRAVITY_NORTH_WEST;
723 window->decorated = TRUE;
724 window->mnemonic_modifier = GDK_MOD1_MASK;
725 window->screen = gdk_screen_get_default ();
727 colormap = _gtk_widget_peek_colormap ();
729 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
731 g_object_ref (window);
732 gtk_object_sink (GTK_OBJECT (window));
733 window->has_user_ref_count = TRUE;
734 toplevel_list = g_slist_prepend (toplevel_list, window);
736 gtk_decorated_window_init (window);
738 g_signal_connect (window,
740 G_CALLBACK (gtk_window_event),
745 gtk_window_set_property (GObject *object,
752 window = GTK_WINDOW (object);
757 window->type = g_value_get_enum (value);
760 gtk_window_set_title (window, g_value_get_string (value));
762 case PROP_ALLOW_SHRINK:
763 window->allow_shrink = g_value_get_boolean (value);
764 gtk_widget_queue_resize (GTK_WIDGET (window));
766 case PROP_ALLOW_GROW:
767 window->allow_grow = g_value_get_boolean (value);
768 gtk_widget_queue_resize (GTK_WIDGET (window));
769 g_object_notify (G_OBJECT (window), "resizable");
772 window->allow_grow = g_value_get_boolean (value);
773 gtk_widget_queue_resize (GTK_WIDGET (window));
774 g_object_notify (G_OBJECT (window), "allow_grow");
777 gtk_window_set_modal (window, g_value_get_boolean (value));
780 gtk_window_set_position (window, g_value_get_enum (value));
782 case PROP_DEFAULT_WIDTH:
783 gtk_window_set_default_size_internal (window,
784 TRUE, g_value_get_int (value),
787 case PROP_DEFAULT_HEIGHT:
788 gtk_window_set_default_size_internal (window,
790 TRUE, g_value_get_int (value), FALSE);
792 case PROP_DESTROY_WITH_PARENT:
793 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
796 gtk_window_set_icon (window,
797 g_value_get_object (value));
800 gtk_window_set_screen (window, g_value_get_object (value));
803 gtk_window_set_type_hint (window,
804 g_value_get_enum (value));
806 case PROP_SKIP_TASKBAR_HINT:
807 gtk_window_set_skip_taskbar_hint (window,
808 g_value_get_boolean (value));
810 case PROP_SKIP_PAGER_HINT:
811 gtk_window_set_skip_pager_hint (window,
812 g_value_get_boolean (value));
821 gtk_window_get_property (GObject *object,
828 window = GTK_WINDOW (object);
832 GtkWindowGeometryInfo *info;
834 g_value_set_enum (value, window->type);
837 g_value_set_string (value, window->title);
839 case PROP_ALLOW_SHRINK:
840 g_value_set_boolean (value, window->allow_shrink);
842 case PROP_ALLOW_GROW:
843 g_value_set_boolean (value, window->allow_grow);
846 g_value_set_boolean (value, window->allow_grow);
849 g_value_set_boolean (value, window->modal);
852 g_value_set_enum (value, window->position);
854 case PROP_DEFAULT_WIDTH:
855 info = gtk_window_get_geometry_info (window, FALSE);
857 g_value_set_int (value, -1);
859 g_value_set_int (value, info->default_width);
861 case PROP_DEFAULT_HEIGHT:
862 info = gtk_window_get_geometry_info (window, FALSE);
864 g_value_set_int (value, -1);
866 g_value_set_int (value, info->default_height);
868 case PROP_DESTROY_WITH_PARENT:
869 g_value_set_boolean (value, window->destroy_with_parent);
872 g_value_set_object (value, gtk_window_get_icon (window));
875 g_value_set_object (value, window->screen);
878 g_value_set_boolean (value, window->is_active);
880 case PROP_HAS_TOPLEVEL_FOCUS:
881 g_value_set_boolean (value, window->has_toplevel_focus);
884 g_value_set_enum (value,
887 case PROP_SKIP_TASKBAR_HINT:
888 g_value_set_boolean (value,
889 gtk_window_get_skip_taskbar_hint (window));
891 case PROP_SKIP_PAGER_HINT:
892 g_value_set_boolean (value,
893 gtk_window_get_skip_pager_hint (window));
896 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
903 * @type: type of window
905 * Creates a new #GtkWindow, which is a toplevel window that can
906 * contain other widgets. Nearly always, the type of the window should
907 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
908 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
909 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
910 * dialogs, though in some other toolkits dialogs are called "popups".
911 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
912 * On X11, popup windows are not controlled by the <link
913 * linkend="gtk-X11-arch">window manager</link>.
915 * If you simply want an undecorated window (no window borders), use
916 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
918 * Return value: a new #GtkWindow.
921 gtk_window_new (GtkWindowType type)
925 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
927 window = g_object_new (GTK_TYPE_WINDOW, NULL);
931 return GTK_WIDGET (window);
935 * gtk_window_set_title:
936 * @window: a #GtkWindow
937 * @title: title of the window
939 * Sets the title of the #GtkWindow. The title of a window will be
940 * displayed in its title bar; on the X Window System, the title bar
941 * is rendered by the <link linkend="gtk-X11-arch">window
942 * manager</link>, so exactly how the title appears to users may vary
943 * according to a user's exact configuration. The title should help a
944 * user distinguish this window from other windows they may have
945 * open. A good title might include the application name and current
946 * document filename, for example.
950 gtk_window_set_title (GtkWindow *window,
953 g_return_if_fail (GTK_IS_WINDOW (window));
956 g_free (window->title);
957 window->title = g_strdup (title);
959 if (GTK_WIDGET_REALIZED (window))
961 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
963 gtk_decorated_window_set_title (window, title);
966 g_object_notify (G_OBJECT (window), "title");
970 * gtk_window_get_title:
971 * @window: a #GtkWindow
973 * Retrieves the title of the window. See gtk_window_set_title().
975 * Return value: the title of the window, or %NULL if none has
976 * been set explicitely. The returned string is owned by the widget
977 * and must not be modified or freed.
979 G_CONST_RETURN gchar *
980 gtk_window_get_title (GtkWindow *window)
982 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
984 return window->title;
988 * gtk_window_set_wmclass:
989 * @window: a #GtkWindow
990 * @wmclass_name: window name hint
991 * @wmclass_class: window class hint
993 * Don't use this function. It sets the X Window System "class" and
994 * "name" hints for a window. According to the ICCCM, you should
995 * always set these to the same value for all windows in an
996 * application, and GTK+ sets them to that value by default, so calling
997 * this function is sort of pointless. However, you may want to call
998 * gtk_window_set_role() on each window in your application, for the
999 * benefit of the session manager. Setting the role allows the window
1000 * manager to restore window positions when loading a saved session.
1004 gtk_window_set_wmclass (GtkWindow *window,
1005 const gchar *wmclass_name,
1006 const gchar *wmclass_class)
1008 g_return_if_fail (GTK_IS_WINDOW (window));
1010 g_free (window->wmclass_name);
1011 window->wmclass_name = g_strdup (wmclass_name);
1013 g_free (window->wmclass_class);
1014 window->wmclass_class = g_strdup (wmclass_class);
1016 if (GTK_WIDGET_REALIZED (window))
1017 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1021 * gtk_window_set_role:
1022 * @window: a #GtkWindow
1023 * @role: unique identifier for the window to be used when restoring a session
1025 * This function is only useful on X11, not with other GTK+ targets.
1027 * In combination with the window title, the window role allows a
1028 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1029 * same" window when an application is restarted. So for example you
1030 * might set the "toolbox" role on your app's toolbox window, so that
1031 * when the user restarts their session, the window manager can put
1032 * the toolbox back in the same place.
1034 * If a window already has a unique title, you don't need to set the
1035 * role, since the WM can use the title to identify the window when
1036 * restoring the session.
1040 gtk_window_set_role (GtkWindow *window,
1043 g_return_if_fail (GTK_IS_WINDOW (window));
1045 if (role == window->wm_role)
1048 g_free (window->wm_role);
1049 window->wm_role = g_strdup (role);
1051 if (GTK_WIDGET_REALIZED (window))
1052 g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
1056 * gtk_window_get_role:
1057 * @window: a #GtkWindow
1059 * Returns the role of the window. See gtk_window_set_role() for
1060 * further explanation.
1062 * Return value: the role of the window if set, or %NULL. The
1063 * returned is owned by the widget and must not be modified
1066 G_CONST_RETURN gchar *
1067 gtk_window_get_role (GtkWindow *window)
1069 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1071 return window->wm_role;
1075 * gtk_window_set_focus:
1076 * @window: a #GtkWindow
1077 * @focus: widget to be the new focus widget, or %NULL to unset
1078 * any focus widget for the toplevel window.
1080 * If @focus is not the current focus widget, and is focusable, sets
1081 * it as the focus widget for the window. If @focus is %NULL, unsets
1082 * the focus widget for this window. To set the focus to a particular
1083 * widget in the toplevel, it is usually more convenient to use
1084 * gtk_widget_grab_focus() instead of this function.
1087 gtk_window_set_focus (GtkWindow *window,
1090 g_return_if_fail (GTK_IS_WINDOW (window));
1093 g_return_if_fail (GTK_IS_WIDGET (focus));
1094 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1098 gtk_widget_grab_focus (focus);
1101 /* Clear the existing focus chain, so that when we focus into
1102 * the window again, we start at the beginnning.
1104 GtkWidget *widget = window->focus_widget;
1107 while (widget->parent)
1109 widget = widget->parent;
1110 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1114 _gtk_window_internal_set_focus (window, NULL);
1119 _gtk_window_internal_set_focus (GtkWindow *window,
1122 g_return_if_fail (GTK_IS_WINDOW (window));
1124 if ((window->focus_widget != focus) ||
1125 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1126 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1130 * gtk_window_set_default:
1131 * @window: a #GtkWindow
1132 * @default_widget: widget to be the default, or %NULL to unset the
1133 * default widget for the toplevel.
1135 * The default widget is the widget that's activated when the user
1136 * presses Enter in a dialog (for example). This function sets or
1137 * unsets the default widget for a #GtkWindow about. When setting
1138 * (rather than unsetting) the default widget it's generally easier to
1139 * call gtk_widget_grab_focus() on the widget. Before making a widget
1140 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1141 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1144 gtk_window_set_default (GtkWindow *window,
1145 GtkWidget *default_widget)
1147 g_return_if_fail (GTK_IS_WINDOW (window));
1150 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1152 if (window->default_widget != default_widget)
1154 GtkWidget *old_default_widget = NULL;
1157 g_object_ref (default_widget);
1159 if (window->default_widget)
1161 old_default_widget = window->default_widget;
1163 if (window->focus_widget != window->default_widget ||
1164 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1165 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1166 gtk_widget_queue_draw (window->default_widget);
1169 window->default_widget = default_widget;
1171 if (window->default_widget)
1173 if (window->focus_widget == NULL ||
1174 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1175 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1176 gtk_widget_queue_draw (window->default_widget);
1179 if (old_default_widget)
1180 g_object_notify (G_OBJECT (old_default_widget), "has_default");
1184 g_object_notify (G_OBJECT (default_widget), "has_default");
1185 g_object_unref (default_widget);
1191 gtk_window_set_policy (GtkWindow *window,
1192 gboolean allow_shrink,
1193 gboolean allow_grow,
1194 gboolean auto_shrink)
1196 g_return_if_fail (GTK_IS_WINDOW (window));
1198 window->allow_shrink = (allow_shrink != FALSE);
1199 window->allow_grow = (allow_grow != FALSE);
1201 g_object_freeze_notify (G_OBJECT (window));
1202 g_object_notify (G_OBJECT (window), "allow_shrink");
1203 g_object_notify (G_OBJECT (window), "allow_grow");
1204 g_object_notify (G_OBJECT (window), "resizable");
1205 g_object_thaw_notify (G_OBJECT (window));
1207 gtk_widget_queue_resize (GTK_WIDGET (window));
1211 handle_keys_changed (gpointer data)
1215 GDK_THREADS_ENTER ();
1216 window = GTK_WINDOW (data);
1218 if (window->keys_changed_handler)
1220 gtk_idle_remove (window->keys_changed_handler);
1221 window->keys_changed_handler = 0;
1224 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1225 GDK_THREADS_LEAVE ();
1231 gtk_window_notify_keys_changed (GtkWindow *window)
1233 if (!window->keys_changed_handler)
1234 window->keys_changed_handler = gtk_idle_add (handle_keys_changed, window);
1238 * gtk_window_add_accel_group:
1239 * @window: window to attach accelerator group to
1240 * @accel_group: a #GtkAccelGroup
1242 * Associate @accel_group with @window, such that calling
1243 * gtk_accel_groups_activate() on @window will activate accelerators
1247 gtk_window_add_accel_group (GtkWindow *window,
1248 GtkAccelGroup *accel_group)
1250 g_return_if_fail (GTK_IS_WINDOW (window));
1251 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1253 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1254 g_signal_connect_object (accel_group, "accel_changed",
1255 G_CALLBACK (gtk_window_notify_keys_changed),
1256 window, G_CONNECT_SWAPPED);
1260 * gtk_window_remove_accel_group:
1261 * @window: a #GtkWindow
1262 * @accel_group: a #GtkAccelGroup
1264 * Reverses the effects of gtk_window_add_accel_group().
1267 gtk_window_remove_accel_group (GtkWindow *window,
1268 GtkAccelGroup *accel_group)
1270 g_return_if_fail (GTK_IS_WINDOW (window));
1271 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1273 g_signal_handlers_disconnect_by_func (accel_group,
1274 gtk_window_notify_keys_changed,
1276 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1280 * gtk_window_add_mnemonic:
1281 * @window: a #GtkWindow
1282 * @keyval: the mnemonic
1283 * @target: the widget that gets activated by the mnemonic
1285 * Adds a mnemonic to this window.
1288 gtk_window_add_mnemonic (GtkWindow *window,
1292 GtkWindowMnemonic key;
1293 GtkWindowMnemonic *mnemonic;
1295 g_return_if_fail (GTK_IS_WINDOW (window));
1296 g_return_if_fail (GTK_IS_WIDGET (target));
1298 key.window = window;
1299 key.keyval = keyval;
1300 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1304 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1305 mnemonic->targets = g_slist_append (mnemonic->targets, target);
1309 mnemonic = g_new (GtkWindowMnemonic, 1);
1311 mnemonic->targets = g_slist_prepend (NULL, target);
1312 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1314 gtk_window_notify_keys_changed (window);
1318 * gtk_window_remove_mnemonic:
1319 * @window: a #GtkWindow
1320 * @keyval: the mnemonic
1321 * @target: the widget that gets activated by the mnemonic
1323 * Removes a mnemonic from this window.
1326 gtk_window_remove_mnemonic (GtkWindow *window,
1330 GtkWindowMnemonic key;
1331 GtkWindowMnemonic *mnemonic;
1333 g_return_if_fail (GTK_IS_WINDOW (window));
1334 g_return_if_fail (GTK_IS_WIDGET (target));
1336 key.window = window;
1337 key.keyval = keyval;
1338 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1340 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1342 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1343 if (mnemonic->targets == NULL)
1345 g_hash_table_remove (mnemonic_hash_table, mnemonic);
1348 gtk_window_notify_keys_changed (window);
1352 * gtk_window_mnemonic_activate:
1353 * @window: a #GtkWindow
1354 * @keyval: the mnemonic
1355 * @modifier: the modifiers
1356 * @returns: %TRUE if the activation is done.
1358 * Activates the targets associated with the mnemonic.
1361 gtk_window_mnemonic_activate (GtkWindow *window,
1363 GdkModifierType modifier)
1365 GtkWindowMnemonic key;
1366 GtkWindowMnemonic *mnemonic;
1368 GtkWidget *widget, *chosen_widget;
1369 gboolean overloaded;
1371 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1373 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1376 key.window = window;
1377 key.keyval = keyval;
1378 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1384 chosen_widget = NULL;
1385 list = mnemonic->targets;
1388 widget = GTK_WIDGET (list->data);
1390 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1391 GTK_WIDGET_MAPPED (widget))
1399 chosen_widget = widget;
1401 list = g_slist_next (list);
1406 /* For round robin we put the activated entry on
1407 * the end of the list after activation
1409 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1410 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1412 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1418 * gtk_window_set_mnemonic_modifier:
1419 * @window: a #GtkWindow
1420 * @modifier: the modifier mask used to activate
1421 * mnemonics on this window.
1423 * Sets the mnemonic modifier for this window.
1426 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1427 GdkModifierType modifier)
1429 g_return_if_fail (GTK_IS_WINDOW (window));
1430 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1432 window->mnemonic_modifier = modifier;
1433 gtk_window_notify_keys_changed (window);
1437 * gtk_window_get_mnemonic_modifier:
1438 * @window: a #GtkWindow
1440 * Returns the mnemonic modifier for this window. See
1441 * gtk_window_set_mnemonic_modifier().
1443 * Return value: the modifier mask used to activate
1444 * mnemonics on this window.
1447 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1449 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1451 return window->mnemonic_modifier;
1455 * gtk_window_set_position:
1456 * @window: a #GtkWindow.
1457 * @position: a position constraint.
1459 * Sets a position constraint for this window. If the old or new
1460 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1461 * the window to be repositioned to satisfy the new constraint.
1464 gtk_window_set_position (GtkWindow *window,
1465 GtkWindowPosition position)
1467 g_return_if_fail (GTK_IS_WINDOW (window));
1469 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1470 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1472 GtkWindowGeometryInfo *info;
1474 info = gtk_window_get_geometry_info (window, TRUE);
1476 /* this flag causes us to re-request the CENTER_ALWAYS
1477 * constraint in gtk_window_move_resize(), see
1478 * comment in that function.
1480 info->position_constraints_changed = TRUE;
1482 gtk_widget_queue_resize (GTK_WIDGET (window));
1485 window->position = position;
1487 g_object_notify (G_OBJECT (window), "window_position");
1491 gtk_window_activate_focus (GtkWindow *window)
1493 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1495 if (window->focus_widget)
1497 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1498 gtk_widget_activate (window->focus_widget);
1506 * gtk_window_get_focus:
1507 * @window: a #GtkWindow
1509 * Retrieves the current focused widget within the window.
1510 * Note that this is the widget that would have the focus
1511 * if the toplevel window focused; if the toplevel window
1512 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1513 * not be %TRUE for the widget.
1515 * Return value: the currently focused widget.
1518 gtk_window_get_focus (GtkWindow *window)
1520 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1522 return window->focus_widget;
1526 gtk_window_activate_default (GtkWindow *window)
1528 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1530 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1531 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1533 gtk_widget_activate (window->default_widget);
1536 else if (window->focus_widget)
1538 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1539 gtk_widget_activate (window->focus_widget);
1547 * gtk_window_set_modal:
1548 * @window: a #GtkWindow
1549 * @modal: whether the window is modal
1551 * Sets a window modal or non-modal. Modal windows prevent interaction
1552 * with other windows in the same application. To keep modal dialogs
1553 * on top of main application windows, use
1554 * gtk_window_set_transient_for() to make the dialog transient for the
1555 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1556 * will then disallow lowering the dialog below the parent.
1561 gtk_window_set_modal (GtkWindow *window,
1564 g_return_if_fail (GTK_IS_WINDOW (window));
1566 window->modal = modal != FALSE;
1568 /* adjust desired modality state */
1569 if (GTK_WIDGET_VISIBLE (window) && window->modal)
1570 gtk_grab_add (GTK_WIDGET (window));
1572 gtk_grab_remove (GTK_WIDGET (window));
1574 g_object_notify (G_OBJECT (window), "modal");
1578 * gtk_window_get_modal:
1579 * @window: a #GtkWindow
1581 * Returns whether the window is modal. See gtk_window_set_modal().
1583 * Return value: %TRUE if the window is set to be modal and
1584 * establishes a grab when shown
1587 gtk_window_get_modal (GtkWindow *window)
1589 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1591 return window->modal;
1595 * gtk_window_list_toplevels:
1597 * Returns a list of all existing toplevel windows. The widgets
1598 * in the list are not individually referenced. If you want
1599 * to iterate through the list and perform actions involving
1600 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1601 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1602 * then unref all the widgets afterwards.
1604 * Return value: list of toplevel widgets
1607 gtk_window_list_toplevels (void)
1612 for (slist = toplevel_list; slist; slist = slist->next)
1613 list = g_list_prepend (list, slist->data);
1619 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1621 GList *embedded_windows;
1623 g_return_if_fail (GTK_IS_WINDOW (window));
1625 embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1626 if (embedded_windows)
1627 g_object_steal_qdata (G_OBJECT (window),
1628 g_quark_from_static_string ("gtk-embedded"));
1629 embedded_windows = g_list_prepend (embedded_windows,
1630 GUINT_TO_POINTER (xid));
1632 g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
1635 (GDestroyNotify) g_list_free : NULL);
1639 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1641 GList *embedded_windows;
1644 g_return_if_fail (GTK_IS_WINDOW (window));
1646 embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1647 if (embedded_windows)
1648 g_object_steal_qdata (G_OBJECT (window),
1649 g_quark_from_static_string ("gtk-embedded"));
1651 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1654 embedded_windows = g_list_remove_link (embedded_windows, node);
1655 g_list_free_1 (node);
1658 g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
1661 (GDestroyNotify) g_list_free : NULL);
1665 _gtk_window_reposition (GtkWindow *window,
1669 g_return_if_fail (GTK_IS_WINDOW (window));
1671 gtk_window_move (window, x, y);
1675 gtk_window_dispose (GObject *object)
1677 GtkWindow *window = GTK_WINDOW (object);
1679 gtk_window_set_focus (window, NULL);
1680 gtk_window_set_default (window, NULL);
1682 G_OBJECT_CLASS (parent_class)->dispose (object);
1686 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1688 gtk_widget_destroy (GTK_WIDGET (child));
1692 connect_parent_destroyed (GtkWindow *window)
1694 if (window->transient_parent)
1696 g_signal_connect (window->transient_parent,
1698 G_CALLBACK (parent_destroyed_callback),
1704 disconnect_parent_destroyed (GtkWindow *window)
1706 if (window->transient_parent)
1708 g_signal_handlers_disconnect_by_func (window->transient_parent,
1709 parent_destroyed_callback,
1715 gtk_window_transient_parent_realized (GtkWidget *parent,
1718 if (GTK_WIDGET_REALIZED (window))
1719 gdk_window_set_transient_for (window->window, parent->window);
1723 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1726 if (GTK_WIDGET_REALIZED (window))
1727 gdk_property_delete (window->window,
1728 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1732 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
1736 gtk_window_set_screen (window, parent->screen);
1740 gtk_window_unset_transient_for (GtkWindow *window)
1742 if (window->transient_parent)
1744 g_signal_handlers_disconnect_by_func (window->transient_parent,
1745 gtk_window_transient_parent_realized,
1747 g_signal_handlers_disconnect_by_func (window->transient_parent,
1748 gtk_window_transient_parent_unrealized,
1750 g_signal_handlers_disconnect_by_func (window->transient_parent,
1751 gtk_window_transient_parent_screen_changed,
1753 g_signal_handlers_disconnect_by_func (window->transient_parent,
1754 gtk_widget_destroyed,
1755 &window->transient_parent);
1757 if (window->destroy_with_parent)
1758 disconnect_parent_destroyed (window);
1760 window->transient_parent = NULL;
1765 * gtk_window_set_transient_for:
1766 * @window: a #GtkWindow
1767 * @parent: parent window
1769 * Dialog windows should be set transient for the main application
1770 * window they were spawned from. This allows <link
1771 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1772 * dialog on top of the main window, or center the dialog over the
1773 * main window. gtk_dialog_new_with_buttons() and other convenience
1774 * functions in GTK+ will sometimes call
1775 * gtk_window_set_transient_for() on your behalf.
1777 * On Windows, this function will and put the child window
1778 * on top of the parent, much as the window manager would have
1783 gtk_window_set_transient_for (GtkWindow *window,
1786 g_return_if_fail (GTK_IS_WINDOW (window));
1787 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1788 g_return_if_fail (window != parent);
1791 if (window->transient_parent)
1793 if (GTK_WIDGET_REALIZED (window) &&
1794 GTK_WIDGET_REALIZED (window->transient_parent) &&
1795 (!parent || !GTK_WIDGET_REALIZED (parent)))
1796 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1797 GTK_WIDGET (window));
1799 gtk_window_unset_transient_for (window);
1802 window->transient_parent = parent;
1806 g_signal_connect (parent, "destroy",
1807 G_CALLBACK (gtk_widget_destroyed),
1808 &window->transient_parent);
1809 g_signal_connect (parent, "realize",
1810 G_CALLBACK (gtk_window_transient_parent_realized),
1812 g_signal_connect (parent, "unrealize",
1813 G_CALLBACK (gtk_window_transient_parent_unrealized),
1815 g_signal_connect (parent, "notify::screen",
1816 G_CALLBACK (gtk_window_transient_parent_screen_changed),
1819 gtk_window_set_screen (window, parent->screen);
1821 if (window->destroy_with_parent)
1822 connect_parent_destroyed (window);
1824 if (GTK_WIDGET_REALIZED (window) &&
1825 GTK_WIDGET_REALIZED (parent))
1826 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1827 GTK_WIDGET (window));
1832 * gtk_window_get_transient_for:
1833 * @window: a #GtkWindow
1835 * Fetches the transient parent for this window. See
1836 * gtk_window_set_transient_for().
1838 * Return value: the transient parent for this window, or %NULL
1839 * if no transient parent has been set.
1842 gtk_window_get_transient_for (GtkWindow *window)
1844 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1846 return window->transient_parent;
1850 * gtk_window_set_type_hint:
1851 * @window: a #GtkWindow
1852 * @hint: the window type
1854 * By setting the type hint for the window, you allow the window
1855 * manager to decorate and handle the window in a way which is
1856 * suitable to the function of the window in your application.
1858 * This function should be called before the window becomes visible.
1860 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1861 * will sometimes call gtk_window_set_type_hint() on your behalf.
1865 gtk_window_set_type_hint (GtkWindow *window,
1866 GdkWindowTypeHint hint)
1868 g_return_if_fail (GTK_IS_WINDOW (window));
1869 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1870 window->type_hint = hint;
1874 * gtk_window_get_type_hint:
1875 * @window: a #GtkWindow
1877 * Gets the type hint for this window. See gtk_window_set_type_hint().
1879 * Return value: the type hint for @window.
1882 gtk_window_get_type_hint (GtkWindow *window)
1884 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1886 return window->type_hint;
1890 * gtk_window_set_skip_taskbar_hint:
1891 * @window: a #GtkWindow
1892 * @setting: %TRUE to keep this window from appearing in the task bar
1894 * Windows may set a hint asking the desktop environment not to display
1895 * the window in the task bar. This function toggles this hint.
1900 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
1903 GtkWindowPrivate *priv;
1905 g_return_if_fail (GTK_IS_WINDOW (window));
1907 priv = gtk_window_get_private (window);
1909 setting = setting != FALSE;
1911 if (priv->skips_taskbar != setting)
1913 priv->skips_taskbar = setting;
1914 if (GTK_WIDGET_REALIZED (window))
1915 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
1916 priv->skips_taskbar);
1917 g_object_notify (G_OBJECT (window), "skip_taskbar_hint");
1922 * gtk_window_get_skip_taskbar_hint:
1923 * @window: a #GtkWindow
1925 * Gets the value set by gtk_window_set_skip_taskbar_hint()
1927 * Return value: %TRUE if window shouldn't be in taskbar
1932 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
1934 GtkWindowPrivate *priv;
1936 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1938 priv = gtk_window_get_private (window);
1940 return priv->skips_taskbar;
1944 * gtk_window_set_skip_pager_hint:
1945 * @window: a #GtkWindow
1946 * @setting: %TRUE to keep this window from appearing in the pager
1948 * Windows may set a hint asking the desktop environment not to display
1949 * the window in the pager. This function toggles this hint.
1950 * (A "pager" is any desktop navigation tool such as a workspace
1951 * switcher that displays a thumbnail representation of the windows
1957 gtk_window_set_skip_pager_hint (GtkWindow *window,
1960 GtkWindowPrivate *priv;
1962 g_return_if_fail (GTK_IS_WINDOW (window));
1964 priv = gtk_window_get_private (window);
1966 setting = setting != FALSE;
1968 if (priv->skips_pager != setting)
1970 priv->skips_pager = setting;
1971 if (GTK_WIDGET_REALIZED (window))
1972 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
1974 g_object_notify (G_OBJECT (window), "skip_pager_hint");
1979 * gtk_window_get_skip_pager_hint:
1980 * @window: a #GtkWindow
1982 * Gets the value set by gtk_window_set_skip_pager_hint().
1984 * Return value: %TRUE if window shouldn't be in pager
1989 gtk_window_get_skip_pager_hint (GtkWindow *window)
1991 GtkWindowPrivate *priv;
1993 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1995 priv = gtk_window_get_private (window);
1997 return priv->skips_pager;
2001 * gtk_window_set_destroy_with_parent:
2002 * @window: a #GtkWindow
2003 * @setting: whether to destroy @window with its transient parent
2005 * If @setting is %TRUE, then destroying the transient parent of @window
2006 * will also destroy @window itself. This is useful for dialogs that
2007 * shouldn't persist beyond the lifetime of the main window they're
2008 * associated with, for example.
2011 gtk_window_set_destroy_with_parent (GtkWindow *window,
2014 g_return_if_fail (GTK_IS_WINDOW (window));
2016 if (window->destroy_with_parent == (setting != FALSE))
2019 if (window->destroy_with_parent)
2021 disconnect_parent_destroyed (window);
2025 connect_parent_destroyed (window);
2028 window->destroy_with_parent = setting;
2030 g_object_notify (G_OBJECT (window), "destroy_with_parent");
2034 * gtk_window_get_destroy_with_parent:
2035 * @window: a #GtkWindow
2037 * Returns whether the window will be destroyed with its transient parent. See
2038 * gtk_window_set_destroy_with_parent ().
2040 * Return value: %TRUE if the window will be destroyed with its transient parent.
2043 gtk_window_get_destroy_with_parent (GtkWindow *window)
2045 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2047 return window->destroy_with_parent;
2050 static GtkWindowGeometryInfo*
2051 gtk_window_get_geometry_info (GtkWindow *window,
2054 GtkWindowGeometryInfo *info;
2056 info = window->geometry_info;
2057 if (!info && create)
2059 info = g_new0 (GtkWindowGeometryInfo, 1);
2061 info->default_width = -1;
2062 info->default_height = -1;
2063 info->resize_width = -1;
2064 info->resize_height = -1;
2065 info->initial_x = 0;
2066 info->initial_y = 0;
2067 info->initial_pos_set = FALSE;
2068 info->default_is_geometry = FALSE;
2069 info->position_constraints_changed = FALSE;
2070 info->last.configure_request.x = 0;
2071 info->last.configure_request.y = 0;
2072 info->last.configure_request.width = -1;
2073 info->last.configure_request.height = -1;
2074 info->widget = NULL;
2076 window->geometry_info = info;
2083 * gtk_window_set_geometry_hints:
2084 * @window: a #GtkWindow
2085 * @geometry_widget: widget the geometry hints will be applied to
2086 * @geometry: struct containing geometry information
2087 * @geom_mask: mask indicating which struct fields should be paid attention to
2089 * This function sets up hints about how a window can be resized by
2090 * the user. You can set a minimum and maximum size; allowed resize
2091 * increments (e.g. for xterm, you can only resize by the size of a
2092 * character); aspect ratios; and more. See the #GdkGeometry struct.
2096 gtk_window_set_geometry_hints (GtkWindow *window,
2097 GtkWidget *geometry_widget,
2098 GdkGeometry *geometry,
2099 GdkWindowHints geom_mask)
2101 GtkWindowGeometryInfo *info;
2103 g_return_if_fail (GTK_IS_WINDOW (window));
2104 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2106 info = gtk_window_get_geometry_info (window, TRUE);
2109 g_signal_handlers_disconnect_by_func (info->widget,
2110 gtk_widget_destroyed,
2113 info->widget = geometry_widget;
2115 g_signal_connect (geometry_widget, "destroy",
2116 G_CALLBACK (gtk_widget_destroyed),
2120 info->geometry = *geometry;
2122 /* We store gravity in window->gravity not in the hints. */
2123 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2125 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2127 gtk_window_set_gravity (window, geometry->win_gravity);
2130 gtk_widget_queue_resize (GTK_WIDGET (window));
2134 * gtk_window_set_decorated:
2135 * @window: a #GtkWindow
2136 * @setting: %TRUE to decorate the window
2138 * By default, windows are decorated with a title bar, resize
2139 * controls, etc. Some <link linkend="gtk-X11-arch">window
2140 * managers</link> allow GTK+ to disable these decorations, creating a
2141 * borderless window. If you set the decorated property to %FALSE
2142 * using this function, GTK+ will do its best to convince the window
2143 * manager not to decorate the window. Depending on the system, this
2144 * function may not have any effect when called on a window that is
2145 * already visible, so you should call it before calling gtk_window_show().
2147 * On Windows, this function always works, since there's no window manager
2152 gtk_window_set_decorated (GtkWindow *window,
2155 g_return_if_fail (GTK_IS_WINDOW (window));
2157 setting = setting != FALSE;
2159 if (setting == window->decorated)
2162 window->decorated = setting;
2164 if (GTK_WIDGET (window)->window)
2166 if (window->decorated)
2167 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2170 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2176 * gtk_window_get_decorated:
2177 * @window: a #GtkWindow
2179 * Returns whether the window has been set to have decorations
2180 * such as a title bar via gtk_window_set_decorated().
2182 * Return value: %TRUE if the window has been set to have decorations
2185 gtk_window_get_decorated (GtkWindow *window)
2187 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2189 return window->decorated;
2192 static GtkWindowIconInfo*
2193 get_icon_info (GtkWindow *window)
2195 return g_object_get_data (G_OBJECT (window),
2196 "gtk-window-icon-info");
2199 static GtkWindowIconInfo*
2200 ensure_icon_info (GtkWindow *window)
2202 GtkWindowIconInfo *info;
2204 info = get_icon_info (window);
2208 info = g_new0 (GtkWindowIconInfo, 1);
2209 g_object_set_data_full (G_OBJECT (window),
2210 "gtk-window-icon-info",
2225 get_screen_icon_info (GdkScreen *screen)
2227 ScreenIconInfo *info = g_object_get_data (G_OBJECT (screen),
2228 "gtk-window-default-icon-pixmap");
2231 info = g_new0 (ScreenIconInfo, 1);
2232 g_object_set_data (G_OBJECT (screen), "gtk-window-default-icon-pixmap", info);
2235 if (info->serial != default_icon_serial)
2239 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2240 info->pixmap = NULL;
2245 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2249 info->serial = default_icon_serial;
2256 get_pixmap_and_mask (GdkWindow *window,
2257 GtkWindowIconInfo *parent_info,
2258 gboolean is_default_list,
2260 GdkPixmap **pmap_return,
2261 GdkBitmap **mask_return)
2263 GdkScreen *screen = gdk_drawable_get_screen (window);
2264 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2265 GdkPixbuf *best_icon;
2269 *pmap_return = NULL;
2270 *mask_return = NULL;
2272 if (is_default_list &&
2273 default_icon_info->pixmap != NULL)
2275 /* Use shared icon pixmap for all windows on this screen.
2277 if (default_icon_info->pixmap)
2278 g_object_ref (default_icon_info->pixmap);
2279 if (default_icon_info->mask)
2280 g_object_ref (default_icon_info->mask);
2282 *pmap_return = default_icon_info->pixmap;
2283 *mask_return = default_icon_info->mask;
2285 else if (parent_info && parent_info->icon_pixmap)
2287 if (parent_info->icon_pixmap)
2288 g_object_ref (parent_info->icon_pixmap);
2289 if (parent_info->icon_mask)
2290 g_object_ref (parent_info->icon_mask);
2292 *pmap_return = parent_info->icon_pixmap;
2293 *mask_return = parent_info->icon_mask;
2297 #define IDEAL_SIZE 48
2299 best_size = G_MAXINT;
2301 tmp_list = icon_list;
2302 while (tmp_list != NULL)
2304 GdkPixbuf *pixbuf = tmp_list->data;
2307 /* average width and height - if someone passes in a rectangular
2308 * icon they deserve what they get.
2310 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2313 if (best_icon == NULL)
2320 /* icon is better if it's 32 pixels or larger, and closer to
2321 * the ideal size than the current best.
2324 (ABS (best_size - IDEAL_SIZE) <
2325 ABS (this - IDEAL_SIZE)))
2332 tmp_list = tmp_list->next;
2336 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2337 gdk_screen_get_system_colormap (screen),
2342 /* Save pmap/mask for others to use if appropriate */
2345 parent_info->icon_pixmap = *pmap_return;
2346 parent_info->icon_mask = *mask_return;
2348 if (parent_info->icon_pixmap)
2349 g_object_ref (parent_info->icon_pixmap);
2350 if (parent_info->icon_mask)
2351 g_object_ref (parent_info->icon_mask);
2353 else if (is_default_list)
2355 default_icon_info->pixmap = *pmap_return;
2356 default_icon_info->mask = *mask_return;
2358 if (default_icon_info->pixmap)
2359 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2360 (gpointer*)&default_icon_info->pixmap);
2361 if (default_icon_info->mask)
2362 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2363 (gpointer*)&default_icon_info->mask);
2369 gtk_window_realize_icon (GtkWindow *window)
2372 GtkWindowIconInfo *info;
2375 widget = GTK_WIDGET (window);
2377 g_return_if_fail (widget->window != NULL);
2379 /* no point setting an icon on override-redirect */
2380 if (window->type == GTK_WINDOW_POPUP)
2385 info = ensure_icon_info (window);
2390 g_return_if_fail (info->icon_pixmap == NULL);
2391 g_return_if_fail (info->icon_mask == NULL);
2393 info->using_default_icon = FALSE;
2394 info->using_parent_icon = FALSE;
2396 icon_list = info->icon_list;
2398 /* Inherit from transient parent */
2399 if (icon_list == NULL && window->transient_parent)
2401 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2403 info->using_parent_icon = TRUE;
2406 /* Inherit from default */
2407 if (icon_list == NULL)
2409 icon_list = default_icon_list;
2411 info->using_default_icon = TRUE;
2414 gdk_window_set_icon_list (widget->window, icon_list);
2416 get_pixmap_and_mask (widget->window,
2417 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2418 info->using_default_icon,
2423 /* This is a slight ICCCM violation since it's a color pixmap not
2424 * a bitmap, but everyone does it.
2426 gdk_window_set_icon (widget->window,
2431 info->realized = TRUE;
2435 gtk_window_unrealize_icon (GtkWindow *window)
2437 GtkWindowIconInfo *info;
2440 widget = GTK_WIDGET (window);
2442 info = get_icon_info (window);
2447 if (info->icon_pixmap)
2448 g_object_unref (info->icon_pixmap);
2450 if (info->icon_mask)
2451 g_object_unref (info->icon_mask);
2453 info->icon_pixmap = NULL;
2454 info->icon_mask = NULL;
2456 /* We don't clear the properties on the window, just figure the
2457 * window is going away.
2460 info->realized = FALSE;
2464 * gtk_window_set_icon_list:
2465 * @window: a #GtkWindow
2466 * @list: list of #GdkPixbuf
2468 * Sets up the icon representing a #GtkWindow. The icon is used when
2469 * the window is minimized (also known as iconified). Some window
2470 * managers or desktop environments may also place it in the window
2471 * frame, or display it in other contexts.
2473 * gtk_window_set_icon_list() allows you to pass in the same icon in
2474 * several hand-drawn sizes. The list should contain the natural sizes
2475 * your icon is available in; that is, don't scale the image before
2476 * passing it to GTK+. Scaling is postponed until the last minute,
2477 * when the desired final size is known, to allow best quality.
2479 * By passing several sizes, you may improve the final image quality
2480 * of the icon, by reducing or eliminating automatic image scaling.
2482 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2483 * larger images (64x64, 128x128) if you have them.
2485 * See also gtk_window_set_default_icon_list() to set the icon
2486 * for all windows in your application in one go.
2488 * Note that transient windows (those who have been set transient for another
2489 * window using gtk_window_set_transient_for()) will inherit their
2490 * icon from their transient parent. So there's no need to explicitly
2491 * set the icon on transient windows.
2494 gtk_window_set_icon_list (GtkWindow *window,
2497 GtkWindowIconInfo *info;
2499 g_return_if_fail (GTK_IS_WINDOW (window));
2501 info = ensure_icon_info (window);
2503 if (info->icon_list == list) /* check for NULL mostly */
2506 g_list_foreach (info->icon_list,
2507 (GFunc) g_object_unref, NULL);
2509 g_list_free (info->icon_list);
2511 info->icon_list = g_list_copy (list);
2512 g_list_foreach (info->icon_list,
2513 (GFunc) g_object_ref, NULL);
2515 g_object_notify (G_OBJECT (window), "icon");
2517 gtk_window_unrealize_icon (window);
2519 if (GTK_WIDGET_REALIZED (window))
2520 gtk_window_realize_icon (window);
2522 /* We could try to update our transient children, but I don't think
2523 * it's really worth it. If we did it, the best way would probably
2524 * be to have children connect to notify::icon_list
2529 * gtk_window_get_icon_list:
2530 * @window: a #GtkWindow
2532 * Retrieves the list of icons set by gtk_window_set_icon_list().
2533 * The list is copied, but the reference count on each
2534 * member won't be incremented.
2536 * Return value: copy of window's icon list
2539 gtk_window_get_icon_list (GtkWindow *window)
2541 GtkWindowIconInfo *info;
2543 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2545 info = get_icon_info (window);
2548 return g_list_copy (info->icon_list);
2554 * gtk_window_set_icon:
2555 * @window: a #GtkWindow
2556 * @icon: icon image, or %NULL
2558 * Sets up the icon representing a #GtkWindow. This icon is used when
2559 * the window is minimized (also known as iconified). Some window
2560 * managers or desktop environments may also place it in the window
2561 * frame, or display it in other contexts.
2563 * The icon should be provided in whatever size it was naturally
2564 * drawn; that is, don't scale the image before passing it to
2565 * GTK+. Scaling is postponed until the last minute, when the desired
2566 * final size is known, to allow best quality.
2568 * If you have your icon hand-drawn in multiple sizes, use
2569 * gtk_window_set_icon_list(). Then the best size will be used.
2571 * This function is equivalent to calling gtk_window_set_icon_list()
2572 * with a 1-element list.
2574 * See also gtk_window_set_default_icon_list() to set the icon
2575 * for all windows in your application in one go.
2578 gtk_window_set_icon (GtkWindow *window,
2583 g_return_if_fail (GTK_IS_WINDOW (window));
2584 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2589 list = g_list_append (list, icon);
2591 gtk_window_set_icon_list (window, list);
2596 * gtk_window_get_icon:
2597 * @window: a #GtkWindow
2599 * Gets the value set by gtk_window_set_icon() (or if you've
2600 * called gtk_window_set_icon_list(), gets the first icon in
2603 * Return value: icon for window
2606 gtk_window_get_icon (GtkWindow *window)
2608 GtkWindowIconInfo *info;
2610 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2612 info = get_icon_info (window);
2613 if (info && info->icon_list)
2614 return GDK_PIXBUF (info->icon_list->data);
2619 /* Load pixbuf, printing warning on failure if error == NULL
2622 load_pixbuf_verbosely (const char *filename,
2625 GError *local_err = NULL;
2628 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
2636 g_warning ("Error loading icon from file '%s':\n\t%s",
2637 filename, local_err->message);
2638 g_error_free (local_err);
2646 * gtk_window_set_icon_from_file:
2647 * @window: a #GtkWindow
2648 * @filename: location of icon file
2649 * @err: location to store error, or %NULL.
2651 * Sets the icon for @window.
2652 * Warns on failure if @err is %NULL.
2654 * This function is equivalent to calling gtk_window_set_icon()
2655 * with a pixbuf created by loading the image from @filename.
2657 * Returns: %TRUE if setting the icon succeeded.
2662 gtk_window_set_icon_from_file (GtkWindow *window,
2663 const gchar *filename,
2666 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2670 gtk_window_set_icon (window, pixbuf);
2671 g_object_unref (pixbuf);
2680 * gtk_window_set_default_icon_list:
2681 * @list: a list of #GdkPixbuf
2683 * Sets an icon list to be used as fallback for windows that haven't
2684 * had gtk_window_set_icon_list() called on them to set up a
2685 * window-specific icon list. This function allows you to set up the
2686 * icon for all windows in your app at once.
2688 * See gtk_window_set_icon_list() for more details.
2692 gtk_window_set_default_icon_list (GList *list)
2696 if (list == default_icon_list)
2699 /* Update serial so we don't used cached pixmaps/masks
2701 default_icon_serial++;
2703 g_list_foreach (default_icon_list,
2704 (GFunc) g_object_unref, NULL);
2706 g_list_free (default_icon_list);
2708 default_icon_list = g_list_copy (list);
2709 g_list_foreach (default_icon_list,
2710 (GFunc) g_object_ref, NULL);
2712 /* Update all toplevels */
2713 toplevels = gtk_window_list_toplevels ();
2714 tmp_list = toplevels;
2715 while (tmp_list != NULL)
2717 GtkWindowIconInfo *info;
2718 GtkWindow *w = tmp_list->data;
2720 info = get_icon_info (w);
2721 if (info && info->using_default_icon)
2723 gtk_window_unrealize_icon (w);
2724 if (GTK_WIDGET_REALIZED (w))
2725 gtk_window_realize_icon (w);
2728 tmp_list = tmp_list->next;
2730 g_list_free (toplevels);
2734 * gtk_window_set_default_icon_from_file:
2735 * @filename: location of icon file
2736 * @err: location to store error, or %NULL.
2738 * Sets an icon to be used as fallback for windows that haven't
2739 * had gtk_window_set_icon_list() called on them from a file
2740 * on disk. Warns on failure if @err is %NULL.
2742 * Returns: %TRUE if setting the icon succeeded.
2747 gtk_window_set_default_icon_from_file (const gchar *filename,
2750 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2754 GList *list = g_list_prepend (NULL, pixbuf);
2755 gtk_window_set_default_icon_list (list);
2758 g_object_unref (pixbuf);
2767 * gtk_window_get_default_icon_list:
2769 * Gets the value set by gtk_window_set_default_icon_list().
2770 * The list is a copy and should be freed with g_list_free(),
2771 * but the pixbufs in the list have not had their reference count
2774 * Return value: copy of default icon list
2777 gtk_window_get_default_icon_list (void)
2779 return g_list_copy (default_icon_list);
2783 gtk_window_set_default_size_internal (GtkWindow *window,
2784 gboolean change_width,
2786 gboolean change_height,
2788 gboolean is_geometry)
2790 GtkWindowGeometryInfo *info;
2792 g_return_if_fail (change_width == FALSE || width >= -1);
2793 g_return_if_fail (change_height == FALSE || height >= -1);
2795 info = gtk_window_get_geometry_info (window, TRUE);
2797 g_object_freeze_notify (G_OBJECT (window));
2799 info->default_is_geometry = is_geometry != FALSE;
2809 info->default_width = width;
2811 g_object_notify (G_OBJECT (window), "default_width");
2822 info->default_height = height;
2824 g_object_notify (G_OBJECT (window), "default_height");
2827 g_object_thaw_notify (G_OBJECT (window));
2829 gtk_widget_queue_resize (GTK_WIDGET (window));
2833 * gtk_window_set_default_size:
2834 * @window: a #GtkWindow
2835 * @width: width in pixels, or -1 to unset the default width
2836 * @height: height in pixels, or -1 to unset the default height
2838 * Sets the default size of a window. If the window's "natural" size
2839 * (its size request) is larger than the default, the default will be
2840 * ignored. More generally, if the default size does not obey the
2841 * geometry hints for the window (gtk_window_set_geometry_hints() can
2842 * be used to set these explicitly), the default size will be clamped
2843 * to the nearest permitted size.
2845 * Unlike gtk_widget_set_size_request(), which sets a size request for
2846 * a widget and thus would keep users from shrinking the window, this
2847 * function only sets the initial size, just as if the user had
2848 * resized the window themselves. Users can still shrink the window
2849 * again as they normally would. Setting a default size of -1 means to
2850 * use the "natural" default size (the size request of the window).
2852 * For more control over a window's initial size and how resizing works,
2853 * investigate gtk_window_set_geometry_hints().
2855 * For some uses, gtk_window_resize() is a more appropriate function.
2856 * gtk_window_resize() changes the current size of the window, rather
2857 * than the size to be used on initial display. gtk_window_resize() always
2858 * affects the window itself, not the geometry widget.
2860 * The default size of a window only affects the first time a window is
2861 * shown; if a window is hidden and re-shown, it will remember the size
2862 * it had prior to hiding, rather than using the default size.
2864 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2865 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2868 gtk_window_set_default_size (GtkWindow *window,
2872 g_return_if_fail (GTK_IS_WINDOW (window));
2873 g_return_if_fail (width >= -1);
2874 g_return_if_fail (height >= -1);
2876 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
2880 * gtk_window_get_default_size:
2881 * @window: a #GtkWindow
2882 * @width: location to store the default width, or %NULL
2883 * @height: location to store the default height, or %NULL
2885 * Gets the default size of the window. A value of -1 for the width or
2886 * height indicates that a default size has not been explicitly set
2887 * for that dimension, so the "natural" size of the window will be
2892 gtk_window_get_default_size (GtkWindow *window,
2896 GtkWindowGeometryInfo *info;
2898 g_return_if_fail (GTK_IS_WINDOW (window));
2900 info = gtk_window_get_geometry_info (window, FALSE);
2903 *width = info->default_width;
2906 *height = info->default_height;
2910 * gtk_window_resize:
2911 * @window: a #GtkWindow
2912 * @width: width in pixels to resize the window to
2913 * @height: height in pixels to resize the window to
2915 * Resizes the window as if the user had done so, obeying geometry
2916 * constraints. The default geometry constraint is that windows may
2917 * not be smaller than their size request; to override this
2918 * constraint, call gtk_widget_set_size_request() to set the window's
2919 * request to a smaller value.
2921 * If gtk_window_resize() is called before showing a window for the
2922 * first time, it overrides any default size set with
2923 * gtk_window_set_default_size().
2925 * Windows may not be resized smaller than 1 by 1 pixels.
2929 gtk_window_resize (GtkWindow *window,
2933 GtkWindowGeometryInfo *info;
2935 g_return_if_fail (GTK_IS_WINDOW (window));
2936 g_return_if_fail (width > 0);
2937 g_return_if_fail (height > 0);
2939 info = gtk_window_get_geometry_info (window, TRUE);
2941 info->resize_width = width;
2942 info->resize_height = height;
2944 gtk_widget_queue_resize (GTK_WIDGET (window));
2948 * gtk_window_get_size:
2949 * @window: a #GtkWindow
2950 * @width: return location for width, or %NULL
2951 * @height: return location for height, or %NULL
2953 * Obtains the current size of @window. If @window is not onscreen,
2954 * it returns the size GTK+ will suggest to the <link
2955 * linkend="gtk-X11-arch">window manager</link> for the initial window
2956 * size (but this is not reliably the same as the size the window
2957 * manager will actually select). The size obtained by
2958 * gtk_window_get_size() is the last size received in a
2959 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2960 * rather than querying the X server for the size. As a result, if you
2961 * call gtk_window_resize() then immediately call
2962 * gtk_window_get_size(), the size won't have taken effect yet. After
2963 * the window manager processes the resize request, GTK+ receives
2964 * notification that the size has changed via a configure event, and
2965 * the size of the window gets updated.
2967 * Note 1: Nearly any use of this function creates a race condition,
2968 * because the size of the window may change between the time that you
2969 * get the size and the time that you perform some action assuming
2970 * that size is the current size. To avoid race conditions, connect to
2971 * "configure_event" on the window and adjust your size-dependent
2972 * state to match the size delivered in the #GdkEventConfigure.
2974 * Note 2: The returned size does <emphasis>not</emphasis> include the
2975 * size of the window manager decorations (aka the window frame or
2976 * border). Those are not drawn by GTK+ and GTK+ has no reliable
2977 * method of determining their size.
2979 * Note 3: If you are getting a window size in order to position
2980 * the window onscreen, there may be a better way. The preferred
2981 * way is to simply set the window's semantic type with
2982 * gtk_window_set_type_hint(), which allows the window manager to
2983 * e.g. center dialogs. Also, if you set the transient parent of
2984 * dialogs with gtk_window_set_transient_for() window managers
2985 * will often center the dialog over its parent window. It's
2986 * much preferred to let the window manager handle these
2987 * things rather than doing it yourself, because all apps will
2988 * behave consistently and according to user prefs if the window
2989 * manager handles it. Also, the window manager can take the size
2990 * of the window decorations/border into account, while your
2991 * application cannot.
2993 * In any case, if you insist on application-specified window
2994 * positioning, there's <emphasis>still</emphasis> a better way than
2995 * doing it yourself - gtk_window_set_position() will frequently
2996 * handle the details for you.
3000 gtk_window_get_size (GtkWindow *window,
3007 g_return_if_fail (GTK_IS_WINDOW (window));
3009 widget = GTK_WIDGET (window);
3011 if (width == NULL && height == NULL)
3014 if (GTK_WIDGET_MAPPED (window))
3016 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3021 GdkRectangle configure_request;
3023 gtk_window_compute_configure_request (window,
3027 w = configure_request.width;
3028 h = configure_request.height;
3039 * @window: a #GtkWindow
3040 * @x: X coordinate to move window to
3041 * @y: Y coordinate to move window to
3043 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3044 * @window to the given position. Window managers are free to ignore
3045 * this; most window managers ignore requests for initial window
3046 * positions (instead using a user-defined placement algorithm) and
3047 * honor requests after the window has already been shown.
3049 * Note: the position is the position of the gravity-determined
3050 * reference point for the window. The gravity determines two things:
3051 * first, the location of the reference point in root window
3052 * coordinates; and second, which point on the window is positioned at
3053 * the reference point.
3055 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3056 * point is simply the @x, @y supplied to gtk_window_move(). The
3057 * top-left corner of the window decorations (aka window frame or
3058 * border) will be placed at @x, @y. Therefore, to position a window
3059 * at the top left of the screen, you want to use the default gravity
3060 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3062 * To position a window at the bottom right corner of the screen, you
3063 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3064 * point is at @x + the window width and @y + the window height, and
3065 * the bottom-right corner of the window border will be placed at that
3066 * reference point. So, to place a window in the bottom right corner
3067 * you would first set gravity to south east, then write:
3068 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3069 * gdk_screen_height () - window_height)</literal>.
3071 * The extended window manager hints specification at <ulink
3072 * url="http://www.freedesktop.org/standards/wm-spec.html">
3073 * http://www.freedesktop.org/standards/wm-spec.html</ulink> has a
3074 * nice table of gravities in the "implementation notes" section.
3076 * The gtk_window_get_position() documentation may also be relevant.
3080 gtk_window_move (GtkWindow *window,
3084 GtkWindowGeometryInfo *info;
3087 g_return_if_fail (GTK_IS_WINDOW (window));
3089 widget = GTK_WIDGET (window);
3091 info = gtk_window_get_geometry_info (window, TRUE);
3093 if (GTK_WIDGET_MAPPED (window))
3095 /* we have now sent a request with this position
3096 * with currently-active constraints, so toggle flag.
3098 info->position_constraints_changed = FALSE;
3100 /* we only constrain if mapped - if not mapped,
3101 * then gtk_window_compute_configure_request()
3102 * will apply the constraints later, and we
3103 * don't want to lose information about
3104 * what position the user set before then.
3105 * i.e. if you do a move() then turn off POS_CENTER
3106 * then show the window, your move() will work.
3108 gtk_window_constrain_position (window,
3109 widget->allocation.width,
3110 widget->allocation.height,
3113 /* Note that this request doesn't go through our standard request
3114 * framework, e.g. doesn't increment configure_request_count,
3115 * doesn't set info->last, etc.; that's because
3116 * we don't save the info needed to arrive at this same request
3119 * To gtk_window_move_resize(), this will end up looking exactly
3120 * the same as the position being changed by the window
3124 /* FIXME are we handling gravity properly for framed windows? */
3126 gdk_window_move (window->frame,
3127 x - window->frame_left,
3128 y - window->frame_top);
3130 gdk_window_move (GTK_WIDGET (window)->window,
3135 /* Save this position to apply on mapping */
3136 info->initial_x = x;
3137 info->initial_y = y;
3138 info->initial_pos_set = TRUE;
3143 * gtk_window_get_position:
3144 * @window: a #GtkWindow
3145 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3146 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3148 * This function returns the position you need to pass to
3149 * gtk_window_move() to keep @window in its current position. This
3150 * means that the meaning of the returned value varies with window
3151 * gravity. See gtk_window_move() for more details.
3153 * If you haven't changed the window gravity, its gravity will be
3154 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3155 * gets the position of the top-left corner of the window manager
3156 * frame for the window. gtk_window_move() sets the position of this
3157 * same top-left corner.
3159 * gtk_window_get_position() is not 100% reliable because the X Window System
3160 * does not specify a way to obtain the geometry of the
3161 * decorations placed on a window by the window manager.
3162 * Thus GTK+ is using a "best guess" that works with most
3165 * Moreover, nearly all window managers are historically broken with
3166 * respect to their handling of window gravity. So moving a window to
3167 * its current position as returned by gtk_window_get_position() tends
3168 * to result in moving the window slightly. Window managers are
3169 * slowly getting better over time.
3171 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3172 * frame is not relevant, and thus gtk_window_get_position() will
3173 * always produce accurate results. However you can't use static
3174 * gravity to do things like place a window in a corner of the screen,
3175 * because static gravity ignores the window manager decorations.
3177 * If you are saving and restoring your application's window
3178 * positions, you should know that it's impossible for applications to
3179 * do this without getting it somewhat wrong because applications do
3180 * not have sufficient knowledge of window manager state. The Correct
3181 * Mechanism is to support the session management protocol (see the
3182 * "GnomeClient" object in the GNOME libraries for example) and allow
3183 * the window manager to save your window sizes and positions.
3188 gtk_window_get_position (GtkWindow *window,
3194 g_return_if_fail (GTK_IS_WINDOW (window));
3196 widget = GTK_WIDGET (window);
3198 if (window->gravity == GDK_GRAVITY_STATIC)
3200 if (GTK_WIDGET_MAPPED (widget))
3202 /* This does a server round-trip, which is sort of wrong;
3203 * but a server round-trip is inevitable for
3204 * gdk_window_get_frame_extents() in the usual
3205 * NorthWestGravity case below, so not sure what else to
3206 * do. We should likely be consistent about whether we get
3207 * the client-side info or the server-side info.
3209 gdk_window_get_origin (widget->window, root_x, root_y);
3213 GdkRectangle configure_request;
3215 gtk_window_compute_configure_request (window,
3219 *root_x = configure_request.x;
3220 *root_y = configure_request.y;
3225 GdkRectangle frame_extents;
3230 if (GTK_WIDGET_MAPPED (widget))
3233 gdk_window_get_frame_extents (window->frame, &frame_extents);
3235 gdk_window_get_frame_extents (widget->window, &frame_extents);
3236 x = frame_extents.x;
3237 y = frame_extents.y;
3238 gtk_window_get_size (window, &w, &h);
3242 /* We just say the frame has 0 size on all sides.
3243 * Not sure what else to do.
3245 gtk_window_compute_configure_request (window,
3248 x = frame_extents.x;
3249 y = frame_extents.y;
3250 w = frame_extents.width;
3251 h = frame_extents.height;
3254 switch (window->gravity)
3256 case GDK_GRAVITY_NORTH:
3257 case GDK_GRAVITY_CENTER:
3258 case GDK_GRAVITY_SOUTH:
3259 /* Find center of frame. */
3260 x += frame_extents.width / 2;
3261 /* Center client window on that point. */
3265 case GDK_GRAVITY_SOUTH_EAST:
3266 case GDK_GRAVITY_EAST:
3267 case GDK_GRAVITY_NORTH_EAST:
3268 /* Find right edge of frame */
3269 x += frame_extents.width;
3270 /* Align left edge of client at that point. */
3277 switch (window->gravity)
3279 case GDK_GRAVITY_WEST:
3280 case GDK_GRAVITY_CENTER:
3281 case GDK_GRAVITY_EAST:
3282 /* Find center of frame. */
3283 y += frame_extents.height / 2;
3284 /* Center client window there. */
3287 case GDK_GRAVITY_SOUTH_WEST:
3288 case GDK_GRAVITY_SOUTH:
3289 case GDK_GRAVITY_SOUTH_EAST:
3290 /* Find south edge of frame */
3291 y += frame_extents.height;
3292 /* Place bottom edge of client there */
3307 * gtk_window_reshow_with_initial_size:
3308 * @window: a #GtkWindow
3310 * Hides @window, then reshows it, resetting the
3311 * default size and position of the window. Used
3312 * by GUI builders only.
3315 gtk_window_reshow_with_initial_size (GtkWindow *window)
3319 g_return_if_fail (GTK_IS_WINDOW (window));
3321 widget = GTK_WIDGET (window);
3323 gtk_widget_hide (widget);
3324 gtk_widget_unrealize (widget);
3325 gtk_widget_show (widget);
3329 gtk_window_destroy (GtkObject *object)
3331 GtkWindow *window = GTK_WINDOW (object);
3333 if (window->transient_parent)
3334 gtk_window_set_transient_for (window, NULL);
3336 /* frees the icons */
3337 gtk_window_set_icon_list (window, NULL);
3339 if (window->has_user_ref_count)
3341 window->has_user_ref_count = FALSE;
3342 g_object_unref (window);
3346 gtk_window_group_remove_window (window->group, window);
3348 gtk_window_free_key_hash (window);
3350 GTK_OBJECT_CLASS (parent_class)->destroy (object);
3354 gtk_window_mnemonic_hash_remove (gpointer key,
3358 GtkWindowMnemonic *mnemonic = key;
3359 GtkWindow *window = user;
3361 if (mnemonic->window == window)
3363 if (mnemonic->targets)
3365 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
3367 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
3368 name, mnemonic->targets->data);
3371 g_slist_free (mnemonic->targets);
3380 gtk_window_private_finalize (GtkWindowPrivate *priv)
3387 gtk_window_finalize (GObject *object)
3389 GtkWindow *window = GTK_WINDOW (object);
3391 toplevel_list = g_slist_remove (toplevel_list, window);
3393 g_free (window->title);
3394 g_free (window->wmclass_name);
3395 g_free (window->wmclass_class);
3396 g_free (window->wm_role);
3398 g_hash_table_foreach_remove (mnemonic_hash_table,
3399 gtk_window_mnemonic_hash_remove,
3401 if (window->geometry_info)
3403 if (window->geometry_info->widget)
3404 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3405 gtk_widget_destroyed,
3406 &window->geometry_info->widget);
3407 g_free (window->geometry_info);
3410 if (window->keys_changed_handler)
3412 gtk_idle_remove (window->keys_changed_handler);
3413 window->keys_changed_handler = 0;
3416 G_OBJECT_CLASS (parent_class)->finalize (object);
3420 gtk_window_show (GtkWidget *widget)
3422 GtkWindow *window = GTK_WINDOW (widget);
3423 GtkContainer *container = GTK_CONTAINER (window);
3424 gboolean need_resize;
3426 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3428 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3429 container->need_resize = FALSE;
3433 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3434 GtkAllocation allocation = { 0, 0 };
3435 GdkRectangle configure_request;
3436 GdkGeometry new_geometry;
3438 gboolean was_realized;
3440 /* We are going to go ahead and perform this configure request
3441 * and then emulate a configure notify by going ahead and
3442 * doing a size allocate. Sort of a synchronous
3443 * mini-copy of gtk_window_move_resize() here.
3445 gtk_window_compute_configure_request (window,
3450 /* We update this because we are going to go ahead
3451 * and gdk_window_resize() below, rather than
3454 info->last.configure_request.width = configure_request.width;
3455 info->last.configure_request.height = configure_request.height;
3457 /* and allocate the window - this is normally done
3458 * in move_resize in response to configure notify
3460 allocation.width = configure_request.width;
3461 allocation.height = configure_request.height;
3462 gtk_widget_size_allocate (widget, &allocation);
3464 /* Then we guarantee we have a realize */
3465 was_realized = FALSE;
3466 if (!GTK_WIDGET_REALIZED (widget))
3468 gtk_widget_realize (widget);
3469 was_realized = TRUE;
3472 /* Must be done after the windows are realized,
3473 * so that the decorations can be read
3475 gtk_decorated_window_calculate_frame_size (window);
3477 /* We only send configure request if we didn't just finish
3478 * creating the window; if we just created the window
3479 * then we created it with widget->allocation anyhow.
3482 gdk_window_resize (widget->window,
3483 configure_request.width,
3484 configure_request.height);
3487 gtk_container_check_resize (container);
3489 gtk_widget_map (widget);
3491 /* Try to make sure that we have some focused widget
3493 #ifdef GDK_WINDOWING_X11
3494 if (!window->focus_widget && !GTK_IS_PLUG (window))
3496 if (!window->focus_widget)
3498 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
3501 gtk_grab_add (widget);
3505 gtk_window_hide (GtkWidget *widget)
3507 GtkWindow *window = GTK_WINDOW (widget);
3509 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3510 gtk_widget_unmap (widget);
3513 gtk_grab_remove (widget);
3517 gtk_window_map (GtkWidget *widget)
3519 GtkWindow *window = GTK_WINDOW (widget);
3520 GdkWindow *toplevel;
3521 GtkWindowPrivate *priv;
3523 priv = gtk_window_get_private (window);
3525 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3527 if (window->bin.child &&
3528 GTK_WIDGET_VISIBLE (window->bin.child) &&
3529 !GTK_WIDGET_MAPPED (window->bin.child))
3530 gtk_widget_map (window->bin.child);
3533 toplevel = window->frame;
3535 toplevel = widget->window;
3537 if (window->maximize_initially)
3538 gdk_window_maximize (toplevel);
3540 gdk_window_unmaximize (toplevel);
3542 if (window->stick_initially)
3543 gdk_window_stick (toplevel);
3545 gdk_window_unstick (toplevel);
3547 if (window->iconify_initially)
3548 gdk_window_iconify (toplevel);
3550 gdk_window_deiconify (toplevel);
3552 if (priv->fullscreen_initially)
3553 gdk_window_fullscreen (toplevel);
3555 gdk_window_unfullscreen (toplevel);
3557 /* No longer use the default settings */
3558 window->need_default_size = FALSE;
3559 window->need_default_position = FALSE;
3561 gdk_window_show (widget->window);
3564 gdk_window_show (window->frame);
3566 if (!disable_startup_notification &&
3567 !sent_startup_notification)
3569 sent_startup_notification = TRUE;
3570 gdk_notify_startup_complete ();
3575 gtk_window_unmap (GtkWidget *widget)
3577 GtkWindow *window = GTK_WINDOW (widget);
3578 GtkWindowGeometryInfo *info;
3579 GdkWindowState state;
3581 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3583 gdk_window_withdraw (window->frame);
3585 gdk_window_withdraw (widget->window);
3587 window->configure_request_count = 0;
3588 window->configure_notify_received = FALSE;
3590 /* on unmap, we reset the default positioning of the window,
3591 * so it's placed again, but we don't reset the default
3592 * size of the window, so it's remembered.
3594 window->need_default_position = TRUE;
3596 info = gtk_window_get_geometry_info (window, FALSE);
3599 info->initial_pos_set = FALSE;
3600 info->position_constraints_changed = FALSE;
3603 state = gdk_window_get_state (widget->window);
3604 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
3605 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
3606 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
3610 gtk_window_realize (GtkWidget *widget)
3613 GdkWindow *parent_window;
3614 GdkWindowAttr attributes;
3615 gint attributes_mask;
3617 window = GTK_WINDOW (widget);
3619 /* ensure widget tree is properly size allocated */
3620 if (widget->allocation.x == -1 &&
3621 widget->allocation.y == -1 &&
3622 widget->allocation.width == 1 &&
3623 widget->allocation.height == 1)
3625 GtkRequisition requisition;
3626 GtkAllocation allocation = { 0, 0, 200, 200 };
3628 gtk_widget_size_request (widget, &requisition);
3629 if (requisition.width || requisition.height)
3631 /* non-empty window */
3632 allocation.width = requisition.width;
3633 allocation.height = requisition.height;
3635 gtk_widget_size_allocate (widget, &allocation);
3637 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3639 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3642 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3644 switch (window->type)
3646 case GTK_WINDOW_TOPLEVEL:
3647 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3649 case GTK_WINDOW_POPUP:
3650 attributes.window_type = GDK_WINDOW_TEMP;
3653 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3657 attributes.title = window->title;
3658 attributes.wmclass_name = window->wmclass_name;
3659 attributes.wmclass_class = window->wmclass_class;
3660 attributes.wclass = GDK_INPUT_OUTPUT;
3661 attributes.visual = gtk_widget_get_visual (widget);
3662 attributes.colormap = gtk_widget_get_colormap (widget);
3664 if (window->has_frame)
3666 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3667 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3668 attributes.event_mask = (GDK_EXPOSURE_MASK |
3669 GDK_KEY_PRESS_MASK |
3670 GDK_ENTER_NOTIFY_MASK |
3671 GDK_LEAVE_NOTIFY_MASK |
3672 GDK_FOCUS_CHANGE_MASK |
3673 GDK_STRUCTURE_MASK |
3674 GDK_BUTTON_MOTION_MASK |
3675 GDK_POINTER_MOTION_HINT_MASK |
3676 GDK_BUTTON_PRESS_MASK |
3677 GDK_BUTTON_RELEASE_MASK);
3679 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3681 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
3682 &attributes, attributes_mask);
3684 gdk_window_set_user_data (window->frame, widget);
3686 attributes.window_type = GDK_WINDOW_CHILD;
3687 attributes.x = window->frame_left;
3688 attributes.y = window->frame_top;
3690 attributes_mask = GDK_WA_X | GDK_WA_Y;
3692 parent_window = window->frame;
3696 attributes_mask = 0;
3697 parent_window = gtk_widget_get_root_window (widget);
3700 attributes.width = widget->allocation.width;
3701 attributes.height = widget->allocation.height;
3702 attributes.event_mask = gtk_widget_get_events (widget);
3703 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3704 GDK_KEY_PRESS_MASK |
3705 GDK_KEY_RELEASE_MASK |
3706 GDK_ENTER_NOTIFY_MASK |
3707 GDK_LEAVE_NOTIFY_MASK |
3708 GDK_FOCUS_CHANGE_MASK |
3709 GDK_STRUCTURE_MASK);
3711 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3712 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3713 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3715 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3717 gdk_window_set_user_data (widget->window, window);
3719 widget->style = gtk_style_attach (widget->style, widget->window);
3720 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3722 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3724 /* This is a bad hack to set the window background. */
3725 gtk_window_paint (widget, NULL);
3727 if (window->transient_parent &&
3728 GTK_WIDGET_REALIZED (window->transient_parent))
3729 gdk_window_set_transient_for (widget->window,
3730 GTK_WIDGET (window->transient_parent)->window);
3732 if (window->wm_role)
3733 gdk_window_set_role (widget->window, window->wm_role);
3735 if (!window->decorated)
3736 gdk_window_set_decorations (widget->window, 0);
3738 gdk_window_set_type_hint (widget->window, window->type_hint);
3740 if (gtk_window_get_skip_pager_hint (window))
3741 gdk_window_set_skip_pager_hint (widget->window, TRUE);
3743 if (gtk_window_get_skip_taskbar_hint (window))
3744 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
3746 /* transient_for must be set to allow the modal hint */
3747 if (window->transient_parent && window->modal)
3748 gdk_window_set_modal_hint (widget->window, TRUE);
3750 gdk_window_set_modal_hint (widget->window, FALSE);
3753 gtk_window_realize_icon (window);
3757 gtk_window_unrealize (GtkWidget *widget)
3760 GtkWindowGeometryInfo *info;
3762 window = GTK_WINDOW (widget);
3764 /* On unrealize, we reset the size of the window such
3765 * that we will re-apply the default sizing stuff
3766 * next time we show the window.
3768 * Default positioning is reset on unmap, instead of unrealize.
3770 window->need_default_size = TRUE;
3771 info = gtk_window_get_geometry_info (window, FALSE);
3774 info->resize_width = -1;
3775 info->resize_height = -1;
3776 info->last.configure_request.x = 0;
3777 info->last.configure_request.y = 0;
3778 info->last.configure_request.width = -1;
3779 info->last.configure_request.height = -1;
3780 /* be sure we reset geom hints on re-realize */
3781 info->last.flags = 0;
3786 gdk_window_set_user_data (window->frame, NULL);
3787 gdk_window_destroy (window->frame);
3788 window->frame = NULL;
3792 gtk_window_unrealize_icon (window);
3794 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3798 gtk_window_size_request (GtkWidget *widget,
3799 GtkRequisition *requisition)
3804 window = GTK_WINDOW (widget);
3805 bin = GTK_BIN (window);
3807 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3808 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3810 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3812 GtkRequisition child_requisition;
3814 gtk_widget_size_request (bin->child, &child_requisition);
3816 requisition->width += child_requisition.width;
3817 requisition->height += child_requisition.height;
3822 gtk_window_size_allocate (GtkWidget *widget,
3823 GtkAllocation *allocation)
3826 GtkAllocation child_allocation;
3828 window = GTK_WINDOW (widget);
3829 widget->allocation = *allocation;
3831 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3833 child_allocation.x = GTK_CONTAINER (window)->border_width;
3834 child_allocation.y = GTK_CONTAINER (window)->border_width;
3835 child_allocation.width =
3836 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3837 child_allocation.height =
3838 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3840 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3843 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3845 gdk_window_resize (window->frame,
3846 allocation->width + window->frame_left + window->frame_right,
3847 allocation->height + window->frame_top + window->frame_bottom);
3852 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3855 gboolean return_val;
3857 window = GTK_WINDOW (widget);
3859 if (window->frame && (event->any.window == window->frame))
3861 if ((event->type != GDK_KEY_PRESS) &&
3862 (event->type != GDK_KEY_RELEASE) &&
3863 (event->type != GDK_FOCUS_CHANGE))
3865 g_signal_stop_emission_by_name (widget, "event");
3867 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
3872 g_object_unref (event->any.window);
3873 event->any.window = g_object_ref (widget->window);
3881 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3883 GdkEventConfigure *configure_event;
3886 switch (event->type)
3889 configure_event = (GdkEventConfigure *)event;
3891 /* Invalidate the decorations */
3894 rect.width = configure_event->width;
3895 rect.height = configure_event->height;
3897 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3899 /* Pass on the (modified) configure event */
3900 configure_event->width -= window->frame_left + window->frame_right;
3901 configure_event->height -= window->frame_top + window->frame_bottom;
3902 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3911 gtk_window_configure_event (GtkWidget *widget,
3912 GdkEventConfigure *event)
3914 GtkWindow *window = GTK_WINDOW (widget);
3915 gboolean expected_reply = window->configure_request_count > 0;
3917 /* window->configure_request_count incremented for each
3918 * configure request, and decremented to a min of 0 for
3919 * each configure notify.
3921 * All it means is that we know we will get at least
3922 * window->configure_request_count more configure notifies.
3923 * We could get more configure notifies than that; some
3924 * of the configure notifies we get may be unrelated to
3925 * the configure requests. But we will get at least
3926 * window->configure_request_count notifies.
3929 if (window->configure_request_count > 0)
3930 window->configure_request_count -= 1;
3932 /* As an optimization, we avoid a resize when possible.
3934 * The only times we can avoid a resize are:
3935 * - we know only the position changed, not the size
3936 * - we know we have made more requests and so will get more
3937 * notifies and can wait to resize when we get them
3940 if (!expected_reply &&
3941 (widget->allocation.width == event->width &&
3942 widget->allocation.height == event->height))
3946 * If we do need to resize, we do that by:
3947 * - filling in widget->allocation with the new size
3948 * - setting configure_notify_received to TRUE
3949 * for use in gtk_window_move_resize()
3950 * - queueing a resize, leading to invocation of
3951 * gtk_window_move_resize() in an idle handler
3955 window->configure_notify_received = TRUE;
3957 widget->allocation.width = event->width;
3958 widget->allocation.height = event->height;
3960 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3965 /* the accel_key and accel_mods fields of the key have to be setup
3966 * upon calling this function. it'll then return whether that key
3967 * is at all used as accelerator, and if so will OR in the
3968 * accel_flags member of the key.
3971 _gtk_window_query_nonaccels (GtkWindow *window,
3973 GdkModifierType accel_mods)
3975 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3977 /* movement keys are considered locked accels */
3980 static const guint bindings[] = {
3981 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
3982 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
3986 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
3987 if (bindings[i] == accel_key)
3991 /* mnemonics are considered locked accels */
3992 if (accel_mods == window->mnemonic_modifier)
3994 GtkWindowMnemonic mkey;
3996 mkey.window = window;
3997 mkey.keyval = accel_key;
3998 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
4006 gtk_window_key_press_event (GtkWidget *widget,
4013 window = GTK_WINDOW (widget);
4017 /* Check for mnemonics and accelerators
4020 handled = _gtk_window_activate_key (window, event);
4024 focus = window->focus_widget;
4026 g_object_ref (focus);
4029 focus && focus != widget &&
4030 gtk_widget_get_toplevel (focus) == widget)
4034 if (GTK_WIDGET_IS_SENSITIVE (focus))
4035 handled = gtk_widget_event (focus, (GdkEvent*) event);
4037 parent = focus->parent;
4039 g_object_ref (parent);
4041 g_object_unref (focus);
4047 g_object_unref (focus);
4050 /* Chain up, invokes binding set */
4051 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
4052 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4058 gtk_window_key_release_event (GtkWidget *widget,
4064 window = GTK_WINDOW (widget);
4066 if (window->focus_widget &&
4067 window->focus_widget != widget &&
4068 GTK_WIDGET_SENSITIVE (window->focus_widget))
4070 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
4073 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
4074 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
4080 gtk_window_real_activate_default (GtkWindow *window)
4082 gtk_window_activate_default (window);
4086 gtk_window_real_activate_focus (GtkWindow *window)
4088 gtk_window_activate_focus (window);
4092 gtk_window_move_focus (GtkWindow *window,
4093 GtkDirectionType dir)
4095 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4097 if (!GTK_CONTAINER (window)->focus_child)
4098 gtk_window_set_focus (window, NULL);
4102 gtk_window_enter_notify_event (GtkWidget *widget,
4103 GdkEventCrossing *event)
4109 gtk_window_leave_notify_event (GtkWidget *widget,
4110 GdkEventCrossing *event)
4116 do_focus_change (GtkWidget *widget,
4119 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4121 g_object_ref (widget);
4124 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4126 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4128 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4129 fevent->focus_change.window = widget->window;
4131 g_object_ref (widget->window);
4132 fevent->focus_change.in = in;
4134 gtk_widget_event (widget, fevent);
4136 g_object_notify (G_OBJECT (widget), "has_focus");
4138 g_object_unref (widget);
4139 gdk_event_free (fevent);
4143 gtk_window_focus_in_event (GtkWidget *widget,
4144 GdkEventFocus *event)
4146 GtkWindow *window = GTK_WINDOW (widget);
4148 /* It appears spurious focus in events can occur when
4149 * the window is hidden. So we'll just check to see if
4150 * the window is visible before actually handling the
4153 if (GTK_WIDGET_VISIBLE (widget))
4155 _gtk_window_set_has_toplevel_focus (window, TRUE);
4156 _gtk_window_set_is_active (window, TRUE);
4163 gtk_window_focus_out_event (GtkWidget *widget,
4164 GdkEventFocus *event)
4166 GtkWindow *window = GTK_WINDOW (widget);
4168 _gtk_window_set_has_toplevel_focus (window, FALSE);
4169 _gtk_window_set_is_active (window, FALSE);
4174 static GdkAtom atom_rcfiles = GDK_NONE;
4177 gtk_window_read_rcfiles (GtkWidget *widget,
4178 GdkEventClient *event)
4180 GList *embedded_windows;
4182 embedded_windows = g_object_get_data (G_OBJECT (widget), "gtk-embedded");
4183 if (embedded_windows)
4185 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4188 for (i = 0; i < 5; i++)
4189 send_event->client.data.l[i] = 0;
4190 send_event->client.data_format = 32;
4191 send_event->client.message_type = atom_rcfiles;
4193 while (embedded_windows)
4195 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4196 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4197 embedded_windows = embedded_windows->next;
4200 gdk_event_free (send_event);
4203 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4207 gtk_window_client_event (GtkWidget *widget,
4208 GdkEventClient *event)
4211 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
4213 if (event->message_type == atom_rcfiles)
4214 gtk_window_read_rcfiles (widget, event);
4220 gtk_window_check_resize (GtkContainer *container)
4222 GtkWindow *window = GTK_WINDOW (container);
4224 if (GTK_WIDGET_VISIBLE (container))
4225 gtk_window_move_resize (window);
4229 gtk_window_focus (GtkWidget *widget,
4230 GtkDirectionType direction)
4234 GtkContainer *container;
4235 GtkWidget *old_focus_child;
4238 container = GTK_CONTAINER (widget);
4239 window = GTK_WINDOW (widget);
4240 bin = GTK_BIN (widget);
4242 old_focus_child = container->focus_child;
4244 /* We need a special implementation here to deal properly with wrapping
4245 * around in the tab chain without the danger of going into an
4248 if (old_focus_child)
4250 if (gtk_widget_child_focus (old_focus_child, direction))
4254 if (window->focus_widget)
4256 /* Wrapped off the end, clear the focus setting for the toplpevel */
4257 parent = window->focus_widget->parent;
4260 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4261 parent = GTK_WIDGET (parent)->parent;
4264 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4267 /* Now try to focus the first widget in the window */
4270 if (gtk_widget_child_focus (bin->child, direction))
4278 gtk_window_real_set_focus (GtkWindow *window,
4281 GtkWidget *old_focus = window->focus_widget;
4282 gboolean def_flags = 0;
4286 g_object_ref (old_focus);
4287 g_object_freeze_notify (G_OBJECT (old_focus));
4291 g_object_ref (focus);
4292 g_object_freeze_notify (G_OBJECT (focus));
4295 if (window->default_widget)
4296 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4298 if (window->focus_widget)
4300 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4301 (window->focus_widget != window->default_widget))
4303 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4305 if (window->default_widget)
4306 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4309 if (window->has_focus)
4310 do_focus_change (window->focus_widget, FALSE);
4312 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4315 window->focus_widget = focus;
4317 if (window->focus_widget)
4319 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4320 (window->focus_widget != window->default_widget))
4322 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4323 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4325 if (window->default_widget)
4326 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4329 if (window->has_focus)
4330 do_focus_change (window->focus_widget, TRUE);
4332 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4335 if (window->default_widget &&
4336 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
4337 gtk_widget_queue_draw (window->default_widget);
4341 g_object_thaw_notify (G_OBJECT (old_focus));
4342 g_object_unref (old_focus);
4346 g_object_thaw_notify (G_OBJECT (focus));
4347 g_object_unref (focus);
4352 * _gtk_window_unset_focus_and_default:
4353 * @window: a #GtkWindow
4354 * @widget: a widget inside of @window
4356 * Checks whether the focus and default widgets of @window are
4357 * @widget or a descendent of @widget, and if so, unset them.
4360 _gtk_window_unset_focus_and_default (GtkWindow *window,
4366 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
4368 child = window->focus_widget;
4370 while (child && child != widget)
4371 child = child->parent;
4373 if (child == widget)
4374 gtk_window_set_focus (GTK_WINDOW (window), NULL);
4377 child = window->default_widget;
4379 while (child && child != widget)
4380 child = child->parent;
4382 if (child == widget)
4383 gtk_window_set_default (window, NULL);
4386 /*********************************
4387 * Functions related to resizing *
4388 *********************************/
4390 /* This function doesn't constrain to geometry hints */
4392 gtk_window_compute_configure_request_size (GtkWindow *window,
4396 GtkRequisition requisition;
4397 GtkWindowGeometryInfo *info;
4401 * - we've done a size request
4404 widget = GTK_WIDGET (window);
4406 info = gtk_window_get_geometry_info (window, FALSE);
4408 if (window->need_default_size)
4410 gtk_widget_get_child_requisition (widget, &requisition);
4412 /* Default to requisition */
4413 *width = requisition.width;
4414 *height = requisition.height;
4416 /* If window is empty so requests 0, default to random nonzero size */
4417 if (*width == 0 && *height == 0)
4423 /* Override requisition with default size */
4427 gint base_width = 0;
4428 gint base_height = 0;
4430 gint height_inc = 1;
4432 if (info->default_is_geometry &&
4433 (info->default_width > 0 || info->default_height > 0))
4435 GdkGeometry geometry;
4438 gtk_window_compute_hints (window, &geometry, &flags);
4440 if (flags & GDK_HINT_BASE_SIZE)
4442 base_width = geometry.base_width;
4443 base_height = geometry.base_height;
4445 else if (flags & GDK_HINT_MIN_SIZE)
4447 base_width = geometry.min_width;
4448 base_height = geometry.min_height;
4450 if (flags & GDK_HINT_RESIZE_INC)
4452 width_inc = geometry.width_inc;
4453 height_inc = geometry.height_inc;
4457 if (info->default_width > 0)
4458 *width = info->default_width * width_inc + base_width;
4460 if (info->default_height > 0)
4461 *height = info->default_height * height_inc + base_height;
4466 /* Default to keeping current size */
4467 *width = widget->allocation.width;
4468 *height = widget->allocation.height;
4471 /* Override any size with gtk_window_resize() values */
4474 if (info->resize_width > 0)
4475 *width = info->resize_width;
4477 if (info->resize_height > 0)
4478 *height = info->resize_height;
4482 static GtkWindowPosition
4483 get_effective_position (GtkWindow *window)
4485 GtkWindowPosition pos = window->position;
4486 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
4487 (window->transient_parent == NULL ||
4488 !GTK_WIDGET_MAPPED (window->transient_parent)))
4489 pos = GTK_WIN_POS_NONE;
4495 get_center_monitor_of_window (GtkWindow *window)
4497 /* We could try to sort out the relative positions of the monitors and
4498 * stuff, or we could just be losers and assume you have a row
4499 * or column of monitors.
4501 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
4505 get_monitor_containing_pointer (GtkWindow *window)
4509 GdkScreen *window_screen;
4510 GdkScreen *pointer_screen;
4512 window_screen = gtk_window_check_screen (window);
4513 gdk_display_get_pointer (gdk_screen_get_display (window_screen),
4517 if (pointer_screen == window_screen)
4518 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
4526 center_window_on_monitor (GtkWindow *window,
4532 GdkRectangle monitor;
4535 monitor_num = get_monitor_containing_pointer (window);
4537 if (monitor_num == -1)
4538 monitor_num = get_center_monitor_of_window (window);
4540 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
4541 monitor_num, &monitor);
4543 *x = (monitor.width - w) / 2 + monitor.x;
4544 *y = (monitor.height - h) / 2 + monitor.y;
4546 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
4547 * and WM decorations.
4556 clamp_window_to_rectangle (gint *x,
4560 const GdkRectangle *rect)
4562 gint outside_w, outside_h;
4564 outside_w = (*x + w) - (rect->x + rect->width);
4568 outside_h = (*y + h) - (rect->y + rect->height);
4572 /* if larger than the screen, center on the screen. */
4574 *x += (rect->x - *x) / 2;
4576 *y += (rect->y - *y) / 2;
4581 gtk_window_compute_configure_request (GtkWindow *window,
4582 GdkRectangle *request,
4583 GdkGeometry *geometry,
4586 GdkGeometry new_geometry;
4590 GtkWindowPosition pos;
4591 GtkWidget *parent_widget;
4592 GtkWindowGeometryInfo *info;
4596 widget = GTK_WIDGET (window);
4598 screen = gtk_window_check_screen (window);
4600 gtk_widget_size_request (widget, NULL);
4601 gtk_window_compute_configure_request_size (window, &w, &h);
4603 gtk_window_compute_hints (window, &new_geometry, &new_flags);
4604 gtk_window_constrain_size (window,
4605 &new_geometry, new_flags,
4609 parent_widget = (GtkWidget*) window->transient_parent;
4611 pos = get_effective_position (window);
4612 info = gtk_window_get_geometry_info (window, TRUE);
4614 /* by default, don't change position requested */
4615 x = info->last.configure_request.x;
4616 y = info->last.configure_request.y;
4618 if (window->need_default_position)
4621 /* FIXME this all interrelates with window gravity.
4622 * For most of them I think we want to set GRAVITY_CENTER.
4624 * Not sure how to go about that.
4629 /* here we are only handling CENTER_ALWAYS
4630 * as it relates to default positioning,
4631 * where it's equivalent to simply CENTER
4633 case GTK_WIN_POS_CENTER_ALWAYS:
4634 case GTK_WIN_POS_CENTER:
4635 center_window_on_monitor (window, w, h, &x, &y);
4638 case GTK_WIN_POS_CENTER_ON_PARENT:
4641 GdkRectangle monitor;
4644 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
4646 if (parent_widget->window != NULL)
4647 monitor_num = gdk_screen_get_monitor_at_window (screen,
4648 parent_widget->window);
4652 gdk_window_get_origin (parent_widget->window,
4655 x = ox + (parent_widget->allocation.width - w) / 2;
4656 y = oy + (parent_widget->allocation.height - h) / 2;
4658 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4659 * WM decorations. If parent wasn't on a monitor, just
4662 if (monitor_num >= 0)
4664 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
4665 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4670 case GTK_WIN_POS_MOUSE:
4672 gint screen_width = gdk_screen_get_width (screen);
4673 gint screen_height = gdk_screen_get_height (screen);
4675 GdkRectangle monitor;
4676 GdkScreen *pointer_screen;
4679 gdk_display_get_pointer (gdk_screen_get_display (screen),
4683 if (pointer_screen == screen)
4684 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
4690 x = CLAMP (x, 0, screen_width - w);
4691 y = CLAMP (y, 0, screen_height - h);
4693 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4694 * WM decorations. Don't try to figure out what's going
4695 * on if the mouse wasn't inside a monitor.
4697 if (monitor_num >= 0)
4699 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
4700 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4708 } /* if (window->need_default_position) */
4710 if (window->need_default_position &&
4711 info->initial_pos_set)
4713 x = info->initial_x;
4714 y = info->initial_y;
4715 gtk_window_constrain_position (window, w, h, &x, &y);
4721 request->height = h;
4724 *geometry = new_geometry;
4730 gtk_window_constrain_position (GtkWindow *window,
4736 /* See long comments in gtk_window_move_resize()
4737 * on when it's safe to call this function.
4739 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4741 gint center_x, center_y;
4743 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
4751 gtk_window_move_resize (GtkWindow *window)
4755 * First we determine whether any information has changed that would
4756 * cause us to revise our last configure request. If we would send
4757 * a different configure request from last time, then
4758 * configure_request_size_changed = TRUE or
4759 * configure_request_pos_changed = TRUE. configure_request_size_changed
4760 * may be true due to new hints, a gtk_window_resize(), or whatever.
4761 * configure_request_pos_changed may be true due to gtk_window_set_position()
4762 * or gtk_window_move().
4764 * If the configure request has changed, we send off a new one. To
4765 * ensure GTK+ invariants are maintained (resize queue does what it
4766 * should), we go ahead and size_allocate the requested size in this
4769 * If the configure request has not changed, we don't ever resend
4770 * it, because it could mean fighting the user or window manager.
4773 * To prepare the configure request, we come up with a base size/pos:
4774 * - the one from gtk_window_move()/gtk_window_resize()
4775 * - else default_width, default_height if we haven't ever
4777 * - else the size request if we haven't ever been mapped,
4778 * as a substitute default size
4779 * - else the current size of the window, as received from
4780 * configure notifies (i.e. the current allocation)
4782 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4783 * the position request to be centered.
4786 GtkContainer *container;
4787 GtkWindowGeometryInfo *info;
4788 GdkGeometry new_geometry;
4790 GdkRectangle new_request;
4791 gboolean configure_request_size_changed;
4792 gboolean configure_request_pos_changed;
4793 gboolean hints_changed; /* do we need to send these again */
4794 GtkWindowLastGeometryInfo saved_last_info;
4796 widget = GTK_WIDGET (window);
4797 container = GTK_CONTAINER (widget);
4798 info = gtk_window_get_geometry_info (window, TRUE);
4800 configure_request_size_changed = FALSE;
4801 configure_request_pos_changed = FALSE;
4803 gtk_window_compute_configure_request (window, &new_request,
4804 &new_geometry, &new_flags);
4806 /* This check implies the invariant that we never set info->last
4807 * without setting the hints and sending off a configure request.
4809 * If we change info->last without sending the request, we may
4812 if (info->last.configure_request.x != new_request.x ||
4813 info->last.configure_request.y != new_request.y)
4814 configure_request_pos_changed = TRUE;
4816 if ((info->last.configure_request.width != new_request.width ||
4817 info->last.configure_request.height != new_request.height))
4818 configure_request_size_changed = TRUE;
4820 hints_changed = FALSE;
4822 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4823 &new_geometry, new_flags))
4825 hints_changed = TRUE;
4828 /* Position Constraints
4829 * ====================
4831 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4832 * a default. The other POS_ values are used only when the
4833 * window is shown, not after that.
4835 * However, we can't implement a position constraint as
4836 * "anytime the window size changes, center the window"
4837 * because this may well end up fighting the WM or user. In
4838 * fact it gets in an infinite loop with at least one WM.
4840 * Basically, applications are in no way in a position to
4841 * constrain the position of a window, with one exception:
4842 * override redirect windows. (Really the intended purpose
4843 * of CENTER_ALWAYS anyhow, I would think.)
4845 * So the way we implement this "constraint" is to say that when WE
4846 * cause a move or resize, i.e. we make a configure request changing
4847 * window size, we recompute the CENTER_ALWAYS position to reflect
4848 * the new window size, and include it in our request. Also, if we
4849 * just turned on CENTER_ALWAYS we snap to center with a new
4850 * request. Otherwise, if we are just NOTIFIED of a move or resize
4851 * done by someone else e.g. the window manager, we do NOT send a
4852 * new configure request.
4854 * For override redirect windows, this works fine; all window
4855 * sizes are from our configure requests. For managed windows,
4856 * it is at least semi-sane, though who knows what the
4857 * app author is thinking.
4860 /* This condition should be kept in sync with the condition later on
4861 * that determines whether we send a configure request. i.e. we
4862 * should do this position constraining anytime we were going to
4863 * send a configure request anyhow, plus when constraints have
4866 if (configure_request_pos_changed ||
4867 configure_request_size_changed ||
4869 info->position_constraints_changed)
4871 /* We request the constrained position if:
4872 * - we were changing position, and need to clamp
4873 * the change to the constraint
4874 * - we're changing the size anyway
4875 * - set_position() was called to toggle CENTER_ALWAYS on
4878 gtk_window_constrain_position (window,
4884 /* Update whether we need to request a move */
4885 if (info->last.configure_request.x != new_request.x ||
4886 info->last.configure_request.y != new_request.y)
4887 configure_request_pos_changed = TRUE;
4889 configure_request_pos_changed = FALSE;
4893 if (window->type == GTK_WINDOW_TOPLEVEL)
4895 int notify_x, notify_y;
4897 /* this is the position from the last configure notify */
4898 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4900 g_message ("--- %s ---\n"
4901 "last : %d,%d\t%d x %d\n"
4902 "this : %d,%d\t%d x %d\n"
4903 "alloc : %d,%d\t%d x %d\n"
4905 "resize: \t%d x %d\n"
4906 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4907 "configure_notify_received: %d\n"
4908 "configure_request_count: %d\n"
4909 "position_constraints_changed: %d\n",
4910 window->title ? window->title : "(no title)",
4911 info->last.configure_request.x,
4912 info->last.configure_request.y,
4913 info->last.configure_request.width,
4914 info->last.configure_request.height,
4920 widget->allocation.width,
4921 widget->allocation.height,
4922 widget->requisition.width,
4923 widget->requisition.height,
4925 info->resize_height,
4926 configure_request_pos_changed,
4927 configure_request_size_changed,
4929 window->configure_notify_received,
4930 window->configure_request_count,
4931 info->position_constraints_changed);
4935 saved_last_info = info->last;
4936 info->last.geometry = new_geometry;
4937 info->last.flags = new_flags;
4938 info->last.configure_request = new_request;
4940 /* need to set PPosition so the WM will look at our position,
4941 * but we don't want to count PPosition coming and going as a hints
4942 * change for future iterations. So we saved info->last prior to
4946 /* Also, if the initial position was explicitly set, then we always
4947 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4951 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4952 * this is an initial map
4955 if ((configure_request_pos_changed ||
4956 info->initial_pos_set ||
4957 (window->need_default_position &&
4958 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
4959 (new_flags & GDK_HINT_POS) == 0)
4961 new_flags |= GDK_HINT_POS;
4962 hints_changed = TRUE;
4965 /* Set hints if necessary
4968 gdk_window_set_geometry_hints (widget->window,
4972 /* handle resizing/moving and widget tree allocation
4974 if (window->configure_notify_received)
4976 GtkAllocation allocation;
4978 /* If we have received a configure event since
4979 * the last time in this function, we need to
4980 * accept our new size and size_allocate child widgets.
4981 * (see gtk_window_configure_event() for more details).
4983 * 1 or more configure notifies may have been received.
4984 * Also, configure_notify_received will only be TRUE
4985 * if all expected configure notifies have been received
4986 * (one per configure request), as an optimization.
4989 window->configure_notify_received = FALSE;
4991 /* gtk_window_configure_event() filled in widget->allocation */
4992 allocation = widget->allocation;
4993 gtk_widget_size_allocate (widget, &allocation);
4995 /* If the configure request changed, it means that
4997 * 1) coincidentally changed hints or widget properties
4998 * impacting the configure request before getting
4999 * a configure notify, or
5000 * 2) some broken widget is changing its size request
5001 * during size allocation, resulting in
5002 * a false appearance of changed configure request.
5004 * For 1), we could just go ahead and ask for the
5005 * new size right now, but doing that for 2)
5006 * might well be fighting the user (and can even
5007 * trigger a loop). Since we really don't want to
5008 * do that, we requeue a resize in hopes that
5009 * by the time it gets handled, the child has seen
5010 * the light and is willing to go along with the
5011 * new size. (this happens for the zvt widget, since
5012 * the size_allocate() above will have stored the
5013 * requisition corresponding to the new size in the
5016 * This doesn't buy us anything for 1), but it shouldn't
5017 * hurt us too badly, since it is what would have
5018 * happened if we had gotten the configure event before
5019 * the new size had been set.
5022 if (configure_request_size_changed ||
5023 configure_request_pos_changed)
5025 /* Don't change the recorded last info after all, because we
5026 * haven't actually updated to the new info yet - we decided
5027 * to postpone our configure request until later.
5029 info->last = saved_last_info;
5031 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
5034 return; /* Bail out, we didn't really process the move/resize */
5036 else if ((configure_request_size_changed || hints_changed) &&
5037 (widget->allocation.width != new_request.width ||
5038 widget->allocation.height != new_request.height))
5041 /* We are in one of the following situations:
5042 * A. configure_request_size_changed
5043 * our requisition has changed and we need a different window size,
5044 * so we request it from the window manager.
5045 * B. !configure_request_size_changed && hints_changed
5046 * the window manager rejects our size, but we have just changed the
5047 * window manager hints, so there's a chance our request will
5048 * be honoured this time, so we try again.
5050 * However, if the new requisition is the same as the current allocation,
5051 * we don't request it again, since we won't get a ConfigureNotify back from
5052 * the window manager unless it decides to change our requisition. If
5053 * we don't get the ConfigureNotify back, the resize queue will never be run.
5056 /* Now send the configure request */
5057 if (configure_request_pos_changed)
5061 gdk_window_move_resize (window->frame,
5062 new_request.x - window->frame_left,
5063 new_request.y - window->frame_top,
5064 new_request.width + window->frame_left + window->frame_right,
5065 new_request.height + window->frame_top + window->frame_bottom);
5066 gdk_window_resize (widget->window,
5067 new_request.width, new_request.height);
5070 gdk_window_move_resize (widget->window,
5071 new_request.x, new_request.y,
5072 new_request.width, new_request.height);
5074 else /* only size changed */
5077 gdk_window_resize (window->frame,
5078 new_request.width + window->frame_left + window->frame_right,
5079 new_request.height + window->frame_top + window->frame_bottom);
5080 gdk_window_resize (widget->window,
5081 new_request.width, new_request.height);
5084 /* Increment the number of have-not-yet-received-notify requests */
5085 window->configure_request_count += 1;
5087 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5088 * configure event in response to our resizing request.
5089 * the configure event will cause a new resize with
5090 * ->configure_notify_received=TRUE.
5091 * until then, we want to
5092 * - discard expose events
5093 * - coalesce resizes for our children
5094 * - defer any window resizes until the configure event arrived
5095 * to achieve this, we queue a resize for the window, but remove its
5096 * resizing handler, so resizing will not be handled from the next
5097 * idle handler but when the configure event arrives.
5099 * FIXME: we should also dequeue the pending redraws here, since
5100 * we handle those ourselves upon ->configure_notify_received==TRUE.
5102 if (container->resize_mode == GTK_RESIZE_QUEUE)
5104 gtk_widget_queue_resize (widget);
5105 _gtk_container_dequeue_resize_handler (container);
5110 /* Handle any position changes.
5112 if (configure_request_pos_changed)
5116 gdk_window_move (window->frame,
5117 new_request.x - window->frame_left,
5118 new_request.y - window->frame_top);
5121 gdk_window_move (widget->window,
5122 new_request.x, new_request.y);
5125 /* And run the resize queue.
5127 gtk_container_resize_children (container);
5130 /* We have now processed a move/resize since the last position
5131 * constraint change, setting of the initial position, or resize.
5132 * (Not resetting these flags here can lead to infinite loops for
5133 * GTK_RESIZE_IMMEDIATE containers)
5135 info->position_constraints_changed = FALSE;
5136 info->initial_pos_set = FALSE;
5137 info->resize_width = -1;
5138 info->resize_height = -1;
5141 /* Compare two sets of Geometry hints for equality.
5144 gtk_window_compare_hints (GdkGeometry *geometry_a,
5146 GdkGeometry *geometry_b,
5149 if (flags_a != flags_b)
5152 if ((flags_a & GDK_HINT_MIN_SIZE) &&
5153 (geometry_a->min_width != geometry_b->min_width ||
5154 geometry_a->min_height != geometry_b->min_height))
5157 if ((flags_a & GDK_HINT_MAX_SIZE) &&
5158 (geometry_a->max_width != geometry_b->max_width ||
5159 geometry_a->max_height != geometry_b->max_height))
5162 if ((flags_a & GDK_HINT_BASE_SIZE) &&
5163 (geometry_a->base_width != geometry_b->base_width ||
5164 geometry_a->base_height != geometry_b->base_height))
5167 if ((flags_a & GDK_HINT_ASPECT) &&
5168 (geometry_a->min_aspect != geometry_b->min_aspect ||
5169 geometry_a->max_aspect != geometry_b->max_aspect))
5172 if ((flags_a & GDK_HINT_RESIZE_INC) &&
5173 (geometry_a->width_inc != geometry_b->width_inc ||
5174 geometry_a->height_inc != geometry_b->height_inc))
5177 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5178 geometry_a->win_gravity != geometry_b->win_gravity)
5185 _gtk_window_constrain_size (GtkWindow *window,
5191 GtkWindowGeometryInfo *info;
5193 g_return_if_fail (GTK_IS_WINDOW (window));
5195 info = window->geometry_info;
5198 GdkWindowHints flags = info->last.flags;
5199 GdkGeometry *geometry = &info->last.geometry;
5201 gtk_window_constrain_size (window,
5212 gtk_window_constrain_size (GtkWindow *window,
5213 GdkGeometry *geometry,
5220 gdk_window_constrain_size (geometry, flags, width, height,
5221 new_width, new_height);
5224 /* Compute the set of geometry hints and flags for a window
5225 * based on the application set geometry, and requisiition
5226 * of the window. gtk_widget_size_request() must have been
5230 gtk_window_compute_hints (GtkWindow *window,
5231 GdkGeometry *new_geometry,
5235 gint extra_width = 0;
5236 gint extra_height = 0;
5237 GtkWindowGeometryInfo *geometry_info;
5238 GtkRequisition requisition;
5240 widget = GTK_WIDGET (window);
5242 gtk_widget_get_child_requisition (widget, &requisition);
5243 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5247 *new_flags = geometry_info->mask;
5248 *new_geometry = geometry_info->geometry;
5255 if (geometry_info && geometry_info->widget)
5257 GtkRequisition child_requisition;
5259 /* FIXME: This really isn't right. It gets the min size wrong and forces
5260 * callers to do horrible hacks like set a huge usize on the child requisition
5261 * to get the base size right. We really want to find the answers to:
5263 * - If the geometry widget was infinitely big, how much extra space
5264 * would be needed for the stuff around it.
5266 * - If the geometry widget was infinitely small, how big would the
5267 * window still have to be.
5269 * Finding these answers would be a bit of a mess here. (Bug #68668)
5271 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5273 extra_width = widget->requisition.width - child_requisition.width;
5274 extra_height = widget->requisition.height - child_requisition.height;
5277 /* We don't want to set GDK_HINT_POS in here, we just set it
5278 * in gtk_window_move_resize() when we want the position
5282 if (*new_flags & GDK_HINT_BASE_SIZE)
5284 new_geometry->base_width += extra_width;
5285 new_geometry->base_height += extra_height;
5287 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5288 (*new_flags & GDK_HINT_RESIZE_INC) &&
5289 ((extra_width != 0) || (extra_height != 0)))
5291 *new_flags |= GDK_HINT_BASE_SIZE;
5293 new_geometry->base_width = extra_width;
5294 new_geometry->base_height = extra_height;
5297 if (*new_flags & GDK_HINT_MIN_SIZE)
5299 if (new_geometry->min_width < 0)
5300 new_geometry->min_width = requisition.width;
5302 new_geometry->min_width += extra_width;
5304 if (new_geometry->min_height < 0)
5305 new_geometry->min_height = requisition.height;
5307 new_geometry->min_height += extra_height;
5309 else if (!window->allow_shrink)
5311 *new_flags |= GDK_HINT_MIN_SIZE;
5313 new_geometry->min_width = requisition.width;
5314 new_geometry->min_height = requisition.height;
5317 if (*new_flags & GDK_HINT_MAX_SIZE)
5319 if (new_geometry->max_width < 0)
5320 new_geometry->max_width = requisition.width;
5322 new_geometry->max_width += extra_width;
5324 if (new_geometry->max_height < 0)
5325 new_geometry->max_width = requisition.height;
5327 new_geometry->max_height += extra_height;
5329 else if (!window->allow_grow)
5331 *new_flags |= GDK_HINT_MAX_SIZE;
5333 new_geometry->max_width = requisition.width;
5334 new_geometry->max_height = requisition.height;
5337 *new_flags |= GDK_HINT_WIN_GRAVITY;
5338 new_geometry->win_gravity = window->gravity;
5341 /***********************
5342 * Redrawing functions *
5343 ***********************/
5346 gtk_window_paint (GtkWidget *widget,
5349 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
5350 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
5354 gtk_window_expose (GtkWidget *widget,
5355 GdkEventExpose *event)
5357 if (!GTK_WIDGET_APP_PAINTABLE (widget))
5358 gtk_window_paint (widget, &event->area);
5360 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
5361 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
5367 * gtk_window_set_has_frame:
5368 * @window: a #GtkWindow
5369 * @setting: a boolean
5371 * (Note: this is a special-purpose function for the framebuffer port,
5372 * that causes GTK+ to draw its own window border. For most applications,
5373 * you want gtk_window_set_decorated() instead, which tells the window
5374 * manager whether to draw the window border.)
5376 * If this function is called on a window with setting of %TRUE, before
5377 * it is realized or showed, it will have a "frame" window around
5378 * @window->window, accessible in @window->frame. Using the signal
5379 * frame_event you can recieve all events targeted at the frame.
5381 * This function is used by the linux-fb port to implement managed
5382 * windows, but it could concievably be used by X-programs that
5383 * want to do their own window decorations.
5387 gtk_window_set_has_frame (GtkWindow *window,
5390 g_return_if_fail (GTK_IS_WINDOW (window));
5391 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
5393 window->has_frame = setting != FALSE;
5397 * gtk_window_get_has_frame:
5398 * @window: a #GtkWindow
5400 * Accessor for whether the window has a frame window exterior to
5401 * @window->window. Gets the value set by gtk_window_set_has_frame ().
5403 * Return value: %TRUE if a frame has been added to the window
5404 * via gtk_window_set_has_frame().
5407 gtk_window_get_has_frame (GtkWindow *window)
5409 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5411 return window->has_frame;
5415 * gtk_window_set_frame_dimensions:
5416 * @window: a #GtkWindow that has a frame
5417 * @left: The width of the left border
5418 * @top: The height of the top border
5419 * @right: The width of the right border
5420 * @bottom: The height of the bottom border
5422 * (Note: this is a special-purpose function intended for the framebuffer
5423 * port; see gtk_window_set_has_frame(). It will have no effect on the
5424 * window border drawn by the window manager, which is the normal
5425 * case when using the X Window system.)
5427 * For windows with frames (see gtk_window_set_has_frame()) this function
5428 * can be used to change the size of the frame border.
5431 gtk_window_set_frame_dimensions (GtkWindow *window,
5439 g_return_if_fail (GTK_IS_WINDOW (window));
5441 widget = GTK_WIDGET (window);
5443 if (window->frame_left == left &&
5444 window->frame_top == top &&
5445 window->frame_right == right &&
5446 window->frame_bottom == bottom)
5449 window->frame_left = left;
5450 window->frame_top = top;
5451 window->frame_right = right;
5452 window->frame_bottom = bottom;
5454 if (GTK_WIDGET_REALIZED (widget) && window->frame)
5456 gint width = widget->allocation.width + left + right;
5457 gint height = widget->allocation.height + top + bottom;
5458 gdk_window_resize (window->frame, width, height);
5459 gtk_decorated_window_move_resize_window (window,
5461 widget->allocation.width,
5462 widget->allocation.height);
5467 * gtk_window_present:
5468 * @window: a #GtkWindow
5470 * Presents a window to the user. This may mean raising the window
5471 * in the stacking order, deiconifying it, moving it to the current
5472 * desktop, and/or giving it the keyboard focus, possibly dependent
5473 * on the user's platform, window manager, and preferences.
5475 * If @window is hidden, this function calls gtk_widget_show()
5478 * This function should be used when the user tries to open a window
5479 * that's already open. Say for example the preferences dialog is
5480 * currently open, and the user chooses Preferences from the menu
5481 * a second time; use gtk_window_present() to move the already-open dialog
5482 * where the user can see it.
5486 gtk_window_present (GtkWindow *window)
5490 g_return_if_fail (GTK_IS_WINDOW (window));
5492 widget = GTK_WIDGET (window);
5494 if (GTK_WIDGET_VISIBLE (window))
5496 g_assert (widget->window != NULL);
5498 gdk_window_show (widget->window);
5500 /* note that gdk_window_focus() will also move the window to
5501 * the current desktop, for WM spec compliant window managers.
5503 gdk_window_focus (widget->window,
5504 gtk_get_current_event_time ());
5508 gtk_widget_show (widget);
5513 * gtk_window_iconify:
5514 * @window: a #GtkWindow
5516 * Asks to iconify (i.e. minimize) the specified @window. Note that
5517 * you shouldn't assume the window is definitely iconified afterward,
5518 * because other entities (e.g. the user or <link
5519 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
5520 * again, or there may not be a window manager in which case
5521 * iconification isn't possible, etc. But normally the window will end
5522 * up iconified. Just don't write code that crashes if not.
5524 * It's permitted to call this function before showing a window,
5525 * in which case the window will be iconified before it ever appears
5528 * You can track iconification via the "window_state_event" signal
5533 gtk_window_iconify (GtkWindow *window)
5536 GdkWindow *toplevel;
5538 g_return_if_fail (GTK_IS_WINDOW (window));
5540 widget = GTK_WIDGET (window);
5542 window->iconify_initially = TRUE;
5545 toplevel = window->frame;
5547 toplevel = widget->window;
5549 if (toplevel != NULL)
5550 gdk_window_iconify (toplevel);
5554 * gtk_window_deiconify:
5555 * @window: a #GtkWindow
5557 * Asks to deiconify (i.e. unminimize) the specified @window. Note
5558 * that you shouldn't assume the window is definitely deiconified
5559 * afterward, because other entities (e.g. the user or <link
5560 * linkend="gtk-X11-arch">window manager</link>) could iconify it
5561 * again before your code which assumes deiconification gets to run.
5563 * You can track iconification via the "window_state_event" signal
5567 gtk_window_deiconify (GtkWindow *window)
5570 GdkWindow *toplevel;
5572 g_return_if_fail (GTK_IS_WINDOW (window));
5574 widget = GTK_WIDGET (window);
5576 window->iconify_initially = FALSE;
5579 toplevel = window->frame;
5581 toplevel = widget->window;
5583 if (toplevel != NULL)
5584 gdk_window_deiconify (toplevel);
5589 * @window: a #GtkWindow
5591 * Asks to stick @window, which means that it will appear on all user
5592 * desktops. Note that you shouldn't assume the window is definitely
5593 * stuck afterward, because other entities (e.g. the user or <link
5594 * linkend="gtk-X11-arch">window manager</link>) could unstick it
5595 * again, and some window managers do not support sticking
5596 * windows. But normally the window will end up stuck. Just don't
5597 * write code that crashes if not.
5599 * It's permitted to call this function before showing a window.
5601 * You can track stickiness via the "window_state_event" signal
5606 gtk_window_stick (GtkWindow *window)
5609 GdkWindow *toplevel;
5611 g_return_if_fail (GTK_IS_WINDOW (window));
5613 widget = GTK_WIDGET (window);
5615 window->stick_initially = TRUE;
5618 toplevel = window->frame;
5620 toplevel = widget->window;
5622 if (toplevel != NULL)
5623 gdk_window_stick (toplevel);
5627 * gtk_window_unstick:
5628 * @window: a #GtkWindow
5630 * Asks to unstick @window, which means that it will appear on only
5631 * one of the user's desktops. Note that you shouldn't assume the
5632 * window is definitely unstuck afterward, because other entities
5633 * (e.g. the user or <link linkend="gtk-X11-arch">window
5634 * manager</link>) could stick it again. But normally the window will
5635 * end up stuck. Just don't write code that crashes if not.
5637 * You can track stickiness via the "window_state_event" signal
5642 gtk_window_unstick (GtkWindow *window)
5645 GdkWindow *toplevel;
5647 g_return_if_fail (GTK_IS_WINDOW (window));
5649 widget = GTK_WIDGET (window);
5651 window->stick_initially = FALSE;
5654 toplevel = window->frame;
5656 toplevel = widget->window;
5658 if (toplevel != NULL)
5659 gdk_window_unstick (toplevel);
5663 * gtk_window_maximize:
5664 * @window: a #GtkWindow
5666 * Asks to maximize @window, so that it becomes full-screen. Note that
5667 * you shouldn't assume the window is definitely maximized afterward,
5668 * because other entities (e.g. the user or <link
5669 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
5670 * again, and not all window managers support maximization. But
5671 * normally the window will end up maximized. Just don't write code
5672 * that crashes if not.
5674 * It's permitted to call this function before showing a window,
5675 * in which case the window will be maximized when it appears onscreen
5678 * You can track maximization via the "window_state_event" signal
5683 gtk_window_maximize (GtkWindow *window)
5686 GdkWindow *toplevel;
5688 g_return_if_fail (GTK_IS_WINDOW (window));
5690 widget = GTK_WIDGET (window);
5692 window->maximize_initially = TRUE;
5695 toplevel = window->frame;
5697 toplevel = widget->window;
5699 if (toplevel != NULL)
5700 gdk_window_maximize (toplevel);
5704 * gtk_window_unmaximize:
5705 * @window: a #GtkWindow
5707 * Asks to unmaximize @window. Note that you shouldn't assume the
5708 * window is definitely unmaximized afterward, because other entities
5709 * (e.g. the user or <link linkend="gtk-X11-arch">window
5710 * manager</link>) could maximize it again, and not all window
5711 * managers honor requests to unmaximize. But normally the window will
5712 * end up unmaximized. Just don't write code that crashes if not.
5714 * You can track maximization via the "window_state_event" signal
5719 gtk_window_unmaximize (GtkWindow *window)
5722 GdkWindow *toplevel;
5724 g_return_if_fail (GTK_IS_WINDOW (window));
5726 widget = GTK_WIDGET (window);
5728 window->maximize_initially = FALSE;
5731 toplevel = window->frame;
5733 toplevel = widget->window;
5735 if (toplevel != NULL)
5736 gdk_window_unmaximize (toplevel);
5740 * gtk_window_fullscreen:
5741 * @window: a #GtkWindow
5743 * Asks to place @window in the fullscreen state. Note that you
5744 * shouldn't assume the window is definitely full screen afterward,
5745 * because other entities (e.g. the user or <link
5746 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
5747 * again, and not all window managers honor requests to fullscreen
5748 * windows. But normally the window will end up fullscreen. Just
5749 * don't write code that crashes if not.
5751 * You can track the fullscreen state via the "window_state_event" signal
5757 gtk_window_fullscreen (GtkWindow *window)
5760 GdkWindow *toplevel;
5761 GtkWindowPrivate *priv;
5763 g_return_if_fail (GTK_IS_WINDOW (window));
5765 widget = GTK_WIDGET (window);
5766 priv = gtk_window_get_private (window);
5768 priv->fullscreen_initially = TRUE;
5771 toplevel = window->frame;
5773 toplevel = widget->window;
5775 if (toplevel != NULL)
5776 gdk_window_fullscreen (toplevel);
5780 * gtk_window_unfullscreen:
5781 * @window: a #GtkWindow
5783 * Asks to toggle off the fullscreen state for @window. Note that you
5784 * shouldn't assume the window is definitely not full screen
5785 * afterward, because other entities (e.g. the user or <link
5786 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
5787 * again, and not all window managers honor requests to unfullscreen
5788 * windows. But normally the window will end up restored to its normal
5789 * state. Just don't write code that crashes if not.
5791 * You can track the fullscreen state via the "window_state_event" signal
5797 gtk_window_unfullscreen (GtkWindow *window)
5800 GdkWindow *toplevel;
5801 GtkWindowPrivate *priv;
5803 g_return_if_fail (GTK_IS_WINDOW (window));
5805 widget = GTK_WIDGET (window);
5806 priv = gtk_window_get_private (window);
5808 priv->fullscreen_initially = FALSE;
5811 toplevel = window->frame;
5813 toplevel = widget->window;
5815 if (toplevel != NULL)
5816 gdk_window_unfullscreen (toplevel);
5821 * gtk_window_set_resizable:
5822 * @window: a #GtkWindow
5823 * @resizable: %TRUE if the user can resize this window
5825 * Sets whether the user can resize a window. Windows are user resizable
5829 gtk_window_set_resizable (GtkWindow *window,
5832 g_return_if_fail (GTK_IS_WINDOW (window));
5834 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5838 * gtk_window_get_resizable:
5839 * @window: a #GtkWindow
5841 * Gets the value set by gtk_window_set_resizable().
5843 * Return value: %TRUE if the user can resize the window
5846 gtk_window_get_resizable (GtkWindow *window)
5848 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5850 /* allow_grow is most likely to indicate the semantic concept we
5851 * mean by "resizable" (and will be a reliable indicator if
5852 * set_policy() hasn't been called)
5854 return window->allow_grow;
5858 * gtk_window_set_gravity:
5859 * @window: a #GtkWindow
5860 * @gravity: window gravity
5862 * Window gravity defines the meaning of coordinates passed to
5863 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5866 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5867 * typically "do what you mean."
5871 gtk_window_set_gravity (GtkWindow *window,
5874 g_return_if_fail (GTK_IS_WINDOW (window));
5876 if (gravity != window->gravity)
5878 window->gravity = gravity;
5880 /* gtk_window_move_resize() will adapt gravity
5882 gtk_widget_queue_resize (GTK_WIDGET (window));
5887 * gtk_window_get_gravity:
5888 * @window: a #GtkWindow
5890 * Gets the value set by gtk_window_set_gravity().
5892 * Return value: window gravity
5895 gtk_window_get_gravity (GtkWindow *window)
5897 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5899 return window->gravity;
5903 * gtk_window_begin_resize_drag:
5904 * @window: a #GtkWindow
5905 * @button: mouse button that initiated the drag
5906 * @edge: position of the resize control
5907 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5908 * @root_y: Y position where the user clicked to initiate the drag
5909 * @timestamp: timestamp from the click event that initiated the drag
5911 * Starts resizing a window. This function is used if an application
5912 * has window resizing controls. When GDK can support it, the resize
5913 * will be done using the standard mechanism for the <link
5914 * linkend="gtk-X11-arch">window manager</link> or windowing
5915 * system. Otherwise, GDK will try to emulate window resizing,
5916 * potentially not all that well, depending on the windowing system.
5920 gtk_window_begin_resize_drag (GtkWindow *window,
5928 GdkWindow *toplevel;
5930 g_return_if_fail (GTK_IS_WINDOW (window));
5931 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5933 widget = GTK_WIDGET (window);
5936 toplevel = window->frame;
5938 toplevel = widget->window;
5940 gdk_window_begin_resize_drag (toplevel,
5947 * gtk_window_get_frame_dimensions:
5948 * @window: a #GtkWindow
5949 * @left: location to store the width of the frame at the left, or %NULL
5950 * @top: location to store the height of the frame at the top, or %NULL
5951 * @right: location to store the width of the frame at the returns, or %NULL
5952 * @bottom: location to store the height of the frame at the bottom, or %NULL
5954 * (Note: this is a special-purpose function intended for the
5955 * framebuffer port; see gtk_window_set_has_frame(). It will not
5956 * return the size of the window border drawn by the <link
5957 * linkend="gtk-X11-arch">window manager</link>, which is the normal
5958 * case when using a windowing system. See
5959 * gdk_window_get_frame_extents() to get the standard window border
5962 * Retrieves the dimensions of the frame window for this toplevel.
5963 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5966 gtk_window_get_frame_dimensions (GtkWindow *window,
5972 g_return_if_fail (GTK_IS_WINDOW (window));
5975 *left = window->frame_left;
5977 *top = window->frame_top;
5979 *right = window->frame_right;
5981 *bottom = window->frame_bottom;
5985 * gtk_window_begin_move_drag:
5986 * @window: a #GtkWindow
5987 * @button: mouse button that initiated the drag
5988 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5989 * @root_y: Y position where the user clicked to initiate the drag
5990 * @timestamp: timestamp from the click event that initiated the drag
5992 * Starts moving a window. This function is used if an application has
5993 * window movement grips. When GDK can support it, the window movement
5994 * will be done using the standard mechanism for the <link
5995 * linkend="gtk-X11-arch">window manager</link> or windowing
5996 * system. Otherwise, GDK will try to emulate window movement,
5997 * potentially not all that well, depending on the windowing system.
6001 gtk_window_begin_move_drag (GtkWindow *window,
6008 GdkWindow *toplevel;
6010 g_return_if_fail (GTK_IS_WINDOW (window));
6011 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6013 widget = GTK_WIDGET (window);
6016 toplevel = window->frame;
6018 toplevel = widget->window;
6020 gdk_window_begin_move_drag (toplevel,
6027 * gtk_window_set_screen:
6028 * @window: a #GtkWindow.
6029 * @screen: a #GdkScreen.
6031 * Sets the #GdkScreen where the @window is displayed; if
6032 * the window is already mapped, it will be unmapped, and
6033 * then remapped on the new screen.
6038 gtk_window_set_screen (GtkWindow *window,
6042 GdkScreen *previous_screen;
6043 gboolean was_mapped;
6045 g_return_if_fail (GTK_IS_WINDOW (window));
6046 g_return_if_fail (GDK_IS_SCREEN (screen));
6048 if (screen == window->screen)
6051 widget = GTK_WIDGET (window);
6053 previous_screen = window->screen;
6054 was_mapped = GTK_WIDGET_MAPPED (widget);
6057 gtk_widget_unmap (widget);
6058 if (GTK_WIDGET_REALIZED (widget))
6059 gtk_widget_unrealize (widget);
6061 gtk_window_free_key_hash (window);
6062 window->screen = screen;
6063 gtk_widget_reset_rc_styles (widget);
6064 if (screen != previous_screen)
6065 _gtk_widget_propagate_screen_changed (widget, previous_screen);
6066 g_object_notify (G_OBJECT (window), "screen");
6069 gtk_widget_map (widget);
6073 gtk_window_check_screen (GtkWindow *window)
6076 return window->screen;
6079 g_warning ("Screen for GtkWindow not set; you must always set\n"
6080 "a screen for a GtkWindow before using the window");
6086 * gtk_window_get_screen:
6087 * @window: a #GtkWindow.
6089 * Returns the #GdkScreen associated with @window.
6091 * Return value: a #GdkScreen.
6096 gtk_window_get_screen (GtkWindow *window)
6098 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6100 return window->screen;
6105 gtk_window_group_class_init (GtkWindowGroupClass *klass)
6110 gtk_window_group_get_type (void)
6112 static GType window_group_type = 0;
6114 if (!window_group_type)
6116 static const GTypeInfo window_group_info =
6118 sizeof (GtkWindowGroupClass),
6119 NULL, /* base_init */
6120 NULL, /* base_finalize */
6121 (GClassInitFunc) gtk_window_group_class_init,
6122 NULL, /* class_finalize */
6123 NULL, /* class_data */
6124 sizeof (GtkWindowGroup),
6125 16, /* n_preallocs */
6126 (GInstanceInitFunc) NULL,
6129 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
6132 return window_group_type;
6136 * gtk_window_group_new:
6138 * Creates a new #GtkWindowGroup object. Grabs added with
6139 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
6141 * Return value: a new #GtkWindowGroup.
6144 gtk_window_group_new (void)
6146 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
6150 window_group_cleanup_grabs (GtkWindowGroup *group,
6154 GSList *to_remove = NULL;
6156 tmp_list = group->grabs;
6159 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
6160 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
6161 tmp_list = tmp_list->next;
6166 gtk_grab_remove (to_remove->data);
6167 g_object_unref (to_remove->data);
6168 to_remove = g_slist_delete_link (to_remove, to_remove);
6173 * gtk_window_group_add_window:
6174 * @window_group: a #GtkWindowGroup
6175 * @window: the #GtkWindow to add
6177 * Adds a window to a #GtkWindowGroup.
6180 gtk_window_group_add_window (GtkWindowGroup *window_group,
6183 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6184 g_return_if_fail (GTK_IS_WINDOW (window));
6186 if (window->group != window_group)
6188 g_object_ref (window);
6189 g_object_ref (window_group);
6192 gtk_window_group_remove_window (window->group, window);
6194 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
6196 window->group = window_group;
6198 g_object_unref (window);
6203 * gtk_window_group_remove_window:
6204 * @window_group: a #GtkWindowGroup
6205 * @window: the #GtkWindow to remove
6207 * Removes a window from a #GtkWindowGroup.
6210 gtk_window_group_remove_window (GtkWindowGroup *window_group,
6213 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6214 g_return_if_fail (GTK_IS_WIDGET (window));
6215 g_return_if_fail (window->group == window_group);
6217 g_object_ref (window);
6219 window_group_cleanup_grabs (window_group, window);
6220 window->group = NULL;
6222 g_object_unref (window_group);
6223 g_object_unref (window);
6226 /* Return the group for the window or the default group
6229 _gtk_window_get_group (GtkWindow *window)
6231 if (window && window->group)
6232 return window->group;
6235 static GtkWindowGroup *default_group = NULL;
6238 default_group = gtk_window_group_new ();
6240 return default_group;
6246 Derived from XParseGeometry() in XFree86
6248 Copyright 1985, 1986, 1987,1998 The Open Group
6250 All Rights Reserved.
6252 The above copyright notice and this permission notice shall be included
6253 in all copies or substantial portions of the Software.
6255 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
6256 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6257 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6258 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
6259 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
6260 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
6261 OTHER DEALINGS IN THE SOFTWARE.
6263 Except as contained in this notice, the name of The Open Group shall
6264 not be used in advertising or otherwise to promote the sale, use or
6265 other dealings in this Software without prior written authorization
6266 from The Open Group.
6271 * XParseGeometry parses strings of the form
6272 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
6273 * width, height, xoffset, and yoffset are unsigned integers.
6274 * Example: "=80x24+300-49"
6275 * The equal sign is optional.
6276 * It returns a bitmask that indicates which of the four values
6277 * were actually found in the string. For each value found,
6278 * the corresponding argument is updated; for each value
6279 * not found, the corresponding argument is left unchanged.
6282 /* The following code is from Xlib, and is minimally modified, so we
6283 * can track any upstream changes if required. Don't change this
6284 * code. Or if you do, put in a huge comment marking which thing
6289 read_int (gchar *string,
6297 else if (*string == '-')
6303 for (; (*string >= '0') && (*string <= '9'); string++)
6305 result = (result * 10) + (*string - '0');
6317 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
6318 * value (x, y, width, height) was found in the parsed string.
6320 #define NoValue 0x0000
6321 #define XValue 0x0001
6322 #define YValue 0x0002
6323 #define WidthValue 0x0004
6324 #define HeightValue 0x0008
6325 #define AllValues 0x000F
6326 #define XNegative 0x0010
6327 #define YNegative 0x0020
6329 /* Try not to reformat/modify, so we can compare/sync with X sources */
6331 gtk_XParseGeometry (const char *string,
6334 unsigned int *width,
6335 unsigned int *height)
6339 unsigned int tempWidth, tempHeight;
6341 char *nextCharacter;
6343 /* These initializations are just to silence gcc */
6349 if ( (string == NULL) || (*string == '\0')) return(mask);
6351 string++; /* ignore possible '=' at beg of geometry spec */
6353 strind = (char *)string;
6354 if (*strind != '+' && *strind != '-' && *strind != 'x') {
6355 tempWidth = read_int(strind, &nextCharacter);
6356 if (strind == nextCharacter)
6358 strind = nextCharacter;
6362 if (*strind == 'x' || *strind == 'X') {
6364 tempHeight = read_int(strind, &nextCharacter);
6365 if (strind == nextCharacter)
6367 strind = nextCharacter;
6368 mask |= HeightValue;
6371 if ((*strind == '+') || (*strind == '-')) {
6372 if (*strind == '-') {
6374 tempX = -read_int(strind, &nextCharacter);
6375 if (strind == nextCharacter)
6377 strind = nextCharacter;
6383 tempX = read_int(strind, &nextCharacter);
6384 if (strind == nextCharacter)
6386 strind = nextCharacter;
6389 if ((*strind == '+') || (*strind == '-')) {
6390 if (*strind == '-') {
6392 tempY = -read_int(strind, &nextCharacter);
6393 if (strind == nextCharacter)
6395 strind = nextCharacter;
6402 tempY = read_int(strind, &nextCharacter);
6403 if (strind == nextCharacter)
6405 strind = nextCharacter;
6411 /* If strind isn't at the end of the string the it's an invalid
6412 geometry specification. */
6414 if (*strind != '\0') return (0);
6420 if (mask & WidthValue)
6422 if (mask & HeightValue)
6423 *height = tempHeight;
6428 * gtk_window_parse_geometry:
6429 * @window: a #GtkWindow
6430 * @geometry: geometry string
6432 * Parses a standard X Window System geometry string - see the
6433 * manual page for X (type 'man X') for details on this.
6434 * gtk_window_parse_geometry() does work on all GTK+ ports
6435 * including Win32 but is primarily intended for an X environment.
6437 * If either a size or a position can be extracted from the
6438 * geometry string, gtk_window_parse_geometry() returns %TRUE
6439 * and calls gtk_window_set_default_size() and/or gtk_window_move()
6440 * to resize/move the window.
6442 * If gtk_window_parse_geometry() returns %TRUE, it will also
6443 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
6444 * indicating to the window manager that the size/position of
6445 * the window was user-specified. This causes most window
6446 * managers to honor the geometry.
6448 * Return value: %TRUE if string was parsed successfully
6451 gtk_window_parse_geometry (GtkWindow *window,
6452 const gchar *geometry)
6457 gboolean size_set, pos_set;
6460 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6461 g_return_val_if_fail (geometry != NULL, FALSE);
6463 screen = gtk_window_check_screen (window);
6465 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
6467 if ((result & WidthValue) == 0 ||
6470 if ((result & HeightValue) == 0 ||
6475 if ((result & WidthValue) || (result & HeightValue))
6477 gtk_window_set_default_size_internal (window, TRUE, w, TRUE, h, TRUE);
6481 gtk_window_get_size (window, &w, &h);
6483 grav = GDK_GRAVITY_NORTH_WEST;
6485 if ((result & XNegative) && (result & YNegative))
6486 grav = GDK_GRAVITY_SOUTH_EAST;
6487 else if (result & XNegative)
6488 grav = GDK_GRAVITY_NORTH_EAST;
6489 else if (result & YNegative)
6490 grav = GDK_GRAVITY_SOUTH_WEST;
6492 if ((result & XValue) == 0)
6495 if ((result & YValue) == 0)
6498 if (grav == GDK_GRAVITY_SOUTH_WEST ||
6499 grav == GDK_GRAVITY_SOUTH_EAST)
6500 y = gdk_screen_get_height (screen) - h + y;
6502 if (grav == GDK_GRAVITY_SOUTH_EAST ||
6503 grav == GDK_GRAVITY_NORTH_EAST)
6504 x = gdk_screen_get_width (screen) - w + x;
6506 /* we don't let you put a window offscreen; maybe some people would
6507 * prefer to be able to, but it's kind of a bogus thing to do.
6516 if ((result & XValue) || (result & YValue))
6518 gtk_window_set_gravity (window, grav);
6519 gtk_window_move (window, x, y);
6523 if (size_set || pos_set)
6525 /* Set USSize, USPosition hints */
6526 GtkWindowGeometryInfo *info;
6528 info = gtk_window_get_geometry_info (window, TRUE);
6531 info->mask |= GDK_HINT_USER_POS;
6533 info->mask |= GDK_HINT_USER_SIZE;
6540 gtk_window_mnemonic_hash_foreach (gpointer key,
6546 GtkWindowKeysForeachFunc func;
6550 GtkWindowMnemonic *mnemonic = value;
6552 if (mnemonic->window == info->window)
6553 (*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
6557 _gtk_window_keys_foreach (GtkWindow *window,
6558 GtkWindowKeysForeachFunc func,
6565 GtkWindowKeysForeachFunc func;
6569 info.window = window;
6571 info.func_data = func_data;
6573 g_hash_table_foreach (mnemonic_hash_table,
6574 gtk_window_mnemonic_hash_foreach,
6577 groups = gtk_accel_groups_from_object (G_OBJECT (window));
6580 GtkAccelGroup *group = groups->data;
6583 for (i = 0; i < group->n_accels; i++)
6585 GtkAccelKey *key = &group->priv_accels[i].key;
6588 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
6591 groups = groups->next;
6596 gtk_window_keys_changed (GtkWindow *window)
6598 gtk_window_free_key_hash (window);
6599 gtk_window_get_key_hash (window);
6602 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
6604 struct _GtkWindowKeyEntry
6608 gboolean is_mnemonic;
6612 add_to_key_hash (GtkWindow *window,
6614 GdkModifierType modifiers,
6615 gboolean is_mnemonic,
6618 GtkKeyHash *key_hash = data;
6620 GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
6622 entry->keyval = keyval;
6623 entry->modifiers = modifiers;
6624 entry->is_mnemonic = is_mnemonic;
6626 /* GtkAccelGroup stores lowercased accelerators. To deal
6627 * with this, if <Shift> was specified, uppercase.
6629 if (modifiers & GDK_SHIFT_MASK)
6631 if (keyval == GDK_Tab)
6632 keyval = GDK_ISO_Left_Tab;
6634 keyval = gdk_keyval_to_upper (keyval);
6637 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
6641 gtk_window_get_key_hash (GtkWindow *window)
6643 GdkScreen *screen = gtk_window_check_screen (window);
6644 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6649 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
6650 (GDestroyNotify)g_free);
6651 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
6652 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
6658 gtk_window_free_key_hash (GtkWindow *window)
6660 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6663 _gtk_key_hash_free (key_hash);
6664 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
6669 * _gtk_window_activate_key:
6670 * @window: a #GtkWindow
6671 * @event: a #GdkEventKey
6673 * Activates mnemonics and accelerators for this #GtKWindow
6675 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
6678 _gtk_window_activate_key (GtkWindow *window,
6681 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6682 GtkWindowKeyEntry *found_entry = NULL;
6686 gtk_window_keys_changed (window);
6687 key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6692 GSList *entries = _gtk_key_hash_lookup (key_hash,
6693 event->hardware_keycode,
6694 event->state & gtk_accelerator_get_default_mod_mask (),
6698 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
6700 GtkWindowKeyEntry *entry = tmp_list->data;
6701 if (entry->is_mnemonic)
6703 found_entry = entry;
6708 if (!found_entry && entries)
6709 found_entry = entries->data;
6711 g_slist_free (entries);
6716 if (found_entry->is_mnemonic)
6717 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
6719 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
6726 window_update_has_focus (GtkWindow *window)
6728 GtkWidget *widget = GTK_WIDGET (window);
6729 gboolean has_focus = window->has_toplevel_focus && window->is_active;
6731 if (has_focus != window->has_focus)
6733 window->has_focus = has_focus;
6737 if (window->focus_widget &&
6738 window->focus_widget != widget &&
6739 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6740 do_focus_change (window->focus_widget, TRUE);
6744 if (window->focus_widget &&
6745 window->focus_widget != widget &&
6746 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6747 do_focus_change (window->focus_widget, FALSE);
6753 * _gtk_window_set_is_active:
6754 * @window: a #GtkWindow
6755 * @is_active: %TRUE if the window is in the currently active toplevel
6757 * Internal function that sets whether the #GtkWindow is part
6758 * of the currently active toplevel window (taking into account inter-process
6762 _gtk_window_set_is_active (GtkWindow *window,
6765 g_return_if_fail (GTK_IS_WINDOW (window));
6767 is_active = is_active != FALSE;
6769 if (is_active != window->is_active)
6771 window->is_active = is_active;
6772 window_update_has_focus (window);
6774 g_object_notify (G_OBJECT (window), "is_active");
6779 * _gtk_window_set_has_toplevel_focus:
6780 * @window: a #GtkWindow
6781 * @has_toplevel_focus: %TRUE if the in
6783 * Internal function that sets whether the keyboard focus for the
6784 * toplevel window (taking into account inter-process embedding.)
6787 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
6788 gboolean has_toplevel_focus)
6790 g_return_if_fail (GTK_IS_WINDOW (window));
6792 has_toplevel_focus = has_toplevel_focus != FALSE;
6794 if (has_toplevel_focus != window->has_toplevel_focus)
6796 window->has_toplevel_focus = has_toplevel_focus;
6797 window_update_has_focus (window);
6799 g_object_notify (G_OBJECT (window), "has_toplevel_focus");
6804 * gtk_window_set_auto_startup_notification:
6805 * @setting: %TRUE to automatically do startup notification
6807 * By default, after showing the first #GtkWindow for each #GdkScreen,
6808 * GTK+ calls gdk_screen_notify_startup_complete(). Call this
6809 * function to disable the automatic startup notification. You might
6810 * do this if your first window is a splash screen, and you want to
6811 * delay notification until after your real main window has been
6812 * shown, for example.
6814 * In that example, you would disable startup notification
6815 * temporarily, show your splash screen, then re-enable it so that
6816 * showing the main window would automatically result in notification.
6821 gtk_window_set_auto_startup_notification (gboolean setting)
6823 disable_startup_notification = !setting;