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.
1899 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
1902 GtkWindowPrivate *priv;
1904 g_return_if_fail (GTK_IS_WINDOW (window));
1906 priv = gtk_window_get_private (window);
1908 setting = setting != FALSE;
1910 if (priv->skips_taskbar != setting)
1912 priv->skips_taskbar = setting;
1913 if (GTK_WIDGET_REALIZED (window))
1914 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
1915 priv->skips_taskbar);
1916 g_object_notify (G_OBJECT (window), "skip_taskbar_hint");
1921 * gtk_window_get_skip_taskbar_hint:
1922 * @window: a #GtkWindow
1924 * Gets the value set by gtk_window_set_skip_taskbar_hint()
1926 * Return value: %TRUE if window shouldn't be in taskbar
1929 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
1931 GtkWindowPrivate *priv;
1933 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1935 priv = gtk_window_get_private (window);
1937 return priv->skips_taskbar;
1941 * gtk_window_set_skip_pager_hint:
1942 * @window: a #GtkWindow
1943 * @setting: %TRUE to keep this window from appearing in the pager
1945 * Windows may set a hint asking the desktop environment not to display
1946 * the window in the pager. This function toggles this hint.
1947 * (A "pager" is any desktop navigation tool such as a workspace
1948 * switcher that displays a thumbnail representation of the windows
1953 gtk_window_set_skip_pager_hint (GtkWindow *window,
1956 GtkWindowPrivate *priv;
1958 g_return_if_fail (GTK_IS_WINDOW (window));
1960 priv = gtk_window_get_private (window);
1962 setting = setting != FALSE;
1964 if (priv->skips_pager != setting)
1966 priv->skips_pager = setting;
1967 if (GTK_WIDGET_REALIZED (window))
1968 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
1970 g_object_notify (G_OBJECT (window), "skip_pager_hint");
1975 * gtk_window_get_skip_pager_hint:
1976 * @window: a #GtkWindow
1978 * Gets the value set by gtk_window_set_skip_pager_hint().
1980 * Return value: %TRUE if window shouldn't be in pager
1983 gtk_window_get_skip_pager_hint (GtkWindow *window)
1985 GtkWindowPrivate *priv;
1987 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1989 priv = gtk_window_get_private (window);
1991 return priv->skips_pager;
1995 * gtk_window_set_destroy_with_parent:
1996 * @window: a #GtkWindow
1997 * @setting: whether to destroy @window with its transient parent
1999 * If @setting is %TRUE, then destroying the transient parent of @window
2000 * will also destroy @window itself. This is useful for dialogs that
2001 * shouldn't persist beyond the lifetime of the main window they're
2002 * associated with, for example.
2005 gtk_window_set_destroy_with_parent (GtkWindow *window,
2008 g_return_if_fail (GTK_IS_WINDOW (window));
2010 if (window->destroy_with_parent == (setting != FALSE))
2013 if (window->destroy_with_parent)
2015 disconnect_parent_destroyed (window);
2019 connect_parent_destroyed (window);
2022 window->destroy_with_parent = setting;
2024 g_object_notify (G_OBJECT (window), "destroy_with_parent");
2028 * gtk_window_get_destroy_with_parent:
2029 * @window: a #GtkWindow
2031 * Returns whether the window will be destroyed with its transient parent. See
2032 * gtk_window_set_destroy_with_parent ().
2034 * Return value: %TRUE if the window will be destroyed with its transient parent.
2037 gtk_window_get_destroy_with_parent (GtkWindow *window)
2039 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2041 return window->destroy_with_parent;
2044 static GtkWindowGeometryInfo*
2045 gtk_window_get_geometry_info (GtkWindow *window,
2048 GtkWindowGeometryInfo *info;
2050 info = window->geometry_info;
2051 if (!info && create)
2053 info = g_new0 (GtkWindowGeometryInfo, 1);
2055 info->default_width = -1;
2056 info->default_height = -1;
2057 info->resize_width = -1;
2058 info->resize_height = -1;
2059 info->initial_x = 0;
2060 info->initial_y = 0;
2061 info->initial_pos_set = FALSE;
2062 info->default_is_geometry = FALSE;
2063 info->position_constraints_changed = FALSE;
2064 info->last.configure_request.x = 0;
2065 info->last.configure_request.y = 0;
2066 info->last.configure_request.width = -1;
2067 info->last.configure_request.height = -1;
2068 info->widget = NULL;
2070 window->geometry_info = info;
2077 * gtk_window_set_geometry_hints:
2078 * @window: a #GtkWindow
2079 * @geometry_widget: widget the geometry hints will be applied to
2080 * @geometry: struct containing geometry information
2081 * @geom_mask: mask indicating which struct fields should be paid attention to
2083 * This function sets up hints about how a window can be resized by
2084 * the user. You can set a minimum and maximum size; allowed resize
2085 * increments (e.g. for xterm, you can only resize by the size of a
2086 * character); aspect ratios; and more. See the #GdkGeometry struct.
2090 gtk_window_set_geometry_hints (GtkWindow *window,
2091 GtkWidget *geometry_widget,
2092 GdkGeometry *geometry,
2093 GdkWindowHints geom_mask)
2095 GtkWindowGeometryInfo *info;
2097 g_return_if_fail (GTK_IS_WINDOW (window));
2098 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2100 info = gtk_window_get_geometry_info (window, TRUE);
2103 g_signal_handlers_disconnect_by_func (info->widget,
2104 gtk_widget_destroyed,
2107 info->widget = geometry_widget;
2109 g_signal_connect (geometry_widget, "destroy",
2110 G_CALLBACK (gtk_widget_destroyed),
2114 info->geometry = *geometry;
2116 /* We store gravity in window->gravity not in the hints. */
2117 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2119 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2121 gtk_window_set_gravity (window, geometry->win_gravity);
2124 gtk_widget_queue_resize (GTK_WIDGET (window));
2128 * gtk_window_set_decorated:
2129 * @window: a #GtkWindow
2130 * @setting: %TRUE to decorate the window
2132 * By default, windows are decorated with a title bar, resize
2133 * controls, etc. Some <link linkend="gtk-X11-arch">window
2134 * managers</link> allow GTK+ to disable these decorations, creating a
2135 * borderless window. If you set the decorated property to %FALSE
2136 * using this function, GTK+ will do its best to convince the window
2137 * manager not to decorate the window. Depending on the system, this
2138 * function may not have any effect when called on a window that is
2139 * already visible, so you should call it before calling gtk_window_show().
2141 * On Windows, this function always works, since there's no window manager
2146 gtk_window_set_decorated (GtkWindow *window,
2149 g_return_if_fail (GTK_IS_WINDOW (window));
2151 setting = setting != FALSE;
2153 if (setting == window->decorated)
2156 window->decorated = setting;
2158 if (GTK_WIDGET (window)->window)
2160 if (window->decorated)
2161 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2164 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2170 * gtk_window_get_decorated:
2171 * @window: a #GtkWindow
2173 * Returns whether the window has been set to have decorations
2174 * such as a title bar via gtk_window_set_decorated().
2176 * Return value: %TRUE if the window has been set to have decorations
2179 gtk_window_get_decorated (GtkWindow *window)
2181 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2183 return window->decorated;
2186 static GtkWindowIconInfo*
2187 get_icon_info (GtkWindow *window)
2189 return g_object_get_data (G_OBJECT (window),
2190 "gtk-window-icon-info");
2193 static GtkWindowIconInfo*
2194 ensure_icon_info (GtkWindow *window)
2196 GtkWindowIconInfo *info;
2198 info = get_icon_info (window);
2202 info = g_new0 (GtkWindowIconInfo, 1);
2203 g_object_set_data_full (G_OBJECT (window),
2204 "gtk-window-icon-info",
2219 get_screen_icon_info (GdkScreen *screen)
2221 ScreenIconInfo *info = g_object_get_data (G_OBJECT (screen),
2222 "gtk-window-default-icon-pixmap");
2225 info = g_new0 (ScreenIconInfo, 1);
2226 g_object_set_data (G_OBJECT (screen), "gtk-window-default-icon-pixmap", info);
2229 if (info->serial != default_icon_serial)
2233 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2234 info->pixmap = NULL;
2239 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2243 info->serial = default_icon_serial;
2250 get_pixmap_and_mask (GdkWindow *window,
2251 GtkWindowIconInfo *parent_info,
2252 gboolean is_default_list,
2254 GdkPixmap **pmap_return,
2255 GdkBitmap **mask_return)
2257 GdkScreen *screen = gdk_drawable_get_screen (window);
2258 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2259 GdkPixbuf *best_icon;
2263 *pmap_return = NULL;
2264 *mask_return = NULL;
2266 if (is_default_list &&
2267 default_icon_info->pixmap != NULL)
2269 /* Use shared icon pixmap for all windows on this screen.
2271 if (default_icon_info->pixmap)
2272 g_object_ref (default_icon_info->pixmap);
2273 if (default_icon_info->mask)
2274 g_object_ref (default_icon_info->mask);
2276 *pmap_return = default_icon_info->pixmap;
2277 *mask_return = default_icon_info->mask;
2279 else if (parent_info && parent_info->icon_pixmap)
2281 if (parent_info->icon_pixmap)
2282 g_object_ref (parent_info->icon_pixmap);
2283 if (parent_info->icon_mask)
2284 g_object_ref (parent_info->icon_mask);
2286 *pmap_return = parent_info->icon_pixmap;
2287 *mask_return = parent_info->icon_mask;
2291 #define IDEAL_SIZE 48
2293 best_size = G_MAXINT;
2295 tmp_list = icon_list;
2296 while (tmp_list != NULL)
2298 GdkPixbuf *pixbuf = tmp_list->data;
2301 /* average width and height - if someone passes in a rectangular
2302 * icon they deserve what they get.
2304 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2307 if (best_icon == NULL)
2314 /* icon is better if it's 32 pixels or larger, and closer to
2315 * the ideal size than the current best.
2318 (ABS (best_size - IDEAL_SIZE) <
2319 ABS (this - IDEAL_SIZE)))
2326 tmp_list = tmp_list->next;
2330 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2331 gdk_screen_get_system_colormap (screen),
2336 /* Save pmap/mask for others to use if appropriate */
2339 parent_info->icon_pixmap = *pmap_return;
2340 parent_info->icon_mask = *mask_return;
2342 if (parent_info->icon_pixmap)
2343 g_object_ref (parent_info->icon_pixmap);
2344 if (parent_info->icon_mask)
2345 g_object_ref (parent_info->icon_mask);
2347 else if (is_default_list)
2349 default_icon_info->pixmap = *pmap_return;
2350 default_icon_info->mask = *mask_return;
2352 if (default_icon_info->pixmap)
2353 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2354 (gpointer*)&default_icon_info->pixmap);
2355 if (default_icon_info->mask)
2356 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2357 (gpointer*)&default_icon_info->mask);
2363 gtk_window_realize_icon (GtkWindow *window)
2366 GtkWindowIconInfo *info;
2369 widget = GTK_WIDGET (window);
2371 g_return_if_fail (widget->window != NULL);
2373 /* no point setting an icon on override-redirect */
2374 if (window->type == GTK_WINDOW_POPUP)
2379 info = ensure_icon_info (window);
2384 g_return_if_fail (info->icon_pixmap == NULL);
2385 g_return_if_fail (info->icon_mask == NULL);
2387 info->using_default_icon = FALSE;
2388 info->using_parent_icon = FALSE;
2390 icon_list = info->icon_list;
2392 /* Inherit from transient parent */
2393 if (icon_list == NULL && window->transient_parent)
2395 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2397 info->using_parent_icon = TRUE;
2400 /* Inherit from default */
2401 if (icon_list == NULL)
2403 icon_list = default_icon_list;
2405 info->using_default_icon = TRUE;
2408 gdk_window_set_icon_list (widget->window, icon_list);
2410 get_pixmap_and_mask (widget->window,
2411 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2412 info->using_default_icon,
2417 /* This is a slight ICCCM violation since it's a color pixmap not
2418 * a bitmap, but everyone does it.
2420 gdk_window_set_icon (widget->window,
2425 info->realized = TRUE;
2429 gtk_window_unrealize_icon (GtkWindow *window)
2431 GtkWindowIconInfo *info;
2434 widget = GTK_WIDGET (window);
2436 info = get_icon_info (window);
2441 if (info->icon_pixmap)
2442 g_object_unref (info->icon_pixmap);
2444 if (info->icon_mask)
2445 g_object_unref (info->icon_mask);
2447 info->icon_pixmap = NULL;
2448 info->icon_mask = NULL;
2450 /* We don't clear the properties on the window, just figure the
2451 * window is going away.
2454 info->realized = FALSE;
2458 * gtk_window_set_icon_list:
2459 * @window: a #GtkWindow
2460 * @list: list of #GdkPixbuf
2462 * Sets up the icon representing a #GtkWindow. The icon is used when
2463 * the window is minimized (also known as iconified). Some window
2464 * managers or desktop environments may also place it in the window
2465 * frame, or display it in other contexts.
2467 * gtk_window_set_icon_list() allows you to pass in the same icon in
2468 * several hand-drawn sizes. The list should contain the natural sizes
2469 * your icon is available in; that is, don't scale the image before
2470 * passing it to GTK+. Scaling is postponed until the last minute,
2471 * when the desired final size is known, to allow best quality.
2473 * By passing several sizes, you may improve the final image quality
2474 * of the icon, by reducing or eliminating automatic image scaling.
2476 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2477 * larger images (64x64, 128x128) if you have them.
2479 * See also gtk_window_set_default_icon_list() to set the icon
2480 * for all windows in your application in one go.
2482 * Note that transient windows (those who have been set transient for another
2483 * window using gtk_window_set_transient_for()) will inherit their
2484 * icon from their transient parent. So there's no need to explicitly
2485 * set the icon on transient windows.
2488 gtk_window_set_icon_list (GtkWindow *window,
2491 GtkWindowIconInfo *info;
2493 g_return_if_fail (GTK_IS_WINDOW (window));
2495 info = ensure_icon_info (window);
2497 if (info->icon_list == list) /* check for NULL mostly */
2500 g_list_foreach (info->icon_list,
2501 (GFunc) g_object_unref, NULL);
2503 g_list_free (info->icon_list);
2505 info->icon_list = g_list_copy (list);
2506 g_list_foreach (info->icon_list,
2507 (GFunc) g_object_ref, NULL);
2509 g_object_notify (G_OBJECT (window), "icon");
2511 gtk_window_unrealize_icon (window);
2513 if (GTK_WIDGET_REALIZED (window))
2514 gtk_window_realize_icon (window);
2516 /* We could try to update our transient children, but I don't think
2517 * it's really worth it. If we did it, the best way would probably
2518 * be to have children connect to notify::icon_list
2523 * gtk_window_get_icon_list:
2524 * @window: a #GtkWindow
2526 * Retrieves the list of icons set by gtk_window_set_icon_list().
2527 * The list is copied, but the reference count on each
2528 * member won't be incremented.
2530 * Return value: copy of window's icon list
2533 gtk_window_get_icon_list (GtkWindow *window)
2535 GtkWindowIconInfo *info;
2537 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2539 info = get_icon_info (window);
2542 return g_list_copy (info->icon_list);
2548 * gtk_window_set_icon:
2549 * @window: a #GtkWindow
2550 * @icon: icon image, or %NULL
2552 * Sets up the icon representing a #GtkWindow. This icon is used when
2553 * the window is minimized (also known as iconified). Some window
2554 * managers or desktop environments may also place it in the window
2555 * frame, or display it in other contexts.
2557 * The icon should be provided in whatever size it was naturally
2558 * drawn; that is, don't scale the image before passing it to
2559 * GTK+. Scaling is postponed until the last minute, when the desired
2560 * final size is known, to allow best quality.
2562 * If you have your icon hand-drawn in multiple sizes, use
2563 * gtk_window_set_icon_list(). Then the best size will be used.
2565 * This function is equivalent to calling gtk_window_set_icon_list()
2566 * with a 1-element list.
2568 * See also gtk_window_set_default_icon_list() to set the icon
2569 * for all windows in your application in one go.
2572 gtk_window_set_icon (GtkWindow *window,
2577 g_return_if_fail (GTK_IS_WINDOW (window));
2578 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2583 list = g_list_append (list, icon);
2585 gtk_window_set_icon_list (window, list);
2590 * gtk_window_get_icon:
2591 * @window: a #GtkWindow
2593 * Gets the value set by gtk_window_set_icon() (or if you've
2594 * called gtk_window_set_icon_list(), gets the first icon in
2597 * Return value: icon for window
2600 gtk_window_get_icon (GtkWindow *window)
2602 GtkWindowIconInfo *info;
2604 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2606 info = get_icon_info (window);
2607 if (info && info->icon_list)
2608 return GDK_PIXBUF (info->icon_list->data);
2613 /* Load pixbuf, printing warning on failure if error == NULL
2616 load_pixbuf_verbosely (const char *filename,
2619 GError *local_err = NULL;
2622 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
2630 g_warning ("Error loading icon from file '%s':\n\t%s",
2631 filename, local_err->message);
2632 g_error_free (local_err);
2640 * gtk_window_set_icon_from_file:
2641 * @window: a #GtkWindow
2642 * @filename: location of icon file
2643 * @err: location to store error, or %NULL.
2645 * Sets the icon for @window.
2646 * Warns on failure if @err is %NULL.
2648 * This function is equivalent to calling gtk_window_set_icon()
2649 * with a pixbuf created by loading the image from @filename.
2651 * Returns: %TRUE if setting the icon succeeded.
2654 gtk_window_set_icon_from_file (GtkWindow *window,
2655 const gchar *filename,
2658 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2662 gtk_window_set_icon (window, pixbuf);
2663 g_object_unref (pixbuf);
2672 * gtk_window_set_default_icon_list:
2673 * @list: a list of #GdkPixbuf
2675 * Sets an icon list to be used as fallback for windows that haven't
2676 * had gtk_window_set_icon_list() called on them to set up a
2677 * window-specific icon list. This function allows you to set up the
2678 * icon for all windows in your app at once.
2680 * See gtk_window_set_icon_list() for more details.
2684 gtk_window_set_default_icon_list (GList *list)
2688 if (list == default_icon_list)
2691 /* Update serial so we don't used cached pixmaps/masks
2693 default_icon_serial++;
2695 g_list_foreach (default_icon_list,
2696 (GFunc) g_object_unref, NULL);
2698 g_list_free (default_icon_list);
2700 default_icon_list = g_list_copy (list);
2701 g_list_foreach (default_icon_list,
2702 (GFunc) g_object_ref, NULL);
2704 /* Update all toplevels */
2705 toplevels = gtk_window_list_toplevels ();
2706 tmp_list = toplevels;
2707 while (tmp_list != NULL)
2709 GtkWindowIconInfo *info;
2710 GtkWindow *w = tmp_list->data;
2712 info = get_icon_info (w);
2713 if (info && info->using_default_icon)
2715 gtk_window_unrealize_icon (w);
2716 if (GTK_WIDGET_REALIZED (w))
2717 gtk_window_realize_icon (w);
2720 tmp_list = tmp_list->next;
2722 g_list_free (toplevels);
2726 * gtk_window_set_default_icon_from_file:
2727 * @filename: location of icon file
2728 * @err: location to store error, or %NULL.
2730 * Sets an icon to be used as fallback for windows that haven't
2731 * had gtk_window_set_icon_list() called on them from a file
2732 * on disk. Warns on failure if @err is %NULL.
2734 * Returns: %TRUE if setting the icon succeeded.
2737 gtk_window_set_default_icon_from_file (const gchar *filename,
2740 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2744 GList *list = g_list_prepend (NULL, pixbuf);
2745 gtk_window_set_default_icon_list (list);
2748 g_object_unref (pixbuf);
2757 * gtk_window_get_default_icon_list:
2759 * Gets the value set by gtk_window_set_default_icon_list().
2760 * The list is a copy and should be freed with g_list_free(),
2761 * but the pixbufs in the list have not had their reference count
2764 * Return value: copy of default icon list
2767 gtk_window_get_default_icon_list (void)
2769 return g_list_copy (default_icon_list);
2773 gtk_window_set_default_size_internal (GtkWindow *window,
2774 gboolean change_width,
2776 gboolean change_height,
2778 gboolean is_geometry)
2780 GtkWindowGeometryInfo *info;
2782 g_return_if_fail (change_width == FALSE || width >= -1);
2783 g_return_if_fail (change_height == FALSE || height >= -1);
2785 info = gtk_window_get_geometry_info (window, TRUE);
2787 g_object_freeze_notify (G_OBJECT (window));
2789 info->default_is_geometry = is_geometry != FALSE;
2799 info->default_width = width;
2801 g_object_notify (G_OBJECT (window), "default_width");
2812 info->default_height = height;
2814 g_object_notify (G_OBJECT (window), "default_height");
2817 g_object_thaw_notify (G_OBJECT (window));
2819 gtk_widget_queue_resize (GTK_WIDGET (window));
2823 * gtk_window_set_default_size:
2824 * @window: a #GtkWindow
2825 * @width: width in pixels, or -1 to unset the default width
2826 * @height: height in pixels, or -1 to unset the default height
2828 * Sets the default size of a window. If the window's "natural" size
2829 * (its size request) is larger than the default, the default will be
2830 * ignored. More generally, if the default size does not obey the
2831 * geometry hints for the window (gtk_window_set_geometry_hints() can
2832 * be used to set these explicitly), the default size will be clamped
2833 * to the nearest permitted size.
2835 * Unlike gtk_widget_set_size_request(), which sets a size request for
2836 * a widget and thus would keep users from shrinking the window, this
2837 * function only sets the initial size, just as if the user had
2838 * resized the window themselves. Users can still shrink the window
2839 * again as they normally would. Setting a default size of -1 means to
2840 * use the "natural" default size (the size request of the window).
2842 * For more control over a window's initial size and how resizing works,
2843 * investigate gtk_window_set_geometry_hints().
2845 * For some uses, gtk_window_resize() is a more appropriate function.
2846 * gtk_window_resize() changes the current size of the window, rather
2847 * than the size to be used on initial display. gtk_window_resize() always
2848 * affects the window itself, not the geometry widget.
2850 * The default size of a window only affects the first time a window is
2851 * shown; if a window is hidden and re-shown, it will remember the size
2852 * it had prior to hiding, rather than using the default size.
2854 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2855 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2858 gtk_window_set_default_size (GtkWindow *window,
2862 g_return_if_fail (GTK_IS_WINDOW (window));
2863 g_return_if_fail (width >= -1);
2864 g_return_if_fail (height >= -1);
2866 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
2870 * gtk_window_get_default_size:
2871 * @window: a #GtkWindow
2872 * @width: location to store the default width, or %NULL
2873 * @height: location to store the default height, or %NULL
2875 * Gets the default size of the window. A value of -1 for the width or
2876 * height indicates that a default size has not been explicitly set
2877 * for that dimension, so the "natural" size of the window will be
2882 gtk_window_get_default_size (GtkWindow *window,
2886 GtkWindowGeometryInfo *info;
2888 g_return_if_fail (GTK_IS_WINDOW (window));
2890 info = gtk_window_get_geometry_info (window, FALSE);
2893 *width = info->default_width;
2896 *height = info->default_height;
2900 * gtk_window_resize:
2901 * @window: a #GtkWindow
2902 * @width: width in pixels to resize the window to
2903 * @height: height in pixels to resize the window to
2905 * Resizes the window as if the user had done so, obeying geometry
2906 * constraints. The default geometry constraint is that windows may
2907 * not be smaller than their size request; to override this
2908 * constraint, call gtk_widget_set_size_request() to set the window's
2909 * request to a smaller value.
2911 * If gtk_window_resize() is called before showing a window for the
2912 * first time, it overrides any default size set with
2913 * gtk_window_set_default_size().
2915 * Windows may not be resized smaller than 1 by 1 pixels.
2919 gtk_window_resize (GtkWindow *window,
2923 GtkWindowGeometryInfo *info;
2925 g_return_if_fail (GTK_IS_WINDOW (window));
2926 g_return_if_fail (width > 0);
2927 g_return_if_fail (height > 0);
2929 info = gtk_window_get_geometry_info (window, TRUE);
2931 info->resize_width = width;
2932 info->resize_height = height;
2934 gtk_widget_queue_resize (GTK_WIDGET (window));
2938 * gtk_window_get_size:
2939 * @window: a #GtkWindow
2940 * @width: return location for width, or %NULL
2941 * @height: return location for height, or %NULL
2943 * Obtains the current size of @window. If @window is not onscreen,
2944 * it returns the size GTK+ will suggest to the <link
2945 * linkend="gtk-X11-arch">window manager</link> for the initial window
2946 * size (but this is not reliably the same as the size the window
2947 * manager will actually select). The size obtained by
2948 * gtk_window_get_size() is the last size received in a
2949 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2950 * rather than querying the X server for the size. As a result, if you
2951 * call gtk_window_resize() then immediately call
2952 * gtk_window_get_size(), the size won't have taken effect yet. After
2953 * the window manager processes the resize request, GTK+ receives
2954 * notification that the size has changed via a configure event, and
2955 * the size of the window gets updated.
2957 * Note 1: Nearly any use of this function creates a race condition,
2958 * because the size of the window may change between the time that you
2959 * get the size and the time that you perform some action assuming
2960 * that size is the current size. To avoid race conditions, connect to
2961 * "configure_event" on the window and adjust your size-dependent
2962 * state to match the size delivered in the #GdkEventConfigure.
2964 * Note 2: The returned size does <emphasis>not</emphasis> include the
2965 * size of the window manager decorations (aka the window frame or
2966 * border). Those are not drawn by GTK+ and GTK+ has no reliable
2967 * method of determining their size.
2969 * Note 3: If you are getting a window size in order to position
2970 * the window onscreen, there may be a better way. The preferred
2971 * way is to simply set the window's semantic type with
2972 * gtk_window_set_type_hint(), which allows the window manager to
2973 * e.g. center dialogs. Also, if you set the transient parent of
2974 * dialogs with gtk_window_set_transient_for() window managers
2975 * will often center the dialog over its parent window. It's
2976 * much preferred to let the window manager handle these
2977 * things rather than doing it yourself, because all apps will
2978 * behave consistently and according to user prefs if the window
2979 * manager handles it. Also, the window manager can take the size
2980 * of the window decorations/border into account, while your
2981 * application cannot.
2983 * In any case, if you insist on application-specified window
2984 * positioning, there's <emphasis>still</emphasis> a better way than
2985 * doing it yourself - gtk_window_set_position() will frequently
2986 * handle the details for you.
2990 gtk_window_get_size (GtkWindow *window,
2997 g_return_if_fail (GTK_IS_WINDOW (window));
2999 widget = GTK_WIDGET (window);
3001 if (width == NULL && height == NULL)
3004 if (GTK_WIDGET_MAPPED (window))
3006 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3011 GdkRectangle configure_request;
3013 gtk_window_compute_configure_request (window,
3017 w = configure_request.width;
3018 h = configure_request.height;
3029 * @window: a #GtkWindow
3030 * @x: X coordinate to move window to
3031 * @y: Y coordinate to move window to
3033 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3034 * @window to the given position. Window managers are free to ignore
3035 * this; most window managers ignore requests for initial window
3036 * positions (instead using a user-defined placement algorithm) and
3037 * honor requests after the window has already been shown.
3039 * Note: the position is the position of the gravity-determined
3040 * reference point for the window. The gravity determines two things:
3041 * first, the location of the reference point in root window
3042 * coordinates; and second, which point on the window is positioned at
3043 * the reference point.
3045 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3046 * point is simply the @x, @y supplied to gtk_window_move(). The
3047 * top-left corner of the window decorations (aka window frame or
3048 * border) will be placed at @x, @y. Therefore, to position a window
3049 * at the top left of the screen, you want to use the default gravity
3050 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3052 * To position a window at the bottom right corner of the screen, you
3053 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3054 * point is at @x + the window width and @y + the window height, and
3055 * the bottom-right corner of the window border will be placed at that
3056 * reference point. So, to place a window in the bottom right corner
3057 * you would first set gravity to south east, then write:
3058 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3059 * gdk_screen_height () - window_height)</literal>.
3061 * The extended window manager hints specification at <ulink
3062 * url="http://www.freedesktop.org/standards/wm-spec.html">
3063 * http://www.freedesktop.org/standards/wm-spec.html</ulink> has a
3064 * nice table of gravities in the "implementation notes" section.
3066 * The gtk_window_get_position() documentation may also be relevant.
3070 gtk_window_move (GtkWindow *window,
3074 GtkWindowGeometryInfo *info;
3077 g_return_if_fail (GTK_IS_WINDOW (window));
3079 widget = GTK_WIDGET (window);
3081 info = gtk_window_get_geometry_info (window, TRUE);
3083 if (GTK_WIDGET_MAPPED (window))
3085 /* we have now sent a request with this position
3086 * with currently-active constraints, so toggle flag.
3088 info->position_constraints_changed = FALSE;
3090 /* we only constrain if mapped - if not mapped,
3091 * then gtk_window_compute_configure_request()
3092 * will apply the constraints later, and we
3093 * don't want to lose information about
3094 * what position the user set before then.
3095 * i.e. if you do a move() then turn off POS_CENTER
3096 * then show the window, your move() will work.
3098 gtk_window_constrain_position (window,
3099 widget->allocation.width,
3100 widget->allocation.height,
3103 /* Note that this request doesn't go through our standard request
3104 * framework, e.g. doesn't increment configure_request_count,
3105 * doesn't set info->last, etc.; that's because
3106 * we don't save the info needed to arrive at this same request
3109 * To gtk_window_move_resize(), this will end up looking exactly
3110 * the same as the position being changed by the window
3114 /* FIXME are we handling gravity properly for framed windows? */
3116 gdk_window_move (window->frame,
3117 x - window->frame_left,
3118 y - window->frame_top);
3120 gdk_window_move (GTK_WIDGET (window)->window,
3125 /* Save this position to apply on mapping */
3126 info->initial_x = x;
3127 info->initial_y = y;
3128 info->initial_pos_set = TRUE;
3133 * gtk_window_get_position:
3134 * @window: a #GtkWindow
3135 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3136 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3138 * This function returns the position you need to pass to
3139 * gtk_window_move() to keep @window in its current position. This
3140 * means that the meaning of the returned value varies with window
3141 * gravity. See gtk_window_move() for more details.
3143 * If you haven't changed the window gravity, its gravity will be
3144 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3145 * gets the position of the top-left corner of the window manager
3146 * frame for the window. gtk_window_move() sets the position of this
3147 * same top-left corner.
3149 * gtk_window_get_position() is not 100% reliable because the X Window System
3150 * does not specify a way to obtain the geometry of the
3151 * decorations placed on a window by the window manager.
3152 * Thus GTK+ is using a "best guess" that works with most
3155 * Moreover, nearly all window managers are historically broken with
3156 * respect to their handling of window gravity. So moving a window to
3157 * its current position as returned by gtk_window_get_position() tends
3158 * to result in moving the window slightly. Window managers are
3159 * slowly getting better over time.
3161 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3162 * frame is not relevant, and thus gtk_window_get_position() will
3163 * always produce accurate results. However you can't use static
3164 * gravity to do things like place a window in a corner of the screen,
3165 * because static gravity ignores the window manager decorations.
3167 * If you are saving and restoring your application's window
3168 * positions, you should know that it's impossible for applications to
3169 * do this without getting it somewhat wrong because applications do
3170 * not have sufficient knowledge of window manager state. The Correct
3171 * Mechanism is to support the session management protocol (see the
3172 * "GnomeClient" object in the GNOME libraries for example) and allow
3173 * the window manager to save your window sizes and positions.
3178 gtk_window_get_position (GtkWindow *window,
3184 g_return_if_fail (GTK_IS_WINDOW (window));
3186 widget = GTK_WIDGET (window);
3188 if (window->gravity == GDK_GRAVITY_STATIC)
3190 if (GTK_WIDGET_MAPPED (widget))
3192 /* This does a server round-trip, which is sort of wrong;
3193 * but a server round-trip is inevitable for
3194 * gdk_window_get_frame_extents() in the usual
3195 * NorthWestGravity case below, so not sure what else to
3196 * do. We should likely be consistent about whether we get
3197 * the client-side info or the server-side info.
3199 gdk_window_get_origin (widget->window, root_x, root_y);
3203 GdkRectangle configure_request;
3205 gtk_window_compute_configure_request (window,
3209 *root_x = configure_request.x;
3210 *root_y = configure_request.y;
3215 GdkRectangle frame_extents;
3220 if (GTK_WIDGET_MAPPED (widget))
3223 gdk_window_get_frame_extents (window->frame, &frame_extents);
3225 gdk_window_get_frame_extents (widget->window, &frame_extents);
3226 x = frame_extents.x;
3227 y = frame_extents.y;
3228 gtk_window_get_size (window, &w, &h);
3232 /* We just say the frame has 0 size on all sides.
3233 * Not sure what else to do.
3235 gtk_window_compute_configure_request (window,
3238 x = frame_extents.x;
3239 y = frame_extents.y;
3240 w = frame_extents.width;
3241 h = frame_extents.height;
3244 switch (window->gravity)
3246 case GDK_GRAVITY_NORTH:
3247 case GDK_GRAVITY_CENTER:
3248 case GDK_GRAVITY_SOUTH:
3249 /* Find center of frame. */
3250 x += frame_extents.width / 2;
3251 /* Center client window on that point. */
3255 case GDK_GRAVITY_SOUTH_EAST:
3256 case GDK_GRAVITY_EAST:
3257 case GDK_GRAVITY_NORTH_EAST:
3258 /* Find right edge of frame */
3259 x += frame_extents.width;
3260 /* Align left edge of client at that point. */
3267 switch (window->gravity)
3269 case GDK_GRAVITY_WEST:
3270 case GDK_GRAVITY_CENTER:
3271 case GDK_GRAVITY_EAST:
3272 /* Find center of frame. */
3273 y += frame_extents.height / 2;
3274 /* Center client window there. */
3277 case GDK_GRAVITY_SOUTH_WEST:
3278 case GDK_GRAVITY_SOUTH:
3279 case GDK_GRAVITY_SOUTH_EAST:
3280 /* Find south edge of frame */
3281 y += frame_extents.height;
3282 /* Place bottom edge of client there */
3297 * gtk_window_reshow_with_initial_size:
3298 * @window: a #GtkWindow
3300 * Hides @window, then reshows it, resetting the
3301 * default size and position of the window. Used
3302 * by GUI builders only.
3305 gtk_window_reshow_with_initial_size (GtkWindow *window)
3309 g_return_if_fail (GTK_IS_WINDOW (window));
3311 widget = GTK_WIDGET (window);
3313 gtk_widget_hide (widget);
3314 gtk_widget_unrealize (widget);
3315 gtk_widget_show (widget);
3319 gtk_window_destroy (GtkObject *object)
3321 GtkWindow *window = GTK_WINDOW (object);
3323 if (window->transient_parent)
3324 gtk_window_set_transient_for (window, NULL);
3326 /* frees the icons */
3327 gtk_window_set_icon_list (window, NULL);
3329 if (window->has_user_ref_count)
3331 window->has_user_ref_count = FALSE;
3332 g_object_unref (window);
3336 gtk_window_group_remove_window (window->group, window);
3338 gtk_window_free_key_hash (window);
3340 GTK_OBJECT_CLASS (parent_class)->destroy (object);
3344 gtk_window_mnemonic_hash_remove (gpointer key,
3348 GtkWindowMnemonic *mnemonic = key;
3349 GtkWindow *window = user;
3351 if (mnemonic->window == window)
3353 if (mnemonic->targets)
3355 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
3357 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
3358 name, mnemonic->targets->data);
3361 g_slist_free (mnemonic->targets);
3370 gtk_window_private_finalize (GtkWindowPrivate *priv)
3377 gtk_window_finalize (GObject *object)
3379 GtkWindow *window = GTK_WINDOW (object);
3381 toplevel_list = g_slist_remove (toplevel_list, window);
3383 g_free (window->title);
3384 g_free (window->wmclass_name);
3385 g_free (window->wmclass_class);
3386 g_free (window->wm_role);
3388 g_hash_table_foreach_remove (mnemonic_hash_table,
3389 gtk_window_mnemonic_hash_remove,
3391 if (window->geometry_info)
3393 if (window->geometry_info->widget)
3394 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3395 gtk_widget_destroyed,
3396 &window->geometry_info->widget);
3397 g_free (window->geometry_info);
3400 if (window->keys_changed_handler)
3402 gtk_idle_remove (window->keys_changed_handler);
3403 window->keys_changed_handler = 0;
3406 G_OBJECT_CLASS (parent_class)->finalize (object);
3410 gtk_window_show (GtkWidget *widget)
3412 GtkWindow *window = GTK_WINDOW (widget);
3413 GtkContainer *container = GTK_CONTAINER (window);
3414 gboolean need_resize;
3416 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3418 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3419 container->need_resize = FALSE;
3423 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3424 GtkAllocation allocation = { 0, 0 };
3425 GdkRectangle configure_request;
3426 GdkGeometry new_geometry;
3428 gboolean was_realized;
3430 /* We are going to go ahead and perform this configure request
3431 * and then emulate a configure notify by going ahead and
3432 * doing a size allocate. Sort of a synchronous
3433 * mini-copy of gtk_window_move_resize() here.
3435 gtk_window_compute_configure_request (window,
3440 /* We update this because we are going to go ahead
3441 * and gdk_window_resize() below, rather than
3444 info->last.configure_request.width = configure_request.width;
3445 info->last.configure_request.height = configure_request.height;
3447 /* and allocate the window - this is normally done
3448 * in move_resize in response to configure notify
3450 allocation.width = configure_request.width;
3451 allocation.height = configure_request.height;
3452 gtk_widget_size_allocate (widget, &allocation);
3454 /* Then we guarantee we have a realize */
3455 was_realized = FALSE;
3456 if (!GTK_WIDGET_REALIZED (widget))
3458 gtk_widget_realize (widget);
3459 was_realized = TRUE;
3462 /* Must be done after the windows are realized,
3463 * so that the decorations can be read
3465 gtk_decorated_window_calculate_frame_size (window);
3467 /* We only send configure request if we didn't just finish
3468 * creating the window; if we just created the window
3469 * then we created it with widget->allocation anyhow.
3472 gdk_window_resize (widget->window,
3473 configure_request.width,
3474 configure_request.height);
3477 gtk_container_check_resize (container);
3479 gtk_widget_map (widget);
3481 /* Try to make sure that we have some focused widget
3483 #ifdef GDK_WINDOWING_X11
3484 if (!window->focus_widget && !GTK_IS_PLUG (window))
3486 if (!window->focus_widget)
3488 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
3491 gtk_grab_add (widget);
3495 gtk_window_hide (GtkWidget *widget)
3497 GtkWindow *window = GTK_WINDOW (widget);
3499 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3500 gtk_widget_unmap (widget);
3503 gtk_grab_remove (widget);
3507 gtk_window_map (GtkWidget *widget)
3509 GtkWindow *window = GTK_WINDOW (widget);
3510 GdkWindow *toplevel;
3511 GtkWindowPrivate *priv;
3513 priv = gtk_window_get_private (window);
3515 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3517 if (window->bin.child &&
3518 GTK_WIDGET_VISIBLE (window->bin.child) &&
3519 !GTK_WIDGET_MAPPED (window->bin.child))
3520 gtk_widget_map (window->bin.child);
3523 toplevel = window->frame;
3525 toplevel = widget->window;
3527 if (window->maximize_initially)
3528 gdk_window_maximize (toplevel);
3530 gdk_window_unmaximize (toplevel);
3532 if (window->stick_initially)
3533 gdk_window_stick (toplevel);
3535 gdk_window_unstick (toplevel);
3537 if (window->iconify_initially)
3538 gdk_window_iconify (toplevel);
3540 gdk_window_deiconify (toplevel);
3542 if (priv->fullscreen_initially)
3543 gdk_window_fullscreen (toplevel);
3545 gdk_window_unfullscreen (toplevel);
3547 /* No longer use the default settings */
3548 window->need_default_size = FALSE;
3549 window->need_default_position = FALSE;
3551 gdk_window_show (widget->window);
3554 gdk_window_show (window->frame);
3556 if (!disable_startup_notification &&
3557 !sent_startup_notification)
3559 sent_startup_notification = TRUE;
3560 gdk_notify_startup_complete ();
3565 gtk_window_unmap (GtkWidget *widget)
3567 GtkWindow *window = GTK_WINDOW (widget);
3568 GtkWindowGeometryInfo *info;
3569 GdkWindowState state;
3571 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3573 gdk_window_withdraw (window->frame);
3575 gdk_window_withdraw (widget->window);
3577 window->configure_request_count = 0;
3578 window->configure_notify_received = FALSE;
3580 /* on unmap, we reset the default positioning of the window,
3581 * so it's placed again, but we don't reset the default
3582 * size of the window, so it's remembered.
3584 window->need_default_position = TRUE;
3586 info = gtk_window_get_geometry_info (window, FALSE);
3589 info->initial_pos_set = FALSE;
3590 info->position_constraints_changed = FALSE;
3593 state = gdk_window_get_state (widget->window);
3594 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
3595 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
3596 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
3600 gtk_window_realize (GtkWidget *widget)
3603 GdkWindow *parent_window;
3604 GdkWindowAttr attributes;
3605 gint attributes_mask;
3607 window = GTK_WINDOW (widget);
3609 /* ensure widget tree is properly size allocated */
3610 if (widget->allocation.x == -1 &&
3611 widget->allocation.y == -1 &&
3612 widget->allocation.width == 1 &&
3613 widget->allocation.height == 1)
3615 GtkRequisition requisition;
3616 GtkAllocation allocation = { 0, 0, 200, 200 };
3618 gtk_widget_size_request (widget, &requisition);
3619 if (requisition.width || requisition.height)
3621 /* non-empty window */
3622 allocation.width = requisition.width;
3623 allocation.height = requisition.height;
3625 gtk_widget_size_allocate (widget, &allocation);
3627 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3629 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3632 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3634 switch (window->type)
3636 case GTK_WINDOW_TOPLEVEL:
3637 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3639 case GTK_WINDOW_POPUP:
3640 attributes.window_type = GDK_WINDOW_TEMP;
3643 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3647 attributes.title = window->title;
3648 attributes.wmclass_name = window->wmclass_name;
3649 attributes.wmclass_class = window->wmclass_class;
3650 attributes.wclass = GDK_INPUT_OUTPUT;
3651 attributes.visual = gtk_widget_get_visual (widget);
3652 attributes.colormap = gtk_widget_get_colormap (widget);
3654 if (window->has_frame)
3656 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3657 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3658 attributes.event_mask = (GDK_EXPOSURE_MASK |
3659 GDK_KEY_PRESS_MASK |
3660 GDK_ENTER_NOTIFY_MASK |
3661 GDK_LEAVE_NOTIFY_MASK |
3662 GDK_FOCUS_CHANGE_MASK |
3663 GDK_STRUCTURE_MASK |
3664 GDK_BUTTON_MOTION_MASK |
3665 GDK_POINTER_MOTION_HINT_MASK |
3666 GDK_BUTTON_PRESS_MASK |
3667 GDK_BUTTON_RELEASE_MASK);
3669 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3671 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
3672 &attributes, attributes_mask);
3674 gdk_window_set_user_data (window->frame, widget);
3676 attributes.window_type = GDK_WINDOW_CHILD;
3677 attributes.x = window->frame_left;
3678 attributes.y = window->frame_top;
3680 attributes_mask = GDK_WA_X | GDK_WA_Y;
3682 parent_window = window->frame;
3686 attributes_mask = 0;
3687 parent_window = gtk_widget_get_root_window (widget);
3690 attributes.width = widget->allocation.width;
3691 attributes.height = widget->allocation.height;
3692 attributes.event_mask = gtk_widget_get_events (widget);
3693 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3694 GDK_KEY_PRESS_MASK |
3695 GDK_KEY_RELEASE_MASK |
3696 GDK_ENTER_NOTIFY_MASK |
3697 GDK_LEAVE_NOTIFY_MASK |
3698 GDK_FOCUS_CHANGE_MASK |
3699 GDK_STRUCTURE_MASK);
3701 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3702 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3703 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3705 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3707 gdk_window_set_user_data (widget->window, window);
3709 widget->style = gtk_style_attach (widget->style, widget->window);
3710 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3712 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3714 /* This is a bad hack to set the window background. */
3715 gtk_window_paint (widget, NULL);
3717 if (window->transient_parent &&
3718 GTK_WIDGET_REALIZED (window->transient_parent))
3719 gdk_window_set_transient_for (widget->window,
3720 GTK_WIDGET (window->transient_parent)->window);
3722 if (window->wm_role)
3723 gdk_window_set_role (widget->window, window->wm_role);
3725 if (!window->decorated)
3726 gdk_window_set_decorations (widget->window, 0);
3728 gdk_window_set_type_hint (widget->window, window->type_hint);
3730 if (gtk_window_get_skip_pager_hint (window))
3731 gdk_window_set_skip_pager_hint (widget->window, TRUE);
3733 if (gtk_window_get_skip_taskbar_hint (window))
3734 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
3736 /* transient_for must be set to allow the modal hint */
3737 if (window->transient_parent && window->modal)
3738 gdk_window_set_modal_hint (widget->window, TRUE);
3740 gdk_window_set_modal_hint (widget->window, FALSE);
3743 gtk_window_realize_icon (window);
3747 gtk_window_unrealize (GtkWidget *widget)
3750 GtkWindowGeometryInfo *info;
3752 window = GTK_WINDOW (widget);
3754 /* On unrealize, we reset the size of the window such
3755 * that we will re-apply the default sizing stuff
3756 * next time we show the window.
3758 * Default positioning is reset on unmap, instead of unrealize.
3760 window->need_default_size = TRUE;
3761 info = gtk_window_get_geometry_info (window, FALSE);
3764 info->resize_width = -1;
3765 info->resize_height = -1;
3766 info->last.configure_request.x = 0;
3767 info->last.configure_request.y = 0;
3768 info->last.configure_request.width = -1;
3769 info->last.configure_request.height = -1;
3770 /* be sure we reset geom hints on re-realize */
3771 info->last.flags = 0;
3776 gdk_window_set_user_data (window->frame, NULL);
3777 gdk_window_destroy (window->frame);
3778 window->frame = NULL;
3782 gtk_window_unrealize_icon (window);
3784 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3788 gtk_window_size_request (GtkWidget *widget,
3789 GtkRequisition *requisition)
3794 window = GTK_WINDOW (widget);
3795 bin = GTK_BIN (window);
3797 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3798 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3800 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3802 GtkRequisition child_requisition;
3804 gtk_widget_size_request (bin->child, &child_requisition);
3806 requisition->width += child_requisition.width;
3807 requisition->height += child_requisition.height;
3812 gtk_window_size_allocate (GtkWidget *widget,
3813 GtkAllocation *allocation)
3816 GtkAllocation child_allocation;
3818 window = GTK_WINDOW (widget);
3819 widget->allocation = *allocation;
3821 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3823 child_allocation.x = GTK_CONTAINER (window)->border_width;
3824 child_allocation.y = GTK_CONTAINER (window)->border_width;
3825 child_allocation.width =
3826 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3827 child_allocation.height =
3828 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3830 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3833 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3835 gdk_window_resize (window->frame,
3836 allocation->width + window->frame_left + window->frame_right,
3837 allocation->height + window->frame_top + window->frame_bottom);
3842 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3845 gboolean return_val;
3847 window = GTK_WINDOW (widget);
3849 if (window->frame && (event->any.window == window->frame))
3851 if ((event->type != GDK_KEY_PRESS) &&
3852 (event->type != GDK_KEY_RELEASE) &&
3853 (event->type != GDK_FOCUS_CHANGE))
3855 g_signal_stop_emission_by_name (widget, "event");
3857 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
3862 g_object_unref (event->any.window);
3863 event->any.window = g_object_ref (widget->window);
3871 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3873 GdkEventConfigure *configure_event;
3876 switch (event->type)
3879 configure_event = (GdkEventConfigure *)event;
3881 /* Invalidate the decorations */
3884 rect.width = configure_event->width;
3885 rect.height = configure_event->height;
3887 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3889 /* Pass on the (modified) configure event */
3890 configure_event->width -= window->frame_left + window->frame_right;
3891 configure_event->height -= window->frame_top + window->frame_bottom;
3892 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3901 gtk_window_configure_event (GtkWidget *widget,
3902 GdkEventConfigure *event)
3904 GtkWindow *window = GTK_WINDOW (widget);
3905 gboolean expected_reply = window->configure_request_count > 0;
3907 /* window->configure_request_count incremented for each
3908 * configure request, and decremented to a min of 0 for
3909 * each configure notify.
3911 * All it means is that we know we will get at least
3912 * window->configure_request_count more configure notifies.
3913 * We could get more configure notifies than that; some
3914 * of the configure notifies we get may be unrelated to
3915 * the configure requests. But we will get at least
3916 * window->configure_request_count notifies.
3919 if (window->configure_request_count > 0)
3920 window->configure_request_count -= 1;
3922 /* As an optimization, we avoid a resize when possible.
3924 * The only times we can avoid a resize are:
3925 * - we know only the position changed, not the size
3926 * - we know we have made more requests and so will get more
3927 * notifies and can wait to resize when we get them
3930 if (!expected_reply &&
3931 (widget->allocation.width == event->width &&
3932 widget->allocation.height == event->height))
3936 * If we do need to resize, we do that by:
3937 * - filling in widget->allocation with the new size
3938 * - setting configure_notify_received to TRUE
3939 * for use in gtk_window_move_resize()
3940 * - queueing a resize, leading to invocation of
3941 * gtk_window_move_resize() in an idle handler
3945 window->configure_notify_received = TRUE;
3947 widget->allocation.width = event->width;
3948 widget->allocation.height = event->height;
3950 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3955 /* the accel_key and accel_mods fields of the key have to be setup
3956 * upon calling this function. it'll then return whether that key
3957 * is at all used as accelerator, and if so will OR in the
3958 * accel_flags member of the key.
3961 _gtk_window_query_nonaccels (GtkWindow *window,
3963 GdkModifierType accel_mods)
3965 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3967 /* movement keys are considered locked accels */
3970 static const guint bindings[] = {
3971 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
3972 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
3976 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
3977 if (bindings[i] == accel_key)
3981 /* mnemonics are considered locked accels */
3982 if (accel_mods == window->mnemonic_modifier)
3984 GtkWindowMnemonic mkey;
3986 mkey.window = window;
3987 mkey.keyval = accel_key;
3988 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
3996 gtk_window_key_press_event (GtkWidget *widget,
4003 window = GTK_WINDOW (widget);
4007 /* Check for mnemonics and accelerators
4010 handled = _gtk_window_activate_key (window, event);
4014 focus = window->focus_widget;
4016 g_object_ref (focus);
4019 focus && focus != widget &&
4020 gtk_widget_get_toplevel (focus) == widget)
4024 if (GTK_WIDGET_IS_SENSITIVE (focus))
4025 handled = gtk_widget_event (focus, (GdkEvent*) event);
4027 parent = focus->parent;
4029 g_object_ref (parent);
4031 g_object_unref (focus);
4037 g_object_unref (focus);
4040 /* Chain up, invokes binding set */
4041 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
4042 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4048 gtk_window_key_release_event (GtkWidget *widget,
4054 window = GTK_WINDOW (widget);
4056 if (window->focus_widget &&
4057 window->focus_widget != widget &&
4058 GTK_WIDGET_SENSITIVE (window->focus_widget))
4060 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
4063 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
4064 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
4070 gtk_window_real_activate_default (GtkWindow *window)
4072 gtk_window_activate_default (window);
4076 gtk_window_real_activate_focus (GtkWindow *window)
4078 gtk_window_activate_focus (window);
4082 gtk_window_move_focus (GtkWindow *window,
4083 GtkDirectionType dir)
4085 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4087 if (!GTK_CONTAINER (window)->focus_child)
4088 gtk_window_set_focus (window, NULL);
4092 gtk_window_enter_notify_event (GtkWidget *widget,
4093 GdkEventCrossing *event)
4099 gtk_window_leave_notify_event (GtkWidget *widget,
4100 GdkEventCrossing *event)
4106 do_focus_change (GtkWidget *widget,
4109 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4111 g_object_ref (widget);
4114 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4116 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4118 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4119 fevent->focus_change.window = widget->window;
4121 g_object_ref (widget->window);
4122 fevent->focus_change.in = in;
4124 gtk_widget_event (widget, fevent);
4126 g_object_notify (G_OBJECT (widget), "has_focus");
4128 g_object_unref (widget);
4129 gdk_event_free (fevent);
4133 gtk_window_focus_in_event (GtkWidget *widget,
4134 GdkEventFocus *event)
4136 GtkWindow *window = GTK_WINDOW (widget);
4138 /* It appears spurious focus in events can occur when
4139 * the window is hidden. So we'll just check to see if
4140 * the window is visible before actually handling the
4143 if (GTK_WIDGET_VISIBLE (widget))
4145 _gtk_window_set_has_toplevel_focus (window, TRUE);
4146 _gtk_window_set_is_active (window, TRUE);
4153 gtk_window_focus_out_event (GtkWidget *widget,
4154 GdkEventFocus *event)
4156 GtkWindow *window = GTK_WINDOW (widget);
4158 _gtk_window_set_has_toplevel_focus (window, FALSE);
4159 _gtk_window_set_is_active (window, FALSE);
4164 static GdkAtom atom_rcfiles = GDK_NONE;
4167 gtk_window_read_rcfiles (GtkWidget *widget,
4168 GdkEventClient *event)
4170 GList *embedded_windows;
4172 embedded_windows = g_object_get_data (G_OBJECT (widget), "gtk-embedded");
4173 if (embedded_windows)
4175 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4178 for (i = 0; i < 5; i++)
4179 send_event->client.data.l[i] = 0;
4180 send_event->client.data_format = 32;
4181 send_event->client.message_type = atom_rcfiles;
4183 while (embedded_windows)
4185 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4186 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4187 embedded_windows = embedded_windows->next;
4190 gdk_event_free (send_event);
4193 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4197 gtk_window_client_event (GtkWidget *widget,
4198 GdkEventClient *event)
4201 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
4203 if (event->message_type == atom_rcfiles)
4204 gtk_window_read_rcfiles (widget, event);
4210 gtk_window_check_resize (GtkContainer *container)
4212 GtkWindow *window = GTK_WINDOW (container);
4214 if (GTK_WIDGET_VISIBLE (container))
4215 gtk_window_move_resize (window);
4219 gtk_window_focus (GtkWidget *widget,
4220 GtkDirectionType direction)
4224 GtkContainer *container;
4225 GtkWidget *old_focus_child;
4228 container = GTK_CONTAINER (widget);
4229 window = GTK_WINDOW (widget);
4230 bin = GTK_BIN (widget);
4232 old_focus_child = container->focus_child;
4234 /* We need a special implementation here to deal properly with wrapping
4235 * around in the tab chain without the danger of going into an
4238 if (old_focus_child)
4240 if (gtk_widget_child_focus (old_focus_child, direction))
4244 if (window->focus_widget)
4246 /* Wrapped off the end, clear the focus setting for the toplpevel */
4247 parent = window->focus_widget->parent;
4250 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4251 parent = GTK_WIDGET (parent)->parent;
4254 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4257 /* Now try to focus the first widget in the window */
4260 if (gtk_widget_child_focus (bin->child, direction))
4268 gtk_window_real_set_focus (GtkWindow *window,
4271 GtkWidget *old_focus = window->focus_widget;
4272 gboolean def_flags = 0;
4276 g_object_ref (old_focus);
4277 g_object_freeze_notify (G_OBJECT (old_focus));
4281 g_object_ref (focus);
4282 g_object_freeze_notify (G_OBJECT (focus));
4285 if (window->default_widget)
4286 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4288 if (window->focus_widget)
4290 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4291 (window->focus_widget != window->default_widget))
4293 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4295 if (window->default_widget)
4296 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4299 if (window->has_focus)
4300 do_focus_change (window->focus_widget, FALSE);
4302 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4305 window->focus_widget = focus;
4307 if (window->focus_widget)
4309 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4310 (window->focus_widget != window->default_widget))
4312 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4313 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4315 if (window->default_widget)
4316 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4319 if (window->has_focus)
4320 do_focus_change (window->focus_widget, TRUE);
4322 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4325 if (window->default_widget &&
4326 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
4327 gtk_widget_queue_draw (window->default_widget);
4331 g_object_thaw_notify (G_OBJECT (old_focus));
4332 g_object_unref (old_focus);
4336 g_object_thaw_notify (G_OBJECT (focus));
4337 g_object_unref (focus);
4342 * _gtk_window_unset_focus_and_default:
4343 * @window: a #GtkWindow
4344 * @widget: a widget inside of @window
4346 * Checks whether the focus and default widgets of @window are
4347 * @widget or a descendent of @widget, and if so, unset them.
4350 _gtk_window_unset_focus_and_default (GtkWindow *window,
4356 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
4358 child = window->focus_widget;
4360 while (child && child != widget)
4361 child = child->parent;
4363 if (child == widget)
4364 gtk_window_set_focus (GTK_WINDOW (window), NULL);
4367 child = window->default_widget;
4369 while (child && child != widget)
4370 child = child->parent;
4372 if (child == widget)
4373 gtk_window_set_default (window, NULL);
4376 /*********************************
4377 * Functions related to resizing *
4378 *********************************/
4380 /* This function doesn't constrain to geometry hints */
4382 gtk_window_compute_configure_request_size (GtkWindow *window,
4386 GtkRequisition requisition;
4387 GtkWindowGeometryInfo *info;
4391 * - we've done a size request
4394 widget = GTK_WIDGET (window);
4396 info = gtk_window_get_geometry_info (window, FALSE);
4398 if (window->need_default_size)
4400 gtk_widget_get_child_requisition (widget, &requisition);
4402 /* Default to requisition */
4403 *width = requisition.width;
4404 *height = requisition.height;
4406 /* If window is empty so requests 0, default to random nonzero size */
4407 if (*width == 0 && *height == 0)
4413 /* Override requisition with default size */
4417 gint base_width = 0;
4418 gint base_height = 0;
4420 gint height_inc = 1;
4422 if (info->default_is_geometry &&
4423 (info->default_width > 0 || info->default_height > 0))
4425 GdkGeometry geometry;
4428 gtk_window_compute_hints (window, &geometry, &flags);
4430 if (flags & GDK_HINT_BASE_SIZE)
4432 base_width = geometry.base_width;
4433 base_height = geometry.base_height;
4435 else if (flags & GDK_HINT_MIN_SIZE)
4437 base_width = geometry.min_width;
4438 base_height = geometry.min_height;
4440 if (flags & GDK_HINT_RESIZE_INC)
4442 width_inc = geometry.width_inc;
4443 height_inc = geometry.height_inc;
4447 if (info->default_width > 0)
4448 *width = info->default_width * width_inc + base_width;
4450 if (info->default_height > 0)
4451 *height = info->default_height * height_inc + base_height;
4456 /* Default to keeping current size */
4457 *width = widget->allocation.width;
4458 *height = widget->allocation.height;
4461 /* Override any size with gtk_window_resize() values */
4464 if (info->resize_width > 0)
4465 *width = info->resize_width;
4467 if (info->resize_height > 0)
4468 *height = info->resize_height;
4472 static GtkWindowPosition
4473 get_effective_position (GtkWindow *window)
4475 GtkWindowPosition pos = window->position;
4476 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
4477 (window->transient_parent == NULL ||
4478 !GTK_WIDGET_MAPPED (window->transient_parent)))
4479 pos = GTK_WIN_POS_NONE;
4485 get_center_monitor_of_window (GtkWindow *window)
4487 /* We could try to sort out the relative positions of the monitors and
4488 * stuff, or we could just be losers and assume you have a row
4489 * or column of monitors.
4491 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
4495 get_monitor_containing_pointer (GtkWindow *window)
4499 GdkScreen *window_screen;
4500 GdkScreen *pointer_screen;
4502 window_screen = gtk_window_check_screen (window);
4503 gdk_display_get_pointer (gdk_screen_get_display (window_screen),
4507 if (pointer_screen == window_screen)
4508 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
4516 center_window_on_monitor (GtkWindow *window,
4522 GdkRectangle monitor;
4525 monitor_num = get_monitor_containing_pointer (window);
4527 if (monitor_num == -1)
4528 monitor_num = get_center_monitor_of_window (window);
4530 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
4531 monitor_num, &monitor);
4533 *x = (monitor.width - w) / 2 + monitor.x;
4534 *y = (monitor.height - h) / 2 + monitor.y;
4536 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
4537 * and WM decorations.
4546 clamp_window_to_rectangle (gint *x,
4550 const GdkRectangle *rect)
4552 gint outside_w, outside_h;
4554 outside_w = (*x + w) - (rect->x + rect->width);
4558 outside_h = (*y + h) - (rect->y + rect->height);
4562 /* if larger than the screen, center on the screen. */
4564 *x += (rect->x - *x) / 2;
4566 *y += (rect->y - *y) / 2;
4571 gtk_window_compute_configure_request (GtkWindow *window,
4572 GdkRectangle *request,
4573 GdkGeometry *geometry,
4576 GdkGeometry new_geometry;
4580 GtkWindowPosition pos;
4581 GtkWidget *parent_widget;
4582 GtkWindowGeometryInfo *info;
4586 widget = GTK_WIDGET (window);
4588 screen = gtk_window_check_screen (window);
4590 gtk_widget_size_request (widget, NULL);
4591 gtk_window_compute_configure_request_size (window, &w, &h);
4593 gtk_window_compute_hints (window, &new_geometry, &new_flags);
4594 gtk_window_constrain_size (window,
4595 &new_geometry, new_flags,
4599 parent_widget = (GtkWidget*) window->transient_parent;
4601 pos = get_effective_position (window);
4602 info = gtk_window_get_geometry_info (window, TRUE);
4604 /* by default, don't change position requested */
4605 x = info->last.configure_request.x;
4606 y = info->last.configure_request.y;
4608 if (window->need_default_position)
4611 /* FIXME this all interrelates with window gravity.
4612 * For most of them I think we want to set GRAVITY_CENTER.
4614 * Not sure how to go about that.
4619 /* here we are only handling CENTER_ALWAYS
4620 * as it relates to default positioning,
4621 * where it's equivalent to simply CENTER
4623 case GTK_WIN_POS_CENTER_ALWAYS:
4624 case GTK_WIN_POS_CENTER:
4625 center_window_on_monitor (window, w, h, &x, &y);
4628 case GTK_WIN_POS_CENTER_ON_PARENT:
4631 GdkRectangle monitor;
4634 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
4636 if (parent_widget->window != NULL)
4637 monitor_num = gdk_screen_get_monitor_at_window (screen,
4638 parent_widget->window);
4642 gdk_window_get_origin (parent_widget->window,
4645 x = ox + (parent_widget->allocation.width - w) / 2;
4646 y = oy + (parent_widget->allocation.height - h) / 2;
4648 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4649 * WM decorations. If parent wasn't on a monitor, just
4652 if (monitor_num >= 0)
4654 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
4655 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4660 case GTK_WIN_POS_MOUSE:
4662 gint screen_width = gdk_screen_get_width (screen);
4663 gint screen_height = gdk_screen_get_height (screen);
4665 GdkRectangle monitor;
4666 GdkScreen *pointer_screen;
4669 gdk_display_get_pointer (gdk_screen_get_display (screen),
4673 if (pointer_screen == screen)
4674 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
4680 x = CLAMP (x, 0, screen_width - w);
4681 y = CLAMP (y, 0, screen_height - h);
4683 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4684 * WM decorations. Don't try to figure out what's going
4685 * on if the mouse wasn't inside a monitor.
4687 if (monitor_num >= 0)
4689 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
4690 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4698 } /* if (window->need_default_position) */
4700 if (window->need_default_position &&
4701 info->initial_pos_set)
4703 x = info->initial_x;
4704 y = info->initial_y;
4705 gtk_window_constrain_position (window, w, h, &x, &y);
4711 request->height = h;
4714 *geometry = new_geometry;
4720 gtk_window_constrain_position (GtkWindow *window,
4726 /* See long comments in gtk_window_move_resize()
4727 * on when it's safe to call this function.
4729 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4731 gint center_x, center_y;
4733 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
4741 gtk_window_move_resize (GtkWindow *window)
4745 * First we determine whether any information has changed that would
4746 * cause us to revise our last configure request. If we would send
4747 * a different configure request from last time, then
4748 * configure_request_size_changed = TRUE or
4749 * configure_request_pos_changed = TRUE. configure_request_size_changed
4750 * may be true due to new hints, a gtk_window_resize(), or whatever.
4751 * configure_request_pos_changed may be true due to gtk_window_set_position()
4752 * or gtk_window_move().
4754 * If the configure request has changed, we send off a new one. To
4755 * ensure GTK+ invariants are maintained (resize queue does what it
4756 * should), we go ahead and size_allocate the requested size in this
4759 * If the configure request has not changed, we don't ever resend
4760 * it, because it could mean fighting the user or window manager.
4763 * To prepare the configure request, we come up with a base size/pos:
4764 * - the one from gtk_window_move()/gtk_window_resize()
4765 * - else default_width, default_height if we haven't ever
4767 * - else the size request if we haven't ever been mapped,
4768 * as a substitute default size
4769 * - else the current size of the window, as received from
4770 * configure notifies (i.e. the current allocation)
4772 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4773 * the position request to be centered.
4776 GtkContainer *container;
4777 GtkWindowGeometryInfo *info;
4778 GdkGeometry new_geometry;
4780 GdkRectangle new_request;
4781 gboolean configure_request_size_changed;
4782 gboolean configure_request_pos_changed;
4783 gboolean hints_changed; /* do we need to send these again */
4784 GtkWindowLastGeometryInfo saved_last_info;
4786 widget = GTK_WIDGET (window);
4787 container = GTK_CONTAINER (widget);
4788 info = gtk_window_get_geometry_info (window, TRUE);
4790 configure_request_size_changed = FALSE;
4791 configure_request_pos_changed = FALSE;
4793 gtk_window_compute_configure_request (window, &new_request,
4794 &new_geometry, &new_flags);
4796 /* This check implies the invariant that we never set info->last
4797 * without setting the hints and sending off a configure request.
4799 * If we change info->last without sending the request, we may
4802 if (info->last.configure_request.x != new_request.x ||
4803 info->last.configure_request.y != new_request.y)
4804 configure_request_pos_changed = TRUE;
4806 if ((info->last.configure_request.width != new_request.width ||
4807 info->last.configure_request.height != new_request.height))
4808 configure_request_size_changed = TRUE;
4810 hints_changed = FALSE;
4812 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4813 &new_geometry, new_flags))
4815 hints_changed = TRUE;
4818 /* Position Constraints
4819 * ====================
4821 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4822 * a default. The other POS_ values are used only when the
4823 * window is shown, not after that.
4825 * However, we can't implement a position constraint as
4826 * "anytime the window size changes, center the window"
4827 * because this may well end up fighting the WM or user. In
4828 * fact it gets in an infinite loop with at least one WM.
4830 * Basically, applications are in no way in a position to
4831 * constrain the position of a window, with one exception:
4832 * override redirect windows. (Really the intended purpose
4833 * of CENTER_ALWAYS anyhow, I would think.)
4835 * So the way we implement this "constraint" is to say that when WE
4836 * cause a move or resize, i.e. we make a configure request changing
4837 * window size, we recompute the CENTER_ALWAYS position to reflect
4838 * the new window size, and include it in our request. Also, if we
4839 * just turned on CENTER_ALWAYS we snap to center with a new
4840 * request. Otherwise, if we are just NOTIFIED of a move or resize
4841 * done by someone else e.g. the window manager, we do NOT send a
4842 * new configure request.
4844 * For override redirect windows, this works fine; all window
4845 * sizes are from our configure requests. For managed windows,
4846 * it is at least semi-sane, though who knows what the
4847 * app author is thinking.
4850 /* This condition should be kept in sync with the condition later on
4851 * that determines whether we send a configure request. i.e. we
4852 * should do this position constraining anytime we were going to
4853 * send a configure request anyhow, plus when constraints have
4856 if (configure_request_pos_changed ||
4857 configure_request_size_changed ||
4859 info->position_constraints_changed)
4861 /* We request the constrained position if:
4862 * - we were changing position, and need to clamp
4863 * the change to the constraint
4864 * - we're changing the size anyway
4865 * - set_position() was called to toggle CENTER_ALWAYS on
4868 gtk_window_constrain_position (window,
4874 /* Update whether we need to request a move */
4875 if (info->last.configure_request.x != new_request.x ||
4876 info->last.configure_request.y != new_request.y)
4877 configure_request_pos_changed = TRUE;
4879 configure_request_pos_changed = FALSE;
4883 if (window->type == GTK_WINDOW_TOPLEVEL)
4885 int notify_x, notify_y;
4887 /* this is the position from the last configure notify */
4888 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4890 g_message ("--- %s ---\n"
4891 "last : %d,%d\t%d x %d\n"
4892 "this : %d,%d\t%d x %d\n"
4893 "alloc : %d,%d\t%d x %d\n"
4895 "resize: \t%d x %d\n"
4896 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4897 "configure_notify_received: %d\n"
4898 "configure_request_count: %d\n"
4899 "position_constraints_changed: %d\n",
4900 window->title ? window->title : "(no title)",
4901 info->last.configure_request.x,
4902 info->last.configure_request.y,
4903 info->last.configure_request.width,
4904 info->last.configure_request.height,
4910 widget->allocation.width,
4911 widget->allocation.height,
4912 widget->requisition.width,
4913 widget->requisition.height,
4915 info->resize_height,
4916 configure_request_pos_changed,
4917 configure_request_size_changed,
4919 window->configure_notify_received,
4920 window->configure_request_count,
4921 info->position_constraints_changed);
4925 saved_last_info = info->last;
4926 info->last.geometry = new_geometry;
4927 info->last.flags = new_flags;
4928 info->last.configure_request = new_request;
4930 /* need to set PPosition so the WM will look at our position,
4931 * but we don't want to count PPosition coming and going as a hints
4932 * change for future iterations. So we saved info->last prior to
4936 /* Also, if the initial position was explicitly set, then we always
4937 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4941 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4942 * this is an initial map
4945 if ((configure_request_pos_changed ||
4946 info->initial_pos_set ||
4947 (window->need_default_position &&
4948 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
4949 (new_flags & GDK_HINT_POS) == 0)
4951 new_flags |= GDK_HINT_POS;
4952 hints_changed = TRUE;
4955 /* Set hints if necessary
4958 gdk_window_set_geometry_hints (widget->window,
4962 /* handle resizing/moving and widget tree allocation
4964 if (window->configure_notify_received)
4966 GtkAllocation allocation;
4968 /* If we have received a configure event since
4969 * the last time in this function, we need to
4970 * accept our new size and size_allocate child widgets.
4971 * (see gtk_window_configure_event() for more details).
4973 * 1 or more configure notifies may have been received.
4974 * Also, configure_notify_received will only be TRUE
4975 * if all expected configure notifies have been received
4976 * (one per configure request), as an optimization.
4979 window->configure_notify_received = FALSE;
4981 /* gtk_window_configure_event() filled in widget->allocation */
4982 allocation = widget->allocation;
4983 gtk_widget_size_allocate (widget, &allocation);
4985 /* If the configure request changed, it means that
4987 * 1) coincidentally changed hints or widget properties
4988 * impacting the configure request before getting
4989 * a configure notify, or
4990 * 2) some broken widget is changing its size request
4991 * during size allocation, resulting in
4992 * a false appearance of changed configure request.
4994 * For 1), we could just go ahead and ask for the
4995 * new size right now, but doing that for 2)
4996 * might well be fighting the user (and can even
4997 * trigger a loop). Since we really don't want to
4998 * do that, we requeue a resize in hopes that
4999 * by the time it gets handled, the child has seen
5000 * the light and is willing to go along with the
5001 * new size. (this happens for the zvt widget, since
5002 * the size_allocate() above will have stored the
5003 * requisition corresponding to the new size in the
5006 * This doesn't buy us anything for 1), but it shouldn't
5007 * hurt us too badly, since it is what would have
5008 * happened if we had gotten the configure event before
5009 * the new size had been set.
5012 if (configure_request_size_changed ||
5013 configure_request_pos_changed)
5015 /* Don't change the recorded last info after all, because we
5016 * haven't actually updated to the new info yet - we decided
5017 * to postpone our configure request until later.
5019 info->last = saved_last_info;
5021 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
5024 return; /* Bail out, we didn't really process the move/resize */
5026 else if ((configure_request_size_changed || hints_changed) &&
5027 (widget->allocation.width != new_request.width ||
5028 widget->allocation.height != new_request.height))
5031 /* We are in one of the following situations:
5032 * A. configure_request_size_changed
5033 * our requisition has changed and we need a different window size,
5034 * so we request it from the window manager.
5035 * B. !configure_request_size_changed && hints_changed
5036 * the window manager rejects our size, but we have just changed the
5037 * window manager hints, so there's a chance our request will
5038 * be honoured this time, so we try again.
5040 * However, if the new requisition is the same as the current allocation,
5041 * we don't request it again, since we won't get a ConfigureNotify back from
5042 * the window manager unless it decides to change our requisition. If
5043 * we don't get the ConfigureNotify back, the resize queue will never be run.
5046 /* Now send the configure request */
5047 if (configure_request_pos_changed)
5051 gdk_window_move_resize (window->frame,
5052 new_request.x - window->frame_left,
5053 new_request.y - window->frame_top,
5054 new_request.width + window->frame_left + window->frame_right,
5055 new_request.height + window->frame_top + window->frame_bottom);
5056 gdk_window_resize (widget->window,
5057 new_request.width, new_request.height);
5061 gdk_window_move_resize (widget->window,
5062 new_request.x, new_request.y,
5063 new_request.width, new_request.height);
5065 else /* only size changed */
5068 gdk_window_resize (window->frame,
5069 new_request.width + window->frame_left + window->frame_right,
5070 new_request.height + window->frame_top + window->frame_bottom);
5072 gdk_window_resize (widget->window,
5073 new_request.width, new_request.height);
5076 /* Increment the number of have-not-yet-received-notify requests */
5077 window->configure_request_count += 1;
5079 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5080 * configure event in response to our resizing request.
5081 * the configure event will cause a new resize with
5082 * ->configure_notify_received=TRUE.
5083 * until then, we want to
5084 * - discard expose events
5085 * - coalesce resizes for our children
5086 * - defer any window resizes until the configure event arrived
5087 * to achieve this, we queue a resize for the window, but remove its
5088 * resizing handler, so resizing will not be handled from the next
5089 * idle handler but when the configure event arrives.
5091 * FIXME: we should also dequeue the pending redraws here, since
5092 * we handle those ourselves upon ->configure_notify_received==TRUE.
5094 if (container->resize_mode == GTK_RESIZE_QUEUE)
5096 gtk_widget_queue_resize (widget);
5097 _gtk_container_dequeue_resize_handler (container);
5102 /* Handle any position changes.
5104 if (configure_request_pos_changed)
5108 gdk_window_move (window->frame,
5109 new_request.x - window->frame_left,
5110 new_request.y - window->frame_top);
5113 gdk_window_move (widget->window,
5114 new_request.x, new_request.y);
5117 /* And run the resize queue.
5119 gtk_container_resize_children (container);
5122 /* We have now processed a move/resize since the last position
5123 * constraint change, setting of the initial position, or resize.
5124 * (Not resetting these flags here can lead to infinite loops for
5125 * GTK_RESIZE_IMMEDIATE containers)
5127 info->position_constraints_changed = FALSE;
5128 info->initial_pos_set = FALSE;
5129 info->resize_width = -1;
5130 info->resize_height = -1;
5133 /* Compare two sets of Geometry hints for equality.
5136 gtk_window_compare_hints (GdkGeometry *geometry_a,
5138 GdkGeometry *geometry_b,
5141 if (flags_a != flags_b)
5144 if ((flags_a & GDK_HINT_MIN_SIZE) &&
5145 (geometry_a->min_width != geometry_b->min_width ||
5146 geometry_a->min_height != geometry_b->min_height))
5149 if ((flags_a & GDK_HINT_MAX_SIZE) &&
5150 (geometry_a->max_width != geometry_b->max_width ||
5151 geometry_a->max_height != geometry_b->max_height))
5154 if ((flags_a & GDK_HINT_BASE_SIZE) &&
5155 (geometry_a->base_width != geometry_b->base_width ||
5156 geometry_a->base_height != geometry_b->base_height))
5159 if ((flags_a & GDK_HINT_ASPECT) &&
5160 (geometry_a->min_aspect != geometry_b->min_aspect ||
5161 geometry_a->max_aspect != geometry_b->max_aspect))
5164 if ((flags_a & GDK_HINT_RESIZE_INC) &&
5165 (geometry_a->width_inc != geometry_b->width_inc ||
5166 geometry_a->height_inc != geometry_b->height_inc))
5169 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5170 geometry_a->win_gravity != geometry_b->win_gravity)
5177 _gtk_window_constrain_size (GtkWindow *window,
5183 GtkWindowGeometryInfo *info;
5185 g_return_if_fail (GTK_IS_WINDOW (window));
5187 info = window->geometry_info;
5190 GdkWindowHints flags = info->last.flags;
5191 GdkGeometry *geometry = &info->last.geometry;
5193 gtk_window_constrain_size (window,
5204 gtk_window_constrain_size (GtkWindow *window,
5205 GdkGeometry *geometry,
5212 gdk_window_constrain_size (geometry, flags, width, height,
5213 new_width, new_height);
5216 /* Compute the set of geometry hints and flags for a window
5217 * based on the application set geometry, and requisiition
5218 * of the window. gtk_widget_size_request() must have been
5222 gtk_window_compute_hints (GtkWindow *window,
5223 GdkGeometry *new_geometry,
5227 gint extra_width = 0;
5228 gint extra_height = 0;
5229 GtkWindowGeometryInfo *geometry_info;
5230 GtkRequisition requisition;
5232 widget = GTK_WIDGET (window);
5234 gtk_widget_get_child_requisition (widget, &requisition);
5235 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5239 *new_flags = geometry_info->mask;
5240 *new_geometry = geometry_info->geometry;
5247 if (geometry_info && geometry_info->widget)
5249 GtkRequisition child_requisition;
5251 /* FIXME: This really isn't right. It gets the min size wrong and forces
5252 * callers to do horrible hacks like set a huge usize on the child requisition
5253 * to get the base size right. We really want to find the answers to:
5255 * - If the geometry widget was infinitely big, how much extra space
5256 * would be needed for the stuff around it.
5258 * - If the geometry widget was infinitely small, how big would the
5259 * window still have to be.
5261 * Finding these answers would be a bit of a mess here. (Bug #68668)
5263 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5265 extra_width = widget->requisition.width - child_requisition.width;
5266 extra_height = widget->requisition.height - child_requisition.height;
5269 /* We don't want to set GDK_HINT_POS in here, we just set it
5270 * in gtk_window_move_resize() when we want the position
5274 if (*new_flags & GDK_HINT_BASE_SIZE)
5276 new_geometry->base_width += extra_width;
5277 new_geometry->base_height += extra_height;
5279 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5280 (*new_flags & GDK_HINT_RESIZE_INC) &&
5281 ((extra_width != 0) || (extra_height != 0)))
5283 *new_flags |= GDK_HINT_BASE_SIZE;
5285 new_geometry->base_width = extra_width;
5286 new_geometry->base_height = extra_height;
5289 if (*new_flags & GDK_HINT_MIN_SIZE)
5291 if (new_geometry->min_width < 0)
5292 new_geometry->min_width = requisition.width;
5294 new_geometry->min_width += extra_width;
5296 if (new_geometry->min_height < 0)
5297 new_geometry->min_height = requisition.height;
5299 new_geometry->min_height += extra_height;
5301 else if (!window->allow_shrink)
5303 *new_flags |= GDK_HINT_MIN_SIZE;
5305 new_geometry->min_width = requisition.width;
5306 new_geometry->min_height = requisition.height;
5309 if (*new_flags & GDK_HINT_MAX_SIZE)
5311 if (new_geometry->max_width < 0)
5312 new_geometry->max_width = requisition.width;
5314 new_geometry->max_width += extra_width;
5316 if (new_geometry->max_height < 0)
5317 new_geometry->max_width = requisition.height;
5319 new_geometry->max_height += extra_height;
5321 else if (!window->allow_grow)
5323 *new_flags |= GDK_HINT_MAX_SIZE;
5325 new_geometry->max_width = requisition.width;
5326 new_geometry->max_height = requisition.height;
5329 *new_flags |= GDK_HINT_WIN_GRAVITY;
5330 new_geometry->win_gravity = window->gravity;
5333 /***********************
5334 * Redrawing functions *
5335 ***********************/
5338 gtk_window_paint (GtkWidget *widget,
5341 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
5342 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
5346 gtk_window_expose (GtkWidget *widget,
5347 GdkEventExpose *event)
5349 if (!GTK_WIDGET_APP_PAINTABLE (widget))
5350 gtk_window_paint (widget, &event->area);
5352 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
5353 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
5359 * gtk_window_set_has_frame:
5360 * @window: a #GtkWindow
5361 * @setting: a boolean
5363 * (Note: this is a special-purpose function for the framebuffer port,
5364 * that causes GTK+ to draw its own window border. For most applications,
5365 * you want gtk_window_set_decorated() instead, which tells the window
5366 * manager whether to draw the window border.)
5368 * If this function is called on a window with setting of %TRUE, before
5369 * it is realized or showed, it will have a "frame" window around
5370 * @window->window, accessible in @window->frame. Using the signal
5371 * frame_event you can recieve all events targeted at the frame.
5373 * This function is used by the linux-fb port to implement managed
5374 * windows, but it could concievably be used by X-programs that
5375 * want to do their own window decorations.
5379 gtk_window_set_has_frame (GtkWindow *window,
5382 g_return_if_fail (GTK_IS_WINDOW (window));
5383 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
5385 window->has_frame = setting != FALSE;
5389 * gtk_window_get_has_frame:
5390 * @window: a #GtkWindow
5392 * Accessor for whether the window has a frame window exterior to
5393 * @window->window. Gets the value set by gtk_window_set_has_frame ().
5395 * Return value: %TRUE if a frame has been added to the window
5396 * via gtk_window_set_has_frame().
5399 gtk_window_get_has_frame (GtkWindow *window)
5401 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5403 return window->has_frame;
5407 * gtk_window_set_frame_dimensions:
5408 * @window: a #GtkWindow that has a frame
5409 * @left: The width of the left border
5410 * @top: The height of the top border
5411 * @right: The width of the right border
5412 * @bottom: The height of the bottom border
5414 * (Note: this is a special-purpose function intended for the framebuffer
5415 * port; see gtk_window_set_has_frame(). It will have no effect on the
5416 * window border drawn by the window manager, which is the normal
5417 * case when using the X Window system.)
5419 * For windows with frames (see gtk_window_set_has_frame()) this function
5420 * can be used to change the size of the frame border.
5423 gtk_window_set_frame_dimensions (GtkWindow *window,
5431 g_return_if_fail (GTK_IS_WINDOW (window));
5433 widget = GTK_WIDGET (window);
5435 if (window->frame_left == left &&
5436 window->frame_top == top &&
5437 window->frame_right == right &&
5438 window->frame_bottom == bottom)
5441 window->frame_left = left;
5442 window->frame_top = top;
5443 window->frame_right = right;
5444 window->frame_bottom = bottom;
5446 if (GTK_WIDGET_REALIZED (widget) && window->frame)
5448 gint width = widget->allocation.width + left + right;
5449 gint height = widget->allocation.height + top + bottom;
5450 gdk_window_resize (window->frame, width, height);
5451 gtk_decorated_window_move_resize_window (window,
5453 widget->allocation.width,
5454 widget->allocation.height);
5459 * gtk_window_present:
5460 * @window: a #GtkWindow
5462 * Presents a window to the user. This may mean raising the window
5463 * in the stacking order, deiconifying it, moving it to the current
5464 * desktop, and/or giving it the keyboard focus, possibly dependent
5465 * on the user's platform, window manager, and preferences.
5467 * If @window is hidden, this function calls gtk_widget_show()
5470 * This function should be used when the user tries to open a window
5471 * that's already open. Say for example the preferences dialog is
5472 * currently open, and the user chooses Preferences from the menu
5473 * a second time; use gtk_window_present() to move the already-open dialog
5474 * where the user can see it.
5478 gtk_window_present (GtkWindow *window)
5482 g_return_if_fail (GTK_IS_WINDOW (window));
5484 widget = GTK_WIDGET (window);
5486 if (GTK_WIDGET_VISIBLE (window))
5488 g_assert (widget->window != NULL);
5490 gdk_window_show (widget->window);
5492 /* note that gdk_window_focus() will also move the window to
5493 * the current desktop, for WM spec compliant window managers.
5495 gdk_window_focus (widget->window,
5496 gtk_get_current_event_time ());
5500 gtk_widget_show (widget);
5505 * gtk_window_iconify:
5506 * @window: a #GtkWindow
5508 * Asks to iconify (i.e. minimize) the specified @window. Note that
5509 * you shouldn't assume the window is definitely iconified afterward,
5510 * because other entities (e.g. the user or <link
5511 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
5512 * again, or there may not be a window manager in which case
5513 * iconification isn't possible, etc. But normally the window will end
5514 * up iconified. Just don't write code that crashes if not.
5516 * It's permitted to call this function before showing a window,
5517 * in which case the window will be iconified before it ever appears
5520 * You can track iconification via the "window_state_event" signal
5525 gtk_window_iconify (GtkWindow *window)
5528 GdkWindow *toplevel;
5530 g_return_if_fail (GTK_IS_WINDOW (window));
5532 widget = GTK_WIDGET (window);
5534 window->iconify_initially = TRUE;
5537 toplevel = window->frame;
5539 toplevel = widget->window;
5541 if (toplevel != NULL)
5542 gdk_window_iconify (toplevel);
5546 * gtk_window_deiconify:
5547 * @window: a #GtkWindow
5549 * Asks to deiconify (i.e. unminimize) the specified @window. Note
5550 * that you shouldn't assume the window is definitely deiconified
5551 * afterward, because other entities (e.g. the user or <link
5552 * linkend="gtk-X11-arch">window manager</link>) could iconify it
5553 * again before your code which assumes deiconification gets to run.
5555 * You can track iconification via the "window_state_event" signal
5559 gtk_window_deiconify (GtkWindow *window)
5562 GdkWindow *toplevel;
5564 g_return_if_fail (GTK_IS_WINDOW (window));
5566 widget = GTK_WIDGET (window);
5568 window->iconify_initially = FALSE;
5571 toplevel = window->frame;
5573 toplevel = widget->window;
5575 if (toplevel != NULL)
5576 gdk_window_deiconify (toplevel);
5581 * @window: a #GtkWindow
5583 * Asks to stick @window, which means that it will appear on all user
5584 * desktops. Note that you shouldn't assume the window is definitely
5585 * stuck afterward, because other entities (e.g. the user or <link
5586 * linkend="gtk-X11-arch">window manager</link>) could unstick it
5587 * again, and some window managers do not support sticking
5588 * windows. But normally the window will end up stuck. Just don't
5589 * write code that crashes if not.
5591 * It's permitted to call this function before showing a window.
5593 * You can track stickiness via the "window_state_event" signal
5598 gtk_window_stick (GtkWindow *window)
5601 GdkWindow *toplevel;
5603 g_return_if_fail (GTK_IS_WINDOW (window));
5605 widget = GTK_WIDGET (window);
5607 window->stick_initially = TRUE;
5610 toplevel = window->frame;
5612 toplevel = widget->window;
5614 if (toplevel != NULL)
5615 gdk_window_stick (toplevel);
5619 * gtk_window_unstick:
5620 * @window: a #GtkWindow
5622 * Asks to unstick @window, which means that it will appear on only
5623 * one of the user's desktops. Note that you shouldn't assume the
5624 * window is definitely unstuck afterward, because other entities
5625 * (e.g. the user or <link linkend="gtk-X11-arch">window
5626 * manager</link>) could stick it again. But normally the window will
5627 * end up stuck. Just don't write code that crashes if not.
5629 * You can track stickiness via the "window_state_event" signal
5634 gtk_window_unstick (GtkWindow *window)
5637 GdkWindow *toplevel;
5639 g_return_if_fail (GTK_IS_WINDOW (window));
5641 widget = GTK_WIDGET (window);
5643 window->stick_initially = FALSE;
5646 toplevel = window->frame;
5648 toplevel = widget->window;
5650 if (toplevel != NULL)
5651 gdk_window_unstick (toplevel);
5655 * gtk_window_maximize:
5656 * @window: a #GtkWindow
5658 * Asks to maximize @window, so that it becomes full-screen. Note that
5659 * you shouldn't assume the window is definitely maximized afterward,
5660 * because other entities (e.g. the user or <link
5661 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
5662 * again, and not all window managers support maximization. But
5663 * normally the window will end up maximized. Just don't write code
5664 * that crashes if not.
5666 * It's permitted to call this function before showing a window,
5667 * in which case the window will be maximized when it appears onscreen
5670 * You can track maximization via the "window_state_event" signal
5675 gtk_window_maximize (GtkWindow *window)
5678 GdkWindow *toplevel;
5680 g_return_if_fail (GTK_IS_WINDOW (window));
5682 widget = GTK_WIDGET (window);
5684 window->maximize_initially = TRUE;
5687 toplevel = window->frame;
5689 toplevel = widget->window;
5691 if (toplevel != NULL)
5692 gdk_window_maximize (toplevel);
5696 * gtk_window_unmaximize:
5697 * @window: a #GtkWindow
5699 * Asks to unmaximize @window. Note that you shouldn't assume the
5700 * window is definitely unmaximized afterward, because other entities
5701 * (e.g. the user or <link linkend="gtk-X11-arch">window
5702 * manager</link>) could maximize it again, and not all window
5703 * managers honor requests to unmaximize. But normally the window will
5704 * end up unmaximized. Just don't write code that crashes if not.
5706 * You can track maximization via the "window_state_event" signal
5711 gtk_window_unmaximize (GtkWindow *window)
5714 GdkWindow *toplevel;
5716 g_return_if_fail (GTK_IS_WINDOW (window));
5718 widget = GTK_WIDGET (window);
5720 window->maximize_initially = FALSE;
5723 toplevel = window->frame;
5725 toplevel = widget->window;
5727 if (toplevel != NULL)
5728 gdk_window_unmaximize (toplevel);
5732 * gtk_window_fullscreen:
5733 * @window: a #GtkWindow
5735 * Asks to place @window in the fullscreen state. Note that you
5736 * shouldn't assume the window is definitely full screen afterward,
5737 * because other entities (e.g. the user or <link
5738 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
5739 * again, and not all window managers honor requests to fullscreen
5740 * windows. But normally the window will end up fullscreen. Just
5741 * don't write code that crashes if not.
5743 * You can track the fullscreen state via the "window_state_event" signal
5748 gtk_window_fullscreen (GtkWindow *window)
5751 GdkWindow *toplevel;
5752 GtkWindowPrivate *priv;
5754 g_return_if_fail (GTK_IS_WINDOW (window));
5756 widget = GTK_WIDGET (window);
5757 priv = gtk_window_get_private (window);
5759 priv->fullscreen_initially = TRUE;
5762 toplevel = window->frame;
5764 toplevel = widget->window;
5766 if (toplevel != NULL)
5767 gdk_window_fullscreen (toplevel);
5771 * gtk_window_unfullscreen:
5772 * @window: a #GtkWindow
5774 * Asks to toggle off the fullscreen state for @window. Note that you
5775 * shouldn't assume the window is definitely not full screen
5776 * afterward, because other entities (e.g. the user or <link
5777 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
5778 * again, and not all window managers honor requests to unfullscreen
5779 * windows. But normally the window will end up restored to its normal
5780 * state. Just don't write code that crashes if not.
5782 * You can track the fullscreen state via the "window_state_event" signal
5787 gtk_window_unfullscreen (GtkWindow *window)
5790 GdkWindow *toplevel;
5791 GtkWindowPrivate *priv;
5793 g_return_if_fail (GTK_IS_WINDOW (window));
5795 widget = GTK_WIDGET (window);
5796 priv = gtk_window_get_private (window);
5798 priv->fullscreen_initially = FALSE;
5801 toplevel = window->frame;
5803 toplevel = widget->window;
5805 if (toplevel != NULL)
5806 gdk_window_unfullscreen (toplevel);
5811 * gtk_window_set_resizable:
5812 * @window: a #GtkWindow
5813 * @resizable: %TRUE if the user can resize this window
5815 * Sets whether the user can resize a window. Windows are user resizable
5819 gtk_window_set_resizable (GtkWindow *window,
5822 g_return_if_fail (GTK_IS_WINDOW (window));
5824 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5828 * gtk_window_get_resizable:
5829 * @window: a #GtkWindow
5831 * Gets the value set by gtk_window_set_resizable().
5833 * Return value: %TRUE if the user can resize the window
5836 gtk_window_get_resizable (GtkWindow *window)
5838 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5840 /* allow_grow is most likely to indicate the semantic concept we
5841 * mean by "resizable" (and will be a reliable indicator if
5842 * set_policy() hasn't been called)
5844 return window->allow_grow;
5848 * gtk_window_set_gravity:
5849 * @window: a #GtkWindow
5850 * @gravity: window gravity
5852 * Window gravity defines the meaning of coordinates passed to
5853 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5856 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5857 * typically "do what you mean."
5861 gtk_window_set_gravity (GtkWindow *window,
5864 g_return_if_fail (GTK_IS_WINDOW (window));
5866 if (gravity != window->gravity)
5868 window->gravity = gravity;
5870 /* gtk_window_move_resize() will adapt gravity
5872 gtk_widget_queue_resize (GTK_WIDGET (window));
5877 * gtk_window_get_gravity:
5878 * @window: a #GtkWindow
5880 * Gets the value set by gtk_window_set_gravity().
5882 * Return value: window gravity
5885 gtk_window_get_gravity (GtkWindow *window)
5887 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5889 return window->gravity;
5893 * gtk_window_begin_resize_drag:
5894 * @window: a #GtkWindow
5895 * @button: mouse button that initiated the drag
5896 * @edge: position of the resize control
5897 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5898 * @root_y: Y position where the user clicked to initiate the drag
5899 * @timestamp: timestamp from the click event that initiated the drag
5901 * Starts resizing a window. This function is used if an application
5902 * has window resizing controls. When GDK can support it, the resize
5903 * will be done using the standard mechanism for the <link
5904 * linkend="gtk-X11-arch">window manager</link> or windowing
5905 * system. Otherwise, GDK will try to emulate window resizing,
5906 * potentially not all that well, depending on the windowing system.
5910 gtk_window_begin_resize_drag (GtkWindow *window,
5918 GdkWindow *toplevel;
5920 g_return_if_fail (GTK_IS_WINDOW (window));
5921 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5923 widget = GTK_WIDGET (window);
5926 toplevel = window->frame;
5928 toplevel = widget->window;
5930 gdk_window_begin_resize_drag (toplevel,
5937 * gtk_window_get_frame_dimensions:
5938 * @window: a #GtkWindow
5939 * @left: location to store the width of the frame at the left, or %NULL
5940 * @top: location to store the height of the frame at the top, or %NULL
5941 * @right: location to store the width of the frame at the returns, or %NULL
5942 * @bottom: location to store the height of the frame at the bottom, or %NULL
5944 * (Note: this is a special-purpose function intended for the
5945 * framebuffer port; see gtk_window_set_has_frame(). It will not
5946 * return the size of the window border drawn by the <link
5947 * linkend="gtk-X11-arch">window manager</link>, which is the normal
5948 * case when using a windowing system. See
5949 * gdk_window_get_frame_extents() to get the standard window border
5952 * Retrieves the dimensions of the frame window for this toplevel.
5953 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5956 gtk_window_get_frame_dimensions (GtkWindow *window,
5962 g_return_if_fail (GTK_IS_WINDOW (window));
5965 *left = window->frame_left;
5967 *top = window->frame_top;
5969 *right = window->frame_right;
5971 *bottom = window->frame_bottom;
5975 * gtk_window_begin_move_drag:
5976 * @window: a #GtkWindow
5977 * @button: mouse button that initiated the drag
5978 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5979 * @root_y: Y position where the user clicked to initiate the drag
5980 * @timestamp: timestamp from the click event that initiated the drag
5982 * Starts moving a window. This function is used if an application has
5983 * window movement grips. When GDK can support it, the window movement
5984 * will be done using the standard mechanism for the <link
5985 * linkend="gtk-X11-arch">window manager</link> or windowing
5986 * system. Otherwise, GDK will try to emulate window movement,
5987 * potentially not all that well, depending on the windowing system.
5991 gtk_window_begin_move_drag (GtkWindow *window,
5998 GdkWindow *toplevel;
6000 g_return_if_fail (GTK_IS_WINDOW (window));
6001 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6003 widget = GTK_WIDGET (window);
6006 toplevel = window->frame;
6008 toplevel = widget->window;
6010 gdk_window_begin_move_drag (toplevel,
6017 * gtk_window_set_screen:
6018 * @window: a #GtkWindow.
6019 * @screen: a #GdkScreen.
6021 * Sets the #GdkScreen where the @window is displayed; if
6022 * the window is already mapped, it will be unmapped, and
6023 * then remapped on the new screen.
6026 gtk_window_set_screen (GtkWindow *window,
6030 GdkScreen *previous_screen;
6031 gboolean was_mapped;
6033 g_return_if_fail (GTK_IS_WINDOW (window));
6034 g_return_if_fail (GDK_IS_SCREEN (screen));
6036 if (screen == window->screen)
6039 widget = GTK_WIDGET (window);
6041 previous_screen = window->screen;
6042 was_mapped = GTK_WIDGET_MAPPED (widget);
6045 gtk_widget_unmap (widget);
6046 if (GTK_WIDGET_REALIZED (widget))
6047 gtk_widget_unrealize (widget);
6049 gtk_window_free_key_hash (window);
6050 window->screen = screen;
6051 gtk_widget_reset_rc_styles (widget);
6052 if (screen != previous_screen)
6053 _gtk_widget_propagate_screen_changed (widget, previous_screen);
6054 g_object_notify (G_OBJECT (window), "screen");
6057 gtk_widget_map (widget);
6061 gtk_window_check_screen (GtkWindow *window)
6064 return window->screen;
6067 g_warning ("Screen for GtkWindow not set; you must always set\n"
6068 "a screen for a GtkWindow before using the window");
6074 * gtk_window_get_screen:
6075 * @window: a #GtkWindow.
6077 * Returns the #GdkScreen associated with @window.
6079 * Return value: a #GdkScreen.
6082 gtk_window_get_screen (GtkWindow *window)
6084 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6086 return window->screen;
6091 gtk_window_group_class_init (GtkWindowGroupClass *klass)
6096 gtk_window_group_get_type (void)
6098 static GType window_group_type = 0;
6100 if (!window_group_type)
6102 static const GTypeInfo window_group_info =
6104 sizeof (GtkWindowGroupClass),
6105 NULL, /* base_init */
6106 NULL, /* base_finalize */
6107 (GClassInitFunc) gtk_window_group_class_init,
6108 NULL, /* class_finalize */
6109 NULL, /* class_data */
6110 sizeof (GtkWindowGroup),
6111 16, /* n_preallocs */
6112 (GInstanceInitFunc) NULL,
6115 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
6118 return window_group_type;
6122 * gtk_window_group_new:
6124 * Creates a new #GtkWindowGroup object. Grabs added with
6125 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
6127 * Return value: a new #GtkWindowGroup.
6130 gtk_window_group_new (void)
6132 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
6136 window_group_cleanup_grabs (GtkWindowGroup *group,
6140 GSList *to_remove = NULL;
6142 tmp_list = group->grabs;
6145 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
6146 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
6147 tmp_list = tmp_list->next;
6152 gtk_grab_remove (to_remove->data);
6153 g_object_unref (to_remove->data);
6154 to_remove = g_slist_delete_link (to_remove, to_remove);
6159 * gtk_window_group_add_window:
6160 * @window_group: a #GtkWindowGroup
6161 * @window: the #GtkWindow to add
6163 * Adds a window to a #GtkWindowGroup.
6166 gtk_window_group_add_window (GtkWindowGroup *window_group,
6169 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6170 g_return_if_fail (GTK_IS_WINDOW (window));
6172 if (window->group != window_group)
6174 g_object_ref (window);
6175 g_object_ref (window_group);
6178 gtk_window_group_remove_window (window->group, window);
6180 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
6182 window->group = window_group;
6184 g_object_unref (window);
6189 * gtk_window_group_remove_window:
6190 * @window_group: a #GtkWindowGroup
6191 * @window: the #GtkWindow to remove
6193 * Removes a window from a #GtkWindowGroup.
6196 gtk_window_group_remove_window (GtkWindowGroup *window_group,
6199 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6200 g_return_if_fail (GTK_IS_WIDGET (window));
6201 g_return_if_fail (window->group == window_group);
6203 g_object_ref (window);
6205 window_group_cleanup_grabs (window_group, window);
6206 window->group = NULL;
6208 g_object_unref (window_group);
6209 g_object_unref (window);
6212 /* Return the group for the window or the default group
6215 _gtk_window_get_group (GtkWindow *window)
6217 if (window && window->group)
6218 return window->group;
6221 static GtkWindowGroup *default_group = NULL;
6224 default_group = gtk_window_group_new ();
6226 return default_group;
6232 Derived from XParseGeometry() in XFree86
6234 Copyright 1985, 1986, 1987,1998 The Open Group
6236 All Rights Reserved.
6238 The above copyright notice and this permission notice shall be included
6239 in all copies or substantial portions of the Software.
6241 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
6242 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6243 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6244 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
6245 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
6246 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
6247 OTHER DEALINGS IN THE SOFTWARE.
6249 Except as contained in this notice, the name of The Open Group shall
6250 not be used in advertising or otherwise to promote the sale, use or
6251 other dealings in this Software without prior written authorization
6252 from The Open Group.
6257 * XParseGeometry parses strings of the form
6258 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
6259 * width, height, xoffset, and yoffset are unsigned integers.
6260 * Example: "=80x24+300-49"
6261 * The equal sign is optional.
6262 * It returns a bitmask that indicates which of the four values
6263 * were actually found in the string. For each value found,
6264 * the corresponding argument is updated; for each value
6265 * not found, the corresponding argument is left unchanged.
6268 /* The following code is from Xlib, and is minimally modified, so we
6269 * can track any upstream changes if required. Don't change this
6270 * code. Or if you do, put in a huge comment marking which thing
6275 read_int (gchar *string,
6283 else if (*string == '-')
6289 for (; (*string >= '0') && (*string <= '9'); string++)
6291 result = (result * 10) + (*string - '0');
6303 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
6304 * value (x, y, width, height) was found in the parsed string.
6306 #define NoValue 0x0000
6307 #define XValue 0x0001
6308 #define YValue 0x0002
6309 #define WidthValue 0x0004
6310 #define HeightValue 0x0008
6311 #define AllValues 0x000F
6312 #define XNegative 0x0010
6313 #define YNegative 0x0020
6315 /* Try not to reformat/modify, so we can compare/sync with X sources */
6317 gtk_XParseGeometry (const char *string,
6320 unsigned int *width,
6321 unsigned int *height)
6325 unsigned int tempWidth, tempHeight;
6327 char *nextCharacter;
6329 /* These initializations are just to silence gcc */
6335 if ( (string == NULL) || (*string == '\0')) return(mask);
6337 string++; /* ignore possible '=' at beg of geometry spec */
6339 strind = (char *)string;
6340 if (*strind != '+' && *strind != '-' && *strind != 'x') {
6341 tempWidth = read_int(strind, &nextCharacter);
6342 if (strind == nextCharacter)
6344 strind = nextCharacter;
6348 if (*strind == 'x' || *strind == 'X') {
6350 tempHeight = read_int(strind, &nextCharacter);
6351 if (strind == nextCharacter)
6353 strind = nextCharacter;
6354 mask |= HeightValue;
6357 if ((*strind == '+') || (*strind == '-')) {
6358 if (*strind == '-') {
6360 tempX = -read_int(strind, &nextCharacter);
6361 if (strind == nextCharacter)
6363 strind = nextCharacter;
6369 tempX = read_int(strind, &nextCharacter);
6370 if (strind == nextCharacter)
6372 strind = nextCharacter;
6375 if ((*strind == '+') || (*strind == '-')) {
6376 if (*strind == '-') {
6378 tempY = -read_int(strind, &nextCharacter);
6379 if (strind == nextCharacter)
6381 strind = nextCharacter;
6388 tempY = read_int(strind, &nextCharacter);
6389 if (strind == nextCharacter)
6391 strind = nextCharacter;
6397 /* If strind isn't at the end of the string the it's an invalid
6398 geometry specification. */
6400 if (*strind != '\0') return (0);
6406 if (mask & WidthValue)
6408 if (mask & HeightValue)
6409 *height = tempHeight;
6414 * gtk_window_parse_geometry:
6415 * @window: a #GtkWindow
6416 * @geometry: geometry string
6418 * Parses a standard X Window System geometry string - see the
6419 * manual page for X (type 'man X') for details on this.
6420 * gtk_window_parse_geometry() does work on all GTK+ ports
6421 * including Win32 but is primarily intended for an X environment.
6423 * If either a size or a position can be extracted from the
6424 * geometry string, gtk_window_parse_geometry() returns %TRUE
6425 * and calls gtk_window_set_default_size() and/or gtk_window_move()
6426 * to resize/move the window.
6428 * If gtk_window_parse_geometry() returns %TRUE, it will also
6429 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
6430 * indicating to the window manager that the size/position of
6431 * the window was user-specified. This causes most window
6432 * managers to honor the geometry.
6434 * Return value: %TRUE if string was parsed successfully
6437 gtk_window_parse_geometry (GtkWindow *window,
6438 const gchar *geometry)
6443 gboolean size_set, pos_set;
6446 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6447 g_return_val_if_fail (geometry != NULL, FALSE);
6449 screen = gtk_window_check_screen (window);
6451 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
6453 if ((result & WidthValue) == 0 ||
6456 if ((result & HeightValue) == 0 ||
6461 if ((result & WidthValue) || (result & HeightValue))
6463 gtk_window_set_default_size_internal (window, TRUE, w, TRUE, h, TRUE);
6467 gtk_window_get_size (window, &w, &h);
6469 grav = GDK_GRAVITY_NORTH_WEST;
6471 if ((result & XNegative) && (result & YNegative))
6472 grav = GDK_GRAVITY_SOUTH_EAST;
6473 else if (result & XNegative)
6474 grav = GDK_GRAVITY_NORTH_EAST;
6475 else if (result & YNegative)
6476 grav = GDK_GRAVITY_SOUTH_WEST;
6478 if ((result & XValue) == 0)
6481 if ((result & YValue) == 0)
6484 if (grav == GDK_GRAVITY_SOUTH_WEST ||
6485 grav == GDK_GRAVITY_SOUTH_EAST)
6486 y = gdk_screen_get_height (screen) - h + y;
6488 if (grav == GDK_GRAVITY_SOUTH_EAST ||
6489 grav == GDK_GRAVITY_NORTH_EAST)
6490 x = gdk_screen_get_width (screen) - w + x;
6492 /* we don't let you put a window offscreen; maybe some people would
6493 * prefer to be able to, but it's kind of a bogus thing to do.
6502 if ((result & XValue) || (result & YValue))
6504 gtk_window_set_gravity (window, grav);
6505 gtk_window_move (window, x, y);
6509 if (size_set || pos_set)
6511 /* Set USSize, USPosition hints */
6512 GtkWindowGeometryInfo *info;
6514 info = gtk_window_get_geometry_info (window, TRUE);
6517 info->mask |= GDK_HINT_USER_POS;
6519 info->mask |= GDK_HINT_USER_SIZE;
6526 gtk_window_mnemonic_hash_foreach (gpointer key,
6532 GtkWindowKeysForeachFunc func;
6536 GtkWindowMnemonic *mnemonic = value;
6538 if (mnemonic->window == info->window)
6539 (*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
6543 _gtk_window_keys_foreach (GtkWindow *window,
6544 GtkWindowKeysForeachFunc func,
6551 GtkWindowKeysForeachFunc func;
6555 info.window = window;
6557 info.func_data = func_data;
6559 g_hash_table_foreach (mnemonic_hash_table,
6560 gtk_window_mnemonic_hash_foreach,
6563 groups = gtk_accel_groups_from_object (G_OBJECT (window));
6566 GtkAccelGroup *group = groups->data;
6569 for (i = 0; i < group->n_accels; i++)
6571 GtkAccelKey *key = &group->priv_accels[i].key;
6574 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
6577 groups = groups->next;
6582 gtk_window_keys_changed (GtkWindow *window)
6584 gtk_window_free_key_hash (window);
6585 gtk_window_get_key_hash (window);
6588 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
6590 struct _GtkWindowKeyEntry
6594 gboolean is_mnemonic;
6598 add_to_key_hash (GtkWindow *window,
6600 GdkModifierType modifiers,
6601 gboolean is_mnemonic,
6604 GtkKeyHash *key_hash = data;
6606 GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
6608 entry->keyval = keyval;
6609 entry->modifiers = modifiers;
6610 entry->is_mnemonic = is_mnemonic;
6612 /* GtkAccelGroup stores lowercased accelerators. To deal
6613 * with this, if <Shift> was specified, uppercase.
6615 if (modifiers & GDK_SHIFT_MASK)
6617 if (keyval == GDK_Tab)
6618 keyval = GDK_ISO_Left_Tab;
6620 keyval = gdk_keyval_to_upper (keyval);
6623 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
6627 gtk_window_get_key_hash (GtkWindow *window)
6629 GdkScreen *screen = gtk_window_check_screen (window);
6630 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6635 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
6636 (GDestroyNotify)g_free);
6637 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
6638 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
6644 gtk_window_free_key_hash (GtkWindow *window)
6646 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6649 _gtk_key_hash_free (key_hash);
6650 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
6655 * _gtk_window_activate_key:
6656 * @window: a #GtkWindow
6657 * @event: a #GdkEventKey
6659 * Activates mnemonics and accelerators for this #GtKWindow
6661 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
6664 _gtk_window_activate_key (GtkWindow *window,
6667 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6668 GtkWindowKeyEntry *found_entry = NULL;
6672 gtk_window_keys_changed (window);
6673 key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6678 GSList *entries = _gtk_key_hash_lookup (key_hash,
6679 event->hardware_keycode,
6680 event->state & gtk_accelerator_get_default_mod_mask (),
6684 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
6686 GtkWindowKeyEntry *entry = tmp_list->data;
6687 if (entry->is_mnemonic)
6689 found_entry = entry;
6694 if (!found_entry && entries)
6695 found_entry = entries->data;
6697 g_slist_free (entries);
6702 if (found_entry->is_mnemonic)
6703 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
6705 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
6712 window_update_has_focus (GtkWindow *window)
6714 GtkWidget *widget = GTK_WIDGET (window);
6715 gboolean has_focus = window->has_toplevel_focus && window->is_active;
6717 if (has_focus != window->has_focus)
6719 window->has_focus = has_focus;
6723 if (window->focus_widget &&
6724 window->focus_widget != widget &&
6725 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6726 do_focus_change (window->focus_widget, TRUE);
6730 if (window->focus_widget &&
6731 window->focus_widget != widget &&
6732 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6733 do_focus_change (window->focus_widget, FALSE);
6739 * _gtk_window_set_is_active:
6740 * @window: a #GtkWindow
6741 * @is_active: %TRUE if the window is in the currently active toplevel
6743 * Internal function that sets whether the #GtkWindow is part
6744 * of the currently active toplevel window (taking into account inter-process
6748 _gtk_window_set_is_active (GtkWindow *window,
6751 g_return_if_fail (GTK_IS_WINDOW (window));
6753 is_active = is_active != FALSE;
6755 if (is_active != window->is_active)
6757 window->is_active = is_active;
6758 window_update_has_focus (window);
6760 g_object_notify (G_OBJECT (window), "is_active");
6765 * _gtk_window_set_has_toplevel_focus:
6766 * @window: a #GtkWindow
6767 * @has_toplevel_focus: %TRUE if the in
6769 * Internal function that sets whether the keyboard focus for the
6770 * toplevel window (taking into account inter-process embedding.)
6773 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
6774 gboolean has_toplevel_focus)
6776 g_return_if_fail (GTK_IS_WINDOW (window));
6778 has_toplevel_focus = has_toplevel_focus != FALSE;
6780 if (has_toplevel_focus != window->has_toplevel_focus)
6782 window->has_toplevel_focus = has_toplevel_focus;
6783 window_update_has_focus (window);
6785 g_object_notify (G_OBJECT (window), "has_toplevel_focus");
6790 * gtk_window_set_auto_startup_notification:
6791 * @setting: %TRUE to automatically do startup notification
6793 * By default, after showing the first #GtkWindow for each #GdkScreen,
6794 * GTK+ calls gdk_screen_notify_startup_complete(). Call this
6795 * function to disable the automatic startup notification. You might
6796 * do this if your first window is a splash screen, and you want to
6797 * delay notification until after your real main window has been
6798 * shown, for example.
6800 * In that example, you would disable startup notification
6801 * temporarily, show your splash screen, then re-enable it so that
6802 * showing the main window would automatically result in notification.
6806 gtk_window_set_auto_startup_notification (gboolean setting)
6808 disable_startup_notification = !setting;