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:
1492 * @window: a #GtkWindow
1494 * Activates the current focused widget within the window.
1496 * Return value: %TRUE if a widget got activated.
1499 gtk_window_activate_focus (GtkWindow *window)
1501 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1503 if (window->focus_widget)
1505 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1506 gtk_widget_activate (window->focus_widget);
1514 * gtk_window_get_focus:
1515 * @window: a #GtkWindow
1517 * Retrieves the current focused widget within the window.
1518 * Note that this is the widget that would have the focus
1519 * if the toplevel window focused; if the toplevel window
1520 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1521 * not be %TRUE for the widget.
1523 * Return value: the currently focused widget.
1526 gtk_window_get_focus (GtkWindow *window)
1528 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1530 return window->focus_widget;
1534 * gtk_window_activate_default:
1535 * @window: a #GtkWindow
1537 * Activates the default widget for the window, unless the current
1538 * focused widget has been configured to receive the default action
1539 * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
1540 * focused widget is activated.
1542 * Return value: %TRUE if a widget got activated.
1545 gtk_window_activate_default (GtkWindow *window)
1547 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1549 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1550 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1552 gtk_widget_activate (window->default_widget);
1555 else if (window->focus_widget)
1557 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1558 gtk_widget_activate (window->focus_widget);
1566 * gtk_window_set_modal:
1567 * @window: a #GtkWindow
1568 * @modal: whether the window is modal
1570 * Sets a window modal or non-modal. Modal windows prevent interaction
1571 * with other windows in the same application. To keep modal dialogs
1572 * on top of main application windows, use
1573 * gtk_window_set_transient_for() to make the dialog transient for the
1574 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1575 * will then disallow lowering the dialog below the parent.
1580 gtk_window_set_modal (GtkWindow *window,
1583 g_return_if_fail (GTK_IS_WINDOW (window));
1585 modal = modal != FALSE;
1586 if (window->modal == modal)
1589 window->modal = modal;
1591 /* adjust desired modality state */
1592 if (GTK_WIDGET_REALIZED (window))
1594 GtkWidget *widget = GTK_WIDGET (window);
1597 gdk_window_set_modal_hint (widget->window, TRUE);
1599 gdk_window_set_modal_hint (widget->window, FALSE);
1602 if (GTK_WIDGET_VISIBLE (window))
1605 gtk_grab_add (GTK_WIDGET (window));
1607 gtk_grab_remove (GTK_WIDGET (window));
1610 g_object_notify (G_OBJECT (window), "modal");
1614 * gtk_window_get_modal:
1615 * @window: a #GtkWindow
1617 * Returns whether the window is modal. See gtk_window_set_modal().
1619 * Return value: %TRUE if the window is set to be modal and
1620 * establishes a grab when shown
1623 gtk_window_get_modal (GtkWindow *window)
1625 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1627 return window->modal;
1631 * gtk_window_list_toplevels:
1633 * Returns a list of all existing toplevel windows. The widgets
1634 * in the list are not individually referenced. If you want
1635 * to iterate through the list and perform actions involving
1636 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1637 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1638 * then unref all the widgets afterwards.
1640 * Return value: list of toplevel widgets
1643 gtk_window_list_toplevels (void)
1648 for (slist = toplevel_list; slist; slist = slist->next)
1649 list = g_list_prepend (list, slist->data);
1655 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1657 GList *embedded_windows;
1659 g_return_if_fail (GTK_IS_WINDOW (window));
1661 embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1662 if (embedded_windows)
1663 g_object_steal_qdata (G_OBJECT (window),
1664 g_quark_from_static_string ("gtk-embedded"));
1665 embedded_windows = g_list_prepend (embedded_windows,
1666 GUINT_TO_POINTER (xid));
1668 g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
1671 (GDestroyNotify) g_list_free : NULL);
1675 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1677 GList *embedded_windows;
1680 g_return_if_fail (GTK_IS_WINDOW (window));
1682 embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1683 if (embedded_windows)
1684 g_object_steal_qdata (G_OBJECT (window),
1685 g_quark_from_static_string ("gtk-embedded"));
1687 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1690 embedded_windows = g_list_remove_link (embedded_windows, node);
1691 g_list_free_1 (node);
1694 g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
1697 (GDestroyNotify) g_list_free : NULL);
1701 _gtk_window_reposition (GtkWindow *window,
1705 g_return_if_fail (GTK_IS_WINDOW (window));
1707 gtk_window_move (window, x, y);
1711 gtk_window_dispose (GObject *object)
1713 GtkWindow *window = GTK_WINDOW (object);
1715 gtk_window_set_focus (window, NULL);
1716 gtk_window_set_default (window, NULL);
1718 G_OBJECT_CLASS (parent_class)->dispose (object);
1722 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1724 gtk_widget_destroy (GTK_WIDGET (child));
1728 connect_parent_destroyed (GtkWindow *window)
1730 if (window->transient_parent)
1732 g_signal_connect (window->transient_parent,
1734 G_CALLBACK (parent_destroyed_callback),
1740 disconnect_parent_destroyed (GtkWindow *window)
1742 if (window->transient_parent)
1744 g_signal_handlers_disconnect_by_func (window->transient_parent,
1745 parent_destroyed_callback,
1751 gtk_window_transient_parent_realized (GtkWidget *parent,
1754 if (GTK_WIDGET_REALIZED (window))
1755 gdk_window_set_transient_for (window->window, parent->window);
1759 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1762 if (GTK_WIDGET_REALIZED (window))
1763 gdk_property_delete (window->window,
1764 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1768 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
1772 gtk_window_set_screen (window, parent->screen);
1776 gtk_window_unset_transient_for (GtkWindow *window)
1778 if (window->transient_parent)
1780 g_signal_handlers_disconnect_by_func (window->transient_parent,
1781 gtk_window_transient_parent_realized,
1783 g_signal_handlers_disconnect_by_func (window->transient_parent,
1784 gtk_window_transient_parent_unrealized,
1786 g_signal_handlers_disconnect_by_func (window->transient_parent,
1787 gtk_window_transient_parent_screen_changed,
1789 g_signal_handlers_disconnect_by_func (window->transient_parent,
1790 gtk_widget_destroyed,
1791 &window->transient_parent);
1793 if (window->destroy_with_parent)
1794 disconnect_parent_destroyed (window);
1796 window->transient_parent = NULL;
1801 * gtk_window_set_transient_for:
1802 * @window: a #GtkWindow
1803 * @parent: parent window
1805 * Dialog windows should be set transient for the main application
1806 * window they were spawned from. This allows <link
1807 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1808 * dialog on top of the main window, or center the dialog over the
1809 * main window. gtk_dialog_new_with_buttons() and other convenience
1810 * functions in GTK+ will sometimes call
1811 * gtk_window_set_transient_for() on your behalf.
1813 * On Windows, this function will and put the child window
1814 * on top of the parent, much as the window manager would have
1819 gtk_window_set_transient_for (GtkWindow *window,
1822 g_return_if_fail (GTK_IS_WINDOW (window));
1823 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1824 g_return_if_fail (window != parent);
1827 if (window->transient_parent)
1829 if (GTK_WIDGET_REALIZED (window) &&
1830 GTK_WIDGET_REALIZED (window->transient_parent) &&
1831 (!parent || !GTK_WIDGET_REALIZED (parent)))
1832 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1833 GTK_WIDGET (window));
1835 gtk_window_unset_transient_for (window);
1838 window->transient_parent = parent;
1842 g_signal_connect (parent, "destroy",
1843 G_CALLBACK (gtk_widget_destroyed),
1844 &window->transient_parent);
1845 g_signal_connect (parent, "realize",
1846 G_CALLBACK (gtk_window_transient_parent_realized),
1848 g_signal_connect (parent, "unrealize",
1849 G_CALLBACK (gtk_window_transient_parent_unrealized),
1851 g_signal_connect (parent, "notify::screen",
1852 G_CALLBACK (gtk_window_transient_parent_screen_changed),
1855 gtk_window_set_screen (window, parent->screen);
1857 if (window->destroy_with_parent)
1858 connect_parent_destroyed (window);
1860 if (GTK_WIDGET_REALIZED (window) &&
1861 GTK_WIDGET_REALIZED (parent))
1862 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1863 GTK_WIDGET (window));
1868 * gtk_window_get_transient_for:
1869 * @window: a #GtkWindow
1871 * Fetches the transient parent for this window. See
1872 * gtk_window_set_transient_for().
1874 * Return value: the transient parent for this window, or %NULL
1875 * if no transient parent has been set.
1878 gtk_window_get_transient_for (GtkWindow *window)
1880 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1882 return window->transient_parent;
1886 * gtk_window_set_type_hint:
1887 * @window: a #GtkWindow
1888 * @hint: the window type
1890 * By setting the type hint for the window, you allow the window
1891 * manager to decorate and handle the window in a way which is
1892 * suitable to the function of the window in your application.
1894 * This function should be called before the window becomes visible.
1896 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1897 * will sometimes call gtk_window_set_type_hint() on your behalf.
1901 gtk_window_set_type_hint (GtkWindow *window,
1902 GdkWindowTypeHint hint)
1904 g_return_if_fail (GTK_IS_WINDOW (window));
1905 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1906 window->type_hint = hint;
1910 * gtk_window_get_type_hint:
1911 * @window: a #GtkWindow
1913 * Gets the type hint for this window. See gtk_window_set_type_hint().
1915 * Return value: the type hint for @window.
1918 gtk_window_get_type_hint (GtkWindow *window)
1920 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1922 return window->type_hint;
1926 * gtk_window_set_skip_taskbar_hint:
1927 * @window: a #GtkWindow
1928 * @setting: %TRUE to keep this window from appearing in the task bar
1930 * Windows may set a hint asking the desktop environment not to display
1931 * the window in the task bar. This function toggles this hint.
1936 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
1939 GtkWindowPrivate *priv;
1941 g_return_if_fail (GTK_IS_WINDOW (window));
1943 priv = gtk_window_get_private (window);
1945 setting = setting != FALSE;
1947 if (priv->skips_taskbar != setting)
1949 priv->skips_taskbar = setting;
1950 if (GTK_WIDGET_REALIZED (window))
1951 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
1952 priv->skips_taskbar);
1953 g_object_notify (G_OBJECT (window), "skip_taskbar_hint");
1958 * gtk_window_get_skip_taskbar_hint:
1959 * @window: a #GtkWindow
1961 * Gets the value set by gtk_window_set_skip_taskbar_hint()
1963 * Return value: %TRUE if window shouldn't be in taskbar
1968 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
1970 GtkWindowPrivate *priv;
1972 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1974 priv = gtk_window_get_private (window);
1976 return priv->skips_taskbar;
1980 * gtk_window_set_skip_pager_hint:
1981 * @window: a #GtkWindow
1982 * @setting: %TRUE to keep this window from appearing in the pager
1984 * Windows may set a hint asking the desktop environment not to display
1985 * the window in the pager. This function toggles this hint.
1986 * (A "pager" is any desktop navigation tool such as a workspace
1987 * switcher that displays a thumbnail representation of the windows
1993 gtk_window_set_skip_pager_hint (GtkWindow *window,
1996 GtkWindowPrivate *priv;
1998 g_return_if_fail (GTK_IS_WINDOW (window));
2000 priv = gtk_window_get_private (window);
2002 setting = setting != FALSE;
2004 if (priv->skips_pager != setting)
2006 priv->skips_pager = setting;
2007 if (GTK_WIDGET_REALIZED (window))
2008 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2010 g_object_notify (G_OBJECT (window), "skip_pager_hint");
2015 * gtk_window_get_skip_pager_hint:
2016 * @window: a #GtkWindow
2018 * Gets the value set by gtk_window_set_skip_pager_hint().
2020 * Return value: %TRUE if window shouldn't be in pager
2025 gtk_window_get_skip_pager_hint (GtkWindow *window)
2027 GtkWindowPrivate *priv;
2029 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2031 priv = gtk_window_get_private (window);
2033 return priv->skips_pager;
2037 * gtk_window_set_destroy_with_parent:
2038 * @window: a #GtkWindow
2039 * @setting: whether to destroy @window with its transient parent
2041 * If @setting is %TRUE, then destroying the transient parent of @window
2042 * will also destroy @window itself. This is useful for dialogs that
2043 * shouldn't persist beyond the lifetime of the main window they're
2044 * associated with, for example.
2047 gtk_window_set_destroy_with_parent (GtkWindow *window,
2050 g_return_if_fail (GTK_IS_WINDOW (window));
2052 if (window->destroy_with_parent == (setting != FALSE))
2055 if (window->destroy_with_parent)
2057 disconnect_parent_destroyed (window);
2061 connect_parent_destroyed (window);
2064 window->destroy_with_parent = setting;
2066 g_object_notify (G_OBJECT (window), "destroy_with_parent");
2070 * gtk_window_get_destroy_with_parent:
2071 * @window: a #GtkWindow
2073 * Returns whether the window will be destroyed with its transient parent. See
2074 * gtk_window_set_destroy_with_parent ().
2076 * Return value: %TRUE if the window will be destroyed with its transient parent.
2079 gtk_window_get_destroy_with_parent (GtkWindow *window)
2081 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2083 return window->destroy_with_parent;
2086 static GtkWindowGeometryInfo*
2087 gtk_window_get_geometry_info (GtkWindow *window,
2090 GtkWindowGeometryInfo *info;
2092 info = window->geometry_info;
2093 if (!info && create)
2095 info = g_new0 (GtkWindowGeometryInfo, 1);
2097 info->default_width = -1;
2098 info->default_height = -1;
2099 info->resize_width = -1;
2100 info->resize_height = -1;
2101 info->initial_x = 0;
2102 info->initial_y = 0;
2103 info->initial_pos_set = FALSE;
2104 info->default_is_geometry = FALSE;
2105 info->position_constraints_changed = FALSE;
2106 info->last.configure_request.x = 0;
2107 info->last.configure_request.y = 0;
2108 info->last.configure_request.width = -1;
2109 info->last.configure_request.height = -1;
2110 info->widget = NULL;
2112 window->geometry_info = info;
2119 * gtk_window_set_geometry_hints:
2120 * @window: a #GtkWindow
2121 * @geometry_widget: widget the geometry hints will be applied to
2122 * @geometry: struct containing geometry information
2123 * @geom_mask: mask indicating which struct fields should be paid attention to
2125 * This function sets up hints about how a window can be resized by
2126 * the user. You can set a minimum and maximum size; allowed resize
2127 * increments (e.g. for xterm, you can only resize by the size of a
2128 * character); aspect ratios; and more. See the #GdkGeometry struct.
2132 gtk_window_set_geometry_hints (GtkWindow *window,
2133 GtkWidget *geometry_widget,
2134 GdkGeometry *geometry,
2135 GdkWindowHints geom_mask)
2137 GtkWindowGeometryInfo *info;
2139 g_return_if_fail (GTK_IS_WINDOW (window));
2140 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2142 info = gtk_window_get_geometry_info (window, TRUE);
2145 g_signal_handlers_disconnect_by_func (info->widget,
2146 gtk_widget_destroyed,
2149 info->widget = geometry_widget;
2151 g_signal_connect (geometry_widget, "destroy",
2152 G_CALLBACK (gtk_widget_destroyed),
2156 info->geometry = *geometry;
2158 /* We store gravity in window->gravity not in the hints. */
2159 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2161 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2163 gtk_window_set_gravity (window, geometry->win_gravity);
2166 gtk_widget_queue_resize (GTK_WIDGET (window));
2170 * gtk_window_set_decorated:
2171 * @window: a #GtkWindow
2172 * @setting: %TRUE to decorate the window
2174 * By default, windows are decorated with a title bar, resize
2175 * controls, etc. Some <link linkend="gtk-X11-arch">window
2176 * managers</link> allow GTK+ to disable these decorations, creating a
2177 * borderless window. If you set the decorated property to %FALSE
2178 * using this function, GTK+ will do its best to convince the window
2179 * manager not to decorate the window. Depending on the system, this
2180 * function may not have any effect when called on a window that is
2181 * already visible, so you should call it before calling gtk_window_show().
2183 * On Windows, this function always works, since there's no window manager
2188 gtk_window_set_decorated (GtkWindow *window,
2191 g_return_if_fail (GTK_IS_WINDOW (window));
2193 setting = setting != FALSE;
2195 if (setting == window->decorated)
2198 window->decorated = setting;
2200 if (GTK_WIDGET (window)->window)
2202 if (window->decorated)
2203 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2206 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2212 * gtk_window_get_decorated:
2213 * @window: a #GtkWindow
2215 * Returns whether the window has been set to have decorations
2216 * such as a title bar via gtk_window_set_decorated().
2218 * Return value: %TRUE if the window has been set to have decorations
2221 gtk_window_get_decorated (GtkWindow *window)
2223 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2225 return window->decorated;
2228 static GtkWindowIconInfo*
2229 get_icon_info (GtkWindow *window)
2231 return g_object_get_data (G_OBJECT (window),
2232 "gtk-window-icon-info");
2235 static GtkWindowIconInfo*
2236 ensure_icon_info (GtkWindow *window)
2238 GtkWindowIconInfo *info;
2240 info = get_icon_info (window);
2244 info = g_new0 (GtkWindowIconInfo, 1);
2245 g_object_set_data_full (G_OBJECT (window),
2246 "gtk-window-icon-info",
2261 get_screen_icon_info (GdkScreen *screen)
2263 ScreenIconInfo *info = g_object_get_data (G_OBJECT (screen),
2264 "gtk-window-default-icon-pixmap");
2267 info = g_new0 (ScreenIconInfo, 1);
2268 g_object_set_data (G_OBJECT (screen), "gtk-window-default-icon-pixmap", info);
2271 if (info->serial != default_icon_serial)
2275 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2276 info->pixmap = NULL;
2281 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2285 info->serial = default_icon_serial;
2292 get_pixmap_and_mask (GdkWindow *window,
2293 GtkWindowIconInfo *parent_info,
2294 gboolean is_default_list,
2296 GdkPixmap **pmap_return,
2297 GdkBitmap **mask_return)
2299 GdkScreen *screen = gdk_drawable_get_screen (window);
2300 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2301 GdkPixbuf *best_icon;
2305 *pmap_return = NULL;
2306 *mask_return = NULL;
2308 if (is_default_list &&
2309 default_icon_info->pixmap != NULL)
2311 /* Use shared icon pixmap for all windows on this screen.
2313 if (default_icon_info->pixmap)
2314 g_object_ref (default_icon_info->pixmap);
2315 if (default_icon_info->mask)
2316 g_object_ref (default_icon_info->mask);
2318 *pmap_return = default_icon_info->pixmap;
2319 *mask_return = default_icon_info->mask;
2321 else if (parent_info && parent_info->icon_pixmap)
2323 if (parent_info->icon_pixmap)
2324 g_object_ref (parent_info->icon_pixmap);
2325 if (parent_info->icon_mask)
2326 g_object_ref (parent_info->icon_mask);
2328 *pmap_return = parent_info->icon_pixmap;
2329 *mask_return = parent_info->icon_mask;
2333 #define IDEAL_SIZE 48
2335 best_size = G_MAXINT;
2337 tmp_list = icon_list;
2338 while (tmp_list != NULL)
2340 GdkPixbuf *pixbuf = tmp_list->data;
2343 /* average width and height - if someone passes in a rectangular
2344 * icon they deserve what they get.
2346 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2349 if (best_icon == NULL)
2356 /* icon is better if it's 32 pixels or larger, and closer to
2357 * the ideal size than the current best.
2360 (ABS (best_size - IDEAL_SIZE) <
2361 ABS (this - IDEAL_SIZE)))
2368 tmp_list = tmp_list->next;
2372 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2373 gdk_screen_get_system_colormap (screen),
2378 /* Save pmap/mask for others to use if appropriate */
2381 parent_info->icon_pixmap = *pmap_return;
2382 parent_info->icon_mask = *mask_return;
2384 if (parent_info->icon_pixmap)
2385 g_object_ref (parent_info->icon_pixmap);
2386 if (parent_info->icon_mask)
2387 g_object_ref (parent_info->icon_mask);
2389 else if (is_default_list)
2391 default_icon_info->pixmap = *pmap_return;
2392 default_icon_info->mask = *mask_return;
2394 if (default_icon_info->pixmap)
2395 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2396 (gpointer*)&default_icon_info->pixmap);
2397 if (default_icon_info->mask)
2398 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2399 (gpointer*)&default_icon_info->mask);
2405 gtk_window_realize_icon (GtkWindow *window)
2408 GtkWindowIconInfo *info;
2411 widget = GTK_WIDGET (window);
2413 g_return_if_fail (widget->window != NULL);
2415 /* no point setting an icon on override-redirect */
2416 if (window->type == GTK_WINDOW_POPUP)
2421 info = ensure_icon_info (window);
2426 g_return_if_fail (info->icon_pixmap == NULL);
2427 g_return_if_fail (info->icon_mask == NULL);
2429 info->using_default_icon = FALSE;
2430 info->using_parent_icon = FALSE;
2432 icon_list = info->icon_list;
2434 /* Inherit from transient parent */
2435 if (icon_list == NULL && window->transient_parent)
2437 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2439 info->using_parent_icon = TRUE;
2442 /* Inherit from default */
2443 if (icon_list == NULL)
2445 icon_list = default_icon_list;
2447 info->using_default_icon = TRUE;
2450 gdk_window_set_icon_list (widget->window, icon_list);
2452 get_pixmap_and_mask (widget->window,
2453 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2454 info->using_default_icon,
2459 /* This is a slight ICCCM violation since it's a color pixmap not
2460 * a bitmap, but everyone does it.
2462 gdk_window_set_icon (widget->window,
2467 info->realized = TRUE;
2471 gtk_window_unrealize_icon (GtkWindow *window)
2473 GtkWindowIconInfo *info;
2476 widget = GTK_WIDGET (window);
2478 info = get_icon_info (window);
2483 if (info->icon_pixmap)
2484 g_object_unref (info->icon_pixmap);
2486 if (info->icon_mask)
2487 g_object_unref (info->icon_mask);
2489 info->icon_pixmap = NULL;
2490 info->icon_mask = NULL;
2492 /* We don't clear the properties on the window, just figure the
2493 * window is going away.
2496 info->realized = FALSE;
2500 * gtk_window_set_icon_list:
2501 * @window: a #GtkWindow
2502 * @list: list of #GdkPixbuf
2504 * Sets up the icon representing a #GtkWindow. The icon is used when
2505 * the window is minimized (also known as iconified). Some window
2506 * managers or desktop environments may also place it in the window
2507 * frame, or display it in other contexts.
2509 * gtk_window_set_icon_list() allows you to pass in the same icon in
2510 * several hand-drawn sizes. The list should contain the natural sizes
2511 * your icon is available in; that is, don't scale the image before
2512 * passing it to GTK+. Scaling is postponed until the last minute,
2513 * when the desired final size is known, to allow best quality.
2515 * By passing several sizes, you may improve the final image quality
2516 * of the icon, by reducing or eliminating automatic image scaling.
2518 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2519 * larger images (64x64, 128x128) if you have them.
2521 * See also gtk_window_set_default_icon_list() to set the icon
2522 * for all windows in your application in one go.
2524 * Note that transient windows (those who have been set transient for another
2525 * window using gtk_window_set_transient_for()) will inherit their
2526 * icon from their transient parent. So there's no need to explicitly
2527 * set the icon on transient windows.
2530 gtk_window_set_icon_list (GtkWindow *window,
2533 GtkWindowIconInfo *info;
2535 g_return_if_fail (GTK_IS_WINDOW (window));
2537 info = ensure_icon_info (window);
2539 if (info->icon_list == list) /* check for NULL mostly */
2542 g_list_foreach (info->icon_list,
2543 (GFunc) g_object_unref, NULL);
2545 g_list_free (info->icon_list);
2547 info->icon_list = g_list_copy (list);
2548 g_list_foreach (info->icon_list,
2549 (GFunc) g_object_ref, NULL);
2551 g_object_notify (G_OBJECT (window), "icon");
2553 gtk_window_unrealize_icon (window);
2555 if (GTK_WIDGET_REALIZED (window))
2556 gtk_window_realize_icon (window);
2558 /* We could try to update our transient children, but I don't think
2559 * it's really worth it. If we did it, the best way would probably
2560 * be to have children connect to notify::icon_list
2565 * gtk_window_get_icon_list:
2566 * @window: a #GtkWindow
2568 * Retrieves the list of icons set by gtk_window_set_icon_list().
2569 * The list is copied, but the reference count on each
2570 * member won't be incremented.
2572 * Return value: copy of window's icon list
2575 gtk_window_get_icon_list (GtkWindow *window)
2577 GtkWindowIconInfo *info;
2579 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2581 info = get_icon_info (window);
2584 return g_list_copy (info->icon_list);
2590 * gtk_window_set_icon:
2591 * @window: a #GtkWindow
2592 * @icon: icon image, or %NULL
2594 * Sets up the icon representing a #GtkWindow. This icon is used when
2595 * the window is minimized (also known as iconified). Some window
2596 * managers or desktop environments may also place it in the window
2597 * frame, or display it in other contexts.
2599 * The icon should be provided in whatever size it was naturally
2600 * drawn; that is, don't scale the image before passing it to
2601 * GTK+. Scaling is postponed until the last minute, when the desired
2602 * final size is known, to allow best quality.
2604 * If you have your icon hand-drawn in multiple sizes, use
2605 * gtk_window_set_icon_list(). Then the best size will be used.
2607 * This function is equivalent to calling gtk_window_set_icon_list()
2608 * with a 1-element list.
2610 * See also gtk_window_set_default_icon_list() to set the icon
2611 * for all windows in your application in one go.
2614 gtk_window_set_icon (GtkWindow *window,
2619 g_return_if_fail (GTK_IS_WINDOW (window));
2620 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2625 list = g_list_append (list, icon);
2627 gtk_window_set_icon_list (window, list);
2632 * gtk_window_get_icon:
2633 * @window: a #GtkWindow
2635 * Gets the value set by gtk_window_set_icon() (or if you've
2636 * called gtk_window_set_icon_list(), gets the first icon in
2639 * Return value: icon for window
2642 gtk_window_get_icon (GtkWindow *window)
2644 GtkWindowIconInfo *info;
2646 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2648 info = get_icon_info (window);
2649 if (info && info->icon_list)
2650 return GDK_PIXBUF (info->icon_list->data);
2655 /* Load pixbuf, printing warning on failure if error == NULL
2658 load_pixbuf_verbosely (const char *filename,
2661 GError *local_err = NULL;
2664 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
2672 g_warning ("Error loading icon from file '%s':\n\t%s",
2673 filename, local_err->message);
2674 g_error_free (local_err);
2682 * gtk_window_set_icon_from_file:
2683 * @window: a #GtkWindow
2684 * @filename: location of icon file
2685 * @err: location to store error, or %NULL.
2687 * Sets the icon for @window.
2688 * Warns on failure if @err is %NULL.
2690 * This function is equivalent to calling gtk_window_set_icon()
2691 * with a pixbuf created by loading the image from @filename.
2693 * Returns: %TRUE if setting the icon succeeded.
2698 gtk_window_set_icon_from_file (GtkWindow *window,
2699 const gchar *filename,
2702 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2706 gtk_window_set_icon (window, pixbuf);
2707 g_object_unref (pixbuf);
2716 * gtk_window_set_default_icon_list:
2717 * @list: a list of #GdkPixbuf
2719 * Sets an icon list to be used as fallback for windows that haven't
2720 * had gtk_window_set_icon_list() called on them to set up a
2721 * window-specific icon list. This function allows you to set up the
2722 * icon for all windows in your app at once.
2724 * See gtk_window_set_icon_list() for more details.
2728 gtk_window_set_default_icon_list (GList *list)
2732 if (list == default_icon_list)
2735 /* Update serial so we don't used cached pixmaps/masks
2737 default_icon_serial++;
2739 g_list_foreach (default_icon_list,
2740 (GFunc) g_object_unref, NULL);
2742 g_list_free (default_icon_list);
2744 default_icon_list = g_list_copy (list);
2745 g_list_foreach (default_icon_list,
2746 (GFunc) g_object_ref, NULL);
2748 /* Update all toplevels */
2749 toplevels = gtk_window_list_toplevels ();
2750 tmp_list = toplevels;
2751 while (tmp_list != NULL)
2753 GtkWindowIconInfo *info;
2754 GtkWindow *w = tmp_list->data;
2756 info = get_icon_info (w);
2757 if (info && info->using_default_icon)
2759 gtk_window_unrealize_icon (w);
2760 if (GTK_WIDGET_REALIZED (w))
2761 gtk_window_realize_icon (w);
2764 tmp_list = tmp_list->next;
2766 g_list_free (toplevels);
2770 * gtk_window_set_default_icon_from_file:
2771 * @filename: location of icon file
2772 * @err: location to store error, or %NULL.
2774 * Sets an icon to be used as fallback for windows that haven't
2775 * had gtk_window_set_icon_list() called on them from a file
2776 * on disk. Warns on failure if @err is %NULL.
2778 * Returns: %TRUE if setting the icon succeeded.
2783 gtk_window_set_default_icon_from_file (const gchar *filename,
2786 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2790 GList *list = g_list_prepend (NULL, pixbuf);
2791 gtk_window_set_default_icon_list (list);
2794 g_object_unref (pixbuf);
2803 * gtk_window_get_default_icon_list:
2805 * Gets the value set by gtk_window_set_default_icon_list().
2806 * The list is a copy and should be freed with g_list_free(),
2807 * but the pixbufs in the list have not had their reference count
2810 * Return value: copy of default icon list
2813 gtk_window_get_default_icon_list (void)
2815 return g_list_copy (default_icon_list);
2819 gtk_window_set_default_size_internal (GtkWindow *window,
2820 gboolean change_width,
2822 gboolean change_height,
2824 gboolean is_geometry)
2826 GtkWindowGeometryInfo *info;
2828 g_return_if_fail (change_width == FALSE || width >= -1);
2829 g_return_if_fail (change_height == FALSE || height >= -1);
2831 info = gtk_window_get_geometry_info (window, TRUE);
2833 g_object_freeze_notify (G_OBJECT (window));
2835 info->default_is_geometry = is_geometry != FALSE;
2845 info->default_width = width;
2847 g_object_notify (G_OBJECT (window), "default_width");
2858 info->default_height = height;
2860 g_object_notify (G_OBJECT (window), "default_height");
2863 g_object_thaw_notify (G_OBJECT (window));
2865 gtk_widget_queue_resize (GTK_WIDGET (window));
2869 * gtk_window_set_default_size:
2870 * @window: a #GtkWindow
2871 * @width: width in pixels, or -1 to unset the default width
2872 * @height: height in pixels, or -1 to unset the default height
2874 * Sets the default size of a window. If the window's "natural" size
2875 * (its size request) is larger than the default, the default will be
2876 * ignored. More generally, if the default size does not obey the
2877 * geometry hints for the window (gtk_window_set_geometry_hints() can
2878 * be used to set these explicitly), the default size will be clamped
2879 * to the nearest permitted size.
2881 * Unlike gtk_widget_set_size_request(), which sets a size request for
2882 * a widget and thus would keep users from shrinking the window, this
2883 * function only sets the initial size, just as if the user had
2884 * resized the window themselves. Users can still shrink the window
2885 * again as they normally would. Setting a default size of -1 means to
2886 * use the "natural" default size (the size request of the window).
2888 * For more control over a window's initial size and how resizing works,
2889 * investigate gtk_window_set_geometry_hints().
2891 * For some uses, gtk_window_resize() is a more appropriate function.
2892 * gtk_window_resize() changes the current size of the window, rather
2893 * than the size to be used on initial display. gtk_window_resize() always
2894 * affects the window itself, not the geometry widget.
2896 * The default size of a window only affects the first time a window is
2897 * shown; if a window is hidden and re-shown, it will remember the size
2898 * it had prior to hiding, rather than using the default size.
2900 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2901 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2904 gtk_window_set_default_size (GtkWindow *window,
2908 g_return_if_fail (GTK_IS_WINDOW (window));
2909 g_return_if_fail (width >= -1);
2910 g_return_if_fail (height >= -1);
2912 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
2916 * gtk_window_get_default_size:
2917 * @window: a #GtkWindow
2918 * @width: location to store the default width, or %NULL
2919 * @height: location to store the default height, or %NULL
2921 * Gets the default size of the window. A value of -1 for the width or
2922 * height indicates that a default size has not been explicitly set
2923 * for that dimension, so the "natural" size of the window will be
2928 gtk_window_get_default_size (GtkWindow *window,
2932 GtkWindowGeometryInfo *info;
2934 g_return_if_fail (GTK_IS_WINDOW (window));
2936 info = gtk_window_get_geometry_info (window, FALSE);
2939 *width = info->default_width;
2942 *height = info->default_height;
2946 * gtk_window_resize:
2947 * @window: a #GtkWindow
2948 * @width: width in pixels to resize the window to
2949 * @height: height in pixels to resize the window to
2951 * Resizes the window as if the user had done so, obeying geometry
2952 * constraints. The default geometry constraint is that windows may
2953 * not be smaller than their size request; to override this
2954 * constraint, call gtk_widget_set_size_request() to set the window's
2955 * request to a smaller value.
2957 * If gtk_window_resize() is called before showing a window for the
2958 * first time, it overrides any default size set with
2959 * gtk_window_set_default_size().
2961 * Windows may not be resized smaller than 1 by 1 pixels.
2965 gtk_window_resize (GtkWindow *window,
2969 GtkWindowGeometryInfo *info;
2971 g_return_if_fail (GTK_IS_WINDOW (window));
2972 g_return_if_fail (width > 0);
2973 g_return_if_fail (height > 0);
2975 info = gtk_window_get_geometry_info (window, TRUE);
2977 info->resize_width = width;
2978 info->resize_height = height;
2980 gtk_widget_queue_resize (GTK_WIDGET (window));
2984 * gtk_window_get_size:
2985 * @window: a #GtkWindow
2986 * @width: return location for width, or %NULL
2987 * @height: return location for height, or %NULL
2989 * Obtains the current size of @window. If @window is not onscreen,
2990 * it returns the size GTK+ will suggest to the <link
2991 * linkend="gtk-X11-arch">window manager</link> for the initial window
2992 * size (but this is not reliably the same as the size the window
2993 * manager will actually select). The size obtained by
2994 * gtk_window_get_size() is the last size received in a
2995 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2996 * rather than querying the X server for the size. As a result, if you
2997 * call gtk_window_resize() then immediately call
2998 * gtk_window_get_size(), the size won't have taken effect yet. After
2999 * the window manager processes the resize request, GTK+ receives
3000 * notification that the size has changed via a configure event, and
3001 * the size of the window gets updated.
3003 * Note 1: Nearly any use of this function creates a race condition,
3004 * because the size of the window may change between the time that you
3005 * get the size and the time that you perform some action assuming
3006 * that size is the current size. To avoid race conditions, connect to
3007 * "configure_event" on the window and adjust your size-dependent
3008 * state to match the size delivered in the #GdkEventConfigure.
3010 * Note 2: The returned size does <emphasis>not</emphasis> include the
3011 * size of the window manager decorations (aka the window frame or
3012 * border). Those are not drawn by GTK+ and GTK+ has no reliable
3013 * method of determining their size.
3015 * Note 3: If you are getting a window size in order to position
3016 * the window onscreen, there may be a better way. The preferred
3017 * way is to simply set the window's semantic type with
3018 * gtk_window_set_type_hint(), which allows the window manager to
3019 * e.g. center dialogs. Also, if you set the transient parent of
3020 * dialogs with gtk_window_set_transient_for() window managers
3021 * will often center the dialog over its parent window. It's
3022 * much preferred to let the window manager handle these
3023 * things rather than doing it yourself, because all apps will
3024 * behave consistently and according to user prefs if the window
3025 * manager handles it. Also, the window manager can take the size
3026 * of the window decorations/border into account, while your
3027 * application cannot.
3029 * In any case, if you insist on application-specified window
3030 * positioning, there's <emphasis>still</emphasis> a better way than
3031 * doing it yourself - gtk_window_set_position() will frequently
3032 * handle the details for you.
3036 gtk_window_get_size (GtkWindow *window,
3043 g_return_if_fail (GTK_IS_WINDOW (window));
3045 widget = GTK_WIDGET (window);
3047 if (width == NULL && height == NULL)
3050 if (GTK_WIDGET_MAPPED (window))
3052 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3057 GdkRectangle configure_request;
3059 gtk_window_compute_configure_request (window,
3063 w = configure_request.width;
3064 h = configure_request.height;
3075 * @window: a #GtkWindow
3076 * @x: X coordinate to move window to
3077 * @y: Y coordinate to move window to
3079 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3080 * @window to the given position. Window managers are free to ignore
3081 * this; most window managers ignore requests for initial window
3082 * positions (instead using a user-defined placement algorithm) and
3083 * honor requests after the window has already been shown.
3085 * Note: the position is the position of the gravity-determined
3086 * reference point for the window. The gravity determines two things:
3087 * first, the location of the reference point in root window
3088 * coordinates; and second, which point on the window is positioned at
3089 * the reference point.
3091 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3092 * point is simply the @x, @y supplied to gtk_window_move(). The
3093 * top-left corner of the window decorations (aka window frame or
3094 * border) will be placed at @x, @y. Therefore, to position a window
3095 * at the top left of the screen, you want to use the default gravity
3096 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3098 * To position a window at the bottom right corner of the screen, you
3099 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3100 * point is at @x + the window width and @y + the window height, and
3101 * the bottom-right corner of the window border will be placed at that
3102 * reference point. So, to place a window in the bottom right corner
3103 * you would first set gravity to south east, then write:
3104 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3105 * gdk_screen_height () - window_height)</literal>.
3107 * The extended window manager hints specification at <ulink
3108 * url="http://www.freedesktop.org/standards/wm-spec.html">
3109 * http://www.freedesktop.org/standards/wm-spec.html</ulink> has a
3110 * nice table of gravities in the "implementation notes" section.
3112 * The gtk_window_get_position() documentation may also be relevant.
3116 gtk_window_move (GtkWindow *window,
3120 GtkWindowGeometryInfo *info;
3123 g_return_if_fail (GTK_IS_WINDOW (window));
3125 widget = GTK_WIDGET (window);
3127 info = gtk_window_get_geometry_info (window, TRUE);
3129 if (GTK_WIDGET_MAPPED (window))
3131 /* we have now sent a request with this position
3132 * with currently-active constraints, so toggle flag.
3134 info->position_constraints_changed = FALSE;
3136 /* we only constrain if mapped - if not mapped,
3137 * then gtk_window_compute_configure_request()
3138 * will apply the constraints later, and we
3139 * don't want to lose information about
3140 * what position the user set before then.
3141 * i.e. if you do a move() then turn off POS_CENTER
3142 * then show the window, your move() will work.
3144 gtk_window_constrain_position (window,
3145 widget->allocation.width,
3146 widget->allocation.height,
3149 /* Note that this request doesn't go through our standard request
3150 * framework, e.g. doesn't increment configure_request_count,
3151 * doesn't set info->last, etc.; that's because
3152 * we don't save the info needed to arrive at this same request
3155 * To gtk_window_move_resize(), this will end up looking exactly
3156 * the same as the position being changed by the window
3160 /* FIXME are we handling gravity properly for framed windows? */
3162 gdk_window_move (window->frame,
3163 x - window->frame_left,
3164 y - window->frame_top);
3166 gdk_window_move (GTK_WIDGET (window)->window,
3171 /* Save this position to apply on mapping */
3172 info->initial_x = x;
3173 info->initial_y = y;
3174 info->initial_pos_set = TRUE;
3179 * gtk_window_get_position:
3180 * @window: a #GtkWindow
3181 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3182 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3184 * This function returns the position you need to pass to
3185 * gtk_window_move() to keep @window in its current position. This
3186 * means that the meaning of the returned value varies with window
3187 * gravity. See gtk_window_move() for more details.
3189 * If you haven't changed the window gravity, its gravity will be
3190 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3191 * gets the position of the top-left corner of the window manager
3192 * frame for the window. gtk_window_move() sets the position of this
3193 * same top-left corner.
3195 * gtk_window_get_position() is not 100% reliable because the X Window System
3196 * does not specify a way to obtain the geometry of the
3197 * decorations placed on a window by the window manager.
3198 * Thus GTK+ is using a "best guess" that works with most
3201 * Moreover, nearly all window managers are historically broken with
3202 * respect to their handling of window gravity. So moving a window to
3203 * its current position as returned by gtk_window_get_position() tends
3204 * to result in moving the window slightly. Window managers are
3205 * slowly getting better over time.
3207 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3208 * frame is not relevant, and thus gtk_window_get_position() will
3209 * always produce accurate results. However you can't use static
3210 * gravity to do things like place a window in a corner of the screen,
3211 * because static gravity ignores the window manager decorations.
3213 * If you are saving and restoring your application's window
3214 * positions, you should know that it's impossible for applications to
3215 * do this without getting it somewhat wrong because applications do
3216 * not have sufficient knowledge of window manager state. The Correct
3217 * Mechanism is to support the session management protocol (see the
3218 * "GnomeClient" object in the GNOME libraries for example) and allow
3219 * the window manager to save your window sizes and positions.
3224 gtk_window_get_position (GtkWindow *window,
3230 g_return_if_fail (GTK_IS_WINDOW (window));
3232 widget = GTK_WIDGET (window);
3234 if (window->gravity == GDK_GRAVITY_STATIC)
3236 if (GTK_WIDGET_MAPPED (widget))
3238 /* This does a server round-trip, which is sort of wrong;
3239 * but a server round-trip is inevitable for
3240 * gdk_window_get_frame_extents() in the usual
3241 * NorthWestGravity case below, so not sure what else to
3242 * do. We should likely be consistent about whether we get
3243 * the client-side info or the server-side info.
3245 gdk_window_get_origin (widget->window, root_x, root_y);
3249 GdkRectangle configure_request;
3251 gtk_window_compute_configure_request (window,
3255 *root_x = configure_request.x;
3256 *root_y = configure_request.y;
3261 GdkRectangle frame_extents;
3266 if (GTK_WIDGET_MAPPED (widget))
3269 gdk_window_get_frame_extents (window->frame, &frame_extents);
3271 gdk_window_get_frame_extents (widget->window, &frame_extents);
3272 x = frame_extents.x;
3273 y = frame_extents.y;
3274 gtk_window_get_size (window, &w, &h);
3278 /* We just say the frame has 0 size on all sides.
3279 * Not sure what else to do.
3281 gtk_window_compute_configure_request (window,
3284 x = frame_extents.x;
3285 y = frame_extents.y;
3286 w = frame_extents.width;
3287 h = frame_extents.height;
3290 switch (window->gravity)
3292 case GDK_GRAVITY_NORTH:
3293 case GDK_GRAVITY_CENTER:
3294 case GDK_GRAVITY_SOUTH:
3295 /* Find center of frame. */
3296 x += frame_extents.width / 2;
3297 /* Center client window on that point. */
3301 case GDK_GRAVITY_SOUTH_EAST:
3302 case GDK_GRAVITY_EAST:
3303 case GDK_GRAVITY_NORTH_EAST:
3304 /* Find right edge of frame */
3305 x += frame_extents.width;
3306 /* Align left edge of client at that point. */
3313 switch (window->gravity)
3315 case GDK_GRAVITY_WEST:
3316 case GDK_GRAVITY_CENTER:
3317 case GDK_GRAVITY_EAST:
3318 /* Find center of frame. */
3319 y += frame_extents.height / 2;
3320 /* Center client window there. */
3323 case GDK_GRAVITY_SOUTH_WEST:
3324 case GDK_GRAVITY_SOUTH:
3325 case GDK_GRAVITY_SOUTH_EAST:
3326 /* Find south edge of frame */
3327 y += frame_extents.height;
3328 /* Place bottom edge of client there */
3343 * gtk_window_reshow_with_initial_size:
3344 * @window: a #GtkWindow
3346 * Hides @window, then reshows it, resetting the
3347 * default size and position of the window. Used
3348 * by GUI builders only.
3351 gtk_window_reshow_with_initial_size (GtkWindow *window)
3355 g_return_if_fail (GTK_IS_WINDOW (window));
3357 widget = GTK_WIDGET (window);
3359 gtk_widget_hide (widget);
3360 gtk_widget_unrealize (widget);
3361 gtk_widget_show (widget);
3365 gtk_window_destroy (GtkObject *object)
3367 GtkWindow *window = GTK_WINDOW (object);
3369 if (window->transient_parent)
3370 gtk_window_set_transient_for (window, NULL);
3372 /* frees the icons */
3373 gtk_window_set_icon_list (window, NULL);
3375 if (window->has_user_ref_count)
3377 window->has_user_ref_count = FALSE;
3378 g_object_unref (window);
3382 gtk_window_group_remove_window (window->group, window);
3384 gtk_window_free_key_hash (window);
3386 GTK_OBJECT_CLASS (parent_class)->destroy (object);
3390 gtk_window_mnemonic_hash_remove (gpointer key,
3394 GtkWindowMnemonic *mnemonic = key;
3395 GtkWindow *window = user;
3397 if (mnemonic->window == window)
3399 if (mnemonic->targets)
3401 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
3403 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
3404 name, mnemonic->targets->data);
3407 g_slist_free (mnemonic->targets);
3416 gtk_window_private_finalize (GtkWindowPrivate *priv)
3423 gtk_window_finalize (GObject *object)
3425 GtkWindow *window = GTK_WINDOW (object);
3427 toplevel_list = g_slist_remove (toplevel_list, window);
3429 g_free (window->title);
3430 g_free (window->wmclass_name);
3431 g_free (window->wmclass_class);
3432 g_free (window->wm_role);
3434 g_hash_table_foreach_remove (mnemonic_hash_table,
3435 gtk_window_mnemonic_hash_remove,
3437 if (window->geometry_info)
3439 if (window->geometry_info->widget)
3440 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3441 gtk_widget_destroyed,
3442 &window->geometry_info->widget);
3443 g_free (window->geometry_info);
3446 if (window->keys_changed_handler)
3448 gtk_idle_remove (window->keys_changed_handler);
3449 window->keys_changed_handler = 0;
3452 G_OBJECT_CLASS (parent_class)->finalize (object);
3456 gtk_window_show (GtkWidget *widget)
3458 GtkWindow *window = GTK_WINDOW (widget);
3459 GtkContainer *container = GTK_CONTAINER (window);
3460 gboolean need_resize;
3462 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3464 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3465 container->need_resize = FALSE;
3469 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3470 GtkAllocation allocation = { 0, 0 };
3471 GdkRectangle configure_request;
3472 GdkGeometry new_geometry;
3474 gboolean was_realized;
3476 /* We are going to go ahead and perform this configure request
3477 * and then emulate a configure notify by going ahead and
3478 * doing a size allocate. Sort of a synchronous
3479 * mini-copy of gtk_window_move_resize() here.
3481 gtk_window_compute_configure_request (window,
3486 /* We update this because we are going to go ahead
3487 * and gdk_window_resize() below, rather than
3490 info->last.configure_request.width = configure_request.width;
3491 info->last.configure_request.height = configure_request.height;
3493 /* and allocate the window - this is normally done
3494 * in move_resize in response to configure notify
3496 allocation.width = configure_request.width;
3497 allocation.height = configure_request.height;
3498 gtk_widget_size_allocate (widget, &allocation);
3500 /* Then we guarantee we have a realize */
3501 was_realized = FALSE;
3502 if (!GTK_WIDGET_REALIZED (widget))
3504 gtk_widget_realize (widget);
3505 was_realized = TRUE;
3508 /* Must be done after the windows are realized,
3509 * so that the decorations can be read
3511 gtk_decorated_window_calculate_frame_size (window);
3513 /* We only send configure request if we didn't just finish
3514 * creating the window; if we just created the window
3515 * then we created it with widget->allocation anyhow.
3518 gdk_window_resize (widget->window,
3519 configure_request.width,
3520 configure_request.height);
3523 gtk_container_check_resize (container);
3525 gtk_widget_map (widget);
3527 /* Try to make sure that we have some focused widget
3529 #ifdef GDK_WINDOWING_X11
3530 if (!window->focus_widget && !GTK_IS_PLUG (window))
3532 if (!window->focus_widget)
3534 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
3537 gtk_grab_add (widget);
3541 gtk_window_hide (GtkWidget *widget)
3543 GtkWindow *window = GTK_WINDOW (widget);
3545 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3546 gtk_widget_unmap (widget);
3549 gtk_grab_remove (widget);
3553 gtk_window_map (GtkWidget *widget)
3555 GtkWindow *window = GTK_WINDOW (widget);
3556 GdkWindow *toplevel;
3557 GtkWindowPrivate *priv;
3559 priv = gtk_window_get_private (window);
3561 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3563 if (window->bin.child &&
3564 GTK_WIDGET_VISIBLE (window->bin.child) &&
3565 !GTK_WIDGET_MAPPED (window->bin.child))
3566 gtk_widget_map (window->bin.child);
3569 toplevel = window->frame;
3571 toplevel = widget->window;
3573 if (window->maximize_initially)
3574 gdk_window_maximize (toplevel);
3576 gdk_window_unmaximize (toplevel);
3578 if (window->stick_initially)
3579 gdk_window_stick (toplevel);
3581 gdk_window_unstick (toplevel);
3583 if (window->iconify_initially)
3584 gdk_window_iconify (toplevel);
3586 gdk_window_deiconify (toplevel);
3588 if (priv->fullscreen_initially)
3589 gdk_window_fullscreen (toplevel);
3591 gdk_window_unfullscreen (toplevel);
3593 /* No longer use the default settings */
3594 window->need_default_size = FALSE;
3595 window->need_default_position = FALSE;
3597 gdk_window_show (widget->window);
3600 gdk_window_show (window->frame);
3602 if (!disable_startup_notification &&
3603 !sent_startup_notification)
3605 sent_startup_notification = TRUE;
3606 gdk_notify_startup_complete ();
3611 gtk_window_unmap (GtkWidget *widget)
3613 GtkWindow *window = GTK_WINDOW (widget);
3614 GtkWindowGeometryInfo *info;
3615 GdkWindowState state;
3617 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3619 gdk_window_withdraw (window->frame);
3621 gdk_window_withdraw (widget->window);
3623 window->configure_request_count = 0;
3624 window->configure_notify_received = FALSE;
3626 /* on unmap, we reset the default positioning of the window,
3627 * so it's placed again, but we don't reset the default
3628 * size of the window, so it's remembered.
3630 window->need_default_position = TRUE;
3632 info = gtk_window_get_geometry_info (window, FALSE);
3635 info->initial_pos_set = FALSE;
3636 info->position_constraints_changed = FALSE;
3639 state = gdk_window_get_state (widget->window);
3640 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
3641 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
3642 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
3646 gtk_window_realize (GtkWidget *widget)
3649 GdkWindow *parent_window;
3650 GdkWindowAttr attributes;
3651 gint attributes_mask;
3653 window = GTK_WINDOW (widget);
3655 /* ensure widget tree is properly size allocated */
3656 if (widget->allocation.x == -1 &&
3657 widget->allocation.y == -1 &&
3658 widget->allocation.width == 1 &&
3659 widget->allocation.height == 1)
3661 GtkRequisition requisition;
3662 GtkAllocation allocation = { 0, 0, 200, 200 };
3664 gtk_widget_size_request (widget, &requisition);
3665 if (requisition.width || requisition.height)
3667 /* non-empty window */
3668 allocation.width = requisition.width;
3669 allocation.height = requisition.height;
3671 gtk_widget_size_allocate (widget, &allocation);
3673 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3675 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3678 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3680 switch (window->type)
3682 case GTK_WINDOW_TOPLEVEL:
3683 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3685 case GTK_WINDOW_POPUP:
3686 attributes.window_type = GDK_WINDOW_TEMP;
3689 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3693 attributes.title = window->title;
3694 attributes.wmclass_name = window->wmclass_name;
3695 attributes.wmclass_class = window->wmclass_class;
3696 attributes.wclass = GDK_INPUT_OUTPUT;
3697 attributes.visual = gtk_widget_get_visual (widget);
3698 attributes.colormap = gtk_widget_get_colormap (widget);
3700 if (window->has_frame)
3702 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3703 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3704 attributes.event_mask = (GDK_EXPOSURE_MASK |
3705 GDK_KEY_PRESS_MASK |
3706 GDK_ENTER_NOTIFY_MASK |
3707 GDK_LEAVE_NOTIFY_MASK |
3708 GDK_FOCUS_CHANGE_MASK |
3709 GDK_STRUCTURE_MASK |
3710 GDK_BUTTON_MOTION_MASK |
3711 GDK_POINTER_MOTION_HINT_MASK |
3712 GDK_BUTTON_PRESS_MASK |
3713 GDK_BUTTON_RELEASE_MASK);
3715 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3717 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
3718 &attributes, attributes_mask);
3720 gdk_window_set_user_data (window->frame, widget);
3722 attributes.window_type = GDK_WINDOW_CHILD;
3723 attributes.x = window->frame_left;
3724 attributes.y = window->frame_top;
3726 attributes_mask = GDK_WA_X | GDK_WA_Y;
3728 parent_window = window->frame;
3732 attributes_mask = 0;
3733 parent_window = gtk_widget_get_root_window (widget);
3736 attributes.width = widget->allocation.width;
3737 attributes.height = widget->allocation.height;
3738 attributes.event_mask = gtk_widget_get_events (widget);
3739 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3740 GDK_KEY_PRESS_MASK |
3741 GDK_KEY_RELEASE_MASK |
3742 GDK_ENTER_NOTIFY_MASK |
3743 GDK_LEAVE_NOTIFY_MASK |
3744 GDK_FOCUS_CHANGE_MASK |
3745 GDK_STRUCTURE_MASK);
3747 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3748 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3749 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3751 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3753 gdk_window_set_user_data (widget->window, window);
3755 widget->style = gtk_style_attach (widget->style, widget->window);
3756 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3758 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3760 /* This is a bad hack to set the window background. */
3761 gtk_window_paint (widget, NULL);
3763 if (window->transient_parent &&
3764 GTK_WIDGET_REALIZED (window->transient_parent))
3765 gdk_window_set_transient_for (widget->window,
3766 GTK_WIDGET (window->transient_parent)->window);
3768 if (window->wm_role)
3769 gdk_window_set_role (widget->window, window->wm_role);
3771 if (!window->decorated)
3772 gdk_window_set_decorations (widget->window, 0);
3774 gdk_window_set_type_hint (widget->window, window->type_hint);
3776 if (gtk_window_get_skip_pager_hint (window))
3777 gdk_window_set_skip_pager_hint (widget->window, TRUE);
3779 if (gtk_window_get_skip_taskbar_hint (window))
3780 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
3783 gdk_window_set_modal_hint (widget->window, TRUE);
3785 gdk_window_set_modal_hint (widget->window, FALSE);
3788 gtk_window_realize_icon (window);
3792 gtk_window_unrealize (GtkWidget *widget)
3795 GtkWindowGeometryInfo *info;
3797 window = GTK_WINDOW (widget);
3799 /* On unrealize, we reset the size of the window such
3800 * that we will re-apply the default sizing stuff
3801 * next time we show the window.
3803 * Default positioning is reset on unmap, instead of unrealize.
3805 window->need_default_size = TRUE;
3806 info = gtk_window_get_geometry_info (window, FALSE);
3809 info->resize_width = -1;
3810 info->resize_height = -1;
3811 info->last.configure_request.x = 0;
3812 info->last.configure_request.y = 0;
3813 info->last.configure_request.width = -1;
3814 info->last.configure_request.height = -1;
3815 /* be sure we reset geom hints on re-realize */
3816 info->last.flags = 0;
3821 gdk_window_set_user_data (window->frame, NULL);
3822 gdk_window_destroy (window->frame);
3823 window->frame = NULL;
3827 gtk_window_unrealize_icon (window);
3829 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3833 gtk_window_size_request (GtkWidget *widget,
3834 GtkRequisition *requisition)
3839 window = GTK_WINDOW (widget);
3840 bin = GTK_BIN (window);
3842 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3843 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3845 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3847 GtkRequisition child_requisition;
3849 gtk_widget_size_request (bin->child, &child_requisition);
3851 requisition->width += child_requisition.width;
3852 requisition->height += child_requisition.height;
3857 gtk_window_size_allocate (GtkWidget *widget,
3858 GtkAllocation *allocation)
3861 GtkAllocation child_allocation;
3863 window = GTK_WINDOW (widget);
3864 widget->allocation = *allocation;
3866 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3868 child_allocation.x = GTK_CONTAINER (window)->border_width;
3869 child_allocation.y = GTK_CONTAINER (window)->border_width;
3870 child_allocation.width =
3871 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3872 child_allocation.height =
3873 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3875 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3878 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3880 gdk_window_resize (window->frame,
3881 allocation->width + window->frame_left + window->frame_right,
3882 allocation->height + window->frame_top + window->frame_bottom);
3887 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3890 gboolean return_val;
3892 window = GTK_WINDOW (widget);
3894 if (window->frame && (event->any.window == window->frame))
3896 if ((event->type != GDK_KEY_PRESS) &&
3897 (event->type != GDK_KEY_RELEASE) &&
3898 (event->type != GDK_FOCUS_CHANGE))
3900 g_signal_stop_emission_by_name (widget, "event");
3902 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
3907 g_object_unref (event->any.window);
3908 event->any.window = g_object_ref (widget->window);
3916 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3918 GdkEventConfigure *configure_event;
3921 switch (event->type)
3924 configure_event = (GdkEventConfigure *)event;
3926 /* Invalidate the decorations */
3929 rect.width = configure_event->width;
3930 rect.height = configure_event->height;
3932 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3934 /* Pass on the (modified) configure event */
3935 configure_event->width -= window->frame_left + window->frame_right;
3936 configure_event->height -= window->frame_top + window->frame_bottom;
3937 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3946 gtk_window_configure_event (GtkWidget *widget,
3947 GdkEventConfigure *event)
3949 GtkWindow *window = GTK_WINDOW (widget);
3950 gboolean expected_reply = window->configure_request_count > 0;
3952 /* window->configure_request_count incremented for each
3953 * configure request, and decremented to a min of 0 for
3954 * each configure notify.
3956 * All it means is that we know we will get at least
3957 * window->configure_request_count more configure notifies.
3958 * We could get more configure notifies than that; some
3959 * of the configure notifies we get may be unrelated to
3960 * the configure requests. But we will get at least
3961 * window->configure_request_count notifies.
3964 if (window->configure_request_count > 0)
3965 window->configure_request_count -= 1;
3967 /* As an optimization, we avoid a resize when possible.
3969 * The only times we can avoid a resize are:
3970 * - we know only the position changed, not the size
3971 * - we know we have made more requests and so will get more
3972 * notifies and can wait to resize when we get them
3975 if (!expected_reply &&
3976 (widget->allocation.width == event->width &&
3977 widget->allocation.height == event->height))
3981 * If we do need to resize, we do that by:
3982 * - filling in widget->allocation with the new size
3983 * - setting configure_notify_received to TRUE
3984 * for use in gtk_window_move_resize()
3985 * - queueing a resize, leading to invocation of
3986 * gtk_window_move_resize() in an idle handler
3990 window->configure_notify_received = TRUE;
3992 widget->allocation.width = event->width;
3993 widget->allocation.height = event->height;
3995 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4000 /* the accel_key and accel_mods fields of the key have to be setup
4001 * upon calling this function. it'll then return whether that key
4002 * is at all used as accelerator, and if so will OR in the
4003 * accel_flags member of the key.
4006 _gtk_window_query_nonaccels (GtkWindow *window,
4008 GdkModifierType accel_mods)
4010 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4012 /* movement keys are considered locked accels */
4015 static const guint bindings[] = {
4016 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
4017 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
4021 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
4022 if (bindings[i] == accel_key)
4026 /* mnemonics are considered locked accels */
4027 if (accel_mods == window->mnemonic_modifier)
4029 GtkWindowMnemonic mkey;
4031 mkey.window = window;
4032 mkey.keyval = accel_key;
4033 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
4041 gtk_window_key_press_event (GtkWidget *widget,
4048 window = GTK_WINDOW (widget);
4052 /* Check for mnemonics and accelerators
4055 handled = _gtk_window_activate_key (window, event);
4059 focus = window->focus_widget;
4061 g_object_ref (focus);
4064 focus && focus != widget &&
4065 gtk_widget_get_toplevel (focus) == widget)
4069 if (GTK_WIDGET_IS_SENSITIVE (focus))
4070 handled = gtk_widget_event (focus, (GdkEvent*) event);
4072 parent = focus->parent;
4074 g_object_ref (parent);
4076 g_object_unref (focus);
4082 g_object_unref (focus);
4085 /* Chain up, invokes binding set */
4086 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
4087 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4093 gtk_window_key_release_event (GtkWidget *widget,
4099 window = GTK_WINDOW (widget);
4101 if (window->focus_widget &&
4102 window->focus_widget != widget &&
4103 GTK_WIDGET_SENSITIVE (window->focus_widget))
4105 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
4108 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
4109 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
4115 gtk_window_real_activate_default (GtkWindow *window)
4117 gtk_window_activate_default (window);
4121 gtk_window_real_activate_focus (GtkWindow *window)
4123 gtk_window_activate_focus (window);
4127 gtk_window_move_focus (GtkWindow *window,
4128 GtkDirectionType dir)
4130 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4132 if (!GTK_CONTAINER (window)->focus_child)
4133 gtk_window_set_focus (window, NULL);
4137 gtk_window_enter_notify_event (GtkWidget *widget,
4138 GdkEventCrossing *event)
4144 gtk_window_leave_notify_event (GtkWidget *widget,
4145 GdkEventCrossing *event)
4151 do_focus_change (GtkWidget *widget,
4154 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4156 g_object_ref (widget);
4159 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4161 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4163 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4164 fevent->focus_change.window = widget->window;
4166 g_object_ref (widget->window);
4167 fevent->focus_change.in = in;
4169 gtk_widget_event (widget, fevent);
4171 g_object_notify (G_OBJECT (widget), "has_focus");
4173 g_object_unref (widget);
4174 gdk_event_free (fevent);
4178 gtk_window_focus_in_event (GtkWidget *widget,
4179 GdkEventFocus *event)
4181 GtkWindow *window = GTK_WINDOW (widget);
4183 /* It appears spurious focus in events can occur when
4184 * the window is hidden. So we'll just check to see if
4185 * the window is visible before actually handling the
4188 if (GTK_WIDGET_VISIBLE (widget))
4190 _gtk_window_set_has_toplevel_focus (window, TRUE);
4191 _gtk_window_set_is_active (window, TRUE);
4198 gtk_window_focus_out_event (GtkWidget *widget,
4199 GdkEventFocus *event)
4201 GtkWindow *window = GTK_WINDOW (widget);
4203 _gtk_window_set_has_toplevel_focus (window, FALSE);
4204 _gtk_window_set_is_active (window, FALSE);
4209 static GdkAtom atom_rcfiles = GDK_NONE;
4212 gtk_window_read_rcfiles (GtkWidget *widget,
4213 GdkEventClient *event)
4215 GList *embedded_windows;
4217 embedded_windows = g_object_get_data (G_OBJECT (widget), "gtk-embedded");
4218 if (embedded_windows)
4220 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4223 for (i = 0; i < 5; i++)
4224 send_event->client.data.l[i] = 0;
4225 send_event->client.data_format = 32;
4226 send_event->client.message_type = atom_rcfiles;
4228 while (embedded_windows)
4230 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4231 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4232 embedded_windows = embedded_windows->next;
4235 gdk_event_free (send_event);
4238 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4242 gtk_window_client_event (GtkWidget *widget,
4243 GdkEventClient *event)
4246 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
4248 if (event->message_type == atom_rcfiles)
4249 gtk_window_read_rcfiles (widget, event);
4255 gtk_window_check_resize (GtkContainer *container)
4257 GtkWindow *window = GTK_WINDOW (container);
4259 if (GTK_WIDGET_VISIBLE (container))
4260 gtk_window_move_resize (window);
4264 gtk_window_focus (GtkWidget *widget,
4265 GtkDirectionType direction)
4269 GtkContainer *container;
4270 GtkWidget *old_focus_child;
4273 container = GTK_CONTAINER (widget);
4274 window = GTK_WINDOW (widget);
4275 bin = GTK_BIN (widget);
4277 old_focus_child = container->focus_child;
4279 /* We need a special implementation here to deal properly with wrapping
4280 * around in the tab chain without the danger of going into an
4283 if (old_focus_child)
4285 if (gtk_widget_child_focus (old_focus_child, direction))
4289 if (window->focus_widget)
4291 /* Wrapped off the end, clear the focus setting for the toplpevel */
4292 parent = window->focus_widget->parent;
4295 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4296 parent = GTK_WIDGET (parent)->parent;
4299 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4302 /* Now try to focus the first widget in the window */
4305 if (gtk_widget_child_focus (bin->child, direction))
4313 gtk_window_real_set_focus (GtkWindow *window,
4316 GtkWidget *old_focus = window->focus_widget;
4317 gboolean def_flags = 0;
4321 g_object_ref (old_focus);
4322 g_object_freeze_notify (G_OBJECT (old_focus));
4326 g_object_ref (focus);
4327 g_object_freeze_notify (G_OBJECT (focus));
4330 if (window->default_widget)
4331 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4333 if (window->focus_widget)
4335 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4336 (window->focus_widget != window->default_widget))
4338 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4340 if (window->default_widget)
4341 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4344 if (window->has_focus)
4345 do_focus_change (window->focus_widget, FALSE);
4347 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4350 window->focus_widget = focus;
4352 if (window->focus_widget)
4354 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4355 (window->focus_widget != window->default_widget))
4357 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4358 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4360 if (window->default_widget)
4361 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4364 if (window->has_focus)
4365 do_focus_change (window->focus_widget, TRUE);
4367 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4370 if (window->default_widget &&
4371 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
4372 gtk_widget_queue_draw (window->default_widget);
4376 g_object_thaw_notify (G_OBJECT (old_focus));
4377 g_object_unref (old_focus);
4381 g_object_thaw_notify (G_OBJECT (focus));
4382 g_object_unref (focus);
4387 * _gtk_window_unset_focus_and_default:
4388 * @window: a #GtkWindow
4389 * @widget: a widget inside of @window
4391 * Checks whether the focus and default widgets of @window are
4392 * @widget or a descendent of @widget, and if so, unset them.
4395 _gtk_window_unset_focus_and_default (GtkWindow *window,
4401 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
4403 child = window->focus_widget;
4405 while (child && child != widget)
4406 child = child->parent;
4408 if (child == widget)
4409 gtk_window_set_focus (GTK_WINDOW (window), NULL);
4412 child = window->default_widget;
4414 while (child && child != widget)
4415 child = child->parent;
4417 if (child == widget)
4418 gtk_window_set_default (window, NULL);
4421 /*********************************
4422 * Functions related to resizing *
4423 *********************************/
4425 /* This function doesn't constrain to geometry hints */
4427 gtk_window_compute_configure_request_size (GtkWindow *window,
4431 GtkRequisition requisition;
4432 GtkWindowGeometryInfo *info;
4436 * - we've done a size request
4439 widget = GTK_WIDGET (window);
4441 info = gtk_window_get_geometry_info (window, FALSE);
4443 if (window->need_default_size)
4445 gtk_widget_get_child_requisition (widget, &requisition);
4447 /* Default to requisition */
4448 *width = requisition.width;
4449 *height = requisition.height;
4451 /* If window is empty so requests 0, default to random nonzero size */
4452 if (*width == 0 && *height == 0)
4458 /* Override requisition with default size */
4462 gint base_width = 0;
4463 gint base_height = 0;
4465 gint height_inc = 1;
4467 if (info->default_is_geometry &&
4468 (info->default_width > 0 || info->default_height > 0))
4470 GdkGeometry geometry;
4473 gtk_window_compute_hints (window, &geometry, &flags);
4475 if (flags & GDK_HINT_BASE_SIZE)
4477 base_width = geometry.base_width;
4478 base_height = geometry.base_height;
4480 else if (flags & GDK_HINT_MIN_SIZE)
4482 base_width = geometry.min_width;
4483 base_height = geometry.min_height;
4485 if (flags & GDK_HINT_RESIZE_INC)
4487 width_inc = geometry.width_inc;
4488 height_inc = geometry.height_inc;
4492 if (info->default_width > 0)
4493 *width = info->default_width * width_inc + base_width;
4495 if (info->default_height > 0)
4496 *height = info->default_height * height_inc + base_height;
4501 /* Default to keeping current size */
4502 *width = widget->allocation.width;
4503 *height = widget->allocation.height;
4506 /* Override any size with gtk_window_resize() values */
4509 if (info->resize_width > 0)
4510 *width = info->resize_width;
4512 if (info->resize_height > 0)
4513 *height = info->resize_height;
4517 static GtkWindowPosition
4518 get_effective_position (GtkWindow *window)
4520 GtkWindowPosition pos = window->position;
4521 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
4522 (window->transient_parent == NULL ||
4523 !GTK_WIDGET_MAPPED (window->transient_parent)))
4524 pos = GTK_WIN_POS_NONE;
4530 get_center_monitor_of_window (GtkWindow *window)
4532 /* We could try to sort out the relative positions of the monitors and
4533 * stuff, or we could just be losers and assume you have a row
4534 * or column of monitors.
4536 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
4540 get_monitor_containing_pointer (GtkWindow *window)
4544 GdkScreen *window_screen;
4545 GdkScreen *pointer_screen;
4547 window_screen = gtk_window_check_screen (window);
4548 gdk_display_get_pointer (gdk_screen_get_display (window_screen),
4552 if (pointer_screen == window_screen)
4553 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
4561 center_window_on_monitor (GtkWindow *window,
4567 GdkRectangle monitor;
4570 monitor_num = get_monitor_containing_pointer (window);
4572 if (monitor_num == -1)
4573 monitor_num = get_center_monitor_of_window (window);
4575 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
4576 monitor_num, &monitor);
4578 *x = (monitor.width - w) / 2 + monitor.x;
4579 *y = (monitor.height - h) / 2 + monitor.y;
4581 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
4582 * and WM decorations.
4591 clamp_window_to_rectangle (gint *x,
4595 const GdkRectangle *rect)
4597 gint outside_w, outside_h;
4599 outside_w = (*x + w) - (rect->x + rect->width);
4603 outside_h = (*y + h) - (rect->y + rect->height);
4607 /* if larger than the screen, center on the screen. */
4609 *x += (rect->x - *x) / 2;
4611 *y += (rect->y - *y) / 2;
4616 gtk_window_compute_configure_request (GtkWindow *window,
4617 GdkRectangle *request,
4618 GdkGeometry *geometry,
4621 GdkGeometry new_geometry;
4625 GtkWindowPosition pos;
4626 GtkWidget *parent_widget;
4627 GtkWindowGeometryInfo *info;
4631 widget = GTK_WIDGET (window);
4633 screen = gtk_window_check_screen (window);
4635 gtk_widget_size_request (widget, NULL);
4636 gtk_window_compute_configure_request_size (window, &w, &h);
4638 gtk_window_compute_hints (window, &new_geometry, &new_flags);
4639 gtk_window_constrain_size (window,
4640 &new_geometry, new_flags,
4644 parent_widget = (GtkWidget*) window->transient_parent;
4646 pos = get_effective_position (window);
4647 info = gtk_window_get_geometry_info (window, TRUE);
4649 /* by default, don't change position requested */
4650 x = info->last.configure_request.x;
4651 y = info->last.configure_request.y;
4653 if (window->need_default_position)
4656 /* FIXME this all interrelates with window gravity.
4657 * For most of them I think we want to set GRAVITY_CENTER.
4659 * Not sure how to go about that.
4664 /* here we are only handling CENTER_ALWAYS
4665 * as it relates to default positioning,
4666 * where it's equivalent to simply CENTER
4668 case GTK_WIN_POS_CENTER_ALWAYS:
4669 case GTK_WIN_POS_CENTER:
4670 center_window_on_monitor (window, w, h, &x, &y);
4673 case GTK_WIN_POS_CENTER_ON_PARENT:
4676 GdkRectangle monitor;
4679 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
4681 if (parent_widget->window != NULL)
4682 monitor_num = gdk_screen_get_monitor_at_window (screen,
4683 parent_widget->window);
4687 gdk_window_get_origin (parent_widget->window,
4690 x = ox + (parent_widget->allocation.width - w) / 2;
4691 y = oy + (parent_widget->allocation.height - h) / 2;
4693 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4694 * WM decorations. If parent wasn't on a monitor, just
4697 if (monitor_num >= 0)
4699 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
4700 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4705 case GTK_WIN_POS_MOUSE:
4707 gint screen_width = gdk_screen_get_width (screen);
4708 gint screen_height = gdk_screen_get_height (screen);
4710 GdkRectangle monitor;
4711 GdkScreen *pointer_screen;
4714 gdk_display_get_pointer (gdk_screen_get_display (screen),
4718 if (pointer_screen == screen)
4719 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
4725 x = CLAMP (x, 0, screen_width - w);
4726 y = CLAMP (y, 0, screen_height - h);
4728 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4729 * WM decorations. Don't try to figure out what's going
4730 * on if the mouse wasn't inside a monitor.
4732 if (monitor_num >= 0)
4734 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
4735 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4743 } /* if (window->need_default_position) */
4745 if (window->need_default_position &&
4746 info->initial_pos_set)
4748 x = info->initial_x;
4749 y = info->initial_y;
4750 gtk_window_constrain_position (window, w, h, &x, &y);
4756 request->height = h;
4759 *geometry = new_geometry;
4765 gtk_window_constrain_position (GtkWindow *window,
4771 /* See long comments in gtk_window_move_resize()
4772 * on when it's safe to call this function.
4774 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4776 gint center_x, center_y;
4778 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
4786 gtk_window_move_resize (GtkWindow *window)
4790 * First we determine whether any information has changed that would
4791 * cause us to revise our last configure request. If we would send
4792 * a different configure request from last time, then
4793 * configure_request_size_changed = TRUE or
4794 * configure_request_pos_changed = TRUE. configure_request_size_changed
4795 * may be true due to new hints, a gtk_window_resize(), or whatever.
4796 * configure_request_pos_changed may be true due to gtk_window_set_position()
4797 * or gtk_window_move().
4799 * If the configure request has changed, we send off a new one. To
4800 * ensure GTK+ invariants are maintained (resize queue does what it
4801 * should), we go ahead and size_allocate the requested size in this
4804 * If the configure request has not changed, we don't ever resend
4805 * it, because it could mean fighting the user or window manager.
4808 * To prepare the configure request, we come up with a base size/pos:
4809 * - the one from gtk_window_move()/gtk_window_resize()
4810 * - else default_width, default_height if we haven't ever
4812 * - else the size request if we haven't ever been mapped,
4813 * as a substitute default size
4814 * - else the current size of the window, as received from
4815 * configure notifies (i.e. the current allocation)
4817 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4818 * the position request to be centered.
4821 GtkContainer *container;
4822 GtkWindowGeometryInfo *info;
4823 GdkGeometry new_geometry;
4825 GdkRectangle new_request;
4826 gboolean configure_request_size_changed;
4827 gboolean configure_request_pos_changed;
4828 gboolean hints_changed; /* do we need to send these again */
4829 GtkWindowLastGeometryInfo saved_last_info;
4831 widget = GTK_WIDGET (window);
4832 container = GTK_CONTAINER (widget);
4833 info = gtk_window_get_geometry_info (window, TRUE);
4835 configure_request_size_changed = FALSE;
4836 configure_request_pos_changed = FALSE;
4838 gtk_window_compute_configure_request (window, &new_request,
4839 &new_geometry, &new_flags);
4841 /* This check implies the invariant that we never set info->last
4842 * without setting the hints and sending off a configure request.
4844 * If we change info->last without sending the request, we may
4847 if (info->last.configure_request.x != new_request.x ||
4848 info->last.configure_request.y != new_request.y)
4849 configure_request_pos_changed = TRUE;
4851 if ((info->last.configure_request.width != new_request.width ||
4852 info->last.configure_request.height != new_request.height))
4853 configure_request_size_changed = TRUE;
4855 hints_changed = FALSE;
4857 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4858 &new_geometry, new_flags))
4860 hints_changed = TRUE;
4863 /* Position Constraints
4864 * ====================
4866 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4867 * a default. The other POS_ values are used only when the
4868 * window is shown, not after that.
4870 * However, we can't implement a position constraint as
4871 * "anytime the window size changes, center the window"
4872 * because this may well end up fighting the WM or user. In
4873 * fact it gets in an infinite loop with at least one WM.
4875 * Basically, applications are in no way in a position to
4876 * constrain the position of a window, with one exception:
4877 * override redirect windows. (Really the intended purpose
4878 * of CENTER_ALWAYS anyhow, I would think.)
4880 * So the way we implement this "constraint" is to say that when WE
4881 * cause a move or resize, i.e. we make a configure request changing
4882 * window size, we recompute the CENTER_ALWAYS position to reflect
4883 * the new window size, and include it in our request. Also, if we
4884 * just turned on CENTER_ALWAYS we snap to center with a new
4885 * request. Otherwise, if we are just NOTIFIED of a move or resize
4886 * done by someone else e.g. the window manager, we do NOT send a
4887 * new configure request.
4889 * For override redirect windows, this works fine; all window
4890 * sizes are from our configure requests. For managed windows,
4891 * it is at least semi-sane, though who knows what the
4892 * app author is thinking.
4895 /* This condition should be kept in sync with the condition later on
4896 * that determines whether we send a configure request. i.e. we
4897 * should do this position constraining anytime we were going to
4898 * send a configure request anyhow, plus when constraints have
4901 if (configure_request_pos_changed ||
4902 configure_request_size_changed ||
4904 info->position_constraints_changed)
4906 /* We request the constrained position if:
4907 * - we were changing position, and need to clamp
4908 * the change to the constraint
4909 * - we're changing the size anyway
4910 * - set_position() was called to toggle CENTER_ALWAYS on
4913 gtk_window_constrain_position (window,
4919 /* Update whether we need to request a move */
4920 if (info->last.configure_request.x != new_request.x ||
4921 info->last.configure_request.y != new_request.y)
4922 configure_request_pos_changed = TRUE;
4924 configure_request_pos_changed = FALSE;
4928 if (window->type == GTK_WINDOW_TOPLEVEL)
4930 int notify_x, notify_y;
4932 /* this is the position from the last configure notify */
4933 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4935 g_message ("--- %s ---\n"
4936 "last : %d,%d\t%d x %d\n"
4937 "this : %d,%d\t%d x %d\n"
4938 "alloc : %d,%d\t%d x %d\n"
4940 "resize: \t%d x %d\n"
4941 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4942 "configure_notify_received: %d\n"
4943 "configure_request_count: %d\n"
4944 "position_constraints_changed: %d\n",
4945 window->title ? window->title : "(no title)",
4946 info->last.configure_request.x,
4947 info->last.configure_request.y,
4948 info->last.configure_request.width,
4949 info->last.configure_request.height,
4955 widget->allocation.width,
4956 widget->allocation.height,
4957 widget->requisition.width,
4958 widget->requisition.height,
4960 info->resize_height,
4961 configure_request_pos_changed,
4962 configure_request_size_changed,
4964 window->configure_notify_received,
4965 window->configure_request_count,
4966 info->position_constraints_changed);
4970 saved_last_info = info->last;
4971 info->last.geometry = new_geometry;
4972 info->last.flags = new_flags;
4973 info->last.configure_request = new_request;
4975 /* need to set PPosition so the WM will look at our position,
4976 * but we don't want to count PPosition coming and going as a hints
4977 * change for future iterations. So we saved info->last prior to
4981 /* Also, if the initial position was explicitly set, then we always
4982 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4986 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4987 * this is an initial map
4990 if ((configure_request_pos_changed ||
4991 info->initial_pos_set ||
4992 (window->need_default_position &&
4993 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
4994 (new_flags & GDK_HINT_POS) == 0)
4996 new_flags |= GDK_HINT_POS;
4997 hints_changed = TRUE;
5000 /* Set hints if necessary
5003 gdk_window_set_geometry_hints (widget->window,
5007 /* handle resizing/moving and widget tree allocation
5009 if (window->configure_notify_received)
5011 GtkAllocation allocation;
5013 /* If we have received a configure event since
5014 * the last time in this function, we need to
5015 * accept our new size and size_allocate child widgets.
5016 * (see gtk_window_configure_event() for more details).
5018 * 1 or more configure notifies may have been received.
5019 * Also, configure_notify_received will only be TRUE
5020 * if all expected configure notifies have been received
5021 * (one per configure request), as an optimization.
5024 window->configure_notify_received = FALSE;
5026 /* gtk_window_configure_event() filled in widget->allocation */
5027 allocation = widget->allocation;
5028 gtk_widget_size_allocate (widget, &allocation);
5030 /* If the configure request changed, it means that
5032 * 1) coincidentally changed hints or widget properties
5033 * impacting the configure request before getting
5034 * a configure notify, or
5035 * 2) some broken widget is changing its size request
5036 * during size allocation, resulting in
5037 * a false appearance of changed configure request.
5039 * For 1), we could just go ahead and ask for the
5040 * new size right now, but doing that for 2)
5041 * might well be fighting the user (and can even
5042 * trigger a loop). Since we really don't want to
5043 * do that, we requeue a resize in hopes that
5044 * by the time it gets handled, the child has seen
5045 * the light and is willing to go along with the
5046 * new size. (this happens for the zvt widget, since
5047 * the size_allocate() above will have stored the
5048 * requisition corresponding to the new size in the
5051 * This doesn't buy us anything for 1), but it shouldn't
5052 * hurt us too badly, since it is what would have
5053 * happened if we had gotten the configure event before
5054 * the new size had been set.
5057 if (configure_request_size_changed ||
5058 configure_request_pos_changed)
5060 /* Don't change the recorded last info after all, because we
5061 * haven't actually updated to the new info yet - we decided
5062 * to postpone our configure request until later.
5064 info->last = saved_last_info;
5066 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
5069 return; /* Bail out, we didn't really process the move/resize */
5071 else if ((configure_request_size_changed || hints_changed) &&
5072 (widget->allocation.width != new_request.width ||
5073 widget->allocation.height != new_request.height))
5076 /* We are in one of the following situations:
5077 * A. configure_request_size_changed
5078 * our requisition has changed and we need a different window size,
5079 * so we request it from the window manager.
5080 * B. !configure_request_size_changed && hints_changed
5081 * the window manager rejects our size, but we have just changed the
5082 * window manager hints, so there's a chance our request will
5083 * be honoured this time, so we try again.
5085 * However, if the new requisition is the same as the current allocation,
5086 * we don't request it again, since we won't get a ConfigureNotify back from
5087 * the window manager unless it decides to change our requisition. If
5088 * we don't get the ConfigureNotify back, the resize queue will never be run.
5091 /* Now send the configure request */
5092 if (configure_request_pos_changed)
5096 gdk_window_move_resize (window->frame,
5097 new_request.x - window->frame_left,
5098 new_request.y - window->frame_top,
5099 new_request.width + window->frame_left + window->frame_right,
5100 new_request.height + window->frame_top + window->frame_bottom);
5101 gdk_window_resize (widget->window,
5102 new_request.width, new_request.height);
5105 gdk_window_move_resize (widget->window,
5106 new_request.x, new_request.y,
5107 new_request.width, new_request.height);
5109 else /* only size changed */
5112 gdk_window_resize (window->frame,
5113 new_request.width + window->frame_left + window->frame_right,
5114 new_request.height + window->frame_top + window->frame_bottom);
5115 gdk_window_resize (widget->window,
5116 new_request.width, new_request.height);
5119 /* Increment the number of have-not-yet-received-notify requests */
5120 window->configure_request_count += 1;
5122 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5123 * configure event in response to our resizing request.
5124 * the configure event will cause a new resize with
5125 * ->configure_notify_received=TRUE.
5126 * until then, we want to
5127 * - discard expose events
5128 * - coalesce resizes for our children
5129 * - defer any window resizes until the configure event arrived
5130 * to achieve this, we queue a resize for the window, but remove its
5131 * resizing handler, so resizing will not be handled from the next
5132 * idle handler but when the configure event arrives.
5134 * FIXME: we should also dequeue the pending redraws here, since
5135 * we handle those ourselves upon ->configure_notify_received==TRUE.
5137 if (container->resize_mode == GTK_RESIZE_QUEUE)
5139 gtk_widget_queue_resize (widget);
5140 _gtk_container_dequeue_resize_handler (container);
5145 /* Handle any position changes.
5147 if (configure_request_pos_changed)
5151 gdk_window_move (window->frame,
5152 new_request.x - window->frame_left,
5153 new_request.y - window->frame_top);
5156 gdk_window_move (widget->window,
5157 new_request.x, new_request.y);
5160 /* And run the resize queue.
5162 gtk_container_resize_children (container);
5165 /* We have now processed a move/resize since the last position
5166 * constraint change, setting of the initial position, or resize.
5167 * (Not resetting these flags here can lead to infinite loops for
5168 * GTK_RESIZE_IMMEDIATE containers)
5170 info->position_constraints_changed = FALSE;
5171 info->initial_pos_set = FALSE;
5172 info->resize_width = -1;
5173 info->resize_height = -1;
5176 /* Compare two sets of Geometry hints for equality.
5179 gtk_window_compare_hints (GdkGeometry *geometry_a,
5181 GdkGeometry *geometry_b,
5184 if (flags_a != flags_b)
5187 if ((flags_a & GDK_HINT_MIN_SIZE) &&
5188 (geometry_a->min_width != geometry_b->min_width ||
5189 geometry_a->min_height != geometry_b->min_height))
5192 if ((flags_a & GDK_HINT_MAX_SIZE) &&
5193 (geometry_a->max_width != geometry_b->max_width ||
5194 geometry_a->max_height != geometry_b->max_height))
5197 if ((flags_a & GDK_HINT_BASE_SIZE) &&
5198 (geometry_a->base_width != geometry_b->base_width ||
5199 geometry_a->base_height != geometry_b->base_height))
5202 if ((flags_a & GDK_HINT_ASPECT) &&
5203 (geometry_a->min_aspect != geometry_b->min_aspect ||
5204 geometry_a->max_aspect != geometry_b->max_aspect))
5207 if ((flags_a & GDK_HINT_RESIZE_INC) &&
5208 (geometry_a->width_inc != geometry_b->width_inc ||
5209 geometry_a->height_inc != geometry_b->height_inc))
5212 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5213 geometry_a->win_gravity != geometry_b->win_gravity)
5220 _gtk_window_constrain_size (GtkWindow *window,
5226 GtkWindowGeometryInfo *info;
5228 g_return_if_fail (GTK_IS_WINDOW (window));
5230 info = window->geometry_info;
5233 GdkWindowHints flags = info->last.flags;
5234 GdkGeometry *geometry = &info->last.geometry;
5236 gtk_window_constrain_size (window,
5247 gtk_window_constrain_size (GtkWindow *window,
5248 GdkGeometry *geometry,
5255 gdk_window_constrain_size (geometry, flags, width, height,
5256 new_width, new_height);
5259 /* Compute the set of geometry hints and flags for a window
5260 * based on the application set geometry, and requisiition
5261 * of the window. gtk_widget_size_request() must have been
5265 gtk_window_compute_hints (GtkWindow *window,
5266 GdkGeometry *new_geometry,
5270 gint extra_width = 0;
5271 gint extra_height = 0;
5272 GtkWindowGeometryInfo *geometry_info;
5273 GtkRequisition requisition;
5275 widget = GTK_WIDGET (window);
5277 gtk_widget_get_child_requisition (widget, &requisition);
5278 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5282 *new_flags = geometry_info->mask;
5283 *new_geometry = geometry_info->geometry;
5290 if (geometry_info && geometry_info->widget)
5292 GtkRequisition child_requisition;
5294 /* FIXME: This really isn't right. It gets the min size wrong and forces
5295 * callers to do horrible hacks like set a huge usize on the child requisition
5296 * to get the base size right. We really want to find the answers to:
5298 * - If the geometry widget was infinitely big, how much extra space
5299 * would be needed for the stuff around it.
5301 * - If the geometry widget was infinitely small, how big would the
5302 * window still have to be.
5304 * Finding these answers would be a bit of a mess here. (Bug #68668)
5306 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5308 extra_width = widget->requisition.width - child_requisition.width;
5309 extra_height = widget->requisition.height - child_requisition.height;
5312 /* We don't want to set GDK_HINT_POS in here, we just set it
5313 * in gtk_window_move_resize() when we want the position
5317 if (*new_flags & GDK_HINT_BASE_SIZE)
5319 new_geometry->base_width += extra_width;
5320 new_geometry->base_height += extra_height;
5322 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5323 (*new_flags & GDK_HINT_RESIZE_INC) &&
5324 ((extra_width != 0) || (extra_height != 0)))
5326 *new_flags |= GDK_HINT_BASE_SIZE;
5328 new_geometry->base_width = extra_width;
5329 new_geometry->base_height = extra_height;
5332 if (*new_flags & GDK_HINT_MIN_SIZE)
5334 if (new_geometry->min_width < 0)
5335 new_geometry->min_width = requisition.width;
5337 new_geometry->min_width += extra_width;
5339 if (new_geometry->min_height < 0)
5340 new_geometry->min_height = requisition.height;
5342 new_geometry->min_height += extra_height;
5344 else if (!window->allow_shrink)
5346 *new_flags |= GDK_HINT_MIN_SIZE;
5348 new_geometry->min_width = requisition.width;
5349 new_geometry->min_height = requisition.height;
5352 if (*new_flags & GDK_HINT_MAX_SIZE)
5354 if (new_geometry->max_width < 0)
5355 new_geometry->max_width = requisition.width;
5357 new_geometry->max_width += extra_width;
5359 if (new_geometry->max_height < 0)
5360 new_geometry->max_width = requisition.height;
5362 new_geometry->max_height += extra_height;
5364 else if (!window->allow_grow)
5366 *new_flags |= GDK_HINT_MAX_SIZE;
5368 new_geometry->max_width = requisition.width;
5369 new_geometry->max_height = requisition.height;
5372 *new_flags |= GDK_HINT_WIN_GRAVITY;
5373 new_geometry->win_gravity = window->gravity;
5376 /***********************
5377 * Redrawing functions *
5378 ***********************/
5381 gtk_window_paint (GtkWidget *widget,
5384 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
5385 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
5389 gtk_window_expose (GtkWidget *widget,
5390 GdkEventExpose *event)
5392 if (!GTK_WIDGET_APP_PAINTABLE (widget))
5393 gtk_window_paint (widget, &event->area);
5395 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
5396 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
5402 * gtk_window_set_has_frame:
5403 * @window: a #GtkWindow
5404 * @setting: a boolean
5406 * (Note: this is a special-purpose function for the framebuffer port,
5407 * that causes GTK+ to draw its own window border. For most applications,
5408 * you want gtk_window_set_decorated() instead, which tells the window
5409 * manager whether to draw the window border.)
5411 * If this function is called on a window with setting of %TRUE, before
5412 * it is realized or showed, it will have a "frame" window around
5413 * @window->window, accessible in @window->frame. Using the signal
5414 * frame_event you can recieve all events targeted at the frame.
5416 * This function is used by the linux-fb port to implement managed
5417 * windows, but it could concievably be used by X-programs that
5418 * want to do their own window decorations.
5422 gtk_window_set_has_frame (GtkWindow *window,
5425 g_return_if_fail (GTK_IS_WINDOW (window));
5426 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
5428 window->has_frame = setting != FALSE;
5432 * gtk_window_get_has_frame:
5433 * @window: a #GtkWindow
5435 * Accessor for whether the window has a frame window exterior to
5436 * @window->window. Gets the value set by gtk_window_set_has_frame ().
5438 * Return value: %TRUE if a frame has been added to the window
5439 * via gtk_window_set_has_frame().
5442 gtk_window_get_has_frame (GtkWindow *window)
5444 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5446 return window->has_frame;
5450 * gtk_window_set_frame_dimensions:
5451 * @window: a #GtkWindow that has a frame
5452 * @left: The width of the left border
5453 * @top: The height of the top border
5454 * @right: The width of the right border
5455 * @bottom: The height of the bottom border
5457 * (Note: this is a special-purpose function intended for the framebuffer
5458 * port; see gtk_window_set_has_frame(). It will have no effect on the
5459 * window border drawn by the window manager, which is the normal
5460 * case when using the X Window system.)
5462 * For windows with frames (see gtk_window_set_has_frame()) this function
5463 * can be used to change the size of the frame border.
5466 gtk_window_set_frame_dimensions (GtkWindow *window,
5474 g_return_if_fail (GTK_IS_WINDOW (window));
5476 widget = GTK_WIDGET (window);
5478 if (window->frame_left == left &&
5479 window->frame_top == top &&
5480 window->frame_right == right &&
5481 window->frame_bottom == bottom)
5484 window->frame_left = left;
5485 window->frame_top = top;
5486 window->frame_right = right;
5487 window->frame_bottom = bottom;
5489 if (GTK_WIDGET_REALIZED (widget) && window->frame)
5491 gint width = widget->allocation.width + left + right;
5492 gint height = widget->allocation.height + top + bottom;
5493 gdk_window_resize (window->frame, width, height);
5494 gtk_decorated_window_move_resize_window (window,
5496 widget->allocation.width,
5497 widget->allocation.height);
5502 * gtk_window_present:
5503 * @window: a #GtkWindow
5505 * Presents a window to the user. This may mean raising the window
5506 * in the stacking order, deiconifying it, moving it to the current
5507 * desktop, and/or giving it the keyboard focus, possibly dependent
5508 * on the user's platform, window manager, and preferences.
5510 * If @window is hidden, this function calls gtk_widget_show()
5513 * This function should be used when the user tries to open a window
5514 * that's already open. Say for example the preferences dialog is
5515 * currently open, and the user chooses Preferences from the menu
5516 * a second time; use gtk_window_present() to move the already-open dialog
5517 * where the user can see it.
5521 gtk_window_present (GtkWindow *window)
5525 g_return_if_fail (GTK_IS_WINDOW (window));
5527 widget = GTK_WIDGET (window);
5529 if (GTK_WIDGET_VISIBLE (window))
5531 g_assert (widget->window != NULL);
5533 gdk_window_show (widget->window);
5535 /* note that gdk_window_focus() will also move the window to
5536 * the current desktop, for WM spec compliant window managers.
5538 gdk_window_focus (widget->window,
5539 gtk_get_current_event_time ());
5543 gtk_widget_show (widget);
5548 * gtk_window_iconify:
5549 * @window: a #GtkWindow
5551 * Asks to iconify (i.e. minimize) the specified @window. Note that
5552 * you shouldn't assume the window is definitely iconified afterward,
5553 * because other entities (e.g. the user or <link
5554 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
5555 * again, or there may not be a window manager in which case
5556 * iconification isn't possible, etc. But normally the window will end
5557 * up iconified. Just don't write code that crashes if not.
5559 * It's permitted to call this function before showing a window,
5560 * in which case the window will be iconified before it ever appears
5563 * You can track iconification via the "window_state_event" signal
5568 gtk_window_iconify (GtkWindow *window)
5571 GdkWindow *toplevel;
5573 g_return_if_fail (GTK_IS_WINDOW (window));
5575 widget = GTK_WIDGET (window);
5577 window->iconify_initially = TRUE;
5580 toplevel = window->frame;
5582 toplevel = widget->window;
5584 if (toplevel != NULL)
5585 gdk_window_iconify (toplevel);
5589 * gtk_window_deiconify:
5590 * @window: a #GtkWindow
5592 * Asks to deiconify (i.e. unminimize) the specified @window. Note
5593 * that you shouldn't assume the window is definitely deiconified
5594 * afterward, because other entities (e.g. the user or <link
5595 * linkend="gtk-X11-arch">window manager</link>) could iconify it
5596 * again before your code which assumes deiconification gets to run.
5598 * You can track iconification via the "window_state_event" signal
5602 gtk_window_deiconify (GtkWindow *window)
5605 GdkWindow *toplevel;
5607 g_return_if_fail (GTK_IS_WINDOW (window));
5609 widget = GTK_WIDGET (window);
5611 window->iconify_initially = FALSE;
5614 toplevel = window->frame;
5616 toplevel = widget->window;
5618 if (toplevel != NULL)
5619 gdk_window_deiconify (toplevel);
5624 * @window: a #GtkWindow
5626 * Asks to stick @window, which means that it will appear on all user
5627 * desktops. Note that you shouldn't assume the window is definitely
5628 * stuck afterward, because other entities (e.g. the user or <link
5629 * linkend="gtk-X11-arch">window manager</link>) could unstick it
5630 * again, and some window managers do not support sticking
5631 * windows. But normally the window will end up stuck. Just don't
5632 * write code that crashes if not.
5634 * It's permitted to call this function before showing a window.
5636 * You can track stickiness via the "window_state_event" signal
5641 gtk_window_stick (GtkWindow *window)
5644 GdkWindow *toplevel;
5646 g_return_if_fail (GTK_IS_WINDOW (window));
5648 widget = GTK_WIDGET (window);
5650 window->stick_initially = TRUE;
5653 toplevel = window->frame;
5655 toplevel = widget->window;
5657 if (toplevel != NULL)
5658 gdk_window_stick (toplevel);
5662 * gtk_window_unstick:
5663 * @window: a #GtkWindow
5665 * Asks to unstick @window, which means that it will appear on only
5666 * one of the user's desktops. Note that you shouldn't assume the
5667 * window is definitely unstuck afterward, because other entities
5668 * (e.g. the user or <link linkend="gtk-X11-arch">window
5669 * manager</link>) could stick it again. But normally the window will
5670 * end up stuck. Just don't write code that crashes if not.
5672 * You can track stickiness via the "window_state_event" signal
5677 gtk_window_unstick (GtkWindow *window)
5680 GdkWindow *toplevel;
5682 g_return_if_fail (GTK_IS_WINDOW (window));
5684 widget = GTK_WIDGET (window);
5686 window->stick_initially = FALSE;
5689 toplevel = window->frame;
5691 toplevel = widget->window;
5693 if (toplevel != NULL)
5694 gdk_window_unstick (toplevel);
5698 * gtk_window_maximize:
5699 * @window: a #GtkWindow
5701 * Asks to maximize @window, so that it becomes full-screen. Note that
5702 * you shouldn't assume the window is definitely maximized afterward,
5703 * because other entities (e.g. the user or <link
5704 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
5705 * again, and not all window managers support maximization. But
5706 * normally the window will end up maximized. Just don't write code
5707 * that crashes if not.
5709 * It's permitted to call this function before showing a window,
5710 * in which case the window will be maximized when it appears onscreen
5713 * You can track maximization via the "window_state_event" signal
5718 gtk_window_maximize (GtkWindow *window)
5721 GdkWindow *toplevel;
5723 g_return_if_fail (GTK_IS_WINDOW (window));
5725 widget = GTK_WIDGET (window);
5727 window->maximize_initially = TRUE;
5730 toplevel = window->frame;
5732 toplevel = widget->window;
5734 if (toplevel != NULL)
5735 gdk_window_maximize (toplevel);
5739 * gtk_window_unmaximize:
5740 * @window: a #GtkWindow
5742 * Asks to unmaximize @window. Note that you shouldn't assume the
5743 * window is definitely unmaximized afterward, because other entities
5744 * (e.g. the user or <link linkend="gtk-X11-arch">window
5745 * manager</link>) could maximize it again, and not all window
5746 * managers honor requests to unmaximize. But normally the window will
5747 * end up unmaximized. Just don't write code that crashes if not.
5749 * You can track maximization via the "window_state_event" signal
5754 gtk_window_unmaximize (GtkWindow *window)
5757 GdkWindow *toplevel;
5759 g_return_if_fail (GTK_IS_WINDOW (window));
5761 widget = GTK_WIDGET (window);
5763 window->maximize_initially = FALSE;
5766 toplevel = window->frame;
5768 toplevel = widget->window;
5770 if (toplevel != NULL)
5771 gdk_window_unmaximize (toplevel);
5775 * gtk_window_fullscreen:
5776 * @window: a #GtkWindow
5778 * Asks to place @window in the fullscreen state. Note that you
5779 * shouldn't assume the window is definitely full screen afterward,
5780 * because other entities (e.g. the user or <link
5781 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
5782 * again, and not all window managers honor requests to fullscreen
5783 * windows. But normally the window will end up fullscreen. Just
5784 * don't write code that crashes if not.
5786 * You can track the fullscreen state via the "window_state_event" signal
5792 gtk_window_fullscreen (GtkWindow *window)
5795 GdkWindow *toplevel;
5796 GtkWindowPrivate *priv;
5798 g_return_if_fail (GTK_IS_WINDOW (window));
5800 widget = GTK_WIDGET (window);
5801 priv = gtk_window_get_private (window);
5803 priv->fullscreen_initially = TRUE;
5806 toplevel = window->frame;
5808 toplevel = widget->window;
5810 if (toplevel != NULL)
5811 gdk_window_fullscreen (toplevel);
5815 * gtk_window_unfullscreen:
5816 * @window: a #GtkWindow
5818 * Asks to toggle off the fullscreen state for @window. Note that you
5819 * shouldn't assume the window is definitely not full screen
5820 * afterward, because other entities (e.g. the user or <link
5821 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
5822 * again, and not all window managers honor requests to unfullscreen
5823 * windows. But normally the window will end up restored to its normal
5824 * state. Just don't write code that crashes if not.
5826 * You can track the fullscreen state via the "window_state_event" signal
5832 gtk_window_unfullscreen (GtkWindow *window)
5835 GdkWindow *toplevel;
5836 GtkWindowPrivate *priv;
5838 g_return_if_fail (GTK_IS_WINDOW (window));
5840 widget = GTK_WIDGET (window);
5841 priv = gtk_window_get_private (window);
5843 priv->fullscreen_initially = FALSE;
5846 toplevel = window->frame;
5848 toplevel = widget->window;
5850 if (toplevel != NULL)
5851 gdk_window_unfullscreen (toplevel);
5856 * gtk_window_set_resizable:
5857 * @window: a #GtkWindow
5858 * @resizable: %TRUE if the user can resize this window
5860 * Sets whether the user can resize a window. Windows are user resizable
5864 gtk_window_set_resizable (GtkWindow *window,
5867 g_return_if_fail (GTK_IS_WINDOW (window));
5869 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5873 * gtk_window_get_resizable:
5874 * @window: a #GtkWindow
5876 * Gets the value set by gtk_window_set_resizable().
5878 * Return value: %TRUE if the user can resize the window
5881 gtk_window_get_resizable (GtkWindow *window)
5883 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5885 /* allow_grow is most likely to indicate the semantic concept we
5886 * mean by "resizable" (and will be a reliable indicator if
5887 * set_policy() hasn't been called)
5889 return window->allow_grow;
5893 * gtk_window_set_gravity:
5894 * @window: a #GtkWindow
5895 * @gravity: window gravity
5897 * Window gravity defines the meaning of coordinates passed to
5898 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5901 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5902 * typically "do what you mean."
5906 gtk_window_set_gravity (GtkWindow *window,
5909 g_return_if_fail (GTK_IS_WINDOW (window));
5911 if (gravity != window->gravity)
5913 window->gravity = gravity;
5915 /* gtk_window_move_resize() will adapt gravity
5917 gtk_widget_queue_resize (GTK_WIDGET (window));
5922 * gtk_window_get_gravity:
5923 * @window: a #GtkWindow
5925 * Gets the value set by gtk_window_set_gravity().
5927 * Return value: window gravity
5930 gtk_window_get_gravity (GtkWindow *window)
5932 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5934 return window->gravity;
5938 * gtk_window_begin_resize_drag:
5939 * @window: a #GtkWindow
5940 * @button: mouse button that initiated the drag
5941 * @edge: position of the resize control
5942 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5943 * @root_y: Y position where the user clicked to initiate the drag
5944 * @timestamp: timestamp from the click event that initiated the drag
5946 * Starts resizing a window. This function is used if an application
5947 * has window resizing controls. When GDK can support it, the resize
5948 * will be done using the standard mechanism for the <link
5949 * linkend="gtk-X11-arch">window manager</link> or windowing
5950 * system. Otherwise, GDK will try to emulate window resizing,
5951 * potentially not all that well, depending on the windowing system.
5955 gtk_window_begin_resize_drag (GtkWindow *window,
5963 GdkWindow *toplevel;
5965 g_return_if_fail (GTK_IS_WINDOW (window));
5966 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5968 widget = GTK_WIDGET (window);
5971 toplevel = window->frame;
5973 toplevel = widget->window;
5975 gdk_window_begin_resize_drag (toplevel,
5982 * gtk_window_get_frame_dimensions:
5983 * @window: a #GtkWindow
5984 * @left: location to store the width of the frame at the left, or %NULL
5985 * @top: location to store the height of the frame at the top, or %NULL
5986 * @right: location to store the width of the frame at the returns, or %NULL
5987 * @bottom: location to store the height of the frame at the bottom, or %NULL
5989 * (Note: this is a special-purpose function intended for the
5990 * framebuffer port; see gtk_window_set_has_frame(). It will not
5991 * return the size of the window border drawn by the <link
5992 * linkend="gtk-X11-arch">window manager</link>, which is the normal
5993 * case when using a windowing system. See
5994 * gdk_window_get_frame_extents() to get the standard window border
5997 * Retrieves the dimensions of the frame window for this toplevel.
5998 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
6001 gtk_window_get_frame_dimensions (GtkWindow *window,
6007 g_return_if_fail (GTK_IS_WINDOW (window));
6010 *left = window->frame_left;
6012 *top = window->frame_top;
6014 *right = window->frame_right;
6016 *bottom = window->frame_bottom;
6020 * gtk_window_begin_move_drag:
6021 * @window: a #GtkWindow
6022 * @button: mouse button that initiated the drag
6023 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6024 * @root_y: Y position where the user clicked to initiate the drag
6025 * @timestamp: timestamp from the click event that initiated the drag
6027 * Starts moving a window. This function is used if an application has
6028 * window movement grips. When GDK can support it, the window movement
6029 * will be done using the standard mechanism for the <link
6030 * linkend="gtk-X11-arch">window manager</link> or windowing
6031 * system. Otherwise, GDK will try to emulate window movement,
6032 * potentially not all that well, depending on the windowing system.
6036 gtk_window_begin_move_drag (GtkWindow *window,
6043 GdkWindow *toplevel;
6045 g_return_if_fail (GTK_IS_WINDOW (window));
6046 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6048 widget = GTK_WIDGET (window);
6051 toplevel = window->frame;
6053 toplevel = widget->window;
6055 gdk_window_begin_move_drag (toplevel,
6062 * gtk_window_set_screen:
6063 * @window: a #GtkWindow.
6064 * @screen: a #GdkScreen.
6066 * Sets the #GdkScreen where the @window is displayed; if
6067 * the window is already mapped, it will be unmapped, and
6068 * then remapped on the new screen.
6073 gtk_window_set_screen (GtkWindow *window,
6077 GdkScreen *previous_screen;
6078 gboolean was_mapped;
6080 g_return_if_fail (GTK_IS_WINDOW (window));
6081 g_return_if_fail (GDK_IS_SCREEN (screen));
6083 if (screen == window->screen)
6086 widget = GTK_WIDGET (window);
6088 previous_screen = window->screen;
6089 was_mapped = GTK_WIDGET_MAPPED (widget);
6092 gtk_widget_unmap (widget);
6093 if (GTK_WIDGET_REALIZED (widget))
6094 gtk_widget_unrealize (widget);
6096 gtk_window_free_key_hash (window);
6097 window->screen = screen;
6098 gtk_widget_reset_rc_styles (widget);
6099 if (screen != previous_screen)
6100 _gtk_widget_propagate_screen_changed (widget, previous_screen);
6101 g_object_notify (G_OBJECT (window), "screen");
6104 gtk_widget_map (widget);
6108 gtk_window_check_screen (GtkWindow *window)
6111 return window->screen;
6114 g_warning ("Screen for GtkWindow not set; you must always set\n"
6115 "a screen for a GtkWindow before using the window");
6121 * gtk_window_get_screen:
6122 * @window: a #GtkWindow.
6124 * Returns the #GdkScreen associated with @window.
6126 * Return value: a #GdkScreen.
6131 gtk_window_get_screen (GtkWindow *window)
6133 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6135 return window->screen;
6140 gtk_window_group_class_init (GtkWindowGroupClass *klass)
6145 gtk_window_group_get_type (void)
6147 static GType window_group_type = 0;
6149 if (!window_group_type)
6151 static const GTypeInfo window_group_info =
6153 sizeof (GtkWindowGroupClass),
6154 NULL, /* base_init */
6155 NULL, /* base_finalize */
6156 (GClassInitFunc) gtk_window_group_class_init,
6157 NULL, /* class_finalize */
6158 NULL, /* class_data */
6159 sizeof (GtkWindowGroup),
6160 16, /* n_preallocs */
6161 (GInstanceInitFunc) NULL,
6164 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
6167 return window_group_type;
6171 * gtk_window_group_new:
6173 * Creates a new #GtkWindowGroup object. Grabs added with
6174 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
6176 * Return value: a new #GtkWindowGroup.
6179 gtk_window_group_new (void)
6181 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
6185 window_group_cleanup_grabs (GtkWindowGroup *group,
6189 GSList *to_remove = NULL;
6191 tmp_list = group->grabs;
6194 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
6195 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
6196 tmp_list = tmp_list->next;
6201 gtk_grab_remove (to_remove->data);
6202 g_object_unref (to_remove->data);
6203 to_remove = g_slist_delete_link (to_remove, to_remove);
6208 * gtk_window_group_add_window:
6209 * @window_group: a #GtkWindowGroup
6210 * @window: the #GtkWindow to add
6212 * Adds a window to a #GtkWindowGroup.
6215 gtk_window_group_add_window (GtkWindowGroup *window_group,
6218 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6219 g_return_if_fail (GTK_IS_WINDOW (window));
6221 if (window->group != window_group)
6223 g_object_ref (window);
6224 g_object_ref (window_group);
6227 gtk_window_group_remove_window (window->group, window);
6229 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
6231 window->group = window_group;
6233 g_object_unref (window);
6238 * gtk_window_group_remove_window:
6239 * @window_group: a #GtkWindowGroup
6240 * @window: the #GtkWindow to remove
6242 * Removes a window from a #GtkWindowGroup.
6245 gtk_window_group_remove_window (GtkWindowGroup *window_group,
6248 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6249 g_return_if_fail (GTK_IS_WIDGET (window));
6250 g_return_if_fail (window->group == window_group);
6252 g_object_ref (window);
6254 window_group_cleanup_grabs (window_group, window);
6255 window->group = NULL;
6257 g_object_unref (window_group);
6258 g_object_unref (window);
6261 /* Return the group for the window or the default group
6264 _gtk_window_get_group (GtkWindow *window)
6266 if (window && window->group)
6267 return window->group;
6270 static GtkWindowGroup *default_group = NULL;
6273 default_group = gtk_window_group_new ();
6275 return default_group;
6281 Derived from XParseGeometry() in XFree86
6283 Copyright 1985, 1986, 1987,1998 The Open Group
6285 All Rights Reserved.
6287 The above copyright notice and this permission notice shall be included
6288 in all copies or substantial portions of the Software.
6290 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
6291 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6292 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6293 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
6294 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
6295 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
6296 OTHER DEALINGS IN THE SOFTWARE.
6298 Except as contained in this notice, the name of The Open Group shall
6299 not be used in advertising or otherwise to promote the sale, use or
6300 other dealings in this Software without prior written authorization
6301 from The Open Group.
6306 * XParseGeometry parses strings of the form
6307 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
6308 * width, height, xoffset, and yoffset are unsigned integers.
6309 * Example: "=80x24+300-49"
6310 * The equal sign is optional.
6311 * It returns a bitmask that indicates which of the four values
6312 * were actually found in the string. For each value found,
6313 * the corresponding argument is updated; for each value
6314 * not found, the corresponding argument is left unchanged.
6317 /* The following code is from Xlib, and is minimally modified, so we
6318 * can track any upstream changes if required. Don't change this
6319 * code. Or if you do, put in a huge comment marking which thing
6324 read_int (gchar *string,
6332 else if (*string == '-')
6338 for (; (*string >= '0') && (*string <= '9'); string++)
6340 result = (result * 10) + (*string - '0');
6352 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
6353 * value (x, y, width, height) was found in the parsed string.
6355 #define NoValue 0x0000
6356 #define XValue 0x0001
6357 #define YValue 0x0002
6358 #define WidthValue 0x0004
6359 #define HeightValue 0x0008
6360 #define AllValues 0x000F
6361 #define XNegative 0x0010
6362 #define YNegative 0x0020
6364 /* Try not to reformat/modify, so we can compare/sync with X sources */
6366 gtk_XParseGeometry (const char *string,
6369 unsigned int *width,
6370 unsigned int *height)
6374 unsigned int tempWidth, tempHeight;
6376 char *nextCharacter;
6378 /* These initializations are just to silence gcc */
6384 if ( (string == NULL) || (*string == '\0')) return(mask);
6386 string++; /* ignore possible '=' at beg of geometry spec */
6388 strind = (char *)string;
6389 if (*strind != '+' && *strind != '-' && *strind != 'x') {
6390 tempWidth = read_int(strind, &nextCharacter);
6391 if (strind == nextCharacter)
6393 strind = nextCharacter;
6397 if (*strind == 'x' || *strind == 'X') {
6399 tempHeight = read_int(strind, &nextCharacter);
6400 if (strind == nextCharacter)
6402 strind = nextCharacter;
6403 mask |= HeightValue;
6406 if ((*strind == '+') || (*strind == '-')) {
6407 if (*strind == '-') {
6409 tempX = -read_int(strind, &nextCharacter);
6410 if (strind == nextCharacter)
6412 strind = nextCharacter;
6418 tempX = read_int(strind, &nextCharacter);
6419 if (strind == nextCharacter)
6421 strind = nextCharacter;
6424 if ((*strind == '+') || (*strind == '-')) {
6425 if (*strind == '-') {
6427 tempY = -read_int(strind, &nextCharacter);
6428 if (strind == nextCharacter)
6430 strind = nextCharacter;
6437 tempY = read_int(strind, &nextCharacter);
6438 if (strind == nextCharacter)
6440 strind = nextCharacter;
6446 /* If strind isn't at the end of the string the it's an invalid
6447 geometry specification. */
6449 if (*strind != '\0') return (0);
6455 if (mask & WidthValue)
6457 if (mask & HeightValue)
6458 *height = tempHeight;
6463 * gtk_window_parse_geometry:
6464 * @window: a #GtkWindow
6465 * @geometry: geometry string
6467 * Parses a standard X Window System geometry string - see the
6468 * manual page for X (type 'man X') for details on this.
6469 * gtk_window_parse_geometry() does work on all GTK+ ports
6470 * including Win32 but is primarily intended for an X environment.
6472 * If either a size or a position can be extracted from the
6473 * geometry string, gtk_window_parse_geometry() returns %TRUE
6474 * and calls gtk_window_set_default_size() and/or gtk_window_move()
6475 * to resize/move the window.
6477 * If gtk_window_parse_geometry() returns %TRUE, it will also
6478 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
6479 * indicating to the window manager that the size/position of
6480 * the window was user-specified. This causes most window
6481 * managers to honor the geometry.
6483 * Return value: %TRUE if string was parsed successfully
6486 gtk_window_parse_geometry (GtkWindow *window,
6487 const gchar *geometry)
6492 gboolean size_set, pos_set;
6495 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6496 g_return_val_if_fail (geometry != NULL, FALSE);
6498 screen = gtk_window_check_screen (window);
6500 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
6502 if ((result & WidthValue) == 0 ||
6505 if ((result & HeightValue) == 0 ||
6510 if ((result & WidthValue) || (result & HeightValue))
6512 gtk_window_set_default_size_internal (window, TRUE, w, TRUE, h, TRUE);
6516 gtk_window_get_size (window, &w, &h);
6518 grav = GDK_GRAVITY_NORTH_WEST;
6520 if ((result & XNegative) && (result & YNegative))
6521 grav = GDK_GRAVITY_SOUTH_EAST;
6522 else if (result & XNegative)
6523 grav = GDK_GRAVITY_NORTH_EAST;
6524 else if (result & YNegative)
6525 grav = GDK_GRAVITY_SOUTH_WEST;
6527 if ((result & XValue) == 0)
6530 if ((result & YValue) == 0)
6533 if (grav == GDK_GRAVITY_SOUTH_WEST ||
6534 grav == GDK_GRAVITY_SOUTH_EAST)
6535 y = gdk_screen_get_height (screen) - h + y;
6537 if (grav == GDK_GRAVITY_SOUTH_EAST ||
6538 grav == GDK_GRAVITY_NORTH_EAST)
6539 x = gdk_screen_get_width (screen) - w + x;
6541 /* we don't let you put a window offscreen; maybe some people would
6542 * prefer to be able to, but it's kind of a bogus thing to do.
6551 if ((result & XValue) || (result & YValue))
6553 gtk_window_set_gravity (window, grav);
6554 gtk_window_move (window, x, y);
6558 if (size_set || pos_set)
6560 /* Set USSize, USPosition hints */
6561 GtkWindowGeometryInfo *info;
6563 info = gtk_window_get_geometry_info (window, TRUE);
6566 info->mask |= GDK_HINT_USER_POS;
6568 info->mask |= GDK_HINT_USER_SIZE;
6575 gtk_window_mnemonic_hash_foreach (gpointer key,
6581 GtkWindowKeysForeachFunc func;
6585 GtkWindowMnemonic *mnemonic = value;
6587 if (mnemonic->window == info->window)
6588 (*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
6592 _gtk_window_keys_foreach (GtkWindow *window,
6593 GtkWindowKeysForeachFunc func,
6600 GtkWindowKeysForeachFunc func;
6604 info.window = window;
6606 info.func_data = func_data;
6608 g_hash_table_foreach (mnemonic_hash_table,
6609 gtk_window_mnemonic_hash_foreach,
6612 groups = gtk_accel_groups_from_object (G_OBJECT (window));
6615 GtkAccelGroup *group = groups->data;
6618 for (i = 0; i < group->n_accels; i++)
6620 GtkAccelKey *key = &group->priv_accels[i].key;
6623 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
6626 groups = groups->next;
6631 gtk_window_keys_changed (GtkWindow *window)
6633 gtk_window_free_key_hash (window);
6634 gtk_window_get_key_hash (window);
6637 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
6639 struct _GtkWindowKeyEntry
6643 gboolean is_mnemonic;
6647 add_to_key_hash (GtkWindow *window,
6649 GdkModifierType modifiers,
6650 gboolean is_mnemonic,
6653 GtkKeyHash *key_hash = data;
6655 GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
6657 entry->keyval = keyval;
6658 entry->modifiers = modifiers;
6659 entry->is_mnemonic = is_mnemonic;
6661 /* GtkAccelGroup stores lowercased accelerators. To deal
6662 * with this, if <Shift> was specified, uppercase.
6664 if (modifiers & GDK_SHIFT_MASK)
6666 if (keyval == GDK_Tab)
6667 keyval = GDK_ISO_Left_Tab;
6669 keyval = gdk_keyval_to_upper (keyval);
6672 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
6676 gtk_window_get_key_hash (GtkWindow *window)
6678 GdkScreen *screen = gtk_window_check_screen (window);
6679 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6684 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
6685 (GDestroyNotify)g_free);
6686 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
6687 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
6693 gtk_window_free_key_hash (GtkWindow *window)
6695 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6698 _gtk_key_hash_free (key_hash);
6699 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
6704 * _gtk_window_activate_key:
6705 * @window: a #GtkWindow
6706 * @event: a #GdkEventKey
6708 * Activates mnemonics and accelerators for this #GtKWindow
6710 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
6713 _gtk_window_activate_key (GtkWindow *window,
6716 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6717 GtkWindowKeyEntry *found_entry = NULL;
6721 gtk_window_keys_changed (window);
6722 key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6727 GSList *entries = _gtk_key_hash_lookup (key_hash,
6728 event->hardware_keycode,
6729 event->state & gtk_accelerator_get_default_mod_mask (),
6733 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
6735 GtkWindowKeyEntry *entry = tmp_list->data;
6736 if (entry->is_mnemonic)
6738 found_entry = entry;
6743 if (!found_entry && entries)
6744 found_entry = entries->data;
6746 g_slist_free (entries);
6751 if (found_entry->is_mnemonic)
6752 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
6754 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
6761 window_update_has_focus (GtkWindow *window)
6763 GtkWidget *widget = GTK_WIDGET (window);
6764 gboolean has_focus = window->has_toplevel_focus && window->is_active;
6766 if (has_focus != window->has_focus)
6768 window->has_focus = has_focus;
6772 if (window->focus_widget &&
6773 window->focus_widget != widget &&
6774 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6775 do_focus_change (window->focus_widget, TRUE);
6779 if (window->focus_widget &&
6780 window->focus_widget != widget &&
6781 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6782 do_focus_change (window->focus_widget, FALSE);
6788 * _gtk_window_set_is_active:
6789 * @window: a #GtkWindow
6790 * @is_active: %TRUE if the window is in the currently active toplevel
6792 * Internal function that sets whether the #GtkWindow is part
6793 * of the currently active toplevel window (taking into account inter-process
6797 _gtk_window_set_is_active (GtkWindow *window,
6800 g_return_if_fail (GTK_IS_WINDOW (window));
6802 is_active = is_active != FALSE;
6804 if (is_active != window->is_active)
6806 window->is_active = is_active;
6807 window_update_has_focus (window);
6809 g_object_notify (G_OBJECT (window), "is_active");
6814 * _gtk_window_set_has_toplevel_focus:
6815 * @window: a #GtkWindow
6816 * @has_toplevel_focus: %TRUE if the in
6818 * Internal function that sets whether the keyboard focus for the
6819 * toplevel window (taking into account inter-process embedding.)
6822 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
6823 gboolean has_toplevel_focus)
6825 g_return_if_fail (GTK_IS_WINDOW (window));
6827 has_toplevel_focus = has_toplevel_focus != FALSE;
6829 if (has_toplevel_focus != window->has_toplevel_focus)
6831 window->has_toplevel_focus = has_toplevel_focus;
6832 window_update_has_focus (window);
6834 g_object_notify (G_OBJECT (window), "has_toplevel_focus");
6839 * gtk_window_set_auto_startup_notification:
6840 * @setting: %TRUE to automatically do startup notification
6842 * By default, after showing the first #GtkWindow for each #GdkScreen,
6843 * GTK+ calls gdk_screen_notify_startup_complete(). Call this
6844 * function to disable the automatic startup notification. You might
6845 * do this if your first window is a splash screen, and you want to
6846 * delay notification until after your real main window has been
6847 * shown, for example.
6849 * In that example, you would disable startup notification
6850 * temporarily, show your splash screen, then re-enable it so that
6851 * showing the main window would automatically result in notification.
6856 gtk_window_set_auto_startup_notification (gboolean setting)
6858 disable_startup_notification = !setting;