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 "gtksignal.h"
35 #include "gtkwindow.h"
36 #include "gtkwindow-decorate.h"
37 #include "gtkbindings.h"
38 #include "gtkkeyhash.h"
40 #include "gtkiconfactory.h"
42 #include "gtkmarshalers.h"
70 PROP_DESTROY_WITH_PARENT,
74 /* Readonly properties */
76 PROP_HAS_TOPLEVEL_FOCUS,
84 GdkPixmap *icon_pixmap;
87 guint using_default_icon : 1;
88 guint using_parent_icon : 1;
92 GdkGeometry geometry; /* Last set of geometry hints we set */
94 GdkRectangle configure_request;
95 } GtkWindowLastGeometryInfo;
97 struct _GtkWindowGeometryInfo
99 /* Properties that the app has set on the window
101 GdkGeometry geometry; /* Geometry hints */
103 GtkWidget *widget; /* subwidget to which hints apply */
104 /* from last gtk_window_resize () - if > 0, indicates that
105 * we should resize to this size.
110 /* From last gtk_window_move () prior to mapping -
111 * only used if initial_pos_set
116 /* Default size - used only the FIRST time we map a window,
121 /* whether to use initial_x, initial_y */
122 guint initial_pos_set : 1;
123 /* CENTER_ALWAYS or other position constraint changed since
124 * we sent the last configure request.
126 guint position_constraints_changed : 1;
128 /* if true, default_width, height come from gtk_window_parse_geometry,
129 * and thus should be multiplied by the increments and affect the
130 * geometry widget only
132 guint default_is_geometry : 1;
134 GtkWindowLastGeometryInfo last;
145 static void gtk_window_class_init (GtkWindowClass *klass);
146 static void gtk_window_init (GtkWindow *window);
147 static void gtk_window_dispose (GObject *object);
148 static void gtk_window_destroy (GtkObject *object);
149 static void gtk_window_finalize (GObject *object);
150 static void gtk_window_show (GtkWidget *widget);
151 static void gtk_window_hide (GtkWidget *widget);
152 static void gtk_window_map (GtkWidget *widget);
153 static void gtk_window_unmap (GtkWidget *widget);
154 static void gtk_window_realize (GtkWidget *widget);
155 static void gtk_window_unrealize (GtkWidget *widget);
156 static void gtk_window_size_request (GtkWidget *widget,
157 GtkRequisition *requisition);
158 static void gtk_window_size_allocate (GtkWidget *widget,
159 GtkAllocation *allocation);
160 static gint gtk_window_event (GtkWidget *widget,
162 static gboolean gtk_window_frame_event (GtkWindow *window,
164 static gint gtk_window_configure_event (GtkWidget *widget,
165 GdkEventConfigure *event);
166 static gint gtk_window_key_press_event (GtkWidget *widget,
168 static gint gtk_window_key_release_event (GtkWidget *widget,
170 static gint gtk_window_enter_notify_event (GtkWidget *widget,
171 GdkEventCrossing *event);
172 static gint gtk_window_leave_notify_event (GtkWidget *widget,
173 GdkEventCrossing *event);
174 static gint gtk_window_focus_in_event (GtkWidget *widget,
175 GdkEventFocus *event);
176 static gint gtk_window_focus_out_event (GtkWidget *widget,
177 GdkEventFocus *event);
178 static gint gtk_window_client_event (GtkWidget *widget,
179 GdkEventClient *event);
180 static void gtk_window_check_resize (GtkContainer *container);
181 static gint gtk_window_focus (GtkWidget *widget,
182 GtkDirectionType direction);
183 static void gtk_window_real_set_focus (GtkWindow *window,
186 static void gtk_window_real_activate_default (GtkWindow *window);
187 static void gtk_window_real_activate_focus (GtkWindow *window);
188 static void gtk_window_move_focus (GtkWindow *window,
189 GtkDirectionType dir);
190 static void gtk_window_keys_changed (GtkWindow *window);
191 static void gtk_window_read_rcfiles (GtkWidget *widget,
192 GdkEventClient *event);
193 static void gtk_window_paint (GtkWidget *widget,
195 static gint gtk_window_expose (GtkWidget *widget,
196 GdkEventExpose *event);
197 static void gtk_window_unset_transient_for (GtkWindow *window);
198 static void gtk_window_transient_parent_realized (GtkWidget *parent,
200 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
203 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
206 static void gtk_window_move_resize (GtkWindow *window);
207 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
209 GdkGeometry *geometry_b,
211 static void gtk_window_constrain_size (GtkWindow *window,
212 GdkGeometry *geometry,
218 static void gtk_window_constrain_position (GtkWindow *window,
223 static void gtk_window_compute_hints (GtkWindow *window,
224 GdkGeometry *new_geometry,
226 static void gtk_window_compute_configure_request (GtkWindow *window,
227 GdkRectangle *request,
228 GdkGeometry *geometry,
231 static void gtk_window_set_default_size_internal (GtkWindow *window,
232 gboolean change_width,
234 gboolean change_height,
236 gboolean is_geometry);
238 static void gtk_window_realize_icon (GtkWindow *window);
239 static void gtk_window_unrealize_icon (GtkWindow *window);
241 static void gtk_window_notify_keys_changed (GtkWindow *window);
242 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
243 static void gtk_window_free_key_hash (GtkWindow *window);
245 static GSList *toplevel_list = NULL;
246 static GHashTable *mnemonic_hash_table = NULL;
247 static GtkBinClass *parent_class = NULL;
248 static guint window_signals[LAST_SIGNAL] = { 0 };
249 static GList *default_icon_list = NULL;
250 static guint default_icon_serial = 0;
252 static void gtk_window_set_property (GObject *object,
256 static void gtk_window_get_property (GObject *object,
263 mnemonic_hash (gconstpointer key)
265 const GtkWindowMnemonic *k;
268 k = (GtkWindowMnemonic *)key;
270 h = (gulong) k->window;
271 h ^= k->keyval << 16;
272 h ^= k->keyval >> 16;
278 mnemonic_equal (gconstpointer a, gconstpointer b)
280 const GtkWindowMnemonic *ka;
281 const GtkWindowMnemonic *kb;
283 ka = (GtkWindowMnemonic *)a;
284 kb = (GtkWindowMnemonic *)b;
287 (ka->window == kb->window) &&
288 (ka->keyval == kb->keyval);
292 gtk_window_get_type (void)
294 static GtkType window_type = 0;
298 static const GtkTypeInfo window_info =
302 sizeof (GtkWindowClass),
303 (GtkClassInitFunc) gtk_window_class_init,
304 (GtkObjectInitFunc) gtk_window_init,
305 /* reserved_1 */ NULL,
306 /* reserved_2 */ NULL,
307 (GtkClassInitFunc) NULL,
310 window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
317 add_tab_bindings (GtkBindingSet *binding_set,
318 GdkModifierType modifiers,
319 GtkDirectionType direction)
321 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
323 GTK_TYPE_DIRECTION_TYPE, direction);
324 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
326 GTK_TYPE_DIRECTION_TYPE, direction);
330 add_arrow_bindings (GtkBindingSet *binding_set,
332 GtkDirectionType direction)
334 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
336 gtk_binding_entry_add_signal (binding_set, keysym, 0,
338 GTK_TYPE_DIRECTION_TYPE, direction);
339 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
341 GTK_TYPE_DIRECTION_TYPE, direction);
342 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
344 GTK_TYPE_DIRECTION_TYPE, direction);
345 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
347 GTK_TYPE_DIRECTION_TYPE, direction);
352 gtk_window_class_init (GtkWindowClass *klass)
354 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
355 GtkObjectClass *object_class;
356 GtkWidgetClass *widget_class;
357 GtkContainerClass *container_class;
358 GtkBindingSet *binding_set;
360 object_class = (GtkObjectClass*) klass;
361 widget_class = (GtkWidgetClass*) klass;
362 container_class = (GtkContainerClass*) klass;
364 parent_class = gtk_type_class (gtk_bin_get_type ());
366 mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
368 gobject_class->dispose = gtk_window_dispose;
369 gobject_class->finalize = gtk_window_finalize;
371 gobject_class->set_property = gtk_window_set_property;
372 gobject_class->get_property = gtk_window_get_property;
374 object_class->destroy = gtk_window_destroy;
376 widget_class->show = gtk_window_show;
377 widget_class->hide = gtk_window_hide;
378 widget_class->map = gtk_window_map;
379 widget_class->unmap = gtk_window_unmap;
380 widget_class->realize = gtk_window_realize;
381 widget_class->unrealize = gtk_window_unrealize;
382 widget_class->size_request = gtk_window_size_request;
383 widget_class->size_allocate = gtk_window_size_allocate;
384 widget_class->configure_event = gtk_window_configure_event;
385 widget_class->key_press_event = gtk_window_key_press_event;
386 widget_class->key_release_event = gtk_window_key_release_event;
387 widget_class->enter_notify_event = gtk_window_enter_notify_event;
388 widget_class->leave_notify_event = gtk_window_leave_notify_event;
389 widget_class->focus_in_event = gtk_window_focus_in_event;
390 widget_class->focus_out_event = gtk_window_focus_out_event;
391 widget_class->client_event = gtk_window_client_event;
392 widget_class->focus = gtk_window_focus;
394 widget_class->expose_event = gtk_window_expose;
396 container_class->check_resize = gtk_window_check_resize;
398 klass->set_focus = gtk_window_real_set_focus;
399 klass->frame_event = gtk_window_frame_event;
401 klass->activate_default = gtk_window_real_activate_default;
402 klass->activate_focus = gtk_window_real_activate_focus;
403 klass->move_focus = gtk_window_move_focus;
404 klass->keys_changed = gtk_window_keys_changed;
407 g_object_class_install_property (gobject_class,
409 g_param_spec_enum ("type",
411 _("The type of the window"),
412 GTK_TYPE_WINDOW_TYPE,
414 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
417 g_object_class_install_property (gobject_class,
419 g_param_spec_string ("title",
421 _("The title of the window"),
425 g_object_class_install_property (gobject_class,
427 g_param_spec_boolean ("allow_shrink",
429 /* xgettext:no-c-format */
430 _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea."),
434 g_object_class_install_property (gobject_class,
436 g_param_spec_boolean ("allow_grow",
438 _("If TRUE, users can expand the window beyond its minimum size."),
442 g_object_class_install_property (gobject_class,
444 g_param_spec_boolean ("resizable",
446 _("If TRUE, users can resize the window."),
450 g_object_class_install_property (gobject_class,
452 g_param_spec_boolean ("modal",
454 _("If TRUE, the window is modal (other windows are not usable while this one is up)."),
458 g_object_class_install_property (gobject_class,
460 g_param_spec_enum ("window_position",
461 _("Window Position"),
462 _("The initial position of the window."),
463 GTK_TYPE_WINDOW_POSITION,
467 g_object_class_install_property (gobject_class,
469 g_param_spec_int ("default_width",
471 _("The default width of the window, used when initially showing the window."),
477 g_object_class_install_property (gobject_class,
479 g_param_spec_int ("default_height",
481 _("The default height of the window, used when initially showing the window."),
487 g_object_class_install_property (gobject_class,
488 PROP_DESTROY_WITH_PARENT,
489 g_param_spec_boolean ("destroy_with_parent",
490 _("Destroy with Parent"),
491 _("If this window should be destroyed when the parent is destroyed"),
495 g_object_class_install_property (gobject_class,
497 g_param_spec_object ("icon",
499 _("Icon for this window"),
503 g_object_class_install_property (gobject_class,
505 g_param_spec_object ("screen",
507 _("The screen where this window will be displayed."),
511 g_object_class_install_property (gobject_class,
513 g_param_spec_boolean ("is_active",
515 _("Whether the toplevel is the current active window"),
519 g_object_class_install_property (gobject_class,
520 PROP_HAS_TOPLEVEL_FOCUS,
521 g_param_spec_boolean ("has_toplevel_focus",
522 _("Focus in Toplevel"),
523 _("Whether the input focus is within this GtkWindow"),
527 window_signals[SET_FOCUS] =
528 g_signal_new ("set_focus",
529 G_TYPE_FROM_CLASS (object_class),
531 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
533 _gtk_marshal_VOID__OBJECT,
537 window_signals[FRAME_EVENT] =
538 g_signal_new ("frame_event",
539 G_TYPE_FROM_CLASS(object_class),
541 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
542 _gtk_boolean_handled_accumulator, NULL,
543 _gtk_marshal_BOOLEAN__BOXED,
547 window_signals[ACTIVATE_FOCUS] =
548 g_signal_new ("activate_focus",
549 G_OBJECT_CLASS_TYPE (object_class),
550 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
551 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_focus),
553 _gtk_marshal_VOID__VOID,
557 window_signals[ACTIVATE_DEFAULT] =
558 g_signal_new ("activate_default",
559 G_OBJECT_CLASS_TYPE (object_class),
560 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
561 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_default),
563 _gtk_marshal_VOID__VOID,
567 window_signals[MOVE_FOCUS] =
568 g_signal_new ("move_focus",
569 G_OBJECT_CLASS_TYPE (object_class),
570 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
571 GTK_SIGNAL_OFFSET (GtkWindowClass, move_focus),
573 _gtk_marshal_VOID__ENUM,
576 GTK_TYPE_DIRECTION_TYPE);
578 window_signals[KEYS_CHANGED] =
579 g_signal_new ("keys_changed",
580 G_OBJECT_CLASS_TYPE (object_class),
582 GTK_SIGNAL_OFFSET (GtkWindowClass, keys_changed),
584 gtk_marshal_VOID__VOID,
592 binding_set = gtk_binding_set_by_class (klass);
594 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
595 "activate_focus", 0);
596 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
597 "activate_focus", 0);
599 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
600 "activate_default", 0);
602 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
603 "activate_default", 0);
605 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
606 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
607 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
608 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
610 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
611 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
612 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
613 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
617 gtk_window_init (GtkWindow *window)
619 GdkColormap *colormap;
621 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
622 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
624 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
626 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
628 window->title = NULL;
629 window->wmclass_name = g_strdup (g_get_prgname ());
630 window->wmclass_class = g_strdup (gdk_get_program_class ());
631 window->wm_role = NULL;
632 window->geometry_info = NULL;
633 window->type = GTK_WINDOW_TOPLEVEL;
634 window->focus_widget = NULL;
635 window->default_widget = NULL;
636 window->configure_request_count = 0;
637 window->allow_shrink = FALSE;
638 window->allow_grow = TRUE;
639 window->configure_notify_received = FALSE;
640 window->position = GTK_WIN_POS_NONE;
641 window->need_default_size = TRUE;
642 window->need_default_position = TRUE;
643 window->modal = FALSE;
644 window->frame = NULL;
645 window->has_frame = FALSE;
646 window->frame_left = 0;
647 window->frame_right = 0;
648 window->frame_top = 0;
649 window->frame_bottom = 0;
650 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
651 window->gravity = GDK_GRAVITY_NORTH_WEST;
652 window->decorated = TRUE;
653 window->mnemonic_modifier = GDK_MOD1_MASK;
654 window->screen = gdk_get_default_screen ();
656 colormap = _gtk_widget_peek_colormap ();
658 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
660 gtk_widget_ref (GTK_WIDGET (window));
661 gtk_object_sink (GTK_OBJECT (window));
662 window->has_user_ref_count = TRUE;
663 toplevel_list = g_slist_prepend (toplevel_list, window);
665 gtk_decorated_window_init (window);
667 gtk_signal_connect (GTK_OBJECT (window),
669 GTK_SIGNAL_FUNC (gtk_window_event),
674 gtk_window_set_property (GObject *object,
681 window = GTK_WINDOW (object);
686 window->type = g_value_get_enum (value);
689 gtk_window_set_title (window, g_value_get_string (value));
691 case PROP_ALLOW_SHRINK:
692 window->allow_shrink = g_value_get_boolean (value);
693 gtk_widget_queue_resize (GTK_WIDGET (window));
695 case PROP_ALLOW_GROW:
696 window->allow_grow = g_value_get_boolean (value);
697 gtk_widget_queue_resize (GTK_WIDGET (window));
698 g_object_notify (G_OBJECT (window), "resizable");
701 window->allow_grow = g_value_get_boolean (value);
702 gtk_widget_queue_resize (GTK_WIDGET (window));
703 g_object_notify (G_OBJECT (window), "allow_grow");
706 gtk_window_set_modal (window, g_value_get_boolean (value));
709 gtk_window_set_position (window, g_value_get_enum (value));
711 case PROP_DEFAULT_WIDTH:
712 gtk_window_set_default_size_internal (window,
713 TRUE, g_value_get_int (value),
716 case PROP_DEFAULT_HEIGHT:
717 gtk_window_set_default_size_internal (window,
719 TRUE, g_value_get_int (value), FALSE);
721 case PROP_DESTROY_WITH_PARENT:
722 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
725 gtk_window_set_icon (window,
726 g_value_get_object (value));
729 gtk_window_set_screen (window, g_value_get_object (value));
737 gtk_window_get_property (GObject *object,
744 window = GTK_WINDOW (object);
748 GtkWindowGeometryInfo *info;
750 g_value_set_enum (value, window->type);
753 g_value_set_string (value, window->title);
755 case PROP_ALLOW_SHRINK:
756 g_value_set_boolean (value, window->allow_shrink);
758 case PROP_ALLOW_GROW:
759 g_value_set_boolean (value, window->allow_grow);
762 g_value_set_boolean (value, window->allow_grow);
765 g_value_set_boolean (value, window->modal);
768 g_value_set_enum (value, window->position);
770 case PROP_DEFAULT_WIDTH:
771 info = gtk_window_get_geometry_info (window, FALSE);
773 g_value_set_int (value, -1);
775 g_value_set_int (value, info->default_width);
777 case PROP_DEFAULT_HEIGHT:
778 info = gtk_window_get_geometry_info (window, FALSE);
780 g_value_set_int (value, -1);
782 g_value_set_int (value, info->default_height);
784 case PROP_DESTROY_WITH_PARENT:
785 g_value_set_boolean (value, window->destroy_with_parent);
788 g_value_set_object (value, gtk_window_get_icon (window));
791 g_value_set_object (value, window->screen);
794 g_value_set_boolean (value, window->is_active);
796 case PROP_HAS_TOPLEVEL_FOCUS:
797 g_value_set_boolean (value, window->has_toplevel_focus);
800 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
807 * @type: type of window
809 * Creates a new #GtkWindow, which is a toplevel window that can
810 * contain other widgets. Nearly always, the type of the window should
811 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
812 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
813 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
814 * dialogs, though in some other toolkits dialogs are called "popups".
815 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
816 * On X11, popup windows are not controlled by the <link
817 * linkend="gtk-X11-arch">window manager</link>.
819 * If you simply want an undecorated window (no window borders), use
820 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
822 * Return value: a new #GtkWindow.
825 gtk_window_new (GtkWindowType type)
829 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
831 window = gtk_type_new (GTK_TYPE_WINDOW);
835 return GTK_WIDGET (window);
839 * gtk_window_set_title:
840 * @window: a #GtkWindow
841 * @title: title of the window
843 * Sets the title of the #GtkWindow. The title of a window will be
844 * displayed in its title bar; on the X Window System, the title bar
845 * is rendered by the <link linkend="gtk-X11-arch">window
846 * manager</link>, so exactly how the title appears to users may vary
847 * according to a user's exact configuration. The title should help a
848 * user distinguish this window from other windows they may have
849 * open. A good title might include the application name and current
850 * document filename, for example.
854 gtk_window_set_title (GtkWindow *window,
857 g_return_if_fail (GTK_IS_WINDOW (window));
860 g_free (window->title);
861 window->title = g_strdup (title);
863 if (GTK_WIDGET_REALIZED (window))
865 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
867 gtk_decorated_window_set_title (window, title);
870 g_object_notify (G_OBJECT (window), "title");
874 * gtk_window_get_title:
875 * @window: a #GtkWindow
877 * Retrieves the title of the window. See gtk_window_set_title().
879 * Return value: the title of the window, or %NULL if none has
880 * been set explicitely. The returned string is owned by the widget
881 * and must not be modified or freed.
883 G_CONST_RETURN gchar *
884 gtk_window_get_title (GtkWindow *window)
886 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
888 return window->title;
892 * gtk_window_set_wmclass:
893 * @window: a #GtkWindow
894 * @wmclass_name: window name hint
895 * @wmclass_class: window class hint
897 * Don't use this function. It sets the X Window System "class" and
898 * "name" hints for a window. According to the ICCCM, you should
899 * always set these to the same value for all windows in an
900 * application, and GTK+ sets them to that value by default, so calling
901 * this function is sort of pointless. However, you may want to call
902 * gtk_window_set_role() on each window in your application, for the
903 * benefit of the session manager. Setting the role allows the window
904 * manager to restore window positions when loading a saved session.
908 gtk_window_set_wmclass (GtkWindow *window,
909 const gchar *wmclass_name,
910 const gchar *wmclass_class)
912 g_return_if_fail (GTK_IS_WINDOW (window));
914 g_free (window->wmclass_name);
915 window->wmclass_name = g_strdup (wmclass_name);
917 g_free (window->wmclass_class);
918 window->wmclass_class = g_strdup (wmclass_class);
920 if (GTK_WIDGET_REALIZED (window))
921 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
925 * gtk_window_set_role:
926 * @window: a #GtkWindow
927 * @role: unique identifier for the window to be used when restoring a session
929 * This function is only useful on X11, not with other GTK+ targets.
931 * In combination with the window title, the window role allows a
932 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
933 * same" window when an application is restarted. So for example you
934 * might set the "toolbox" role on your app's toolbox window, so that
935 * when the user restarts their session, the window manager can put
936 * the toolbox back in the same place.
938 * If a window already has a unique title, you don't need to set the
939 * role, since the WM can use the title to identify the window when
940 * restoring the session.
944 gtk_window_set_role (GtkWindow *window,
947 g_return_if_fail (GTK_IS_WINDOW (window));
949 if (role == window->wm_role)
952 g_free (window->wm_role);
953 window->wm_role = g_strdup (role);
955 if (GTK_WIDGET_REALIZED (window))
956 g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
960 * gtk_window_get_role:
961 * @window: a #GtkWindow
963 * Returns the role of the window. See gtk_window_set_role() for
964 * further explanation.
966 * Return value: the role of the window if set, or %NULL. The
967 * returned is owned by the widget and must not be modified
970 G_CONST_RETURN gchar *
971 gtk_window_get_role (GtkWindow *window)
973 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
975 return window->wm_role;
979 * gtk_window_set_focus:
980 * @window: a #GtkWindow
981 * @focus: widget to be the new focus widget, or %NULL to unset
982 * any focus widget for the toplevel window.
984 * If @focus is not the current focus widget, and is focusable, sets
985 * it as the focus widget for the window. If @focus is %NULL, unsets
986 * the focus widget for this window. To set the focus to a particular
987 * widget in the toplevel, it is usually more convenient to use
988 * gtk_widget_grab_focus() instead of this function.
991 gtk_window_set_focus (GtkWindow *window,
994 g_return_if_fail (GTK_IS_WINDOW (window));
997 g_return_if_fail (GTK_IS_WIDGET (focus));
998 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1002 gtk_widget_grab_focus (focus);
1005 /* Clear the existing focus chain, so that when we focus into
1006 * the window again, we start at the beginnning.
1008 GtkWidget *widget = window->focus_widget;
1011 while (widget->parent)
1013 widget = widget->parent;
1014 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1018 _gtk_window_internal_set_focus (window, NULL);
1023 _gtk_window_internal_set_focus (GtkWindow *window,
1026 g_return_if_fail (GTK_IS_WINDOW (window));
1028 if ((window->focus_widget != focus) ||
1029 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1030 gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
1034 * gtk_window_set_default:
1035 * @window: a #GtkWindow
1036 * @default_widget: widget to be the default, or %NULL to unset the
1037 * default widget for the toplevel.
1039 * The default widget is the widget that's activated when the user
1040 * presses Enter in a dialog (for example). This function sets or
1041 * unsets the default widget for a #GtkWindow about. When setting
1042 * (rather than unsetting) the default widget it's generally easier to
1043 * call gtk_widget_grab_focus() on the widget. Before making a widget
1044 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1045 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1048 gtk_window_set_default (GtkWindow *window,
1049 GtkWidget *default_widget)
1051 g_return_if_fail (GTK_IS_WINDOW (window));
1054 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1056 if (window->default_widget != default_widget)
1058 GtkWidget *old_default_widget = NULL;
1061 g_object_ref (default_widget);
1063 if (window->default_widget)
1065 old_default_widget = window->default_widget;
1067 if (window->focus_widget != window->default_widget ||
1068 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1069 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1070 gtk_widget_queue_draw (window->default_widget);
1073 window->default_widget = default_widget;
1075 if (window->default_widget)
1077 if (window->focus_widget == NULL ||
1078 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1079 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1080 gtk_widget_queue_draw (window->default_widget);
1083 if (old_default_widget)
1084 g_object_notify (G_OBJECT (old_default_widget), "has_default");
1088 g_object_notify (G_OBJECT (default_widget), "has_default");
1089 g_object_unref (default_widget);
1095 gtk_window_set_policy (GtkWindow *window,
1096 gboolean allow_shrink,
1097 gboolean allow_grow,
1098 gboolean auto_shrink)
1100 g_return_if_fail (GTK_IS_WINDOW (window));
1102 window->allow_shrink = (allow_shrink != FALSE);
1103 window->allow_grow = (allow_grow != FALSE);
1105 g_object_freeze_notify (G_OBJECT (window));
1106 g_object_notify (G_OBJECT (window), "allow_shrink");
1107 g_object_notify (G_OBJECT (window), "allow_grow");
1108 g_object_notify (G_OBJECT (window), "resizable");
1109 g_object_thaw_notify (G_OBJECT (window));
1111 gtk_widget_queue_resize (GTK_WIDGET (window));
1115 handle_keys_changed (gpointer data)
1119 GDK_THREADS_ENTER ();
1120 window = GTK_WINDOW (data);
1122 if (window->keys_changed_handler)
1124 gtk_idle_remove (window->keys_changed_handler);
1125 window->keys_changed_handler = 0;
1128 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1129 GDK_THREADS_LEAVE ();
1135 gtk_window_notify_keys_changed (GtkWindow *window)
1137 if (!window->keys_changed_handler)
1138 window->keys_changed_handler = gtk_idle_add (handle_keys_changed, window);
1142 * gtk_window_add_accel_group:
1143 * @window: window to attach accelerator group to
1144 * @accel_group: a #GtkAccelGroup
1146 * Associate @accel_group with @window, such that calling
1147 * gtk_accel_groups_activate() on @window will activate accelerators
1151 gtk_window_add_accel_group (GtkWindow *window,
1152 GtkAccelGroup *accel_group)
1154 g_return_if_fail (GTK_IS_WINDOW (window));
1155 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1157 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1158 g_signal_connect_object (accel_group, "accel_changed",
1159 G_CALLBACK (gtk_window_notify_keys_changed),
1160 window, G_CONNECT_SWAPPED);
1164 * gtk_window_remove_accel_group:
1165 * @window: a #GtkWindow
1166 * @accel_group: a #GtkAccelGroup
1168 * Reverses the effects of gtk_window_add_accel_group().
1171 gtk_window_remove_accel_group (GtkWindow *window,
1172 GtkAccelGroup *accel_group)
1174 g_return_if_fail (GTK_IS_WINDOW (window));
1175 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1177 g_signal_handlers_disconnect_by_func (accel_group,
1178 (gpointer) gtk_window_notify_keys_changed,
1180 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1184 * gtk_window_add_mnemonic:
1185 * @window: a #GtkWindow
1186 * @keyval: the mnemonic
1187 * @target: the widget that gets activated by the mnemonic
1189 * Adds a mnemonic to this window.
1192 gtk_window_add_mnemonic (GtkWindow *window,
1196 GtkWindowMnemonic key;
1197 GtkWindowMnemonic *mnemonic;
1199 g_return_if_fail (GTK_IS_WINDOW (window));
1200 g_return_if_fail (GTK_IS_WIDGET (target));
1202 key.window = window;
1203 key.keyval = keyval;
1204 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1208 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1209 mnemonic->targets = g_slist_append (mnemonic->targets, target);
1213 mnemonic = g_new (GtkWindowMnemonic, 1);
1215 mnemonic->targets = g_slist_prepend (NULL, target);
1216 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1218 gtk_window_notify_keys_changed (window);
1222 * gtk_window_remove_mnemonic:
1223 * @window: a #GtkWindow
1224 * @keyval: the mnemonic
1225 * @target: the widget that gets activated by the mnemonic
1227 * Removes a mnemonic from this window.
1230 gtk_window_remove_mnemonic (GtkWindow *window,
1234 GtkWindowMnemonic key;
1235 GtkWindowMnemonic *mnemonic;
1237 g_return_if_fail (GTK_IS_WINDOW (window));
1238 g_return_if_fail (GTK_IS_WIDGET (target));
1240 key.window = window;
1241 key.keyval = keyval;
1242 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1244 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1246 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1247 if (mnemonic->targets == NULL)
1249 g_hash_table_remove (mnemonic_hash_table, mnemonic);
1252 gtk_window_notify_keys_changed (window);
1256 * gtk_window_mnemonic_activate:
1257 * @window: a #GtkWindow
1258 * @keyval: the mnemonic
1259 * @modifier: the modifiers
1260 * @returns: %TRUE if the activation is done.
1262 * Activates the targets associated with the mnemonic.
1265 gtk_window_mnemonic_activate (GtkWindow *window,
1267 GdkModifierType modifier)
1269 GtkWindowMnemonic key;
1270 GtkWindowMnemonic *mnemonic;
1272 GtkWidget *widget, *chosen_widget;
1273 gboolean overloaded;
1275 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1277 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1280 key.window = window;
1281 key.keyval = keyval;
1282 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1288 chosen_widget = NULL;
1289 list = mnemonic->targets;
1292 widget = GTK_WIDGET (list->data);
1294 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1295 GTK_WIDGET_MAPPED (widget))
1303 chosen_widget = widget;
1305 list = g_slist_next (list);
1310 /* For round robin we put the activated entry on
1311 * the end of the list after activation
1313 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1314 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1316 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1322 * gtk_window_set_mnemonic_modifier:
1323 * @window: a #GtkWindow
1324 * @modifier: the modifier mask used to activate
1325 * mnemonics on this window.
1327 * Sets the mnemonic modifier for this window.
1330 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1331 GdkModifierType modifier)
1333 g_return_if_fail (GTK_IS_WINDOW (window));
1334 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1336 window->mnemonic_modifier = modifier;
1337 gtk_window_notify_keys_changed (window);
1341 * gtk_window_get_mnemonic_modifier:
1342 * @window: a #GtkWindow
1344 * Returns the mnemonic modifier for this window. See
1345 * gtk_window_set_mnemonic_modifier().
1347 * Return value: the modifier mask used to activate
1348 * mnemonics on this window.
1351 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1353 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1355 return window->mnemonic_modifier;
1359 * gtk_window_set_position:
1360 * @window: a #GtkWindow.
1361 * @position: a position constraint.
1363 * Sets a position constraint for this window. If the old or new
1364 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1365 * the window to be repositioned to satisfy the new constraint.
1368 gtk_window_set_position (GtkWindow *window,
1369 GtkWindowPosition position)
1371 g_return_if_fail (GTK_IS_WINDOW (window));
1373 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1374 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1376 GtkWindowGeometryInfo *info;
1378 info = gtk_window_get_geometry_info (window, TRUE);
1380 /* this flag causes us to re-request the CENTER_ALWAYS
1381 * constraint in gtk_window_move_resize(), see
1382 * comment in that function.
1384 info->position_constraints_changed = TRUE;
1386 gtk_widget_queue_resize (GTK_WIDGET (window));
1389 window->position = position;
1391 g_object_notify (G_OBJECT (window), "window_position");
1395 gtk_window_activate_focus (GtkWindow *window)
1397 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1399 if (window->focus_widget)
1401 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1402 gtk_widget_activate (window->focus_widget);
1410 * gtk_window_get_focus:
1411 * @window: a #GtkWindow
1413 * Retrieves the current focused widget within the window.
1414 * Note that this is the widget that would have the focus
1415 * if the toplevel window focused; if the toplevel window
1416 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1417 * not be %TRUE for the widget.
1419 * Return value: the currently focused widget.
1422 gtk_window_get_focus (GtkWindow *window)
1424 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1426 return window->focus_widget;
1430 gtk_window_activate_default (GtkWindow *window)
1432 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1434 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1435 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1437 gtk_widget_activate (window->default_widget);
1440 else if (window->focus_widget)
1442 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1443 gtk_widget_activate (window->focus_widget);
1451 * gtk_window_set_modal:
1452 * @window: a #GtkWindow
1453 * @modal: whether the window is modal
1455 * Sets a window modal or non-modal. Modal windows prevent interaction
1456 * with other windows in the same application. To keep modal dialogs
1457 * on top of main application windows, use
1458 * gtk_window_set_transient_for() to make the dialog transient for the
1459 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1460 * will then disallow lowering the dialog below the parent.
1465 gtk_window_set_modal (GtkWindow *window,
1468 g_return_if_fail (GTK_IS_WINDOW (window));
1470 window->modal = modal != FALSE;
1472 /* adjust desired modality state */
1473 if (GTK_WIDGET_VISIBLE (window) && window->modal)
1474 gtk_grab_add (GTK_WIDGET (window));
1476 gtk_grab_remove (GTK_WIDGET (window));
1478 g_object_notify (G_OBJECT (window), "modal");
1482 * gtk_window_get_modal:
1483 * @window: a #GtkWindow
1485 * Returns whether the window is modal. See gtk_window_set_modal().
1487 * Return value: %TRUE if the window is set to be modal and
1488 * establishes a grab when shown
1491 gtk_window_get_modal (GtkWindow *window)
1493 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1495 return window->modal;
1499 * gtk_window_list_toplevels:
1501 * Returns a list of all existing toplevel windows. The widgets
1502 * in the list are not individually referenced. If you want
1503 * to iterate through the list and perform actions involving
1504 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1505 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1506 * then unref all the widgets afterwards.
1508 * Return value: list of toplevel widgets
1511 gtk_window_list_toplevels (void)
1516 for (slist = toplevel_list; slist; slist = slist->next)
1517 list = g_list_prepend (list, slist->data);
1523 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1525 GList *embedded_windows;
1527 g_return_if_fail (GTK_IS_WINDOW (window));
1529 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1530 if (embedded_windows)
1531 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1532 g_quark_from_static_string ("gtk-embedded"));
1533 embedded_windows = g_list_prepend (embedded_windows,
1534 GUINT_TO_POINTER (xid));
1536 gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
1539 (GtkDestroyNotify) g_list_free : NULL);
1543 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1545 GList *embedded_windows;
1548 g_return_if_fail (GTK_IS_WINDOW (window));
1550 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1551 if (embedded_windows)
1552 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1553 g_quark_from_static_string ("gtk-embedded"));
1555 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1558 embedded_windows = g_list_remove_link (embedded_windows, node);
1559 g_list_free_1 (node);
1562 gtk_object_set_data_full (GTK_OBJECT (window),
1563 "gtk-embedded", embedded_windows,
1565 (GtkDestroyNotify) g_list_free : NULL);
1569 _gtk_window_reposition (GtkWindow *window,
1573 g_return_if_fail (GTK_IS_WINDOW (window));
1575 gtk_window_move (window, x, y);
1579 gtk_window_dispose (GObject *object)
1581 GtkWindow *window = GTK_WINDOW (object);
1583 gtk_window_set_focus (window, NULL);
1584 gtk_window_set_default (window, NULL);
1586 G_OBJECT_CLASS (parent_class)->dispose (object);
1590 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1592 gtk_widget_destroy (GTK_WIDGET (child));
1596 connect_parent_destroyed (GtkWindow *window)
1598 if (window->transient_parent)
1600 gtk_signal_connect (GTK_OBJECT (window->transient_parent),
1602 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1608 disconnect_parent_destroyed (GtkWindow *window)
1610 if (window->transient_parent)
1612 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1613 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1619 gtk_window_transient_parent_realized (GtkWidget *parent,
1622 if (GTK_WIDGET_REALIZED (window))
1623 gdk_window_set_transient_for (window->window, parent->window);
1627 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1630 if (GTK_WIDGET_REALIZED (window))
1631 gdk_property_delete (window->window,
1632 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1636 gtk_window_unset_transient_for (GtkWindow *window)
1638 if (window->transient_parent)
1640 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1641 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1643 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1644 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1646 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1647 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1648 &window->transient_parent);
1650 if (window->destroy_with_parent)
1651 disconnect_parent_destroyed (window);
1653 window->transient_parent = NULL;
1658 * gtk_window_set_transient_for:
1659 * @window: a #GtkWindow
1660 * @parent: parent window
1662 * Dialog windows should be set transient for the main application
1663 * window they were spawned from. This allows <link
1664 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1665 * dialog on top of the main window, or center the dialog over the
1666 * main window. gtk_dialog_new_with_buttons() and other convenience
1667 * functions in GTK+ will sometimes call
1668 * gtk_window_set_transient_for() on your behalf.
1670 * On Windows, this function will and put the child window
1671 * on top of the parent, much as the window manager would have
1676 gtk_window_set_transient_for (GtkWindow *window,
1679 g_return_if_fail (GTK_IS_WINDOW (window));
1680 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1681 g_return_if_fail (window != parent);
1684 if (window->transient_parent)
1686 if (GTK_WIDGET_REALIZED (window) &&
1687 GTK_WIDGET_REALIZED (window->transient_parent) &&
1688 (!parent || !GTK_WIDGET_REALIZED (parent)))
1689 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1690 GTK_WIDGET (window));
1692 gtk_window_unset_transient_for (window);
1695 window->transient_parent = parent;
1699 gtk_signal_connect (GTK_OBJECT (parent), "destroy",
1700 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1701 &window->transient_parent);
1702 gtk_signal_connect (GTK_OBJECT (parent), "realize",
1703 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1705 gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
1706 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1709 window->screen = parent->screen;
1711 if (window->destroy_with_parent)
1712 connect_parent_destroyed (window);
1714 if (GTK_WIDGET_REALIZED (window) &&
1715 GTK_WIDGET_REALIZED (parent))
1716 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1717 GTK_WIDGET (window));
1722 * gtk_window_get_transient_for:
1723 * @window: a #GtkWindow
1725 * Fetches the transient parent for this window. See
1726 * gtk_window_set_transient_for().
1728 * Return value: the transient parent for this window, or %NULL
1729 * if no transient parent has been set.
1732 gtk_window_get_transient_for (GtkWindow *window)
1734 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1736 return window->transient_parent;
1740 * gtk_window_set_type_hint:
1741 * @window: a #GtkWindow
1742 * @hint: the window type
1744 * By setting the type hint for the window, you allow the window
1745 * manager to decorate and handle the window in a way which is
1746 * suitable to the function of the window in your application.
1748 * This function should be called before the window becomes visible.
1750 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1751 * will sometimes call gtk_window_set_type_hint() on your behalf.
1755 gtk_window_set_type_hint (GtkWindow *window,
1756 GdkWindowTypeHint hint)
1758 g_return_if_fail (GTK_IS_WINDOW (window));
1759 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1760 window->type_hint = hint;
1764 * gtk_window_get_type_hint:
1765 * @window: a #GtkWindow
1767 * Gets the type hint for this window. See gtk_window_set_type_hint().
1769 * Return value: the type hint for @window.
1772 gtk_window_get_type_hint (GtkWindow *window)
1774 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1776 return window->type_hint;
1780 * gtk_window_set_destroy_with_parent:
1781 * @window: a #GtkWindow
1782 * @setting: whether to destroy @window with its transient parent
1784 * If @setting is %TRUE, then destroying the transient parent of @window
1785 * will also destroy @window itself. This is useful for dialogs that
1786 * shouldn't persist beyond the lifetime of the main window they're
1787 * associated with, for example.
1790 gtk_window_set_destroy_with_parent (GtkWindow *window,
1793 g_return_if_fail (GTK_IS_WINDOW (window));
1795 if (window->destroy_with_parent == (setting != FALSE))
1798 if (window->destroy_with_parent)
1800 disconnect_parent_destroyed (window);
1804 connect_parent_destroyed (window);
1807 window->destroy_with_parent = setting;
1809 g_object_notify (G_OBJECT (window), "destroy_with_parent");
1813 * gtk_window_get_destroy_with_parent:
1814 * @window: a #GtkWindow
1816 * Returns whether the window will be destroyed with its transient parent. See
1817 * gtk_window_set_destroy_with_parent ().
1819 * Return value: %TRUE if the window will be destroyed with its transient parent.
1822 gtk_window_get_destroy_with_parent (GtkWindow *window)
1824 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1826 return window->destroy_with_parent;
1829 static GtkWindowGeometryInfo*
1830 gtk_window_get_geometry_info (GtkWindow *window,
1833 GtkWindowGeometryInfo *info;
1835 info = window->geometry_info;
1836 if (!info && create)
1838 info = g_new0 (GtkWindowGeometryInfo, 1);
1840 info->default_width = -1;
1841 info->default_height = -1;
1842 info->resize_width = -1;
1843 info->resize_height = -1;
1844 info->initial_x = 0;
1845 info->initial_y = 0;
1846 info->initial_pos_set = FALSE;
1847 info->default_is_geometry = FALSE;
1848 info->position_constraints_changed = FALSE;
1849 info->last.configure_request.x = 0;
1850 info->last.configure_request.y = 0;
1851 info->last.configure_request.width = -1;
1852 info->last.configure_request.height = -1;
1853 info->widget = NULL;
1855 window->geometry_info = info;
1862 * gtk_window_set_geometry_hints:
1863 * @window: a #GtkWindow
1864 * @geometry_widget: widget the geometry hints will be applied to
1865 * @geometry: struct containing geometry information
1866 * @geom_mask: mask indicating which struct fields should be paid attention to
1868 * This function sets up hints about how a window can be resized by
1869 * the user. You can set a minimum and maximum size; allowed resize
1870 * increments (e.g. for xterm, you can only resize by the size of a
1871 * character); aspect ratios; and more. See the #GdkGeometry struct.
1875 gtk_window_set_geometry_hints (GtkWindow *window,
1876 GtkWidget *geometry_widget,
1877 GdkGeometry *geometry,
1878 GdkWindowHints geom_mask)
1880 GtkWindowGeometryInfo *info;
1882 g_return_if_fail (GTK_IS_WINDOW (window));
1883 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
1885 info = gtk_window_get_geometry_info (window, TRUE);
1888 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1889 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1892 info->widget = geometry_widget;
1894 gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
1895 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1899 info->geometry = *geometry;
1901 /* We store gravity in window->gravity not in the hints. */
1902 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
1904 if (geom_mask & GDK_HINT_WIN_GRAVITY)
1906 gtk_window_set_gravity (window, geometry->win_gravity);
1909 gtk_widget_queue_resize (GTK_WIDGET (window));
1913 * gtk_window_set_decorated:
1914 * @window: a #GtkWindow
1915 * @setting: %TRUE to decorate the window
1917 * By default, windows are decorated with a title bar, resize
1918 * controls, etc. Some <link linkend="gtk-X11-arch">window
1919 * managers</link> allow GTK+ to disable these decorations, creating a
1920 * borderless window. If you set the decorated property to %FALSE
1921 * using this function, GTK+ will do its best to convince the window
1922 * manager not to decorate the window.
1924 * On Windows, this function always works, since there's no window manager
1929 gtk_window_set_decorated (GtkWindow *window,
1932 g_return_if_fail (GTK_IS_WINDOW (window));
1934 setting = setting != FALSE;
1936 if (setting == window->decorated)
1939 window->decorated = setting;
1941 if (GTK_WIDGET (window)->window)
1943 if (window->decorated)
1944 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1947 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1953 * gtk_window_get_decorated:
1954 * @window: a #GtkWindow
1956 * Returns whether the window has been set to have decorations
1957 * such as a title bar via gtk_window_set_decorated().
1959 * Return value: %TRUE if the window has been set to have decorations
1962 gtk_window_get_decorated (GtkWindow *window)
1964 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
1966 return window->decorated;
1969 static GtkWindowIconInfo*
1970 get_icon_info (GtkWindow *window)
1972 return g_object_get_data (G_OBJECT (window),
1973 "gtk-window-icon-info");
1976 static GtkWindowIconInfo*
1977 ensure_icon_info (GtkWindow *window)
1979 GtkWindowIconInfo *info;
1981 info = get_icon_info (window);
1985 info = g_new0 (GtkWindowIconInfo, 1);
1986 g_object_set_data_full (G_OBJECT (window),
1987 "gtk-window-icon-info",
2002 get_screen_icon_info (GdkScreen *screen)
2004 ScreenIconInfo *info = g_object_get_data (G_OBJECT (screen),
2005 "gtk-window-default-icon-pixmap");
2008 info = g_new0 (ScreenIconInfo, 1);
2009 g_object_set_data (G_OBJECT (screen), "gtk-window-default-icon-pixmap", info);
2012 if (info->serial != default_icon_serial)
2016 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2017 info->pixmap = NULL;
2022 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2026 info->serial = default_icon_serial;
2033 get_pixmap_and_mask (GdkWindow *window,
2034 GtkWindowIconInfo *parent_info,
2035 gboolean is_default_list,
2037 GdkPixmap **pmap_return,
2038 GdkBitmap **mask_return)
2040 GdkScreen *screen = gdk_drawable_get_screen (window);
2041 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2042 GdkPixbuf *best_icon;
2046 *pmap_return = NULL;
2047 *mask_return = NULL;
2049 if (is_default_list &&
2050 default_icon_info->pixmap != NULL)
2052 /* Use shared icon pixmap for all windows on this screen.
2054 if (default_icon_info->pixmap)
2055 g_object_ref (G_OBJECT (default_icon_info->pixmap));
2056 if (default_icon_info->mask)
2057 g_object_ref (G_OBJECT (default_icon_info->mask));
2059 *pmap_return = default_icon_info->pixmap;
2060 *mask_return = default_icon_info->mask;
2062 else if (parent_info && parent_info->icon_pixmap)
2064 if (parent_info->icon_pixmap)
2065 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
2066 if (parent_info->icon_mask)
2067 g_object_ref (G_OBJECT (parent_info->icon_mask));
2069 *pmap_return = parent_info->icon_pixmap;
2070 *mask_return = parent_info->icon_mask;
2074 #define IDEAL_SIZE 48
2076 best_size = G_MAXINT;
2078 tmp_list = icon_list;
2079 while (tmp_list != NULL)
2081 GdkPixbuf *pixbuf = tmp_list->data;
2084 /* average width and height - if someone passes in a rectangular
2085 * icon they deserve what they get.
2087 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2090 if (best_icon == NULL)
2097 /* icon is better if it's 32 pixels or larger, and closer to
2098 * the ideal size than the current best.
2101 (ABS (best_size - IDEAL_SIZE) <
2102 ABS (this - IDEAL_SIZE)))
2109 tmp_list = tmp_list->next;
2113 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2114 gdk_screen_get_system_colormap (screen),
2119 /* Save pmap/mask for others to use if appropriate */
2122 parent_info->icon_pixmap = *pmap_return;
2123 parent_info->icon_mask = *mask_return;
2125 if (parent_info->icon_pixmap)
2126 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
2127 if (parent_info->icon_mask)
2128 g_object_ref (G_OBJECT (parent_info->icon_mask));
2130 else if (is_default_list)
2132 default_icon_info->pixmap = *pmap_return;
2133 default_icon_info->mask = *mask_return;
2135 if (default_icon_info->pixmap)
2136 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2137 (gpointer*)&default_icon_info->pixmap);
2138 if (default_icon_info->mask)
2139 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2140 (gpointer*)&default_icon_info->mask);
2146 gtk_window_realize_icon (GtkWindow *window)
2149 GtkWindowIconInfo *info;
2152 widget = GTK_WIDGET (window);
2154 g_return_if_fail (widget->window != NULL);
2156 /* no point setting an icon on override-redirect */
2157 if (window->type == GTK_WINDOW_POPUP)
2162 info = ensure_icon_info (window);
2167 g_return_if_fail (info->icon_pixmap == NULL);
2168 g_return_if_fail (info->icon_mask == NULL);
2170 info->using_default_icon = FALSE;
2171 info->using_parent_icon = FALSE;
2173 icon_list = info->icon_list;
2175 /* Inherit from transient parent */
2176 if (icon_list == NULL && window->transient_parent)
2178 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2180 info->using_parent_icon = TRUE;
2183 /* Inherit from default */
2184 if (icon_list == NULL)
2186 icon_list = default_icon_list;
2188 info->using_default_icon = TRUE;
2191 gdk_window_set_icon_list (widget->window, icon_list);
2193 get_pixmap_and_mask (widget->window,
2194 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2195 info->using_default_icon,
2200 /* This is a slight ICCCM violation since it's a color pixmap not
2201 * a bitmap, but everyone does it.
2203 gdk_window_set_icon (widget->window,
2208 info->realized = TRUE;
2212 gtk_window_unrealize_icon (GtkWindow *window)
2214 GtkWindowIconInfo *info;
2217 widget = GTK_WIDGET (window);
2219 info = get_icon_info (window);
2224 if (info->icon_pixmap)
2225 g_object_unref (G_OBJECT (info->icon_pixmap));
2227 if (info->icon_mask)
2228 g_object_unref (G_OBJECT (info->icon_mask));
2230 info->icon_pixmap = NULL;
2231 info->icon_mask = NULL;
2233 /* We don't clear the properties on the window, just figure the
2234 * window is going away.
2237 info->realized = FALSE;
2241 * gtk_window_set_icon_list:
2242 * @window: a #GtkWindow
2243 * @list: list of #GdkPixbuf
2245 * Sets up the icon representing a #GtkWindow. The icon is used when
2246 * the window is minimized (also known as iconified). Some window
2247 * managers or desktop environments may also place it in the window
2248 * frame, or display it in other contexts.
2250 * gtk_window_set_icon_list() allows you to pass in the same icon in
2251 * several hand-drawn sizes. The list should contain the natural sizes
2252 * your icon is available in; that is, don't scale the image before
2253 * passing it to GTK+. Scaling is postponed until the last minute,
2254 * when the desired final size is known, to allow best quality.
2256 * By passing several sizes, you may improve the final image quality
2257 * of the icon, by reducing or eliminating automatic image scaling.
2259 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2260 * larger images (64x64, 128x128) if you have them.
2262 * See also gtk_window_set_default_icon_list() to set the icon
2263 * for all windows in your application in one go.
2265 * Note that transient windows (those who have been set transient for another
2266 * window using gtk_window_set_transient_for()) will inherit their
2267 * icon from their transient parent. So there's no need to explicitly
2268 * set the icon on transient windows.
2271 gtk_window_set_icon_list (GtkWindow *window,
2274 GtkWindowIconInfo *info;
2276 g_return_if_fail (GTK_IS_WINDOW (window));
2278 info = ensure_icon_info (window);
2280 if (info->icon_list == list) /* check for NULL mostly */
2283 g_list_foreach (info->icon_list,
2284 (GFunc) g_object_unref, NULL);
2286 g_list_free (info->icon_list);
2288 info->icon_list = g_list_copy (list);
2289 g_list_foreach (info->icon_list,
2290 (GFunc) g_object_ref, NULL);
2292 g_object_notify (G_OBJECT (window), "icon");
2294 gtk_window_unrealize_icon (window);
2296 if (GTK_WIDGET_REALIZED (window))
2297 gtk_window_realize_icon (window);
2299 /* We could try to update our transient children, but I don't think
2300 * it's really worth it. If we did it, the best way would probably
2301 * be to have children connect to notify::icon_list
2306 * gtk_window_get_icon_list:
2307 * @window: a #GtkWindow
2309 * Retrieves the list of icons set by gtk_window_set_icon_list().
2310 * The list is copied, but the reference count on each
2311 * member won't be incremented.
2313 * Return value: copy of window's icon list
2316 gtk_window_get_icon_list (GtkWindow *window)
2318 GtkWindowIconInfo *info;
2320 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2322 info = get_icon_info (window);
2325 return g_list_copy (info->icon_list);
2331 * gtk_window_set_icon:
2332 * @window: a #GtkWindow
2333 * @icon: icon image, or %NULL
2335 * Sets up the icon representing a #GtkWindow. This icon is used when
2336 * the window is minimized (also known as iconified). Some window
2337 * managers or desktop environments may also place it in the window
2338 * frame, or display it in other contexts.
2340 * The icon should be provided in whatever size it was naturally
2341 * drawn; that is, don't scale the image before passing it to
2342 * GTK+. Scaling is postponed until the last minute, when the desired
2343 * final size is known, to allow best quality.
2345 * If you have your icon hand-drawn in multiple sizes, use
2346 * gtk_window_set_icon_list(). Then the best size will be used.
2348 * This function is equivalent to calling gtk_window_set_icon_list()
2349 * with a 1-element list.
2351 * See also gtk_window_set_default_icon_list() to set the icon
2352 * for all windows in your application in one go.
2355 gtk_window_set_icon (GtkWindow *window,
2360 g_return_if_fail (GTK_IS_WINDOW (window));
2361 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2364 list = g_list_append (list, icon);
2365 gtk_window_set_icon_list (window, list);
2370 * gtk_window_get_icon:
2371 * @window: a #GtkWindow
2373 * Gets the value set by gtk_window_set_icon() (or if you've
2374 * called gtk_window_set_icon_list(), gets the first icon in
2377 * Return value: icon for window
2380 gtk_window_get_icon (GtkWindow *window)
2382 GtkWindowIconInfo *info;
2384 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2386 info = get_icon_info (window);
2387 if (info && info->icon_list)
2388 return GDK_PIXBUF (info->icon_list->data);
2394 * gtk_window_set_default_icon_list:
2395 * @list: a list of #GdkPixbuf
2397 * Sets an icon list to be used as fallback for windows that haven't
2398 * had gtk_window_set_icon_list() called on them to set up a
2399 * window-specific icon list. This function allows you to set up the
2400 * icon for all windows in your app at once.
2402 * See gtk_window_set_icon_list() for more details.
2406 gtk_window_set_default_icon_list (GList *list)
2410 if (list == default_icon_list)
2413 /* Update serial so we don't used cached pixmaps/masks
2415 default_icon_serial++;
2417 g_list_foreach (default_icon_list,
2418 (GFunc) g_object_unref, NULL);
2420 g_list_free (default_icon_list);
2422 default_icon_list = g_list_copy (list);
2423 g_list_foreach (default_icon_list,
2424 (GFunc) g_object_ref, NULL);
2426 /* Update all toplevels */
2427 toplevels = gtk_window_list_toplevels ();
2428 tmp_list = toplevels;
2429 while (tmp_list != NULL)
2431 GtkWindowIconInfo *info;
2432 GtkWindow *w = tmp_list->data;
2434 info = get_icon_info (w);
2435 if (info && info->using_default_icon)
2437 gtk_window_unrealize_icon (w);
2438 if (GTK_WIDGET_REALIZED (w))
2439 gtk_window_realize_icon (w);
2442 tmp_list = tmp_list->next;
2444 g_list_free (toplevels);
2448 * gtk_window_get_default_icon_list:
2450 * Gets the value set by gtk_window_set_default_icon_list().
2451 * The list is a copy and should be freed with g_list_free(),
2452 * but the pixbufs in the list have not had their reference count
2455 * Return value: copy of default icon list
2458 gtk_window_get_default_icon_list (void)
2460 return g_list_copy (default_icon_list);
2464 gtk_window_set_default_size_internal (GtkWindow *window,
2465 gboolean change_width,
2467 gboolean change_height,
2469 gboolean is_geometry)
2471 GtkWindowGeometryInfo *info;
2473 g_return_if_fail (change_width == FALSE || width >= -1);
2474 g_return_if_fail (change_height == FALSE || height >= -1);
2476 info = gtk_window_get_geometry_info (window, TRUE);
2478 g_object_freeze_notify (G_OBJECT (window));
2480 info->default_is_geometry = is_geometry != FALSE;
2490 info->default_width = width;
2492 g_object_notify (G_OBJECT (window), "default_width");
2503 info->default_height = height;
2505 g_object_notify (G_OBJECT (window), "default_height");
2508 g_object_thaw_notify (G_OBJECT (window));
2510 gtk_widget_queue_resize (GTK_WIDGET (window));
2514 * gtk_window_set_default_size:
2515 * @window: a #GtkWindow
2516 * @width: width in pixels, or -1 to unset the default width
2517 * @height: height in pixels, or -1 to unset the default height
2519 * Sets the default size of a window. If the window's "natural" size
2520 * (its size request) is larger than the default, the default will be
2521 * ignored. More generally, if the default size does not obey the
2522 * geometry hints for the window (gtk_window_set_geometry_hints() can
2523 * be used to set these explicitly), the default size will be clamped
2524 * to the nearest permitted size.
2526 * Unlike gtk_widget_set_size_request(), which sets a size request for
2527 * a widget and thus would keep users from shrinking the window, this
2528 * function only sets the initial size, just as if the user had
2529 * resized the window themselves. Users can still shrink the window
2530 * again as they normally would. Setting a default size of -1 means to
2531 * use the "natural" default size (the size request of the window).
2533 * For more control over a window's initial size and how resizing works,
2534 * investigate gtk_window_set_geometry_hints().
2536 * For some uses, gtk_window_resize() is a more appropriate function.
2537 * gtk_window_resize() changes the current size of the window, rather
2538 * than the size to be used on initial display. gtk_window_resize() always
2539 * affects the window itself, not the geometry widget.
2541 * The default size of a window only affects the first time a window is
2542 * shown; if a window is hidden and re-shown, it will remember the size
2543 * it had prior to hiding, rather than using the default size.
2545 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2546 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2549 gtk_window_set_default_size (GtkWindow *window,
2553 g_return_if_fail (GTK_IS_WINDOW (window));
2554 g_return_if_fail (width >= -1);
2555 g_return_if_fail (height >= -1);
2557 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
2561 * gtk_window_get_default_size:
2562 * @window: a #GtkWindow
2563 * @width: location to store the default width, or %NULL
2564 * @height: location to store the default height, or %NULL
2566 * Gets the default size of the window. A value of -1 for the width or
2567 * height indicates that a default size has not been explicitly set
2568 * for that dimension, so the "natural" size of the window will be
2573 gtk_window_get_default_size (GtkWindow *window,
2577 GtkWindowGeometryInfo *info;
2579 g_return_if_fail (GTK_IS_WINDOW (window));
2581 info = gtk_window_get_geometry_info (window, FALSE);
2584 *width = info->default_width;
2587 *height = info->default_height;
2591 * gtk_window_resize:
2592 * @window: a #GtkWindow
2593 * @width: width in pixels to resize the window to
2594 * @height: height in pixels to resize the window to
2596 * Resizes the window as if the user had done so, obeying geometry
2597 * constraints. The default geometry constraint is that windows may
2598 * not be smaller than their size request; to override this
2599 * constraint, call gtk_widget_set_size_request() to set the window's
2600 * request to a smaller value.
2602 * If gtk_window_resize() is called before showing a window for the
2603 * first time, it overrides any default size set with
2604 * gtk_window_set_default_size().
2606 * Windows may not be resized smaller than 1 by 1 pixels.
2610 gtk_window_resize (GtkWindow *window,
2614 GtkWindowGeometryInfo *info;
2616 g_return_if_fail (GTK_IS_WINDOW (window));
2617 g_return_if_fail (width > 0);
2618 g_return_if_fail (height > 0);
2620 info = gtk_window_get_geometry_info (window, TRUE);
2622 info->resize_width = width;
2623 info->resize_height = height;
2625 gtk_widget_queue_resize (GTK_WIDGET (window));
2629 * gtk_window_get_size:
2630 * @window: a #GtkWindow
2631 * @width: return location for width, or %NULL
2632 * @height: return location for height, or %NULL
2634 * Obtains the current size of @window. If @window is not onscreen,
2635 * it returns the size GTK+ will suggest to the <link
2636 * linkend="gtk-X11-arch">window manager</link> for the initial window
2637 * size (but this is not reliably the same as the size the window
2638 * manager will actually select). The size obtained by
2639 * gtk_window_get_size() is the last size received in a
2640 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2641 * rather than querying the X server for the size. As a result, if you
2642 * call gtk_window_resize() then immediately call
2643 * gtk_window_get_size(), the size won't have taken effect yet. After
2644 * the window manager processes the resize request, GTK+ receives
2645 * notification that the size has changed via a configure event, and
2646 * the size of the window gets updated.
2648 * Note 1: Nearly any use of this function creates a race condition,
2649 * because the size of the window may change between the time that you
2650 * get the size and the time that you perform some action assuming
2651 * that size is the current size. To avoid race conditions, connect to
2652 * "configure_event" on the window and adjust your size-dependent
2653 * state to match the size delivered in the #GdkEventConfigure.
2655 * Note 2: The returned size does <emphasis>not</emphasis> include the
2656 * size of the window manager decorations (aka the window frame or
2657 * border). Those are not drawn by GTK+ and GTK+ has no reliable
2658 * method of determining their size.
2660 * Note 3: If you are getting a window size in order to position
2661 * the window onscreen, there may be a better way. The preferred
2662 * way is to simply set the window's semantic type with
2663 * gtk_window_set_type_hint(), which allows the window manager to
2664 * e.g. center dialogs. Also, if you set the transient parent of
2665 * dialogs with gtk_window_set_transient_for() window managers
2666 * will often center the dialog over its parent window. It's
2667 * much preferred to let the window manager handle these
2668 * things rather than doing it yourself, because all apps will
2669 * behave consistently and according to user prefs if the window
2670 * manager handles it. Also, the window manager can take the size
2671 * of the window decorations/border into account, while your
2672 * application cannot.
2674 * In any case, if you insist on application-specified window
2675 * positioning, there's <emphasis>still</emphasis> a better way than
2676 * doing it yourself - gtk_window_set_position() will frequently
2677 * handle the details for you.
2681 gtk_window_get_size (GtkWindow *window,
2688 g_return_if_fail (GTK_IS_WINDOW (window));
2690 widget = GTK_WIDGET (window);
2692 if (width == NULL && height == NULL)
2695 if (GTK_WIDGET_MAPPED (window))
2697 gdk_drawable_get_size (GTK_WIDGET (window)->window,
2702 GdkRectangle configure_request;
2704 gtk_window_compute_configure_request (window,
2708 w = configure_request.width;
2709 h = configure_request.height;
2720 * @window: a #GtkWindow
2721 * @x: X coordinate to move window to
2722 * @y: Y coordinate to move window to
2724 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
2725 * @window to the given position. Window managers are free to ignore
2726 * this; most window managers ignore requests for initial window
2727 * positions (instead using a user-defined placement algorithm) and
2728 * honor requests after the window has already been shown.
2730 * Note: the position is the position of the gravity-determined
2731 * reference point for the window. The gravity determines two things:
2732 * first, the location of the reference point in root window
2733 * coordinates; and second, which point on the window is positioned at
2734 * the reference point.
2736 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
2737 * point is simply the @x, @y supplied to gtk_window_move(). The
2738 * top-left corner of the window decorations (aka window frame or
2739 * border) will be placed at @x, @y. Therefore, to position a window
2740 * at the top left of the screen, you want to use the default gravity
2741 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
2743 * To position a window at the bottom right corner of the screen, you
2744 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
2745 * point is at @x + the window width and @y + the window height, and
2746 * the bottom-right corner of the window border will be placed at that
2747 * reference point. So, to place a window in the bottom right corner
2748 * you would first set gravity to south east, then write:
2749 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
2750 * gdk_screen_height () - window_height)</literal>.
2752 * The extended window manager hints specification at <ulink
2753 * url="http://www.freedesktop.org/standards/wm-spec.html">
2754 * http://www.freedesktop.org/standards/wm-spec.html</ulink> has a
2755 * nice table of gravities in the "implementation notes" section.
2757 * The gtk_window_get_position() documentation may also be relevant.
2761 gtk_window_move (GtkWindow *window,
2765 GtkWindowGeometryInfo *info;
2768 g_return_if_fail (GTK_IS_WINDOW (window));
2770 widget = GTK_WIDGET (window);
2772 info = gtk_window_get_geometry_info (window, TRUE);
2774 if (GTK_WIDGET_MAPPED (window))
2776 /* we have now sent a request with this position
2777 * with currently-active constraints, so toggle flag.
2779 info->position_constraints_changed = FALSE;
2781 /* we only constrain if mapped - if not mapped,
2782 * then gtk_window_compute_configure_request()
2783 * will apply the constraints later, and we
2784 * don't want to lose information about
2785 * what position the user set before then.
2786 * i.e. if you do a move() then turn off POS_CENTER
2787 * then show the window, your move() will work.
2789 gtk_window_constrain_position (window,
2790 widget->allocation.width,
2791 widget->allocation.height,
2794 /* Note that this request doesn't go through our standard request
2795 * framework, e.g. doesn't increment configure_request_count,
2796 * doesn't set info->last, etc.; that's because
2797 * we don't save the info needed to arrive at this same request
2800 * To gtk_window_move_resize(), this will end up looking exactly
2801 * the same as the position being changed by the window
2805 /* FIXME are we handling gravity properly for framed windows? */
2807 gdk_window_move (window->frame,
2808 x - window->frame_left,
2809 y - window->frame_top);
2811 gdk_window_move (GTK_WIDGET (window)->window,
2816 /* Save this position to apply on mapping */
2817 info->initial_x = x;
2818 info->initial_y = y;
2819 info->initial_pos_set = TRUE;
2824 * gtk_window_get_position:
2825 * @window: a #GtkWindow
2826 * @root_x: return location for X coordinate of gravity-determined reference p\oint
2827 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
2829 * This function returns the position you need to pass to
2830 * gtk_window_move() to keep @window in its current position. This
2831 * means that the meaning of the returned value varies with window
2832 * gravity. See gtk_window_move() for more details.
2834 * If you haven't changed the window gravity, its gravity will be
2835 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
2836 * gets the position of the top-left corner of the window manager
2837 * frame for the window. gtk_window_move() sets the position of this
2838 * same top-left corner.
2840 * gtk_window_get_position() is not 100% reliable because the X Window System
2841 * does not specify a way to obtain the geometry of the
2842 * decorations placed on a window by the window manager.
2843 * Thus GTK+ is using a "best guess" that works with most
2846 * Moreover, nearly all window managers are historically broken with
2847 * respect to their handling of window gravity. So moving a window to
2848 * its current position as returned by gtk_window_get_position() tends
2849 * to result in moving the window slightly. Window managers are
2850 * slowly getting better over time.
2852 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
2853 * frame is not relevant, and thus gtk_window_get_position() will
2854 * always produce accurate results. However you can't use static
2855 * gravity to do things like place a window in a corner of the screen,
2856 * because static gravity ignores the window manager decorations.
2858 * If you are saving and restoring your application's window
2859 * positions, you should know that it's impossible for applications to
2860 * do this without getting it somewhat wrong because applications do
2861 * not have sufficient knowledge of window manager state. The Correct
2862 * Mechanism is to support the session management protocol (see the
2863 * "GnomeClient" object in the GNOME libraries for example) and allow
2864 * the window manager to save your window sizes and positions.
2869 gtk_window_get_position (GtkWindow *window,
2875 g_return_if_fail (GTK_IS_WINDOW (window));
2877 widget = GTK_WIDGET (window);
2879 if (window->gravity == GDK_GRAVITY_STATIC)
2881 if (GTK_WIDGET_MAPPED (widget))
2883 /* This does a server round-trip, which is sort of wrong;
2884 * but a server round-trip is inevitable for
2885 * gdk_window_get_frame_extents() in the usual
2886 * NorthWestGravity case below, so not sure what else to
2887 * do. We should likely be consistent about whether we get
2888 * the client-side info or the server-side info.
2890 gdk_window_get_origin (widget->window, root_x, root_y);
2894 GdkRectangle configure_request;
2896 gtk_window_compute_configure_request (window,
2900 *root_x = configure_request.x;
2901 *root_y = configure_request.y;
2906 GdkRectangle frame_extents;
2911 if (GTK_WIDGET_MAPPED (widget))
2914 gdk_window_get_frame_extents (window->frame, &frame_extents);
2916 gdk_window_get_frame_extents (widget->window, &frame_extents);
2917 x = frame_extents.x;
2918 y = frame_extents.y;
2919 gtk_window_get_size (window, &w, &h);
2923 /* We just say the frame has 0 size on all sides.
2924 * Not sure what else to do.
2926 gtk_window_compute_configure_request (window,
2929 x = frame_extents.x;
2930 y = frame_extents.y;
2931 w = frame_extents.width;
2932 h = frame_extents.height;
2935 switch (window->gravity)
2937 case GDK_GRAVITY_NORTH:
2938 case GDK_GRAVITY_CENTER:
2939 case GDK_GRAVITY_SOUTH:
2940 /* Find center of frame. */
2941 x += frame_extents.width / 2;
2942 /* Center client window on that point. */
2946 case GDK_GRAVITY_SOUTH_EAST:
2947 case GDK_GRAVITY_EAST:
2948 case GDK_GRAVITY_NORTH_EAST:
2949 /* Find right edge of frame */
2950 x += frame_extents.width;
2951 /* Align left edge of client at that point. */
2958 switch (window->gravity)
2960 case GDK_GRAVITY_WEST:
2961 case GDK_GRAVITY_CENTER:
2962 case GDK_GRAVITY_EAST:
2963 /* Find center of frame. */
2964 y += frame_extents.height / 2;
2965 /* Center client window there. */
2968 case GDK_GRAVITY_SOUTH_WEST:
2969 case GDK_GRAVITY_SOUTH:
2970 case GDK_GRAVITY_SOUTH_EAST:
2971 /* Find south edge of frame */
2972 y += frame_extents.height;
2973 /* Place bottom edge of client there */
2988 * gtk_window_reshow_with_initial_size:
2989 * @window: a #GtkWindow
2991 * Hides @window, then reshows it, resetting the
2992 * default size and position of the window. Used
2993 * by GUI builders only.
2996 gtk_window_reshow_with_initial_size (GtkWindow *window)
3000 g_return_if_fail (GTK_IS_WINDOW (window));
3002 widget = GTK_WIDGET (window);
3004 gtk_widget_hide (widget);
3005 gtk_widget_unrealize (widget);
3006 gtk_widget_show (widget);
3010 gtk_window_destroy (GtkObject *object)
3012 GtkWindow *window = GTK_WINDOW (object);
3014 if (window->transient_parent)
3015 gtk_window_set_transient_for (window, NULL);
3017 /* frees the icons */
3018 gtk_window_set_icon_list (window, NULL);
3020 if (window->has_user_ref_count)
3022 window->has_user_ref_count = FALSE;
3023 gtk_widget_unref (GTK_WIDGET (window));
3027 gtk_window_group_remove_window (window->group, window);
3029 gtk_window_free_key_hash (window);
3031 GTK_OBJECT_CLASS (parent_class)->destroy (object);
3035 gtk_window_mnemonic_hash_remove (gpointer key,
3039 GtkWindowMnemonic *mnemonic = key;
3040 GtkWindow *window = user;
3042 if (mnemonic->window == window)
3044 if (mnemonic->targets)
3046 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
3048 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
3049 name, mnemonic->targets->data);
3052 g_slist_free (mnemonic->targets);
3061 gtk_window_finalize (GObject *object)
3063 GtkWindow *window = GTK_WINDOW (object);
3065 toplevel_list = g_slist_remove (toplevel_list, window);
3067 g_free (window->title);
3068 g_free (window->wmclass_name);
3069 g_free (window->wmclass_class);
3070 g_free (window->wm_role);
3072 g_hash_table_foreach_remove (mnemonic_hash_table,
3073 gtk_window_mnemonic_hash_remove,
3075 if (window->geometry_info)
3077 if (window->geometry_info->widget)
3078 gtk_signal_disconnect_by_func (GTK_OBJECT (window->geometry_info->widget),
3079 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
3080 &window->geometry_info->widget);
3081 g_free (window->geometry_info);
3084 if (window->keys_changed_handler)
3086 gtk_idle_remove (window->keys_changed_handler);
3087 window->keys_changed_handler = 0;
3090 G_OBJECT_CLASS (parent_class)->finalize (object);
3094 gtk_window_show (GtkWidget *widget)
3096 GtkWindow *window = GTK_WINDOW (widget);
3097 GtkContainer *container = GTK_CONTAINER (window);
3098 gboolean need_resize;
3100 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3102 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3103 container->need_resize = FALSE;
3107 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3108 GtkAllocation allocation = { 0, 0 };
3109 GdkRectangle configure_request;
3110 GdkGeometry new_geometry;
3112 gboolean was_realized;
3114 /* We are going to go ahead and perform this configure request
3115 * and then emulate a configure notify by going ahead and
3116 * doing a size allocate. Sort of a synchronous
3117 * mini-copy of gtk_window_move_resize() here.
3119 gtk_window_compute_configure_request (window,
3124 /* We update this because we are going to go ahead
3125 * and gdk_window_resize() below, rather than
3128 info->last.configure_request.width = configure_request.width;
3129 info->last.configure_request.height = configure_request.height;
3131 /* and allocate the window - this is normally done
3132 * in move_resize in response to configure notify
3134 allocation.width = configure_request.width;
3135 allocation.height = configure_request.height;
3136 gtk_widget_size_allocate (widget, &allocation);
3138 /* Then we guarantee we have a realize */
3139 was_realized = FALSE;
3140 if (!GTK_WIDGET_REALIZED (widget))
3142 gtk_widget_realize (widget);
3143 was_realized = TRUE;
3146 /* Must be done after the windows are realized,
3147 * so that the decorations can be read
3149 gtk_decorated_window_calculate_frame_size (window);
3151 /* We only send configure request if we didn't just finish
3152 * creating the window; if we just created the window
3153 * then we created it with widget->allocation anyhow.
3156 gdk_window_resize (widget->window,
3157 configure_request.width,
3158 configure_request.height);
3161 gtk_container_check_resize (container);
3163 gtk_widget_map (widget);
3165 /* Try to make sure that we have some focused widget
3167 if (!window->focus_widget && !GTK_IS_PLUG (window))
3168 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
3171 gtk_grab_add (widget);
3175 gtk_window_hide (GtkWidget *widget)
3177 GtkWindow *window = GTK_WINDOW (widget);
3179 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3180 gtk_widget_unmap (widget);
3183 gtk_grab_remove (widget);
3187 gtk_window_map (GtkWidget *widget)
3189 GtkWindow *window = GTK_WINDOW (widget);
3190 GdkWindow *toplevel;
3192 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3194 if (window->bin.child &&
3195 GTK_WIDGET_VISIBLE (window->bin.child) &&
3196 !GTK_WIDGET_MAPPED (window->bin.child))
3197 gtk_widget_map (window->bin.child);
3200 toplevel = window->frame;
3202 toplevel = widget->window;
3204 if (window->maximize_initially)
3205 gdk_window_maximize (toplevel);
3207 gdk_window_unmaximize (toplevel);
3209 if (window->stick_initially)
3210 gdk_window_stick (toplevel);
3212 gdk_window_unstick (toplevel);
3214 if (window->iconify_initially)
3215 gdk_window_iconify (toplevel);
3217 gdk_window_deiconify (toplevel);
3219 /* No longer use the default settings */
3220 window->need_default_size = FALSE;
3221 window->need_default_position = FALSE;
3223 gdk_window_show (widget->window);
3226 gdk_window_show (window->frame);
3230 gtk_window_unmap (GtkWidget *widget)
3232 GtkWindow *window = GTK_WINDOW (widget);
3233 GtkWindowGeometryInfo *info;
3234 GdkWindowState state;
3236 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3238 gdk_window_withdraw (window->frame);
3240 gdk_window_withdraw (widget->window);
3242 window->configure_request_count = 0;
3243 window->configure_notify_received = FALSE;
3245 /* on unmap, we reset the default positioning of the window,
3246 * so it's placed again, but we don't reset the default
3247 * size of the window, so it's remembered.
3249 window->need_default_position = TRUE;
3251 info = gtk_window_get_geometry_info (window, FALSE);
3254 info->initial_pos_set = FALSE;
3255 info->position_constraints_changed = FALSE;
3258 state = gdk_window_get_state (widget->window);
3259 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
3260 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
3261 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
3265 gtk_window_realize (GtkWidget *widget)
3268 GdkWindow *parent_window;
3269 GdkWindowAttr attributes;
3270 gint attributes_mask;
3272 window = GTK_WINDOW (widget);
3274 /* ensure widget tree is properly size allocated */
3275 if (widget->allocation.x == -1 &&
3276 widget->allocation.y == -1 &&
3277 widget->allocation.width == 1 &&
3278 widget->allocation.height == 1)
3280 GtkRequisition requisition;
3281 GtkAllocation allocation = { 0, 0, 200, 200 };
3283 gtk_widget_size_request (widget, &requisition);
3284 if (requisition.width || requisition.height)
3286 /* non-empty window */
3287 allocation.width = requisition.width;
3288 allocation.height = requisition.height;
3290 gtk_widget_size_allocate (widget, &allocation);
3292 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3294 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3297 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3299 switch (window->type)
3301 case GTK_WINDOW_TOPLEVEL:
3302 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3304 case GTK_WINDOW_POPUP:
3305 attributes.window_type = GDK_WINDOW_TEMP;
3308 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3312 attributes.title = window->title;
3313 attributes.wmclass_name = window->wmclass_name;
3314 attributes.wmclass_class = window->wmclass_class;
3315 attributes.wclass = GDK_INPUT_OUTPUT;
3316 attributes.visual = gtk_widget_get_visual (widget);
3317 attributes.colormap = gtk_widget_get_colormap (widget);
3319 if (window->has_frame)
3321 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3322 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3323 attributes.event_mask = (GDK_EXPOSURE_MASK |
3324 GDK_KEY_PRESS_MASK |
3325 GDK_ENTER_NOTIFY_MASK |
3326 GDK_LEAVE_NOTIFY_MASK |
3327 GDK_FOCUS_CHANGE_MASK |
3328 GDK_STRUCTURE_MASK |
3329 GDK_BUTTON_MOTION_MASK |
3330 GDK_POINTER_MOTION_HINT_MASK |
3331 GDK_BUTTON_PRESS_MASK |
3332 GDK_BUTTON_RELEASE_MASK);
3334 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3336 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
3337 &attributes, attributes_mask);
3339 gdk_window_set_user_data (window->frame, widget);
3341 attributes.window_type = GDK_WINDOW_CHILD;
3342 attributes.x = window->frame_left;
3343 attributes.y = window->frame_top;
3345 attributes_mask = GDK_WA_X | GDK_WA_Y;
3347 parent_window = window->frame;
3351 attributes_mask = 0;
3352 parent_window = gtk_widget_get_root_window (widget);
3355 attributes.width = widget->allocation.width;
3356 attributes.height = widget->allocation.height;
3357 attributes.event_mask = gtk_widget_get_events (widget);
3358 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3359 GDK_KEY_PRESS_MASK |
3360 GDK_KEY_RELEASE_MASK |
3361 GDK_ENTER_NOTIFY_MASK |
3362 GDK_LEAVE_NOTIFY_MASK |
3363 GDK_FOCUS_CHANGE_MASK |
3364 GDK_STRUCTURE_MASK);
3366 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3367 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3368 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3370 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3372 gdk_window_set_user_data (widget->window, window);
3374 widget->style = gtk_style_attach (widget->style, widget->window);
3375 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3377 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3379 /* This is a bad hack to set the window background. */
3380 gtk_window_paint (widget, NULL);
3382 if (window->transient_parent &&
3383 GTK_WIDGET_REALIZED (window->transient_parent))
3384 gdk_window_set_transient_for (widget->window,
3385 GTK_WIDGET (window->transient_parent)->window);
3387 if (window->wm_role)
3388 gdk_window_set_role (widget->window, window->wm_role);
3390 if (!window->decorated)
3391 gdk_window_set_decorations (widget->window, 0);
3393 gdk_window_set_type_hint (widget->window, window->type_hint);
3395 /* transient_for must be set to allow the modal hint */
3396 if (window->transient_parent && window->modal)
3397 gdk_window_set_modal_hint (widget->window, TRUE);
3399 gdk_window_set_modal_hint (widget->window, FALSE);
3402 gtk_window_realize_icon (window);
3406 gtk_window_unrealize (GtkWidget *widget)
3409 GtkWindowGeometryInfo *info;
3411 window = GTK_WINDOW (widget);
3413 /* On unrealize, we reset the size of the window such
3414 * that we will re-apply the default sizing stuff
3415 * next time we show the window.
3417 * Default positioning is reset on unmap, instead of unrealize.
3419 window->need_default_size = TRUE;
3420 info = gtk_window_get_geometry_info (window, FALSE);
3423 info->resize_width = -1;
3424 info->resize_height = -1;
3425 info->last.configure_request.x = 0;
3426 info->last.configure_request.y = 0;
3427 info->last.configure_request.width = -1;
3428 info->last.configure_request.height = -1;
3429 /* be sure we reset geom hints on re-realize */
3430 info->last.flags = 0;
3435 gdk_window_set_user_data (window->frame, NULL);
3436 gdk_window_destroy (window->frame);
3437 window->frame = NULL;
3441 gtk_window_unrealize_icon (window);
3443 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3447 gtk_window_size_request (GtkWidget *widget,
3448 GtkRequisition *requisition)
3453 window = GTK_WINDOW (widget);
3454 bin = GTK_BIN (window);
3456 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3457 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3459 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3461 GtkRequisition child_requisition;
3463 gtk_widget_size_request (bin->child, &child_requisition);
3465 requisition->width += child_requisition.width;
3466 requisition->height += child_requisition.height;
3471 gtk_window_size_allocate (GtkWidget *widget,
3472 GtkAllocation *allocation)
3475 GtkAllocation child_allocation;
3477 window = GTK_WINDOW (widget);
3478 widget->allocation = *allocation;
3480 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3482 child_allocation.x = GTK_CONTAINER (window)->border_width;
3483 child_allocation.y = GTK_CONTAINER (window)->border_width;
3484 child_allocation.width =
3485 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3486 child_allocation.height =
3487 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3489 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3492 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3494 gdk_window_resize (window->frame,
3495 allocation->width + window->frame_left + window->frame_right,
3496 allocation->height + window->frame_top + window->frame_bottom);
3501 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3504 gboolean return_val;
3506 window = GTK_WINDOW (widget);
3508 if (window->frame && (event->any.window == window->frame))
3510 if ((event->type != GDK_KEY_PRESS) &&
3511 (event->type != GDK_KEY_RELEASE) &&
3512 (event->type != GDK_FOCUS_CHANGE))
3514 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
3516 gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
3521 g_object_unref (event->any.window);
3522 event->any.window = g_object_ref (widget->window);
3530 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3532 GdkEventConfigure *configure_event;
3535 switch (event->type)
3538 configure_event = (GdkEventConfigure *)event;
3540 /* Invalidate the decorations */
3543 rect.width = configure_event->width;
3544 rect.height = configure_event->height;
3546 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3548 /* Pass on the (modified) configure event */
3549 configure_event->width -= window->frame_left + window->frame_right;
3550 configure_event->height -= window->frame_top + window->frame_bottom;
3551 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3560 gtk_window_configure_event (GtkWidget *widget,
3561 GdkEventConfigure *event)
3563 GtkWindow *window = GTK_WINDOW (widget);
3564 gboolean expected_reply = window->configure_request_count > 0;
3566 /* window->configure_request_count incremented for each
3567 * configure request, and decremented to a min of 0 for
3568 * each configure notify.
3570 * All it means is that we know we will get at least
3571 * window->configure_request_count more configure notifies.
3572 * We could get more configure notifies than that; some
3573 * of the configure notifies we get may be unrelated to
3574 * the configure requests. But we will get at least
3575 * window->configure_request_count notifies.
3578 if (window->configure_request_count > 0)
3579 window->configure_request_count -= 1;
3581 /* As an optimization, we avoid a resize when possible.
3583 * The only times we can avoid a resize are:
3584 * - we know only the position changed, not the size
3585 * - we know we have made more requests and so will get more
3586 * notifies and can wait to resize when we get them
3589 if (!expected_reply &&
3590 (widget->allocation.width == event->width &&
3591 widget->allocation.height == event->height))
3595 * If we do need to resize, we do that by:
3596 * - filling in widget->allocation with the new size
3597 * - setting configure_notify_received to TRUE
3598 * for use in gtk_window_move_resize()
3599 * - queueing a resize, leading to invocation of
3600 * gtk_window_move_resize() in an idle handler
3604 window->configure_notify_received = TRUE;
3606 widget->allocation.width = event->width;
3607 widget->allocation.height = event->height;
3609 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3614 /* the accel_key and accel_mods fields of the key have to be setup
3615 * upon calling this function. it'll then return whether that key
3616 * is at all used as accelerator, and if so will OR in the
3617 * accel_flags member of the key.
3620 _gtk_window_query_nonaccels (GtkWindow *window,
3622 GdkModifierType accel_mods)
3624 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3626 /* movement keys are considered locked accels */
3629 static const guint bindings[] = {
3630 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
3631 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
3635 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
3636 if (bindings[i] == accel_key)
3640 /* mnemonics are considered locked accels */
3641 if (accel_mods == window->mnemonic_modifier)
3643 GtkWindowMnemonic mkey;
3645 mkey.window = window;
3646 mkey.keyval = accel_key;
3647 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
3655 gtk_window_key_press_event (GtkWidget *widget,
3662 window = GTK_WINDOW (widget);
3666 /* Check for mnemonics and accelerators
3669 handled = _gtk_window_activate_key (window, event);
3673 focus = window->focus_widget;
3675 g_object_ref (focus);
3678 focus && focus != widget &&
3679 gtk_widget_get_toplevel (focus) == widget)
3683 if (GTK_WIDGET_IS_SENSITIVE (focus))
3684 handled = gtk_widget_event (focus, (GdkEvent*) event);
3686 parent = focus->parent;
3688 g_object_ref (parent);
3690 g_object_unref (focus);
3696 g_object_unref (focus);
3699 /* Chain up, invokes binding set */
3700 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
3701 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
3707 gtk_window_key_release_event (GtkWidget *widget,
3713 window = GTK_WINDOW (widget);
3715 if (window->focus_widget &&
3716 window->focus_widget != widget &&
3717 GTK_WIDGET_SENSITIVE (window->focus_widget))
3719 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
3722 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
3723 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
3729 gtk_window_real_activate_default (GtkWindow *window)
3731 gtk_window_activate_default (window);
3735 gtk_window_real_activate_focus (GtkWindow *window)
3737 gtk_window_activate_focus (window);
3741 gtk_window_move_focus (GtkWindow *window,
3742 GtkDirectionType dir)
3744 gtk_widget_child_focus (GTK_WIDGET (window), dir);
3746 if (!GTK_CONTAINER (window)->focus_child)
3747 gtk_window_set_focus (window, NULL);
3751 gtk_window_enter_notify_event (GtkWidget *widget,
3752 GdkEventCrossing *event)
3758 gtk_window_leave_notify_event (GtkWidget *widget,
3759 GdkEventCrossing *event)
3765 do_focus_change (GtkWidget *widget,
3768 GdkEventFocus fevent;
3770 g_object_ref (widget);
3773 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
3775 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
3777 fevent.type = GDK_FOCUS_CHANGE;
3778 fevent.window = widget->window;
3781 gtk_widget_event (widget, (GdkEvent*) &fevent);
3783 g_object_notify (G_OBJECT (widget), "has_focus");
3785 g_object_unref (widget);
3789 gtk_window_focus_in_event (GtkWidget *widget,
3790 GdkEventFocus *event)
3792 GtkWindow *window = GTK_WINDOW (widget);
3794 /* It appears spurious focus in events can occur when
3795 * the window is hidden. So we'll just check to see if
3796 * the window is visible before actually handling the
3799 if (GTK_WIDGET_VISIBLE (widget))
3801 _gtk_window_set_has_toplevel_focus (window, TRUE);
3802 _gtk_window_set_is_active (window, TRUE);
3809 gtk_window_focus_out_event (GtkWidget *widget,
3810 GdkEventFocus *event)
3812 GtkWindow *window = GTK_WINDOW (widget);
3814 _gtk_window_set_has_toplevel_focus (window, FALSE);
3815 _gtk_window_set_is_active (window, FALSE);
3820 static GdkAtom atom_rcfiles = GDK_NONE;
3823 gtk_window_read_rcfiles (GtkWidget *widget,
3824 GdkEventClient *event)
3826 GList *embedded_windows;
3828 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
3829 if (embedded_windows)
3834 for (i = 0; i < 5; i++)
3836 sev.data_format = 32;
3837 sev.message_type = atom_rcfiles;
3839 while (embedded_windows)
3841 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
3842 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), (GdkEvent *) &sev, xid);
3843 embedded_windows = embedded_windows->next;
3847 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
3851 gtk_window_client_event (GtkWidget *widget,
3852 GdkEventClient *event)
3855 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
3857 if (event->message_type == atom_rcfiles)
3858 gtk_window_read_rcfiles (widget, event);
3864 gtk_window_check_resize (GtkContainer *container)
3866 GtkWindow *window = GTK_WINDOW (container);
3868 if (GTK_WIDGET_VISIBLE (container))
3869 gtk_window_move_resize (window);
3873 gtk_window_focus (GtkWidget *widget,
3874 GtkDirectionType direction)
3878 GtkContainer *container;
3879 GtkWidget *old_focus_child;
3882 container = GTK_CONTAINER (widget);
3883 window = GTK_WINDOW (widget);
3884 bin = GTK_BIN (widget);
3886 old_focus_child = container->focus_child;
3888 /* We need a special implementation here to deal properly with wrapping
3889 * around in the tab chain without the danger of going into an
3892 if (old_focus_child)
3894 if (gtk_widget_child_focus (old_focus_child, direction))
3898 if (window->focus_widget)
3900 /* Wrapped off the end, clear the focus setting for the toplpevel */
3901 parent = window->focus_widget->parent;
3904 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
3905 parent = GTK_WIDGET (parent)->parent;
3908 gtk_window_set_focus (GTK_WINDOW (container), NULL);
3911 /* Now try to focus the first widget in the window */
3914 if (gtk_widget_child_focus (bin->child, direction))
3922 gtk_window_real_set_focus (GtkWindow *window,
3925 GtkWidget *old_focus = window->focus_widget;
3926 gboolean def_flags = 0;
3930 g_object_ref (old_focus);
3931 g_object_freeze_notify (G_OBJECT (old_focus));
3935 g_object_ref (focus);
3936 g_object_freeze_notify (G_OBJECT (focus));
3939 if (window->default_widget)
3940 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
3942 if (window->focus_widget)
3944 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3945 (window->focus_widget != window->default_widget))
3947 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3949 if (window->default_widget)
3950 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3953 if (window->has_focus)
3954 do_focus_change (window->focus_widget, FALSE);
3956 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
3959 window->focus_widget = focus;
3961 if (window->focus_widget)
3963 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3964 (window->focus_widget != window->default_widget))
3966 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
3967 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3969 if (window->default_widget)
3970 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3973 if (window->has_focus)
3974 do_focus_change (window->focus_widget, TRUE);
3976 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
3979 if (window->default_widget &&
3980 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
3981 gtk_widget_queue_draw (window->default_widget);
3985 g_object_thaw_notify (G_OBJECT (old_focus));
3986 g_object_unref (old_focus);
3990 g_object_thaw_notify (G_OBJECT (focus));
3991 g_object_unref (focus);
3995 /*********************************
3996 * Functions related to resizing *
3997 *********************************/
3999 /* This function doesn't constrain to geometry hints */
4001 gtk_window_compute_configure_request_size (GtkWindow *window,
4005 GtkRequisition requisition;
4006 GtkWindowGeometryInfo *info;
4010 * - we've done a size request
4013 widget = GTK_WIDGET (window);
4015 info = gtk_window_get_geometry_info (window, FALSE);
4017 if (window->need_default_size)
4019 gtk_widget_get_child_requisition (widget, &requisition);
4021 /* Default to requisition */
4022 *width = requisition.width;
4023 *height = requisition.height;
4025 /* If window is empty so requests 0, default to random nonzero size */
4026 if (*width == 0 && *height == 0)
4032 /* Override requisition with default size */
4036 gint base_width = 0;
4037 gint base_height = 0;
4039 gint height_inc = 1;
4041 if (info->default_is_geometry &&
4042 (info->default_width > 0 || info->default_height > 0))
4044 GdkGeometry geometry;
4047 gtk_window_compute_hints (window, &geometry, &flags);
4049 if (flags & GDK_HINT_BASE_SIZE)
4051 base_width = geometry.base_width;
4052 base_height = geometry.base_height;
4054 else if (flags & GDK_HINT_MIN_SIZE)
4056 base_width = geometry.min_width;
4057 base_height = geometry.min_height;
4059 if (flags & GDK_HINT_RESIZE_INC)
4061 width_inc = geometry.width_inc;
4062 height_inc = geometry.height_inc;
4066 if (info->default_width > 0)
4067 *width = info->default_width * width_inc + base_width;
4069 if (info->default_height > 0)
4070 *height = info->default_height * height_inc + base_height;
4075 /* Default to keeping current size */
4076 *width = widget->allocation.width;
4077 *height = widget->allocation.height;
4080 /* Override any size with gtk_window_resize() values */
4083 if (info->resize_width > 0)
4084 *width = info->resize_width;
4086 if (info->resize_height > 0)
4087 *height = info->resize_height;
4092 gtk_window_compute_configure_request (GtkWindow *window,
4093 GdkRectangle *request,
4094 GdkGeometry *geometry,
4097 GdkGeometry new_geometry;
4101 GtkWindowPosition pos;
4102 GtkWidget *parent_widget;
4103 GtkWindowGeometryInfo *info;
4106 widget = GTK_WIDGET (window);
4108 gtk_widget_size_request (widget, NULL);
4109 gtk_window_compute_configure_request_size (window, &w, &h);
4111 gtk_window_compute_hints (window, &new_geometry, &new_flags);
4112 gtk_window_constrain_size (window,
4113 &new_geometry, new_flags,
4117 parent_widget = (GtkWidget*) window->transient_parent;
4119 pos = window->position;
4120 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
4121 (parent_widget == NULL ||
4122 !GTK_WIDGET_MAPPED (parent_widget)))
4123 pos = GTK_WIN_POS_NONE;
4125 info = gtk_window_get_geometry_info (window, TRUE);
4127 /* by default, don't change position requested */
4128 x = info->last.configure_request.x;
4129 y = info->last.configure_request.y;
4131 if (window->need_default_position)
4134 /* FIXME this all interrelates with window gravity.
4135 * For most of them I think we want to set GRAVITY_CENTER.
4137 * Not sure how to go about that.
4142 /* here we are only handling CENTER_ALWAYS
4143 * as it relates to default positioning,
4144 * where it's equivalent to simply CENTER
4146 case GTK_WIN_POS_CENTER_ALWAYS:
4147 case GTK_WIN_POS_CENTER:
4149 gint px, py, monitor_num;
4150 GdkRectangle monitor;
4152 gdk_window_get_pointer (gdk_screen_get_root_window (window->screen),
4155 monitor_num = gdk_screen_get_monitor_at_point (window->screen, px, py);
4156 if (monitor_num == -1)
4159 gdk_screen_get_monitor_geometry (window->screen, monitor_num, &monitor);
4161 x = (monitor.width - w) / 2 + monitor.x;
4162 y = (monitor.height - h) / 2 + monitor.y;
4166 case GTK_WIN_POS_CENTER_ON_PARENT:
4170 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
4172 gdk_window_get_origin (parent_widget->window,
4175 x = ox + (parent_widget->allocation.width - w) / 2;
4176 y = oy + (parent_widget->allocation.height - h) / 2;
4180 case GTK_WIN_POS_MOUSE:
4182 gint screen_width = gdk_screen_get_width (window->screen);
4183 gint screen_height = gdk_screen_get_height (window->screen);
4186 gdk_window_get_pointer (NULL, &px, &py, NULL);
4189 x = CLAMP (x, 0, screen_width - w);
4190 y = CLAMP (y, 0, screen_height - h);
4197 } /* if (window->need_default_position) */
4199 if (window->need_default_position &&
4200 info->initial_pos_set)
4202 x = info->initial_x;
4203 y = info->initial_y;
4204 gtk_window_constrain_position (window, w, h, &x, &y);
4210 request->height = h;
4213 *geometry = new_geometry;
4219 gtk_window_constrain_position (GtkWindow *window,
4225 /* See long comments in gtk_window_move_resize()
4226 * on when it's safe to call this function.
4228 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4230 gint center_x, center_y;
4231 gint screen_width = gdk_screen_get_width (window->screen);
4232 gint screen_height = gdk_screen_get_height (window->screen);
4234 center_x = (screen_width - new_width) / 2;
4235 center_y = (screen_height - new_height) / 2;
4243 gtk_window_move_resize (GtkWindow *window)
4247 * First we determine whether any information has changed that would
4248 * cause us to revise our last configure request. If we would send
4249 * a different configure request from last time, then
4250 * configure_request_size_changed = TRUE or
4251 * configure_request_pos_changed = TRUE. configure_request_size_changed
4252 * may be true due to new hints, a gtk_window_resize(), or whatever.
4253 * configure_request_pos_changed may be true due to gtk_window_set_position()
4254 * or gtk_window_move().
4256 * If the configure request has changed, we send off a new one. To
4257 * ensure GTK+ invariants are maintained (resize queue does what it
4258 * should), we go ahead and size_allocate the requested size in this
4261 * If the configure request has not changed, we don't ever resend
4262 * it, because it could mean fighting the user or window manager.
4265 * To prepare the configure request, we come up with a base size/pos:
4266 * - the one from gtk_window_move()/gtk_window_resize()
4267 * - else default_width, default_height if we haven't ever
4269 * - else the size request if we haven't ever been mapped,
4270 * as a substitute default size
4271 * - else the current size of the window, as received from
4272 * configure notifies (i.e. the current allocation)
4274 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4275 * the position request to be centered.
4278 GtkContainer *container;
4279 GtkWindowGeometryInfo *info;
4280 GdkGeometry new_geometry;
4282 GdkRectangle new_request;
4283 gboolean configure_request_size_changed;
4284 gboolean configure_request_pos_changed;
4285 gboolean hints_changed; /* do we need to send these again */
4286 GtkWindowLastGeometryInfo saved_last_info;
4288 widget = GTK_WIDGET (window);
4289 container = GTK_CONTAINER (widget);
4290 info = gtk_window_get_geometry_info (window, TRUE);
4292 configure_request_size_changed = FALSE;
4293 configure_request_pos_changed = FALSE;
4295 gtk_window_compute_configure_request (window, &new_request,
4296 &new_geometry, &new_flags);
4298 /* This check implies the invariant that we never set info->last
4299 * without setting the hints and sending off a configure request.
4301 * If we change info->last without sending the request, we may
4304 if (info->last.configure_request.x != new_request.x ||
4305 info->last.configure_request.y != new_request.y)
4306 configure_request_pos_changed = TRUE;
4308 if ((info->last.configure_request.width != new_request.width ||
4309 info->last.configure_request.height != new_request.height))
4310 configure_request_size_changed = TRUE;
4312 hints_changed = FALSE;
4314 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4315 &new_geometry, new_flags))
4317 hints_changed = TRUE;
4320 /* Position Constraints
4321 * ====================
4323 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4324 * a default. The other POS_ values are used only when the
4325 * window is shown, not after that.
4327 * However, we can't implement a position constraint as
4328 * "anytime the window size changes, center the window"
4329 * because this may well end up fighting the WM or user. In
4330 * fact it gets in an infinite loop with at least one WM.
4332 * Basically, applications are in no way in a position to
4333 * constrain the position of a window, with one exception:
4334 * override redirect windows. (Really the intended purpose
4335 * of CENTER_ALWAYS anyhow, I would think.)
4337 * So the way we implement this "constraint" is to say that when WE
4338 * cause a move or resize, i.e. we make a configure request changing
4339 * window size, we recompute the CENTER_ALWAYS position to reflect
4340 * the new window size, and include it in our request. Also, if we
4341 * just turned on CENTER_ALWAYS we snap to center with a new
4342 * request. Otherwise, if we are just NOTIFIED of a move or resize
4343 * done by someone else e.g. the window manager, we do NOT send a
4344 * new configure request.
4346 * For override redirect windows, this works fine; all window
4347 * sizes are from our configure requests. For managed windows,
4348 * it is at least semi-sane, though who knows what the
4349 * app author is thinking.
4352 /* This condition should be kept in sync with the condition later on
4353 * that determines whether we send a configure request. i.e. we
4354 * should do this position constraining anytime we were going to
4355 * send a configure request anyhow, plus when constraints have
4358 if (configure_request_pos_changed ||
4359 configure_request_size_changed ||
4361 info->position_constraints_changed)
4363 /* We request the constrained position if:
4364 * - we were changing position, and need to clamp
4365 * the change to the constraint
4366 * - we're changing the size anyway
4367 * - set_position() was called to toggle CENTER_ALWAYS on
4370 gtk_window_constrain_position (window,
4376 /* Update whether we need to request a move */
4377 if (info->last.configure_request.x != new_request.x ||
4378 info->last.configure_request.y != new_request.y)
4379 configure_request_pos_changed = TRUE;
4381 configure_request_pos_changed = FALSE;
4385 if (window->type == GTK_WINDOW_TOPLEVEL)
4387 int notify_x, notify_y;
4389 /* this is the position from the last configure notify */
4390 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4392 g_message ("--- %s ---\n"
4393 "last : %d,%d\t%d x %d\n"
4394 "this : %d,%d\t%d x %d\n"
4395 "alloc : %d,%d\t%d x %d\n"
4397 "resize: \t%d x %d\n"
4398 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4399 "configure_notify_received: %d\n"
4400 "configure_request_count: %d\n"
4401 "position_constraints_changed: %d\n",
4402 window->title ? window->title : "(no title)",
4403 info->last.configure_request.x,
4404 info->last.configure_request.y,
4405 info->last.configure_request.width,
4406 info->last.configure_request.height,
4412 widget->allocation.width,
4413 widget->allocation.height,
4414 widget->requisition.width,
4415 widget->requisition.height,
4417 info->resize_height,
4418 configure_request_pos_changed,
4419 configure_request_size_changed,
4421 window->configure_notify_received,
4422 window->configure_request_count,
4423 info->position_constraints_changed);
4427 saved_last_info = info->last;
4428 info->last.geometry = new_geometry;
4429 info->last.flags = new_flags;
4430 info->last.configure_request = new_request;
4432 /* need to set PPosition so the WM will look at our position,
4433 * but we don't want to count PPosition coming and going as a hints
4434 * change for future iterations. So we saved info->last prior to
4438 /* Also, if the initial position was explicitly set, then we always
4439 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4443 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4444 * this is an initial map
4447 if ((configure_request_pos_changed ||
4448 info->initial_pos_set ||
4449 (window->need_default_position &&
4450 window->position != GTK_WIN_POS_NONE)) &&
4451 (new_flags & GDK_HINT_POS) == 0)
4453 new_flags |= GDK_HINT_POS;
4454 hints_changed = TRUE;
4457 /* Set hints if necessary
4460 gdk_window_set_geometry_hints (widget->window,
4464 /* handle resizing/moving and widget tree allocation
4466 if (window->configure_notify_received)
4468 GtkAllocation allocation;
4470 /* If we have received a configure event since
4471 * the last time in this function, we need to
4472 * accept our new size and size_allocate child widgets.
4473 * (see gtk_window_configure_event() for more details).
4475 * 1 or more configure notifies may have been received.
4476 * Also, configure_notify_received will only be TRUE
4477 * if all expected configure notifies have been received
4478 * (one per configure request), as an optimization.
4481 window->configure_notify_received = FALSE;
4483 /* gtk_window_configure_event() filled in widget->allocation */
4484 allocation = widget->allocation;
4485 gtk_widget_size_allocate (widget, &allocation);
4487 /* If the configure request changed, it means that
4489 * 1) coincidentally changed hints or widget properties
4490 * impacting the configure request before getting
4491 * a configure notify, or
4492 * 2) some broken widget is changing its size request
4493 * during size allocation, resulting in
4494 * a false appearance of changed configure request.
4496 * For 1), we could just go ahead and ask for the
4497 * new size right now, but doing that for 2)
4498 * might well be fighting the user (and can even
4499 * trigger a loop). Since we really don't want to
4500 * do that, we requeue a resize in hopes that
4501 * by the time it gets handled, the child has seen
4502 * the light and is willing to go along with the
4503 * new size. (this happens for the zvt widget, since
4504 * the size_allocate() above will have stored the
4505 * requisition corresponding to the new size in the
4508 * This doesn't buy us anything for 1), but it shouldn't
4509 * hurt us too badly, since it is what would have
4510 * happened if we had gotten the configure event before
4511 * the new size had been set.
4514 if (configure_request_size_changed ||
4515 configure_request_pos_changed)
4517 /* Don't change the recorded last info after all, because we
4518 * haven't actually updated to the new info yet - we decided
4519 * to postpone our configure request until later.
4521 info->last = saved_last_info;
4523 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
4526 else if ((configure_request_size_changed || hints_changed) &&
4527 (widget->allocation.width != new_request.width ||
4528 widget->allocation.height != new_request.height))
4531 /* We are in one of the following situations:
4532 * A. configure_request_size_changed
4533 * our requisition has changed and we need a different window size,
4534 * so we request it from the window manager.
4535 * B. !configure_request_size_changed && hints_changed
4536 * the window manager rejects our size, but we have just changed the
4537 * window manager hints, so there's a chance our request will
4538 * be honoured this time, so we try again.
4540 * However, if the new requisition is the same as the current allocation,
4541 * we don't request it again, since we won't get a ConfigureNotify back from
4542 * the window manager unless it decides to change our requisition. If
4543 * we don't get the ConfigureNotify back, the resize queue will never be run.
4546 /* Now send the configure request */
4547 if (configure_request_pos_changed)
4551 gdk_window_move_resize (window->frame,
4552 new_request.x - window->frame_left,
4553 new_request.y - window->frame_top,
4554 new_request.width + window->frame_left + window->frame_right,
4555 new_request.height + window->frame_top + window->frame_bottom);
4556 gdk_window_resize (widget->window,
4557 new_request.width, new_request.height);
4561 gdk_window_move_resize (widget->window,
4562 new_request.x, new_request.y,
4563 new_request.width, new_request.height);
4565 else /* only size changed */
4568 gdk_window_resize (window->frame,
4569 new_request.width + window->frame_left + window->frame_right,
4570 new_request.height + window->frame_top + window->frame_bottom);
4572 gdk_window_resize (widget->window,
4573 new_request.width, new_request.height);
4576 /* Increment the number of have-not-yet-received-notify requests */
4577 window->configure_request_count += 1;
4579 /* We have now sent a request since the last position constraint
4580 * change and definitely don't need a an initial size again (not
4581 * resetting this here can lead to infinite loops for
4582 * GTK_RESIZE_IMMEDIATE containers)
4584 info->position_constraints_changed = FALSE;
4585 info->initial_pos_set = FALSE;
4586 info->resize_width = -1;
4587 info->resize_height = -1;
4589 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
4590 * configure event in response to our resizing request.
4591 * the configure event will cause a new resize with
4592 * ->configure_notify_received=TRUE.
4593 * until then, we want to
4594 * - discard expose events
4595 * - coalesce resizes for our children
4596 * - defer any window resizes until the configure event arrived
4597 * to achieve this, we queue a resize for the window, but remove its
4598 * resizing handler, so resizing will not be handled from the next
4599 * idle handler but when the configure event arrives.
4601 * FIXME: we should also dequeue the pending redraws here, since
4602 * we handle those ourselves upon ->configure_notify_received==TRUE.
4604 if (container->resize_mode == GTK_RESIZE_QUEUE)
4606 gtk_widget_queue_resize (widget);
4607 _gtk_container_dequeue_resize_handler (container);
4612 /* Handle any position changes.
4614 if (configure_request_pos_changed)
4618 gdk_window_move (window->frame,
4619 new_request.x - window->frame_left,
4620 new_request.y - window->frame_top);
4623 gdk_window_move (widget->window,
4624 new_request.x, new_request.y);
4627 /* And run the resize queue.
4629 gtk_container_resize_children (container);
4633 /* Compare two sets of Geometry hints for equality.
4636 gtk_window_compare_hints (GdkGeometry *geometry_a,
4638 GdkGeometry *geometry_b,
4641 if (flags_a != flags_b)
4644 if ((flags_a & GDK_HINT_MIN_SIZE) &&
4645 (geometry_a->min_width != geometry_b->min_width ||
4646 geometry_a->min_height != geometry_b->min_height))
4649 if ((flags_a & GDK_HINT_MAX_SIZE) &&
4650 (geometry_a->max_width != geometry_b->max_width ||
4651 geometry_a->max_height != geometry_b->max_height))
4654 if ((flags_a & GDK_HINT_BASE_SIZE) &&
4655 (geometry_a->base_width != geometry_b->base_width ||
4656 geometry_a->base_height != geometry_b->base_height))
4659 if ((flags_a & GDK_HINT_ASPECT) &&
4660 (geometry_a->min_aspect != geometry_b->min_aspect ||
4661 geometry_a->max_aspect != geometry_b->max_aspect))
4664 if ((flags_a & GDK_HINT_RESIZE_INC) &&
4665 (geometry_a->width_inc != geometry_b->width_inc ||
4666 geometry_a->height_inc != geometry_b->height_inc))
4669 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
4670 geometry_a->win_gravity != geometry_b->win_gravity)
4677 _gtk_window_constrain_size (GtkWindow *window,
4683 GtkWindowGeometryInfo *info;
4685 g_return_if_fail (GTK_IS_WINDOW (window));
4687 info = window->geometry_info;
4690 GdkWindowHints flags = info->last.flags;
4691 GdkGeometry *geometry = &info->last.geometry;
4693 gtk_window_constrain_size (window,
4704 gtk_window_constrain_size (GtkWindow *window,
4705 GdkGeometry *geometry,
4712 gdk_window_constrain_size (geometry, flags, width, height,
4713 new_width, new_height);
4716 /* Compute the set of geometry hints and flags for a window
4717 * based on the application set geometry, and requisiition
4718 * of the window. gtk_widget_size_request() must have been
4722 gtk_window_compute_hints (GtkWindow *window,
4723 GdkGeometry *new_geometry,
4727 gint extra_width = 0;
4728 gint extra_height = 0;
4729 GtkWindowGeometryInfo *geometry_info;
4730 GtkRequisition requisition;
4732 widget = GTK_WIDGET (window);
4734 gtk_widget_get_child_requisition (widget, &requisition);
4735 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
4739 *new_flags = geometry_info->mask;
4740 *new_geometry = geometry_info->geometry;
4747 if (geometry_info && geometry_info->widget)
4749 GtkRequisition child_requisition;
4751 /* FIXME: This really isn't right. It gets the min size wrong and forces
4752 * callers to do horrible hacks like set a huge usize on the child requisition
4753 * to get the base size right. We really want to find the answers to:
4755 * - If the geometry widget was infinitely big, how much extra space
4756 * would be needed for the stuff around it.
4758 * - If the geometry widget was infinitely small, how big would the
4759 * window still have to be.
4761 * Finding these answers would be a bit of a mess here. (Bug #68668)
4763 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
4765 extra_width = widget->requisition.width - child_requisition.width;
4766 extra_height = widget->requisition.height - child_requisition.height;
4769 /* We don't want to set GDK_HINT_POS in here, we just set it
4770 * in gtk_window_move_resize() when we want the position
4774 if (*new_flags & GDK_HINT_BASE_SIZE)
4776 new_geometry->base_width += extra_width;
4777 new_geometry->base_height += extra_height;
4779 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
4780 (*new_flags & GDK_HINT_RESIZE_INC) &&
4781 ((extra_width != 0) || (extra_height != 0)))
4783 *new_flags |= GDK_HINT_BASE_SIZE;
4785 new_geometry->base_width = extra_width;
4786 new_geometry->base_height = extra_height;
4789 if (*new_flags & GDK_HINT_MIN_SIZE)
4791 if (new_geometry->min_width < 0)
4792 new_geometry->min_width = requisition.width;
4794 new_geometry->min_width += extra_width;
4796 if (new_geometry->min_height < 0)
4797 new_geometry->min_height = requisition.height;
4799 new_geometry->min_height += extra_height;
4801 else if (!window->allow_shrink)
4803 *new_flags |= GDK_HINT_MIN_SIZE;
4805 new_geometry->min_width = requisition.width;
4806 new_geometry->min_height = requisition.height;
4809 if (*new_flags & GDK_HINT_MAX_SIZE)
4811 if (new_geometry->max_width < 0)
4812 new_geometry->max_width = requisition.width;
4814 new_geometry->max_width += extra_width;
4816 if (new_geometry->max_height < 0)
4817 new_geometry->max_width = requisition.height;
4819 new_geometry->max_height += extra_height;
4821 else if (!window->allow_grow)
4823 *new_flags |= GDK_HINT_MAX_SIZE;
4825 new_geometry->max_width = requisition.width;
4826 new_geometry->max_height = requisition.height;
4829 *new_flags |= GDK_HINT_WIN_GRAVITY;
4830 new_geometry->win_gravity = window->gravity;
4833 /***********************
4834 * Redrawing functions *
4835 ***********************/
4838 gtk_window_paint (GtkWidget *widget,
4841 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
4842 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
4846 gtk_window_expose (GtkWidget *widget,
4847 GdkEventExpose *event)
4849 if (!GTK_WIDGET_APP_PAINTABLE (widget))
4850 gtk_window_paint (widget, &event->area);
4852 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
4853 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
4859 * gtk_window_set_has_frame:
4860 * @window: a #GtkWindow
4861 * @setting: a boolean
4863 * (Note: this is a special-purpose function for the framebuffer port,
4864 * that causes GTK+ to draw its own window border. For most applications,
4865 * you want gtk_window_set_decorated() instead, which tells the window
4866 * manager whether to draw the window border.)
4868 * If this function is called on a window with setting of %TRUE, before
4869 * it is realized or showed, it will have a "frame" window around
4870 * @window->window, accessible in @window->frame. Using the signal
4871 * frame_event you can recieve all events targeted at the frame.
4873 * This function is used by the linux-fb port to implement managed
4874 * windows, but it could concievably be used by X-programs that
4875 * want to do their own window decorations.
4879 gtk_window_set_has_frame (GtkWindow *window,
4882 g_return_if_fail (GTK_IS_WINDOW (window));
4883 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
4885 window->has_frame = setting != FALSE;
4889 * gtk_window_get_has_frame:
4890 * @window: a #GtkWindow
4892 * Accessor for whether the window has a frame window exterior to
4893 * @window->window. Gets the value set by gtk_window_set_has_frame ().
4895 * Return value: %TRUE if a frame has been added to the window
4896 * via gtk_window_set_has_frame().
4899 gtk_window_get_has_frame (GtkWindow *window)
4901 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4903 return window->has_frame;
4907 * gtk_window_set_frame_dimensions:
4908 * @window: a #GtkWindow that has a frame
4909 * @left: The width of the left border
4910 * @top: The height of the top border
4911 * @right: The width of the right border
4912 * @bottom: The height of the bottom border
4914 * (Note: this is a special-purpose function intended for the framebuffer
4915 * port; see gtk_window_set_has_frame(). It will have no effect on the
4916 * window border drawn by the window manager, which is the normal
4917 * case when using the X Window system.)
4919 * For windows with frames (see gtk_window_set_has_frame()) this function
4920 * can be used to change the size of the frame border.
4923 gtk_window_set_frame_dimensions (GtkWindow *window,
4931 g_return_if_fail (GTK_IS_WINDOW (window));
4933 widget = GTK_WIDGET (window);
4935 if (window->frame_left == left &&
4936 window->frame_top == top &&
4937 window->frame_right == right &&
4938 window->frame_bottom == bottom)
4941 window->frame_left = left;
4942 window->frame_top = top;
4943 window->frame_right = right;
4944 window->frame_bottom = bottom;
4946 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4948 gint width = widget->allocation.width + left + right;
4949 gint height = widget->allocation.height + top + bottom;
4950 gdk_window_resize (window->frame, width, height);
4951 gtk_decorated_window_move_resize_window (window,
4953 widget->allocation.width,
4954 widget->allocation.height);
4959 * gtk_window_present:
4960 * @window: a #GtkWindow
4962 * Presents a window to the user. This may mean raising the window
4963 * in the stacking order, deiconifying it, moving it to the current
4964 * desktop, and/or giving it the keyboard focus, possibly dependent
4965 * on the user's platform, window manager, and preferences.
4967 * If @window is hidden, this function calls gtk_widget_show()
4970 * This function should be used when the user tries to open a window
4971 * that's already open. Say for example the preferences dialog is
4972 * currently open, and the user chooses Preferences from the menu
4973 * a second time; use gtk_window_present() to move the already-open dialog
4974 * where the user can see it.
4978 gtk_window_present (GtkWindow *window)
4982 g_return_if_fail (GTK_IS_WINDOW (window));
4984 widget = GTK_WIDGET (window);
4986 if (GTK_WIDGET_VISIBLE (window))
4988 g_assert (widget->window != NULL);
4990 gdk_window_show (widget->window);
4992 /* note that gdk_window_focus() will also move the window to
4993 * the current desktop, for WM spec compliant window managers.
4995 gdk_window_focus (widget->window,
4996 gtk_get_current_event_time ());
5000 gtk_widget_show (widget);
5005 * gtk_window_iconify:
5006 * @window: a #GtkWindow
5008 * Asks to iconify (i.e. minimize) the specified @window. Note that
5009 * you shouldn't assume the window is definitely iconified afterward,
5010 * because other entities (e.g. the user or <link
5011 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
5012 * again, or there may not be a window manager in which case
5013 * iconification isn't possible, etc. But normally the window will end
5014 * up iconified. Just don't write code that crashes if not.
5016 * It's permitted to call this function before showing a window,
5017 * in which case the window will be iconified before it ever appears
5020 * You can track iconification via the "window_state_event" signal
5025 gtk_window_iconify (GtkWindow *window)
5028 GdkWindow *toplevel;
5030 g_return_if_fail (GTK_IS_WINDOW (window));
5032 widget = GTK_WIDGET (window);
5034 window->iconify_initially = TRUE;
5037 toplevel = window->frame;
5039 toplevel = widget->window;
5041 if (toplevel != NULL)
5042 gdk_window_iconify (toplevel);
5046 * gtk_window_deiconify:
5047 * @window: a #GtkWindow
5049 * Asks to deiconify (i.e. unminimize) the specified @window. Note
5050 * that you shouldn't assume the window is definitely deiconified
5051 * afterward, because other entities (e.g. the user or <link
5052 * linkend="gtk-X11-arch">window manager</link>) could iconify it
5053 * again before your code which assumes deiconification gets to run.
5055 * You can track iconification via the "window_state_event" signal
5059 gtk_window_deiconify (GtkWindow *window)
5062 GdkWindow *toplevel;
5064 g_return_if_fail (GTK_IS_WINDOW (window));
5066 widget = GTK_WIDGET (window);
5068 window->iconify_initially = FALSE;
5071 toplevel = window->frame;
5073 toplevel = widget->window;
5075 if (toplevel != NULL)
5076 gdk_window_deiconify (toplevel);
5081 * @window: a #GtkWindow
5083 * Asks to stick @window, which means that it will appear on all user
5084 * desktops. Note that you shouldn't assume the window is definitely
5085 * stuck afterward, because other entities (e.g. the user or <link
5086 * linkend="gtk-X11-arch">window manager</link>) could unstick it
5087 * again, and some window managers do not support sticking
5088 * windows. But normally the window will end up stuck. Just don't
5089 * write code that crashes if not.
5091 * It's permitted to call this function before showing a window.
5093 * You can track stickiness via the "window_state_event" signal
5098 gtk_window_stick (GtkWindow *window)
5101 GdkWindow *toplevel;
5103 g_return_if_fail (GTK_IS_WINDOW (window));
5105 widget = GTK_WIDGET (window);
5107 window->stick_initially = TRUE;
5110 toplevel = window->frame;
5112 toplevel = widget->window;
5114 if (toplevel != NULL)
5115 gdk_window_stick (toplevel);
5119 * gtk_window_unstick:
5120 * @window: a #GtkWindow
5122 * Asks to unstick @window, which means that it will appear on only
5123 * one of the user's desktops. Note that you shouldn't assume the
5124 * window is definitely unstuck afterward, because other entities
5125 * (e.g. the user or <link linkend="gtk-X11-arch">window
5126 * manager</link>) could stick it again. But normally the window will
5127 * end up stuck. Just don't write code that crashes if not.
5129 * You can track stickiness via the "window_state_event" signal
5134 gtk_window_unstick (GtkWindow *window)
5137 GdkWindow *toplevel;
5139 g_return_if_fail (GTK_IS_WINDOW (window));
5141 widget = GTK_WIDGET (window);
5143 window->stick_initially = FALSE;
5146 toplevel = window->frame;
5148 toplevel = widget->window;
5150 if (toplevel != NULL)
5151 gdk_window_unstick (toplevel);
5155 * gtk_window_maximize:
5156 * @window: a #GtkWindow
5158 * Asks to maximize @window, so that it becomes full-screen. Note that
5159 * you shouldn't assume the window is definitely maximized afterward,
5160 * because other entities (e.g. the user or <link
5161 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
5162 * again, and not all window managers support maximization. But
5163 * normally the window will end up maximized. Just don't write code
5164 * that crashes if not.
5166 * It's permitted to call this function before showing a window,
5167 * in which case the window will be maximized when it appears onscreen
5170 * You can track maximization via the "window_state_event" signal
5175 gtk_window_maximize (GtkWindow *window)
5178 GdkWindow *toplevel;
5180 g_return_if_fail (GTK_IS_WINDOW (window));
5182 widget = GTK_WIDGET (window);
5184 window->maximize_initially = TRUE;
5187 toplevel = window->frame;
5189 toplevel = widget->window;
5191 if (toplevel != NULL)
5192 gdk_window_maximize (toplevel);
5196 * gtk_window_unmaximize:
5197 * @window: a #GtkWindow
5199 * Asks to unmaximize @window. Note that you shouldn't assume the
5200 * window is definitely unmaximized afterward, because other entities
5201 * (e.g. the user or <link linkend="gtk-X11-arch">window
5202 * manager</link>) could maximize it again, and not all window
5203 * managers honor requests to unmaximize. But normally the window will
5204 * end up unmaximized. Just don't write code that crashes if not.
5206 * You can track maximization via the "window_state_event" signal
5211 gtk_window_unmaximize (GtkWindow *window)
5214 GdkWindow *toplevel;
5216 g_return_if_fail (GTK_IS_WINDOW (window));
5218 widget = GTK_WIDGET (window);
5220 window->maximize_initially = FALSE;
5223 toplevel = window->frame;
5225 toplevel = widget->window;
5227 if (toplevel != NULL)
5228 gdk_window_unmaximize (toplevel);
5232 * gtk_window_set_resizable:
5233 * @window: a #GtkWindow
5234 * @resizable: %TRUE if the user can resize this window
5236 * Sets whether the user can resize a window. Windows are user resizable
5240 gtk_window_set_resizable (GtkWindow *window,
5243 g_return_if_fail (GTK_IS_WINDOW (window));
5245 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5249 * gtk_window_get_resizable:
5250 * @window: a #GtkWindow
5252 * Gets the value set by gtk_window_set_resizable().
5254 * Return value: %TRUE if the user can resize the window
5257 gtk_window_get_resizable (GtkWindow *window)
5259 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5261 /* allow_grow is most likely to indicate the semantic concept we
5262 * mean by "resizable" (and will be a reliable indicator if
5263 * set_policy() hasn't been called)
5265 return window->allow_grow;
5269 * gtk_window_set_gravity:
5270 * @window: a #GtkWindow
5271 * @gravity: window gravity
5273 * Window gravity defines the meaning of coordinates passed to
5274 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5277 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5278 * typically "do what you mean."
5282 gtk_window_set_gravity (GtkWindow *window,
5285 g_return_if_fail (GTK_IS_WINDOW (window));
5287 if (gravity != window->gravity)
5289 window->gravity = gravity;
5291 /* gtk_window_move_resize() will adapt gravity
5293 gtk_widget_queue_resize (GTK_WIDGET (window));
5298 * gtk_window_get_gravity:
5299 * @window: a #GtkWindow
5301 * Gets the value set by gtk_window_set_gravity().
5303 * Return value: window gravity
5306 gtk_window_get_gravity (GtkWindow *window)
5308 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5310 return window->gravity;
5314 * gtk_window_begin_resize_drag:
5315 * @window: a #GtkWindow
5316 * @button: mouse button that initiated the drag
5317 * @edge: position of the resize control
5318 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5319 * @root_y: Y position where the user clicked to initiate the drag
5320 * @timestamp: timestamp from the click event that initiated the drag
5322 * Starts resizing a window. This function is used if an application
5323 * has window resizing controls. When GDK can support it, the resize
5324 * will be done using the standard mechanism for the <link
5325 * linkend="gtk-X11-arch">window manager</link> or windowing
5326 * system. Otherwise, GDK will try to emulate window resizing,
5327 * potentially not all that well, depending on the windowing system.
5331 gtk_window_begin_resize_drag (GtkWindow *window,
5339 GdkWindow *toplevel;
5341 g_return_if_fail (GTK_IS_WINDOW (window));
5342 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5344 widget = GTK_WIDGET (window);
5347 toplevel = window->frame;
5349 toplevel = widget->window;
5351 gdk_window_begin_resize_drag (toplevel,
5358 * gtk_window_get_frame_dimensions:
5359 * @window: a #GtkWindow
5360 * @left: location to store the width of the frame at the left, or %NULL
5361 * @top: location to store the height of the frame at the top, or %NULL
5362 * @right: location to store the width of the frame at the returns, or %NULL
5363 * @bottom: location to store the height of the frame at the bottom, or %NULL
5365 * (Note: this is a special-purpose function intended for the
5366 * framebuffer port; see gtk_window_set_has_frame(). It will not
5367 * return the size of the window border drawn by the <link
5368 * linkend="gtk-X11-arch">window manager</link>, which is the normal
5369 * case when using a windowing system. See
5370 * gdk_window_get_frame_extents() to get the standard window border
5373 * Retrieves the dimensions of the frame window for this toplevel.
5374 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5377 gtk_window_get_frame_dimensions (GtkWindow *window,
5383 g_return_if_fail (GTK_IS_WINDOW (window));
5386 *left = window->frame_left;
5388 *top = window->frame_top;
5390 *right = window->frame_right;
5392 *bottom = window->frame_bottom;
5396 * gtk_window_begin_move_drag:
5397 * @window: a #GtkWindow
5398 * @button: mouse button that initiated the drag
5399 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5400 * @root_y: Y position where the user clicked to initiate the drag
5401 * @timestamp: timestamp from the click event that initiated the drag
5403 * Starts moving a window. This function is used if an application has
5404 * window movement grips. When GDK can support it, the window movement
5405 * will be done using the standard mechanism for the <link
5406 * linkend="gtk-X11-arch">window manager</link> or windowing
5407 * system. Otherwise, GDK will try to emulate window movement,
5408 * potentially not all that well, depending on the windowing system.
5412 gtk_window_begin_move_drag (GtkWindow *window,
5419 GdkWindow *toplevel;
5421 g_return_if_fail (GTK_IS_WINDOW (window));
5422 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5424 widget = GTK_WIDGET (window);
5427 toplevel = window->frame;
5429 toplevel = widget->window;
5431 gdk_window_begin_move_drag (toplevel,
5438 * gtk_window_set_screen:
5439 * @window: a #GtkWindow.
5440 * @screen: a #GdkScreen.
5442 * Sets the #GdkScreen where the @window is displayed; if
5443 * the window is already mapped, it will be unmapped, and
5444 * then remapped on the new screen.
5447 gtk_window_set_screen (GtkWindow *window,
5451 gboolean was_mapped;
5453 g_return_if_fail (GTK_IS_WINDOW (window));
5454 g_return_if_fail (GDK_IS_SCREEN (screen));
5456 if (screen == window->screen)
5459 widget = GTK_WIDGET (window);
5461 was_mapped = GTK_WIDGET_MAPPED (widget);
5464 gtk_widget_unmap (widget);
5465 if (GTK_WIDGET_REALIZED (widget))
5466 gtk_widget_unrealize (widget);
5468 gtk_window_free_key_hash (window);
5469 window->screen = screen;
5470 gtk_widget_reset_rc_styles (widget);
5471 g_object_notify (G_OBJECT (window), "screen");
5474 gtk_widget_map (widget);
5478 * gtk_window_get_screen:
5479 * @window: a #GtkWindow.
5481 * Returns the #GdkScreen associated with @window.
5483 * Return value: a #GdkScreen.
5486 gtk_window_get_screen (GtkWindow *window)
5488 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
5490 return window->screen;
5495 gtk_window_group_class_init (GtkWindowGroupClass *klass)
5500 gtk_window_group_get_type (void)
5502 static GtkType window_group_type = 0;
5504 if (!window_group_type)
5506 static const GTypeInfo window_group_info =
5508 sizeof (GtkWindowGroupClass),
5509 NULL, /* base_init */
5510 NULL, /* base_finalize */
5511 (GClassInitFunc) gtk_window_group_class_init,
5512 NULL, /* class_finalize */
5513 NULL, /* class_data */
5514 sizeof (GtkWindowGroup),
5515 16, /* n_preallocs */
5516 (GInstanceInitFunc) NULL,
5519 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
5522 return window_group_type;
5526 * gtk_window_group_new:
5528 * Creates a new #GtkWindowGroup object. Grabs added with
5529 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
5531 * Return value: a new #GtkWindowGroup.
5534 gtk_window_group_new (void)
5536 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
5540 window_group_cleanup_grabs (GtkWindowGroup *group,
5544 GSList *to_remove = NULL;
5546 tmp_list = group->grabs;
5549 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
5550 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
5551 tmp_list = tmp_list->next;
5556 gtk_grab_remove (to_remove->data);
5557 g_object_unref (to_remove->data);
5558 to_remove = g_slist_delete_link (to_remove, to_remove);
5563 * gtk_window_group_add_window:
5564 * @window_group: a #GtkWindowGroup
5565 * @window: the #GtkWindow to add
5567 * Adds a window to a #GtkWindowGroup.
5570 gtk_window_group_add_window (GtkWindowGroup *window_group,
5573 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5574 g_return_if_fail (GTK_IS_WINDOW (window));
5576 if (window->group != window_group)
5578 g_object_ref (window);
5579 g_object_ref (window_group);
5582 gtk_window_group_remove_window (window->group, window);
5584 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
5586 window->group = window_group;
5588 g_object_unref (window);
5593 * gtk_window_group_remove_window:
5594 * @window_group: a #GtkWindowGroup
5595 * @window: the #GtkWindow to remove
5597 * Removes a window from a #GtkWindowGroup.
5600 gtk_window_group_remove_window (GtkWindowGroup *window_group,
5603 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5604 g_return_if_fail (GTK_IS_WIDGET (window));
5605 g_return_if_fail (window->group == window_group);
5607 g_object_ref (window);
5609 window_group_cleanup_grabs (window_group, window);
5610 window->group = NULL;
5612 g_object_unref (G_OBJECT (window_group));
5613 g_object_unref (window);
5616 /* Return the group for the window or the default group
5619 _gtk_window_get_group (GtkWindow *window)
5621 if (window && window->group)
5622 return window->group;
5625 static GtkWindowGroup *default_group = NULL;
5628 default_group = gtk_window_group_new ();
5630 return default_group;
5636 Derived from XParseGeometry() in XFree86
5638 Copyright 1985, 1986, 1987,1998 The Open Group
5640 All Rights Reserved.
5642 The above copyright notice and this permission notice shall be included
5643 in all copies or substantial portions of the Software.
5645 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5646 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5647 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
5648 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
5649 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
5650 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
5651 OTHER DEALINGS IN THE SOFTWARE.
5653 Except as contained in this notice, the name of The Open Group shall
5654 not be used in advertising or otherwise to promote the sale, use or
5655 other dealings in this Software without prior written authorization
5656 from The Open Group.
5661 * XParseGeometry parses strings of the form
5662 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5663 * width, height, xoffset, and yoffset are unsigned integers.
5664 * Example: "=80x24+300-49"
5665 * The equal sign is optional.
5666 * It returns a bitmask that indicates which of the four values
5667 * were actually found in the string. For each value found,
5668 * the corresponding argument is updated; for each value
5669 * not found, the corresponding argument is left unchanged.
5672 /* The following code is from Xlib, and is minimally modified, so we
5673 * can track any upstream changes if required. Don't change this
5674 * code. Or if you do, put in a huge comment marking which thing
5679 read_int (gchar *string,
5687 else if (*string == '-')
5693 for (; (*string >= '0') && (*string <= '9'); string++)
5695 result = (result * 10) + (*string - '0');
5707 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
5708 * value (x, y, width, height) was found in the parsed string.
5710 #define NoValue 0x0000
5711 #define XValue 0x0001
5712 #define YValue 0x0002
5713 #define WidthValue 0x0004
5714 #define HeightValue 0x0008
5715 #define AllValues 0x000F
5716 #define XNegative 0x0010
5717 #define YNegative 0x0020
5719 /* Try not to reformat/modify, so we can compare/sync with X sources */
5721 gtk_XParseGeometry (const char *string,
5724 unsigned int *width,
5725 unsigned int *height)
5729 unsigned int tempWidth, tempHeight;
5731 char *nextCharacter;
5733 /* These initializations are just to silence gcc */
5739 if ( (string == NULL) || (*string == '\0')) return(mask);
5741 string++; /* ignore possible '=' at beg of geometry spec */
5743 strind = (char *)string;
5744 if (*strind != '+' && *strind != '-' && *strind != 'x') {
5745 tempWidth = read_int(strind, &nextCharacter);
5746 if (strind == nextCharacter)
5748 strind = nextCharacter;
5752 if (*strind == 'x' || *strind == 'X') {
5754 tempHeight = read_int(strind, &nextCharacter);
5755 if (strind == nextCharacter)
5757 strind = nextCharacter;
5758 mask |= HeightValue;
5761 if ((*strind == '+') || (*strind == '-')) {
5762 if (*strind == '-') {
5764 tempX = -read_int(strind, &nextCharacter);
5765 if (strind == nextCharacter)
5767 strind = nextCharacter;
5773 tempX = read_int(strind, &nextCharacter);
5774 if (strind == nextCharacter)
5776 strind = nextCharacter;
5779 if ((*strind == '+') || (*strind == '-')) {
5780 if (*strind == '-') {
5782 tempY = -read_int(strind, &nextCharacter);
5783 if (strind == nextCharacter)
5785 strind = nextCharacter;
5792 tempY = read_int(strind, &nextCharacter);
5793 if (strind == nextCharacter)
5795 strind = nextCharacter;
5801 /* If strind isn't at the end of the string the it's an invalid
5802 geometry specification. */
5804 if (*strind != '\0') return (0);
5810 if (mask & WidthValue)
5812 if (mask & HeightValue)
5813 *height = tempHeight;
5818 * gtk_window_parse_geometry:
5819 * @window: a #GtkWindow
5820 * @geometry: geometry string
5822 * Parses a standard X Window System geometry string - see the
5823 * manual page for X (type 'man X') for details on this.
5824 * gtk_window_parse_geometry() does work on all GTK+ ports
5825 * including Win32 but is primarily intended for an X environment.
5827 * If either a size or a position can be extracted from the
5828 * geometry string, gtk_window_parse_geometry() returns %TRUE
5829 * and calls gtk_window_set_default_size() and/or gtk_window_move()
5830 * to resize/move the window.
5832 * If gtk_window_parse_geometry() returns %TRUE, it will also
5833 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
5834 * indicating to the window manager that the size/position of
5835 * the window was user-specified. This causes most window
5836 * managers to honor the geometry.
5838 * Return value: %TRUE if string was parsed successfully
5841 gtk_window_parse_geometry (GtkWindow *window,
5842 const gchar *geometry)
5847 gboolean size_set, pos_set;
5849 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5850 g_return_val_if_fail (geometry != NULL, FALSE);
5852 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
5854 if ((result & WidthValue) == 0 ||
5857 if ((result & HeightValue) == 0 ||
5862 if ((result & WidthValue) || (result & HeightValue))
5864 gtk_window_set_default_size_internal (window, TRUE, w, TRUE, h, TRUE);
5868 gtk_window_get_size (window, &w, &h);
5870 grav = GDK_GRAVITY_NORTH_WEST;
5872 if ((result & XNegative) && (result & YNegative))
5873 grav = GDK_GRAVITY_SOUTH_EAST;
5874 else if (result & XNegative)
5875 grav = GDK_GRAVITY_NORTH_EAST;
5876 else if (result & YNegative)
5877 grav = GDK_GRAVITY_SOUTH_WEST;
5879 if ((result & XValue) == 0)
5882 if ((result & YValue) == 0)
5885 if (grav == GDK_GRAVITY_SOUTH_WEST ||
5886 grav == GDK_GRAVITY_SOUTH_EAST)
5887 y = gdk_screen_get_height (window->screen) - h + y;
5889 if (grav == GDK_GRAVITY_SOUTH_EAST ||
5890 grav == GDK_GRAVITY_NORTH_EAST)
5891 x = gdk_screen_get_width (window->screen) - w + x;
5893 /* we don't let you put a window offscreen; maybe some people would
5894 * prefer to be able to, but it's kind of a bogus thing to do.
5903 if ((result & XValue) || (result & YValue))
5905 gtk_window_set_gravity (window, grav);
5906 gtk_window_move (window, x, y);
5910 if (size_set || pos_set)
5912 /* Set USSize, USPosition hints */
5913 GtkWindowGeometryInfo *info;
5915 info = gtk_window_get_geometry_info (window, TRUE);
5918 info->mask |= GDK_HINT_USER_POS;
5920 info->mask |= GDK_HINT_USER_SIZE;
5927 gtk_window_mnemonic_hash_foreach (gpointer key,
5933 GtkWindowKeysForeachFunc func;
5937 GtkWindowMnemonic *mnemonic = value;
5939 if (mnemonic->window == info->window)
5940 (*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
5944 _gtk_window_keys_foreach (GtkWindow *window,
5945 GtkWindowKeysForeachFunc func,
5952 GtkWindowKeysForeachFunc func;
5956 info.window = window;
5958 info.func_data = func_data;
5960 g_hash_table_foreach (mnemonic_hash_table,
5961 gtk_window_mnemonic_hash_foreach,
5964 groups = gtk_accel_groups_from_object (G_OBJECT (window));
5967 GtkAccelGroup *group = groups->data;
5970 for (i = 0; i < group->n_accels; i++)
5972 GtkAccelKey *key = &group->priv_accels[i].key;
5975 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
5978 groups = groups->next;
5983 gtk_window_keys_changed (GtkWindow *window)
5985 gtk_window_free_key_hash (window);
5986 gtk_window_get_key_hash (window);
5989 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
5991 struct _GtkWindowKeyEntry
5995 gboolean is_mnemonic;
5999 add_to_key_hash (GtkWindow *window,
6001 GdkModifierType modifiers,
6002 gboolean is_mnemonic,
6005 GtkKeyHash *key_hash = data;
6007 GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
6009 entry->keyval = keyval;
6010 entry->modifiers = modifiers;
6011 entry->is_mnemonic = is_mnemonic;
6013 /* GtkAccelGroup stores lowercased accelerators. To deal
6014 * with this, if <Shift> was specified, uppercase.
6016 if (modifiers & GDK_SHIFT_MASK)
6018 if (keyval == GDK_Tab)
6019 keyval = GDK_ISO_Left_Tab;
6021 keyval = gdk_keyval_to_upper (keyval);
6024 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
6028 gtk_window_get_key_hash (GtkWindow *window)
6030 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6034 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (window->screen)),
6035 (GDestroyNotify)g_free);
6036 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
6037 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
6043 gtk_window_free_key_hash (GtkWindow *window)
6045 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6048 _gtk_key_hash_free (key_hash);
6049 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
6054 * _gtk_window_activate_key:
6055 * @window: a #GtkWindow
6056 * @event: a #GdkEventKey
6058 * Activates mnemonics and accelerators for this #GtKWindow
6060 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
6063 _gtk_window_activate_key (GtkWindow *window,
6066 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6067 GtkWindowKeyEntry *found_entry = NULL;
6071 gtk_window_keys_changed (window);
6072 key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6077 GSList *entries = _gtk_key_hash_lookup (key_hash,
6078 event->hardware_keycode,
6079 event->state & gtk_accelerator_get_default_mod_mask (),
6083 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
6085 GtkWindowKeyEntry *entry = tmp_list->data;
6086 if (entry->is_mnemonic)
6088 found_entry = entry;
6093 if (!found_entry && entries)
6094 found_entry = entries->data;
6096 g_slist_free (entries);
6101 if (found_entry->is_mnemonic)
6102 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
6104 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
6111 window_update_has_focus (GtkWindow *window)
6113 GtkWidget *widget = GTK_WIDGET (window);
6114 gboolean has_focus = window->has_toplevel_focus && window->is_active;
6116 if (has_focus != window->has_focus)
6118 window->has_focus = has_focus;
6122 if (window->focus_widget &&
6123 window->focus_widget != widget &&
6124 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6125 do_focus_change (window->focus_widget, TRUE);
6129 if (window->focus_widget &&
6130 window->focus_widget != widget &&
6131 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6132 do_focus_change (window->focus_widget, FALSE);
6138 * _gtk_window_set_is_active:
6139 * @window: a #GtkWindow
6140 * @is_active: %TRUE if the window is in the currently active toplevel
6142 * Internal function that sets whether the #GtkWindow is part
6143 * of the currently active toplevel window (taking into account inter-process
6147 _gtk_window_set_is_active (GtkWindow *window,
6150 g_return_if_fail (GTK_IS_WINDOW (window));
6152 is_active = is_active != FALSE;
6154 if (is_active != window->is_active)
6156 window->is_active = is_active;
6157 window_update_has_focus (window);
6159 g_object_notify (G_OBJECT (window), "is_active");
6164 * _gtk_window_set_has_toplevel_focus:
6165 * @window: a #GtkWindow
6166 * @has_toplevel_focus: %TRUE if the in
6168 * Internal function that sets whether the keyboard focus for the
6169 * toplevel window (taking into account inter-process embedding.)
6172 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
6173 gboolean has_toplevel_focus)
6175 g_return_if_fail (GTK_IS_WINDOW (window));
6177 has_toplevel_focus = has_toplevel_focus != FALSE;
6179 if (has_toplevel_focus != window->has_toplevel_focus)
6181 window->has_toplevel_focus = has_toplevel_focus;
6182 window_update_has_focus (window);
6184 g_object_notify (G_OBJECT (window), "has_toplevel_focus");