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_screen_get_default ();
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 #ifdef GDK_WINDOWING_X11
3168 if (!window->focus_widget && !GTK_IS_PLUG (window))
3170 if (!window->focus_widget)
3172 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
3175 gtk_grab_add (widget);
3179 gtk_window_hide (GtkWidget *widget)
3181 GtkWindow *window = GTK_WINDOW (widget);
3183 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3184 gtk_widget_unmap (widget);
3187 gtk_grab_remove (widget);
3191 gtk_window_map (GtkWidget *widget)
3193 GtkWindow *window = GTK_WINDOW (widget);
3194 GdkWindow *toplevel;
3196 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3198 if (window->bin.child &&
3199 GTK_WIDGET_VISIBLE (window->bin.child) &&
3200 !GTK_WIDGET_MAPPED (window->bin.child))
3201 gtk_widget_map (window->bin.child);
3204 toplevel = window->frame;
3206 toplevel = widget->window;
3208 if (window->maximize_initially)
3209 gdk_window_maximize (toplevel);
3211 gdk_window_unmaximize (toplevel);
3213 if (window->stick_initially)
3214 gdk_window_stick (toplevel);
3216 gdk_window_unstick (toplevel);
3218 if (window->iconify_initially)
3219 gdk_window_iconify (toplevel);
3221 gdk_window_deiconify (toplevel);
3223 /* No longer use the default settings */
3224 window->need_default_size = FALSE;
3225 window->need_default_position = FALSE;
3227 gdk_window_show (widget->window);
3230 gdk_window_show (window->frame);
3234 gtk_window_unmap (GtkWidget *widget)
3236 GtkWindow *window = GTK_WINDOW (widget);
3237 GtkWindowGeometryInfo *info;
3238 GdkWindowState state;
3240 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3242 gdk_window_withdraw (window->frame);
3244 gdk_window_withdraw (widget->window);
3246 window->configure_request_count = 0;
3247 window->configure_notify_received = FALSE;
3249 /* on unmap, we reset the default positioning of the window,
3250 * so it's placed again, but we don't reset the default
3251 * size of the window, so it's remembered.
3253 window->need_default_position = TRUE;
3255 info = gtk_window_get_geometry_info (window, FALSE);
3258 info->initial_pos_set = FALSE;
3259 info->position_constraints_changed = FALSE;
3262 state = gdk_window_get_state (widget->window);
3263 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
3264 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
3265 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
3269 gtk_window_realize (GtkWidget *widget)
3272 GdkWindow *parent_window;
3273 GdkWindowAttr attributes;
3274 gint attributes_mask;
3276 window = GTK_WINDOW (widget);
3278 /* ensure widget tree is properly size allocated */
3279 if (widget->allocation.x == -1 &&
3280 widget->allocation.y == -1 &&
3281 widget->allocation.width == 1 &&
3282 widget->allocation.height == 1)
3284 GtkRequisition requisition;
3285 GtkAllocation allocation = { 0, 0, 200, 200 };
3287 gtk_widget_size_request (widget, &requisition);
3288 if (requisition.width || requisition.height)
3290 /* non-empty window */
3291 allocation.width = requisition.width;
3292 allocation.height = requisition.height;
3294 gtk_widget_size_allocate (widget, &allocation);
3296 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3298 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3301 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3303 switch (window->type)
3305 case GTK_WINDOW_TOPLEVEL:
3306 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3308 case GTK_WINDOW_POPUP:
3309 attributes.window_type = GDK_WINDOW_TEMP;
3312 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3316 attributes.title = window->title;
3317 attributes.wmclass_name = window->wmclass_name;
3318 attributes.wmclass_class = window->wmclass_class;
3319 attributes.wclass = GDK_INPUT_OUTPUT;
3320 attributes.visual = gtk_widget_get_visual (widget);
3321 attributes.colormap = gtk_widget_get_colormap (widget);
3323 if (window->has_frame)
3325 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3326 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3327 attributes.event_mask = (GDK_EXPOSURE_MASK |
3328 GDK_KEY_PRESS_MASK |
3329 GDK_ENTER_NOTIFY_MASK |
3330 GDK_LEAVE_NOTIFY_MASK |
3331 GDK_FOCUS_CHANGE_MASK |
3332 GDK_STRUCTURE_MASK |
3333 GDK_BUTTON_MOTION_MASK |
3334 GDK_POINTER_MOTION_HINT_MASK |
3335 GDK_BUTTON_PRESS_MASK |
3336 GDK_BUTTON_RELEASE_MASK);
3338 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3340 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
3341 &attributes, attributes_mask);
3343 gdk_window_set_user_data (window->frame, widget);
3345 attributes.window_type = GDK_WINDOW_CHILD;
3346 attributes.x = window->frame_left;
3347 attributes.y = window->frame_top;
3349 attributes_mask = GDK_WA_X | GDK_WA_Y;
3351 parent_window = window->frame;
3355 attributes_mask = 0;
3356 parent_window = gtk_widget_get_root_window (widget);
3359 attributes.width = widget->allocation.width;
3360 attributes.height = widget->allocation.height;
3361 attributes.event_mask = gtk_widget_get_events (widget);
3362 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3363 GDK_KEY_PRESS_MASK |
3364 GDK_KEY_RELEASE_MASK |
3365 GDK_ENTER_NOTIFY_MASK |
3366 GDK_LEAVE_NOTIFY_MASK |
3367 GDK_FOCUS_CHANGE_MASK |
3368 GDK_STRUCTURE_MASK);
3370 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3371 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3372 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3374 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3376 gdk_window_set_user_data (widget->window, window);
3378 widget->style = gtk_style_attach (widget->style, widget->window);
3379 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3381 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3383 /* This is a bad hack to set the window background. */
3384 gtk_window_paint (widget, NULL);
3386 if (window->transient_parent &&
3387 GTK_WIDGET_REALIZED (window->transient_parent))
3388 gdk_window_set_transient_for (widget->window,
3389 GTK_WIDGET (window->transient_parent)->window);
3391 if (window->wm_role)
3392 gdk_window_set_role (widget->window, window->wm_role);
3394 if (!window->decorated)
3395 gdk_window_set_decorations (widget->window, 0);
3397 gdk_window_set_type_hint (widget->window, window->type_hint);
3399 /* transient_for must be set to allow the modal hint */
3400 if (window->transient_parent && window->modal)
3401 gdk_window_set_modal_hint (widget->window, TRUE);
3403 gdk_window_set_modal_hint (widget->window, FALSE);
3406 gtk_window_realize_icon (window);
3410 gtk_window_unrealize (GtkWidget *widget)
3413 GtkWindowGeometryInfo *info;
3415 window = GTK_WINDOW (widget);
3417 /* On unrealize, we reset the size of the window such
3418 * that we will re-apply the default sizing stuff
3419 * next time we show the window.
3421 * Default positioning is reset on unmap, instead of unrealize.
3423 window->need_default_size = TRUE;
3424 info = gtk_window_get_geometry_info (window, FALSE);
3427 info->resize_width = -1;
3428 info->resize_height = -1;
3429 info->last.configure_request.x = 0;
3430 info->last.configure_request.y = 0;
3431 info->last.configure_request.width = -1;
3432 info->last.configure_request.height = -1;
3433 /* be sure we reset geom hints on re-realize */
3434 info->last.flags = 0;
3439 gdk_window_set_user_data (window->frame, NULL);
3440 gdk_window_destroy (window->frame);
3441 window->frame = NULL;
3445 gtk_window_unrealize_icon (window);
3447 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3451 gtk_window_size_request (GtkWidget *widget,
3452 GtkRequisition *requisition)
3457 window = GTK_WINDOW (widget);
3458 bin = GTK_BIN (window);
3460 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3461 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3463 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3465 GtkRequisition child_requisition;
3467 gtk_widget_size_request (bin->child, &child_requisition);
3469 requisition->width += child_requisition.width;
3470 requisition->height += child_requisition.height;
3475 gtk_window_size_allocate (GtkWidget *widget,
3476 GtkAllocation *allocation)
3479 GtkAllocation child_allocation;
3481 window = GTK_WINDOW (widget);
3482 widget->allocation = *allocation;
3484 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3486 child_allocation.x = GTK_CONTAINER (window)->border_width;
3487 child_allocation.y = GTK_CONTAINER (window)->border_width;
3488 child_allocation.width =
3489 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3490 child_allocation.height =
3491 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3493 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3496 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3498 gdk_window_resize (window->frame,
3499 allocation->width + window->frame_left + window->frame_right,
3500 allocation->height + window->frame_top + window->frame_bottom);
3505 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3508 gboolean return_val;
3510 window = GTK_WINDOW (widget);
3512 if (window->frame && (event->any.window == window->frame))
3514 if ((event->type != GDK_KEY_PRESS) &&
3515 (event->type != GDK_KEY_RELEASE) &&
3516 (event->type != GDK_FOCUS_CHANGE))
3518 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
3520 gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
3525 g_object_unref (event->any.window);
3526 event->any.window = g_object_ref (widget->window);
3534 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3536 GdkEventConfigure *configure_event;
3539 switch (event->type)
3542 configure_event = (GdkEventConfigure *)event;
3544 /* Invalidate the decorations */
3547 rect.width = configure_event->width;
3548 rect.height = configure_event->height;
3550 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3552 /* Pass on the (modified) configure event */
3553 configure_event->width -= window->frame_left + window->frame_right;
3554 configure_event->height -= window->frame_top + window->frame_bottom;
3555 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3564 gtk_window_configure_event (GtkWidget *widget,
3565 GdkEventConfigure *event)
3567 GtkWindow *window = GTK_WINDOW (widget);
3568 gboolean expected_reply = window->configure_request_count > 0;
3570 /* window->configure_request_count incremented for each
3571 * configure request, and decremented to a min of 0 for
3572 * each configure notify.
3574 * All it means is that we know we will get at least
3575 * window->configure_request_count more configure notifies.
3576 * We could get more configure notifies than that; some
3577 * of the configure notifies we get may be unrelated to
3578 * the configure requests. But we will get at least
3579 * window->configure_request_count notifies.
3582 if (window->configure_request_count > 0)
3583 window->configure_request_count -= 1;
3585 /* As an optimization, we avoid a resize when possible.
3587 * The only times we can avoid a resize are:
3588 * - we know only the position changed, not the size
3589 * - we know we have made more requests and so will get more
3590 * notifies and can wait to resize when we get them
3593 if (!expected_reply &&
3594 (widget->allocation.width == event->width &&
3595 widget->allocation.height == event->height))
3599 * If we do need to resize, we do that by:
3600 * - filling in widget->allocation with the new size
3601 * - setting configure_notify_received to TRUE
3602 * for use in gtk_window_move_resize()
3603 * - queueing a resize, leading to invocation of
3604 * gtk_window_move_resize() in an idle handler
3608 window->configure_notify_received = TRUE;
3610 widget->allocation.width = event->width;
3611 widget->allocation.height = event->height;
3613 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3618 /* the accel_key and accel_mods fields of the key have to be setup
3619 * upon calling this function. it'll then return whether that key
3620 * is at all used as accelerator, and if so will OR in the
3621 * accel_flags member of the key.
3624 _gtk_window_query_nonaccels (GtkWindow *window,
3626 GdkModifierType accel_mods)
3628 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3630 /* movement keys are considered locked accels */
3633 static const guint bindings[] = {
3634 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
3635 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
3639 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
3640 if (bindings[i] == accel_key)
3644 /* mnemonics are considered locked accels */
3645 if (accel_mods == window->mnemonic_modifier)
3647 GtkWindowMnemonic mkey;
3649 mkey.window = window;
3650 mkey.keyval = accel_key;
3651 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
3659 gtk_window_key_press_event (GtkWidget *widget,
3666 window = GTK_WINDOW (widget);
3670 /* Check for mnemonics and accelerators
3673 handled = _gtk_window_activate_key (window, event);
3677 focus = window->focus_widget;
3679 g_object_ref (focus);
3682 focus && focus != widget &&
3683 gtk_widget_get_toplevel (focus) == widget)
3687 if (GTK_WIDGET_IS_SENSITIVE (focus))
3688 handled = gtk_widget_event (focus, (GdkEvent*) event);
3690 parent = focus->parent;
3692 g_object_ref (parent);
3694 g_object_unref (focus);
3700 g_object_unref (focus);
3703 /* Chain up, invokes binding set */
3704 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
3705 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
3711 gtk_window_key_release_event (GtkWidget *widget,
3717 window = GTK_WINDOW (widget);
3719 if (window->focus_widget &&
3720 window->focus_widget != widget &&
3721 GTK_WIDGET_SENSITIVE (window->focus_widget))
3723 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
3726 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
3727 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
3733 gtk_window_real_activate_default (GtkWindow *window)
3735 gtk_window_activate_default (window);
3739 gtk_window_real_activate_focus (GtkWindow *window)
3741 gtk_window_activate_focus (window);
3745 gtk_window_move_focus (GtkWindow *window,
3746 GtkDirectionType dir)
3748 gtk_widget_child_focus (GTK_WIDGET (window), dir);
3750 if (!GTK_CONTAINER (window)->focus_child)
3751 gtk_window_set_focus (window, NULL);
3755 gtk_window_enter_notify_event (GtkWidget *widget,
3756 GdkEventCrossing *event)
3762 gtk_window_leave_notify_event (GtkWidget *widget,
3763 GdkEventCrossing *event)
3769 do_focus_change (GtkWidget *widget,
3772 GdkEventFocus fevent;
3774 g_object_ref (widget);
3777 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
3779 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
3781 fevent.type = GDK_FOCUS_CHANGE;
3782 fevent.window = widget->window;
3785 gtk_widget_event (widget, (GdkEvent*) &fevent);
3787 g_object_notify (G_OBJECT (widget), "has_focus");
3789 g_object_unref (widget);
3793 gtk_window_focus_in_event (GtkWidget *widget,
3794 GdkEventFocus *event)
3796 GtkWindow *window = GTK_WINDOW (widget);
3798 /* It appears spurious focus in events can occur when
3799 * the window is hidden. So we'll just check to see if
3800 * the window is visible before actually handling the
3803 if (GTK_WIDGET_VISIBLE (widget))
3805 _gtk_window_set_has_toplevel_focus (window, TRUE);
3806 _gtk_window_set_is_active (window, TRUE);
3813 gtk_window_focus_out_event (GtkWidget *widget,
3814 GdkEventFocus *event)
3816 GtkWindow *window = GTK_WINDOW (widget);
3818 _gtk_window_set_has_toplevel_focus (window, FALSE);
3819 _gtk_window_set_is_active (window, FALSE);
3824 static GdkAtom atom_rcfiles = GDK_NONE;
3827 gtk_window_read_rcfiles (GtkWidget *widget,
3828 GdkEventClient *event)
3830 GList *embedded_windows;
3832 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
3833 if (embedded_windows)
3838 for (i = 0; i < 5; i++)
3840 sev.data_format = 32;
3841 sev.message_type = atom_rcfiles;
3843 while (embedded_windows)
3845 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
3846 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), (GdkEvent *) &sev, xid);
3847 embedded_windows = embedded_windows->next;
3851 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
3855 gtk_window_client_event (GtkWidget *widget,
3856 GdkEventClient *event)
3859 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
3861 if (event->message_type == atom_rcfiles)
3862 gtk_window_read_rcfiles (widget, event);
3868 gtk_window_check_resize (GtkContainer *container)
3870 GtkWindow *window = GTK_WINDOW (container);
3872 if (GTK_WIDGET_VISIBLE (container))
3873 gtk_window_move_resize (window);
3877 gtk_window_focus (GtkWidget *widget,
3878 GtkDirectionType direction)
3882 GtkContainer *container;
3883 GtkWidget *old_focus_child;
3886 container = GTK_CONTAINER (widget);
3887 window = GTK_WINDOW (widget);
3888 bin = GTK_BIN (widget);
3890 old_focus_child = container->focus_child;
3892 /* We need a special implementation here to deal properly with wrapping
3893 * around in the tab chain without the danger of going into an
3896 if (old_focus_child)
3898 if (gtk_widget_child_focus (old_focus_child, direction))
3902 if (window->focus_widget)
3904 /* Wrapped off the end, clear the focus setting for the toplpevel */
3905 parent = window->focus_widget->parent;
3908 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
3909 parent = GTK_WIDGET (parent)->parent;
3912 gtk_window_set_focus (GTK_WINDOW (container), NULL);
3915 /* Now try to focus the first widget in the window */
3918 if (gtk_widget_child_focus (bin->child, direction))
3926 gtk_window_real_set_focus (GtkWindow *window,
3929 GtkWidget *old_focus = window->focus_widget;
3930 gboolean def_flags = 0;
3934 g_object_ref (old_focus);
3935 g_object_freeze_notify (G_OBJECT (old_focus));
3939 g_object_ref (focus);
3940 g_object_freeze_notify (G_OBJECT (focus));
3943 if (window->default_widget)
3944 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
3946 if (window->focus_widget)
3948 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3949 (window->focus_widget != window->default_widget))
3951 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3953 if (window->default_widget)
3954 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3957 if (window->has_focus)
3958 do_focus_change (window->focus_widget, FALSE);
3960 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
3963 window->focus_widget = focus;
3965 if (window->focus_widget)
3967 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3968 (window->focus_widget != window->default_widget))
3970 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
3971 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3973 if (window->default_widget)
3974 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3977 if (window->has_focus)
3978 do_focus_change (window->focus_widget, TRUE);
3980 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
3983 if (window->default_widget &&
3984 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
3985 gtk_widget_queue_draw (window->default_widget);
3989 g_object_thaw_notify (G_OBJECT (old_focus));
3990 g_object_unref (old_focus);
3994 g_object_thaw_notify (G_OBJECT (focus));
3995 g_object_unref (focus);
3999 /*********************************
4000 * Functions related to resizing *
4001 *********************************/
4003 /* This function doesn't constrain to geometry hints */
4005 gtk_window_compute_configure_request_size (GtkWindow *window,
4009 GtkRequisition requisition;
4010 GtkWindowGeometryInfo *info;
4014 * - we've done a size request
4017 widget = GTK_WIDGET (window);
4019 info = gtk_window_get_geometry_info (window, FALSE);
4021 if (window->need_default_size)
4023 gtk_widget_get_child_requisition (widget, &requisition);
4025 /* Default to requisition */
4026 *width = requisition.width;
4027 *height = requisition.height;
4029 /* If window is empty so requests 0, default to random nonzero size */
4030 if (*width == 0 && *height == 0)
4036 /* Override requisition with default size */
4040 gint base_width = 0;
4041 gint base_height = 0;
4043 gint height_inc = 1;
4045 if (info->default_is_geometry &&
4046 (info->default_width > 0 || info->default_height > 0))
4048 GdkGeometry geometry;
4051 gtk_window_compute_hints (window, &geometry, &flags);
4053 if (flags & GDK_HINT_BASE_SIZE)
4055 base_width = geometry.base_width;
4056 base_height = geometry.base_height;
4058 else if (flags & GDK_HINT_MIN_SIZE)
4060 base_width = geometry.min_width;
4061 base_height = geometry.min_height;
4063 if (flags & GDK_HINT_RESIZE_INC)
4065 width_inc = geometry.width_inc;
4066 height_inc = geometry.height_inc;
4070 if (info->default_width > 0)
4071 *width = info->default_width * width_inc + base_width;
4073 if (info->default_height > 0)
4074 *height = info->default_height * height_inc + base_height;
4079 /* Default to keeping current size */
4080 *width = widget->allocation.width;
4081 *height = widget->allocation.height;
4084 /* Override any size with gtk_window_resize() values */
4087 if (info->resize_width > 0)
4088 *width = info->resize_width;
4090 if (info->resize_height > 0)
4091 *height = info->resize_height;
4095 static GtkWindowPosition
4096 get_effective_position (GtkWindow *window)
4098 GtkWindowPosition pos = window->position;
4099 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
4100 (window->transient_parent == NULL ||
4101 !GTK_WIDGET_MAPPED (window->transient_parent)))
4102 pos = GTK_WIN_POS_NONE;
4108 gtk_window_compute_configure_request (GtkWindow *window,
4109 GdkRectangle *request,
4110 GdkGeometry *geometry,
4113 GdkGeometry new_geometry;
4117 GtkWindowPosition pos;
4118 GtkWidget *parent_widget;
4119 GtkWindowGeometryInfo *info;
4122 widget = GTK_WIDGET (window);
4124 gtk_widget_size_request (widget, NULL);
4125 gtk_window_compute_configure_request_size (window, &w, &h);
4127 gtk_window_compute_hints (window, &new_geometry, &new_flags);
4128 gtk_window_constrain_size (window,
4129 &new_geometry, new_flags,
4133 parent_widget = (GtkWidget*) window->transient_parent;
4135 pos = get_effective_position (window);
4136 info = gtk_window_get_geometry_info (window, TRUE);
4138 /* by default, don't change position requested */
4139 x = info->last.configure_request.x;
4140 y = info->last.configure_request.y;
4142 if (window->need_default_position)
4145 /* FIXME this all interrelates with window gravity.
4146 * For most of them I think we want to set GRAVITY_CENTER.
4148 * Not sure how to go about that.
4153 /* here we are only handling CENTER_ALWAYS
4154 * as it relates to default positioning,
4155 * where it's equivalent to simply CENTER
4157 case GTK_WIN_POS_CENTER_ALWAYS:
4158 case GTK_WIN_POS_CENTER:
4160 gint px, py, monitor_num;
4161 GdkRectangle monitor;
4163 gdk_window_get_pointer (gdk_screen_get_root_window (window->screen),
4166 monitor_num = gdk_screen_get_monitor_at_point (window->screen, px, py);
4167 if (monitor_num == -1)
4170 gdk_screen_get_monitor_geometry (window->screen, monitor_num, &monitor);
4172 x = (monitor.width - w) / 2 + monitor.x;
4173 y = (monitor.height - h) / 2 + monitor.y;
4177 case GTK_WIN_POS_CENTER_ON_PARENT:
4181 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
4183 gdk_window_get_origin (parent_widget->window,
4186 x = ox + (parent_widget->allocation.width - w) / 2;
4187 y = oy + (parent_widget->allocation.height - h) / 2;
4191 case GTK_WIN_POS_MOUSE:
4193 gint screen_width = gdk_screen_get_width (window->screen);
4194 gint screen_height = gdk_screen_get_height (window->screen);
4197 gdk_window_get_pointer (gdk_screen_get_root_window (window->screen),
4201 x = CLAMP (x, 0, screen_width - w);
4202 y = CLAMP (y, 0, screen_height - h);
4209 } /* if (window->need_default_position) */
4211 if (window->need_default_position &&
4212 info->initial_pos_set)
4214 x = info->initial_x;
4215 y = info->initial_y;
4216 gtk_window_constrain_position (window, w, h, &x, &y);
4222 request->height = h;
4225 *geometry = new_geometry;
4231 gtk_window_constrain_position (GtkWindow *window,
4237 /* See long comments in gtk_window_move_resize()
4238 * on when it's safe to call this function.
4240 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4242 gint center_x, center_y;
4243 gint screen_width = gdk_screen_get_width (window->screen);
4244 gint screen_height = gdk_screen_get_height (window->screen);
4246 center_x = (screen_width - new_width) / 2;
4247 center_y = (screen_height - new_height) / 2;
4255 gtk_window_move_resize (GtkWindow *window)
4259 * First we determine whether any information has changed that would
4260 * cause us to revise our last configure request. If we would send
4261 * a different configure request from last time, then
4262 * configure_request_size_changed = TRUE or
4263 * configure_request_pos_changed = TRUE. configure_request_size_changed
4264 * may be true due to new hints, a gtk_window_resize(), or whatever.
4265 * configure_request_pos_changed may be true due to gtk_window_set_position()
4266 * or gtk_window_move().
4268 * If the configure request has changed, we send off a new one. To
4269 * ensure GTK+ invariants are maintained (resize queue does what it
4270 * should), we go ahead and size_allocate the requested size in this
4273 * If the configure request has not changed, we don't ever resend
4274 * it, because it could mean fighting the user or window manager.
4277 * To prepare the configure request, we come up with a base size/pos:
4278 * - the one from gtk_window_move()/gtk_window_resize()
4279 * - else default_width, default_height if we haven't ever
4281 * - else the size request if we haven't ever been mapped,
4282 * as a substitute default size
4283 * - else the current size of the window, as received from
4284 * configure notifies (i.e. the current allocation)
4286 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4287 * the position request to be centered.
4290 GtkContainer *container;
4291 GtkWindowGeometryInfo *info;
4292 GdkGeometry new_geometry;
4294 GdkRectangle new_request;
4295 gboolean configure_request_size_changed;
4296 gboolean configure_request_pos_changed;
4297 gboolean hints_changed; /* do we need to send these again */
4298 GtkWindowLastGeometryInfo saved_last_info;
4300 widget = GTK_WIDGET (window);
4301 container = GTK_CONTAINER (widget);
4302 info = gtk_window_get_geometry_info (window, TRUE);
4304 configure_request_size_changed = FALSE;
4305 configure_request_pos_changed = FALSE;
4307 gtk_window_compute_configure_request (window, &new_request,
4308 &new_geometry, &new_flags);
4310 /* This check implies the invariant that we never set info->last
4311 * without setting the hints and sending off a configure request.
4313 * If we change info->last without sending the request, we may
4316 if (info->last.configure_request.x != new_request.x ||
4317 info->last.configure_request.y != new_request.y)
4318 configure_request_pos_changed = TRUE;
4320 if ((info->last.configure_request.width != new_request.width ||
4321 info->last.configure_request.height != new_request.height))
4322 configure_request_size_changed = TRUE;
4324 hints_changed = FALSE;
4326 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4327 &new_geometry, new_flags))
4329 hints_changed = TRUE;
4332 /* Position Constraints
4333 * ====================
4335 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4336 * a default. The other POS_ values are used only when the
4337 * window is shown, not after that.
4339 * However, we can't implement a position constraint as
4340 * "anytime the window size changes, center the window"
4341 * because this may well end up fighting the WM or user. In
4342 * fact it gets in an infinite loop with at least one WM.
4344 * Basically, applications are in no way in a position to
4345 * constrain the position of a window, with one exception:
4346 * override redirect windows. (Really the intended purpose
4347 * of CENTER_ALWAYS anyhow, I would think.)
4349 * So the way we implement this "constraint" is to say that when WE
4350 * cause a move or resize, i.e. we make a configure request changing
4351 * window size, we recompute the CENTER_ALWAYS position to reflect
4352 * the new window size, and include it in our request. Also, if we
4353 * just turned on CENTER_ALWAYS we snap to center with a new
4354 * request. Otherwise, if we are just NOTIFIED of a move or resize
4355 * done by someone else e.g. the window manager, we do NOT send a
4356 * new configure request.
4358 * For override redirect windows, this works fine; all window
4359 * sizes are from our configure requests. For managed windows,
4360 * it is at least semi-sane, though who knows what the
4361 * app author is thinking.
4364 /* This condition should be kept in sync with the condition later on
4365 * that determines whether we send a configure request. i.e. we
4366 * should do this position constraining anytime we were going to
4367 * send a configure request anyhow, plus when constraints have
4370 if (configure_request_pos_changed ||
4371 configure_request_size_changed ||
4373 info->position_constraints_changed)
4375 /* We request the constrained position if:
4376 * - we were changing position, and need to clamp
4377 * the change to the constraint
4378 * - we're changing the size anyway
4379 * - set_position() was called to toggle CENTER_ALWAYS on
4382 gtk_window_constrain_position (window,
4388 /* Update whether we need to request a move */
4389 if (info->last.configure_request.x != new_request.x ||
4390 info->last.configure_request.y != new_request.y)
4391 configure_request_pos_changed = TRUE;
4393 configure_request_pos_changed = FALSE;
4397 if (window->type == GTK_WINDOW_TOPLEVEL)
4399 int notify_x, notify_y;
4401 /* this is the position from the last configure notify */
4402 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4404 g_message ("--- %s ---\n"
4405 "last : %d,%d\t%d x %d\n"
4406 "this : %d,%d\t%d x %d\n"
4407 "alloc : %d,%d\t%d x %d\n"
4409 "resize: \t%d x %d\n"
4410 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4411 "configure_notify_received: %d\n"
4412 "configure_request_count: %d\n"
4413 "position_constraints_changed: %d\n",
4414 window->title ? window->title : "(no title)",
4415 info->last.configure_request.x,
4416 info->last.configure_request.y,
4417 info->last.configure_request.width,
4418 info->last.configure_request.height,
4424 widget->allocation.width,
4425 widget->allocation.height,
4426 widget->requisition.width,
4427 widget->requisition.height,
4429 info->resize_height,
4430 configure_request_pos_changed,
4431 configure_request_size_changed,
4433 window->configure_notify_received,
4434 window->configure_request_count,
4435 info->position_constraints_changed);
4439 saved_last_info = info->last;
4440 info->last.geometry = new_geometry;
4441 info->last.flags = new_flags;
4442 info->last.configure_request = new_request;
4444 /* need to set PPosition so the WM will look at our position,
4445 * but we don't want to count PPosition coming and going as a hints
4446 * change for future iterations. So we saved info->last prior to
4450 /* Also, if the initial position was explicitly set, then we always
4451 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4455 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4456 * this is an initial map
4459 if ((configure_request_pos_changed ||
4460 info->initial_pos_set ||
4461 (window->need_default_position &&
4462 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
4463 (new_flags & GDK_HINT_POS) == 0)
4465 new_flags |= GDK_HINT_POS;
4466 hints_changed = TRUE;
4469 /* Set hints if necessary
4472 gdk_window_set_geometry_hints (widget->window,
4476 /* handle resizing/moving and widget tree allocation
4478 if (window->configure_notify_received)
4480 GtkAllocation allocation;
4482 /* If we have received a configure event since
4483 * the last time in this function, we need to
4484 * accept our new size and size_allocate child widgets.
4485 * (see gtk_window_configure_event() for more details).
4487 * 1 or more configure notifies may have been received.
4488 * Also, configure_notify_received will only be TRUE
4489 * if all expected configure notifies have been received
4490 * (one per configure request), as an optimization.
4493 window->configure_notify_received = FALSE;
4495 /* gtk_window_configure_event() filled in widget->allocation */
4496 allocation = widget->allocation;
4497 gtk_widget_size_allocate (widget, &allocation);
4499 /* If the configure request changed, it means that
4501 * 1) coincidentally changed hints or widget properties
4502 * impacting the configure request before getting
4503 * a configure notify, or
4504 * 2) some broken widget is changing its size request
4505 * during size allocation, resulting in
4506 * a false appearance of changed configure request.
4508 * For 1), we could just go ahead and ask for the
4509 * new size right now, but doing that for 2)
4510 * might well be fighting the user (and can even
4511 * trigger a loop). Since we really don't want to
4512 * do that, we requeue a resize in hopes that
4513 * by the time it gets handled, the child has seen
4514 * the light and is willing to go along with the
4515 * new size. (this happens for the zvt widget, since
4516 * the size_allocate() above will have stored the
4517 * requisition corresponding to the new size in the
4520 * This doesn't buy us anything for 1), but it shouldn't
4521 * hurt us too badly, since it is what would have
4522 * happened if we had gotten the configure event before
4523 * the new size had been set.
4526 if (configure_request_size_changed ||
4527 configure_request_pos_changed)
4529 /* Don't change the recorded last info after all, because we
4530 * haven't actually updated to the new info yet - we decided
4531 * to postpone our configure request until later.
4533 info->last = saved_last_info;
4535 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
4538 else if ((configure_request_size_changed || hints_changed) &&
4539 (widget->allocation.width != new_request.width ||
4540 widget->allocation.height != new_request.height))
4543 /* We are in one of the following situations:
4544 * A. configure_request_size_changed
4545 * our requisition has changed and we need a different window size,
4546 * so we request it from the window manager.
4547 * B. !configure_request_size_changed && hints_changed
4548 * the window manager rejects our size, but we have just changed the
4549 * window manager hints, so there's a chance our request will
4550 * be honoured this time, so we try again.
4552 * However, if the new requisition is the same as the current allocation,
4553 * we don't request it again, since we won't get a ConfigureNotify back from
4554 * the window manager unless it decides to change our requisition. If
4555 * we don't get the ConfigureNotify back, the resize queue will never be run.
4558 /* Now send the configure request */
4559 if (configure_request_pos_changed)
4563 gdk_window_move_resize (window->frame,
4564 new_request.x - window->frame_left,
4565 new_request.y - window->frame_top,
4566 new_request.width + window->frame_left + window->frame_right,
4567 new_request.height + window->frame_top + window->frame_bottom);
4568 gdk_window_resize (widget->window,
4569 new_request.width, new_request.height);
4573 gdk_window_move_resize (widget->window,
4574 new_request.x, new_request.y,
4575 new_request.width, new_request.height);
4577 else /* only size changed */
4580 gdk_window_resize (window->frame,
4581 new_request.width + window->frame_left + window->frame_right,
4582 new_request.height + window->frame_top + window->frame_bottom);
4584 gdk_window_resize (widget->window,
4585 new_request.width, new_request.height);
4588 /* Increment the number of have-not-yet-received-notify requests */
4589 window->configure_request_count += 1;
4591 /* We have now sent a request since the last position constraint
4592 * change and definitely don't need a an initial size again (not
4593 * resetting this here can lead to infinite loops for
4594 * GTK_RESIZE_IMMEDIATE containers)
4596 info->position_constraints_changed = FALSE;
4597 info->initial_pos_set = FALSE;
4598 info->resize_width = -1;
4599 info->resize_height = -1;
4601 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
4602 * configure event in response to our resizing request.
4603 * the configure event will cause a new resize with
4604 * ->configure_notify_received=TRUE.
4605 * until then, we want to
4606 * - discard expose events
4607 * - coalesce resizes for our children
4608 * - defer any window resizes until the configure event arrived
4609 * to achieve this, we queue a resize for the window, but remove its
4610 * resizing handler, so resizing will not be handled from the next
4611 * idle handler but when the configure event arrives.
4613 * FIXME: we should also dequeue the pending redraws here, since
4614 * we handle those ourselves upon ->configure_notify_received==TRUE.
4616 if (container->resize_mode == GTK_RESIZE_QUEUE)
4618 gtk_widget_queue_resize (widget);
4619 _gtk_container_dequeue_resize_handler (container);
4624 /* Handle any position changes.
4626 if (configure_request_pos_changed)
4630 gdk_window_move (window->frame,
4631 new_request.x - window->frame_left,
4632 new_request.y - window->frame_top);
4635 gdk_window_move (widget->window,
4636 new_request.x, new_request.y);
4639 /* And run the resize queue.
4641 gtk_container_resize_children (container);
4645 /* Compare two sets of Geometry hints for equality.
4648 gtk_window_compare_hints (GdkGeometry *geometry_a,
4650 GdkGeometry *geometry_b,
4653 if (flags_a != flags_b)
4656 if ((flags_a & GDK_HINT_MIN_SIZE) &&
4657 (geometry_a->min_width != geometry_b->min_width ||
4658 geometry_a->min_height != geometry_b->min_height))
4661 if ((flags_a & GDK_HINT_MAX_SIZE) &&
4662 (geometry_a->max_width != geometry_b->max_width ||
4663 geometry_a->max_height != geometry_b->max_height))
4666 if ((flags_a & GDK_HINT_BASE_SIZE) &&
4667 (geometry_a->base_width != geometry_b->base_width ||
4668 geometry_a->base_height != geometry_b->base_height))
4671 if ((flags_a & GDK_HINT_ASPECT) &&
4672 (geometry_a->min_aspect != geometry_b->min_aspect ||
4673 geometry_a->max_aspect != geometry_b->max_aspect))
4676 if ((flags_a & GDK_HINT_RESIZE_INC) &&
4677 (geometry_a->width_inc != geometry_b->width_inc ||
4678 geometry_a->height_inc != geometry_b->height_inc))
4681 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
4682 geometry_a->win_gravity != geometry_b->win_gravity)
4689 _gtk_window_constrain_size (GtkWindow *window,
4695 GtkWindowGeometryInfo *info;
4697 g_return_if_fail (GTK_IS_WINDOW (window));
4699 info = window->geometry_info;
4702 GdkWindowHints flags = info->last.flags;
4703 GdkGeometry *geometry = &info->last.geometry;
4705 gtk_window_constrain_size (window,
4716 gtk_window_constrain_size (GtkWindow *window,
4717 GdkGeometry *geometry,
4724 gdk_window_constrain_size (geometry, flags, width, height,
4725 new_width, new_height);
4728 /* Compute the set of geometry hints and flags for a window
4729 * based on the application set geometry, and requisiition
4730 * of the window. gtk_widget_size_request() must have been
4734 gtk_window_compute_hints (GtkWindow *window,
4735 GdkGeometry *new_geometry,
4739 gint extra_width = 0;
4740 gint extra_height = 0;
4741 GtkWindowGeometryInfo *geometry_info;
4742 GtkRequisition requisition;
4744 widget = GTK_WIDGET (window);
4746 gtk_widget_get_child_requisition (widget, &requisition);
4747 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
4751 *new_flags = geometry_info->mask;
4752 *new_geometry = geometry_info->geometry;
4759 if (geometry_info && geometry_info->widget)
4761 GtkRequisition child_requisition;
4763 /* FIXME: This really isn't right. It gets the min size wrong and forces
4764 * callers to do horrible hacks like set a huge usize on the child requisition
4765 * to get the base size right. We really want to find the answers to:
4767 * - If the geometry widget was infinitely big, how much extra space
4768 * would be needed for the stuff around it.
4770 * - If the geometry widget was infinitely small, how big would the
4771 * window still have to be.
4773 * Finding these answers would be a bit of a mess here. (Bug #68668)
4775 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
4777 extra_width = widget->requisition.width - child_requisition.width;
4778 extra_height = widget->requisition.height - child_requisition.height;
4781 /* We don't want to set GDK_HINT_POS in here, we just set it
4782 * in gtk_window_move_resize() when we want the position
4786 if (*new_flags & GDK_HINT_BASE_SIZE)
4788 new_geometry->base_width += extra_width;
4789 new_geometry->base_height += extra_height;
4791 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
4792 (*new_flags & GDK_HINT_RESIZE_INC) &&
4793 ((extra_width != 0) || (extra_height != 0)))
4795 *new_flags |= GDK_HINT_BASE_SIZE;
4797 new_geometry->base_width = extra_width;
4798 new_geometry->base_height = extra_height;
4801 if (*new_flags & GDK_HINT_MIN_SIZE)
4803 if (new_geometry->min_width < 0)
4804 new_geometry->min_width = requisition.width;
4806 new_geometry->min_width += extra_width;
4808 if (new_geometry->min_height < 0)
4809 new_geometry->min_height = requisition.height;
4811 new_geometry->min_height += extra_height;
4813 else if (!window->allow_shrink)
4815 *new_flags |= GDK_HINT_MIN_SIZE;
4817 new_geometry->min_width = requisition.width;
4818 new_geometry->min_height = requisition.height;
4821 if (*new_flags & GDK_HINT_MAX_SIZE)
4823 if (new_geometry->max_width < 0)
4824 new_geometry->max_width = requisition.width;
4826 new_geometry->max_width += extra_width;
4828 if (new_geometry->max_height < 0)
4829 new_geometry->max_width = requisition.height;
4831 new_geometry->max_height += extra_height;
4833 else if (!window->allow_grow)
4835 *new_flags |= GDK_HINT_MAX_SIZE;
4837 new_geometry->max_width = requisition.width;
4838 new_geometry->max_height = requisition.height;
4841 *new_flags |= GDK_HINT_WIN_GRAVITY;
4842 new_geometry->win_gravity = window->gravity;
4845 /***********************
4846 * Redrawing functions *
4847 ***********************/
4850 gtk_window_paint (GtkWidget *widget,
4853 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
4854 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
4858 gtk_window_expose (GtkWidget *widget,
4859 GdkEventExpose *event)
4861 if (!GTK_WIDGET_APP_PAINTABLE (widget))
4862 gtk_window_paint (widget, &event->area);
4864 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
4865 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
4871 * gtk_window_set_has_frame:
4872 * @window: a #GtkWindow
4873 * @setting: a boolean
4875 * (Note: this is a special-purpose function for the framebuffer port,
4876 * that causes GTK+ to draw its own window border. For most applications,
4877 * you want gtk_window_set_decorated() instead, which tells the window
4878 * manager whether to draw the window border.)
4880 * If this function is called on a window with setting of %TRUE, before
4881 * it is realized or showed, it will have a "frame" window around
4882 * @window->window, accessible in @window->frame. Using the signal
4883 * frame_event you can recieve all events targeted at the frame.
4885 * This function is used by the linux-fb port to implement managed
4886 * windows, but it could concievably be used by X-programs that
4887 * want to do their own window decorations.
4891 gtk_window_set_has_frame (GtkWindow *window,
4894 g_return_if_fail (GTK_IS_WINDOW (window));
4895 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
4897 window->has_frame = setting != FALSE;
4901 * gtk_window_get_has_frame:
4902 * @window: a #GtkWindow
4904 * Accessor for whether the window has a frame window exterior to
4905 * @window->window. Gets the value set by gtk_window_set_has_frame ().
4907 * Return value: %TRUE if a frame has been added to the window
4908 * via gtk_window_set_has_frame().
4911 gtk_window_get_has_frame (GtkWindow *window)
4913 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4915 return window->has_frame;
4919 * gtk_window_set_frame_dimensions:
4920 * @window: a #GtkWindow that has a frame
4921 * @left: The width of the left border
4922 * @top: The height of the top border
4923 * @right: The width of the right border
4924 * @bottom: The height of the bottom border
4926 * (Note: this is a special-purpose function intended for the framebuffer
4927 * port; see gtk_window_set_has_frame(). It will have no effect on the
4928 * window border drawn by the window manager, which is the normal
4929 * case when using the X Window system.)
4931 * For windows with frames (see gtk_window_set_has_frame()) this function
4932 * can be used to change the size of the frame border.
4935 gtk_window_set_frame_dimensions (GtkWindow *window,
4943 g_return_if_fail (GTK_IS_WINDOW (window));
4945 widget = GTK_WIDGET (window);
4947 if (window->frame_left == left &&
4948 window->frame_top == top &&
4949 window->frame_right == right &&
4950 window->frame_bottom == bottom)
4953 window->frame_left = left;
4954 window->frame_top = top;
4955 window->frame_right = right;
4956 window->frame_bottom = bottom;
4958 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4960 gint width = widget->allocation.width + left + right;
4961 gint height = widget->allocation.height + top + bottom;
4962 gdk_window_resize (window->frame, width, height);
4963 gtk_decorated_window_move_resize_window (window,
4965 widget->allocation.width,
4966 widget->allocation.height);
4971 * gtk_window_present:
4972 * @window: a #GtkWindow
4974 * Presents a window to the user. This may mean raising the window
4975 * in the stacking order, deiconifying it, moving it to the current
4976 * desktop, and/or giving it the keyboard focus, possibly dependent
4977 * on the user's platform, window manager, and preferences.
4979 * If @window is hidden, this function calls gtk_widget_show()
4982 * This function should be used when the user tries to open a window
4983 * that's already open. Say for example the preferences dialog is
4984 * currently open, and the user chooses Preferences from the menu
4985 * a second time; use gtk_window_present() to move the already-open dialog
4986 * where the user can see it.
4990 gtk_window_present (GtkWindow *window)
4994 g_return_if_fail (GTK_IS_WINDOW (window));
4996 widget = GTK_WIDGET (window);
4998 if (GTK_WIDGET_VISIBLE (window))
5000 g_assert (widget->window != NULL);
5002 gdk_window_show (widget->window);
5004 /* note that gdk_window_focus() will also move the window to
5005 * the current desktop, for WM spec compliant window managers.
5007 gdk_window_focus (widget->window,
5008 gtk_get_current_event_time ());
5012 gtk_widget_show (widget);
5017 * gtk_window_iconify:
5018 * @window: a #GtkWindow
5020 * Asks to iconify (i.e. minimize) the specified @window. Note that
5021 * you shouldn't assume the window is definitely iconified afterward,
5022 * because other entities (e.g. the user or <link
5023 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
5024 * again, or there may not be a window manager in which case
5025 * iconification isn't possible, etc. But normally the window will end
5026 * up iconified. Just don't write code that crashes if not.
5028 * It's permitted to call this function before showing a window,
5029 * in which case the window will be iconified before it ever appears
5032 * You can track iconification via the "window_state_event" signal
5037 gtk_window_iconify (GtkWindow *window)
5040 GdkWindow *toplevel;
5042 g_return_if_fail (GTK_IS_WINDOW (window));
5044 widget = GTK_WIDGET (window);
5046 window->iconify_initially = TRUE;
5049 toplevel = window->frame;
5051 toplevel = widget->window;
5053 if (toplevel != NULL)
5054 gdk_window_iconify (toplevel);
5058 * gtk_window_deiconify:
5059 * @window: a #GtkWindow
5061 * Asks to deiconify (i.e. unminimize) the specified @window. Note
5062 * that you shouldn't assume the window is definitely deiconified
5063 * afterward, because other entities (e.g. the user or <link
5064 * linkend="gtk-X11-arch">window manager</link>) could iconify it
5065 * again before your code which assumes deiconification gets to run.
5067 * You can track iconification via the "window_state_event" signal
5071 gtk_window_deiconify (GtkWindow *window)
5074 GdkWindow *toplevel;
5076 g_return_if_fail (GTK_IS_WINDOW (window));
5078 widget = GTK_WIDGET (window);
5080 window->iconify_initially = FALSE;
5083 toplevel = window->frame;
5085 toplevel = widget->window;
5087 if (toplevel != NULL)
5088 gdk_window_deiconify (toplevel);
5093 * @window: a #GtkWindow
5095 * Asks to stick @window, which means that it will appear on all user
5096 * desktops. Note that you shouldn't assume the window is definitely
5097 * stuck afterward, because other entities (e.g. the user or <link
5098 * linkend="gtk-X11-arch">window manager</link>) could unstick it
5099 * again, and some window managers do not support sticking
5100 * windows. But normally the window will end up stuck. Just don't
5101 * write code that crashes if not.
5103 * It's permitted to call this function before showing a window.
5105 * You can track stickiness via the "window_state_event" signal
5110 gtk_window_stick (GtkWindow *window)
5113 GdkWindow *toplevel;
5115 g_return_if_fail (GTK_IS_WINDOW (window));
5117 widget = GTK_WIDGET (window);
5119 window->stick_initially = TRUE;
5122 toplevel = window->frame;
5124 toplevel = widget->window;
5126 if (toplevel != NULL)
5127 gdk_window_stick (toplevel);
5131 * gtk_window_unstick:
5132 * @window: a #GtkWindow
5134 * Asks to unstick @window, which means that it will appear on only
5135 * one of the user's desktops. Note that you shouldn't assume the
5136 * window is definitely unstuck afterward, because other entities
5137 * (e.g. the user or <link linkend="gtk-X11-arch">window
5138 * manager</link>) could stick it again. But normally the window will
5139 * end up stuck. Just don't write code that crashes if not.
5141 * You can track stickiness via the "window_state_event" signal
5146 gtk_window_unstick (GtkWindow *window)
5149 GdkWindow *toplevel;
5151 g_return_if_fail (GTK_IS_WINDOW (window));
5153 widget = GTK_WIDGET (window);
5155 window->stick_initially = FALSE;
5158 toplevel = window->frame;
5160 toplevel = widget->window;
5162 if (toplevel != NULL)
5163 gdk_window_unstick (toplevel);
5167 * gtk_window_maximize:
5168 * @window: a #GtkWindow
5170 * Asks to maximize @window, so that it becomes full-screen. Note that
5171 * you shouldn't assume the window is definitely maximized afterward,
5172 * because other entities (e.g. the user or <link
5173 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
5174 * again, and not all window managers support maximization. But
5175 * normally the window will end up maximized. Just don't write code
5176 * that crashes if not.
5178 * It's permitted to call this function before showing a window,
5179 * in which case the window will be maximized when it appears onscreen
5182 * You can track maximization via the "window_state_event" signal
5187 gtk_window_maximize (GtkWindow *window)
5190 GdkWindow *toplevel;
5192 g_return_if_fail (GTK_IS_WINDOW (window));
5194 widget = GTK_WIDGET (window);
5196 window->maximize_initially = TRUE;
5199 toplevel = window->frame;
5201 toplevel = widget->window;
5203 if (toplevel != NULL)
5204 gdk_window_maximize (toplevel);
5208 * gtk_window_unmaximize:
5209 * @window: a #GtkWindow
5211 * Asks to unmaximize @window. Note that you shouldn't assume the
5212 * window is definitely unmaximized afterward, because other entities
5213 * (e.g. the user or <link linkend="gtk-X11-arch">window
5214 * manager</link>) could maximize it again, and not all window
5215 * managers honor requests to unmaximize. But normally the window will
5216 * end up unmaximized. Just don't write code that crashes if not.
5218 * You can track maximization via the "window_state_event" signal
5223 gtk_window_unmaximize (GtkWindow *window)
5226 GdkWindow *toplevel;
5228 g_return_if_fail (GTK_IS_WINDOW (window));
5230 widget = GTK_WIDGET (window);
5232 window->maximize_initially = FALSE;
5235 toplevel = window->frame;
5237 toplevel = widget->window;
5239 if (toplevel != NULL)
5240 gdk_window_unmaximize (toplevel);
5244 * gtk_window_set_resizable:
5245 * @window: a #GtkWindow
5246 * @resizable: %TRUE if the user can resize this window
5248 * Sets whether the user can resize a window. Windows are user resizable
5252 gtk_window_set_resizable (GtkWindow *window,
5255 g_return_if_fail (GTK_IS_WINDOW (window));
5257 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5261 * gtk_window_get_resizable:
5262 * @window: a #GtkWindow
5264 * Gets the value set by gtk_window_set_resizable().
5266 * Return value: %TRUE if the user can resize the window
5269 gtk_window_get_resizable (GtkWindow *window)
5271 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5273 /* allow_grow is most likely to indicate the semantic concept we
5274 * mean by "resizable" (and will be a reliable indicator if
5275 * set_policy() hasn't been called)
5277 return window->allow_grow;
5281 * gtk_window_set_gravity:
5282 * @window: a #GtkWindow
5283 * @gravity: window gravity
5285 * Window gravity defines the meaning of coordinates passed to
5286 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5289 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5290 * typically "do what you mean."
5294 gtk_window_set_gravity (GtkWindow *window,
5297 g_return_if_fail (GTK_IS_WINDOW (window));
5299 if (gravity != window->gravity)
5301 window->gravity = gravity;
5303 /* gtk_window_move_resize() will adapt gravity
5305 gtk_widget_queue_resize (GTK_WIDGET (window));
5310 * gtk_window_get_gravity:
5311 * @window: a #GtkWindow
5313 * Gets the value set by gtk_window_set_gravity().
5315 * Return value: window gravity
5318 gtk_window_get_gravity (GtkWindow *window)
5320 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5322 return window->gravity;
5326 * gtk_window_begin_resize_drag:
5327 * @window: a #GtkWindow
5328 * @button: mouse button that initiated the drag
5329 * @edge: position of the resize control
5330 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5331 * @root_y: Y position where the user clicked to initiate the drag
5332 * @timestamp: timestamp from the click event that initiated the drag
5334 * Starts resizing a window. This function is used if an application
5335 * has window resizing controls. When GDK can support it, the resize
5336 * will be done using the standard mechanism for the <link
5337 * linkend="gtk-X11-arch">window manager</link> or windowing
5338 * system. Otherwise, GDK will try to emulate window resizing,
5339 * potentially not all that well, depending on the windowing system.
5343 gtk_window_begin_resize_drag (GtkWindow *window,
5351 GdkWindow *toplevel;
5353 g_return_if_fail (GTK_IS_WINDOW (window));
5354 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5356 widget = GTK_WIDGET (window);
5359 toplevel = window->frame;
5361 toplevel = widget->window;
5363 gdk_window_begin_resize_drag (toplevel,
5370 * gtk_window_get_frame_dimensions:
5371 * @window: a #GtkWindow
5372 * @left: location to store the width of the frame at the left, or %NULL
5373 * @top: location to store the height of the frame at the top, or %NULL
5374 * @right: location to store the width of the frame at the returns, or %NULL
5375 * @bottom: location to store the height of the frame at the bottom, or %NULL
5377 * (Note: this is a special-purpose function intended for the
5378 * framebuffer port; see gtk_window_set_has_frame(). It will not
5379 * return the size of the window border drawn by the <link
5380 * linkend="gtk-X11-arch">window manager</link>, which is the normal
5381 * case when using a windowing system. See
5382 * gdk_window_get_frame_extents() to get the standard window border
5385 * Retrieves the dimensions of the frame window for this toplevel.
5386 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5389 gtk_window_get_frame_dimensions (GtkWindow *window,
5395 g_return_if_fail (GTK_IS_WINDOW (window));
5398 *left = window->frame_left;
5400 *top = window->frame_top;
5402 *right = window->frame_right;
5404 *bottom = window->frame_bottom;
5408 * gtk_window_begin_move_drag:
5409 * @window: a #GtkWindow
5410 * @button: mouse button that initiated the drag
5411 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5412 * @root_y: Y position where the user clicked to initiate the drag
5413 * @timestamp: timestamp from the click event that initiated the drag
5415 * Starts moving a window. This function is used if an application has
5416 * window movement grips. When GDK can support it, the window movement
5417 * will be done using the standard mechanism for the <link
5418 * linkend="gtk-X11-arch">window manager</link> or windowing
5419 * system. Otherwise, GDK will try to emulate window movement,
5420 * potentially not all that well, depending on the windowing system.
5424 gtk_window_begin_move_drag (GtkWindow *window,
5431 GdkWindow *toplevel;
5433 g_return_if_fail (GTK_IS_WINDOW (window));
5434 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5436 widget = GTK_WIDGET (window);
5439 toplevel = window->frame;
5441 toplevel = widget->window;
5443 gdk_window_begin_move_drag (toplevel,
5450 * gtk_window_set_screen:
5451 * @window: a #GtkWindow.
5452 * @screen: a #GdkScreen.
5454 * Sets the #GdkScreen where the @window is displayed; if
5455 * the window is already mapped, it will be unmapped, and
5456 * then remapped on the new screen.
5459 gtk_window_set_screen (GtkWindow *window,
5463 gboolean was_mapped;
5465 g_return_if_fail (GTK_IS_WINDOW (window));
5466 g_return_if_fail (GDK_IS_SCREEN (screen));
5468 if (screen == window->screen)
5471 widget = GTK_WIDGET (window);
5473 was_mapped = GTK_WIDGET_MAPPED (widget);
5476 gtk_widget_unmap (widget);
5477 if (GTK_WIDGET_REALIZED (widget))
5478 gtk_widget_unrealize (widget);
5480 gtk_window_free_key_hash (window);
5481 window->screen = screen;
5482 gtk_widget_reset_rc_styles (widget);
5483 g_object_notify (G_OBJECT (window), "screen");
5486 gtk_widget_map (widget);
5490 * gtk_window_get_screen:
5491 * @window: a #GtkWindow.
5493 * Returns the #GdkScreen associated with @window.
5495 * Return value: a #GdkScreen.
5498 gtk_window_get_screen (GtkWindow *window)
5500 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
5502 return window->screen;
5507 gtk_window_group_class_init (GtkWindowGroupClass *klass)
5512 gtk_window_group_get_type (void)
5514 static GtkType window_group_type = 0;
5516 if (!window_group_type)
5518 static const GTypeInfo window_group_info =
5520 sizeof (GtkWindowGroupClass),
5521 NULL, /* base_init */
5522 NULL, /* base_finalize */
5523 (GClassInitFunc) gtk_window_group_class_init,
5524 NULL, /* class_finalize */
5525 NULL, /* class_data */
5526 sizeof (GtkWindowGroup),
5527 16, /* n_preallocs */
5528 (GInstanceInitFunc) NULL,
5531 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
5534 return window_group_type;
5538 * gtk_window_group_new:
5540 * Creates a new #GtkWindowGroup object. Grabs added with
5541 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
5543 * Return value: a new #GtkWindowGroup.
5546 gtk_window_group_new (void)
5548 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
5552 window_group_cleanup_grabs (GtkWindowGroup *group,
5556 GSList *to_remove = NULL;
5558 tmp_list = group->grabs;
5561 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
5562 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
5563 tmp_list = tmp_list->next;
5568 gtk_grab_remove (to_remove->data);
5569 g_object_unref (to_remove->data);
5570 to_remove = g_slist_delete_link (to_remove, to_remove);
5575 * gtk_window_group_add_window:
5576 * @window_group: a #GtkWindowGroup
5577 * @window: the #GtkWindow to add
5579 * Adds a window to a #GtkWindowGroup.
5582 gtk_window_group_add_window (GtkWindowGroup *window_group,
5585 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5586 g_return_if_fail (GTK_IS_WINDOW (window));
5588 if (window->group != window_group)
5590 g_object_ref (window);
5591 g_object_ref (window_group);
5594 gtk_window_group_remove_window (window->group, window);
5596 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
5598 window->group = window_group;
5600 g_object_unref (window);
5605 * gtk_window_group_remove_window:
5606 * @window_group: a #GtkWindowGroup
5607 * @window: the #GtkWindow to remove
5609 * Removes a window from a #GtkWindowGroup.
5612 gtk_window_group_remove_window (GtkWindowGroup *window_group,
5615 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5616 g_return_if_fail (GTK_IS_WIDGET (window));
5617 g_return_if_fail (window->group == window_group);
5619 g_object_ref (window);
5621 window_group_cleanup_grabs (window_group, window);
5622 window->group = NULL;
5624 g_object_unref (G_OBJECT (window_group));
5625 g_object_unref (window);
5628 /* Return the group for the window or the default group
5631 _gtk_window_get_group (GtkWindow *window)
5633 if (window && window->group)
5634 return window->group;
5637 static GtkWindowGroup *default_group = NULL;
5640 default_group = gtk_window_group_new ();
5642 return default_group;
5648 Derived from XParseGeometry() in XFree86
5650 Copyright 1985, 1986, 1987,1998 The Open Group
5652 All Rights Reserved.
5654 The above copyright notice and this permission notice shall be included
5655 in all copies or substantial portions of the Software.
5657 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5658 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5659 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
5660 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
5661 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
5662 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
5663 OTHER DEALINGS IN THE SOFTWARE.
5665 Except as contained in this notice, the name of The Open Group shall
5666 not be used in advertising or otherwise to promote the sale, use or
5667 other dealings in this Software without prior written authorization
5668 from The Open Group.
5673 * XParseGeometry parses strings of the form
5674 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5675 * width, height, xoffset, and yoffset are unsigned integers.
5676 * Example: "=80x24+300-49"
5677 * The equal sign is optional.
5678 * It returns a bitmask that indicates which of the four values
5679 * were actually found in the string. For each value found,
5680 * the corresponding argument is updated; for each value
5681 * not found, the corresponding argument is left unchanged.
5684 /* The following code is from Xlib, and is minimally modified, so we
5685 * can track any upstream changes if required. Don't change this
5686 * code. Or if you do, put in a huge comment marking which thing
5691 read_int (gchar *string,
5699 else if (*string == '-')
5705 for (; (*string >= '0') && (*string <= '9'); string++)
5707 result = (result * 10) + (*string - '0');
5719 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
5720 * value (x, y, width, height) was found in the parsed string.
5722 #define NoValue 0x0000
5723 #define XValue 0x0001
5724 #define YValue 0x0002
5725 #define WidthValue 0x0004
5726 #define HeightValue 0x0008
5727 #define AllValues 0x000F
5728 #define XNegative 0x0010
5729 #define YNegative 0x0020
5731 /* Try not to reformat/modify, so we can compare/sync with X sources */
5733 gtk_XParseGeometry (const char *string,
5736 unsigned int *width,
5737 unsigned int *height)
5741 unsigned int tempWidth, tempHeight;
5743 char *nextCharacter;
5745 /* These initializations are just to silence gcc */
5751 if ( (string == NULL) || (*string == '\0')) return(mask);
5753 string++; /* ignore possible '=' at beg of geometry spec */
5755 strind = (char *)string;
5756 if (*strind != '+' && *strind != '-' && *strind != 'x') {
5757 tempWidth = read_int(strind, &nextCharacter);
5758 if (strind == nextCharacter)
5760 strind = nextCharacter;
5764 if (*strind == 'x' || *strind == 'X') {
5766 tempHeight = read_int(strind, &nextCharacter);
5767 if (strind == nextCharacter)
5769 strind = nextCharacter;
5770 mask |= HeightValue;
5773 if ((*strind == '+') || (*strind == '-')) {
5774 if (*strind == '-') {
5776 tempX = -read_int(strind, &nextCharacter);
5777 if (strind == nextCharacter)
5779 strind = nextCharacter;
5785 tempX = read_int(strind, &nextCharacter);
5786 if (strind == nextCharacter)
5788 strind = nextCharacter;
5791 if ((*strind == '+') || (*strind == '-')) {
5792 if (*strind == '-') {
5794 tempY = -read_int(strind, &nextCharacter);
5795 if (strind == nextCharacter)
5797 strind = nextCharacter;
5804 tempY = read_int(strind, &nextCharacter);
5805 if (strind == nextCharacter)
5807 strind = nextCharacter;
5813 /* If strind isn't at the end of the string the it's an invalid
5814 geometry specification. */
5816 if (*strind != '\0') return (0);
5822 if (mask & WidthValue)
5824 if (mask & HeightValue)
5825 *height = tempHeight;
5830 * gtk_window_parse_geometry:
5831 * @window: a #GtkWindow
5832 * @geometry: geometry string
5834 * Parses a standard X Window System geometry string - see the
5835 * manual page for X (type 'man X') for details on this.
5836 * gtk_window_parse_geometry() does work on all GTK+ ports
5837 * including Win32 but is primarily intended for an X environment.
5839 * If either a size or a position can be extracted from the
5840 * geometry string, gtk_window_parse_geometry() returns %TRUE
5841 * and calls gtk_window_set_default_size() and/or gtk_window_move()
5842 * to resize/move the window.
5844 * If gtk_window_parse_geometry() returns %TRUE, it will also
5845 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
5846 * indicating to the window manager that the size/position of
5847 * the window was user-specified. This causes most window
5848 * managers to honor the geometry.
5850 * Return value: %TRUE if string was parsed successfully
5853 gtk_window_parse_geometry (GtkWindow *window,
5854 const gchar *geometry)
5859 gboolean size_set, pos_set;
5861 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5862 g_return_val_if_fail (geometry != NULL, FALSE);
5864 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
5866 if ((result & WidthValue) == 0 ||
5869 if ((result & HeightValue) == 0 ||
5874 if ((result & WidthValue) || (result & HeightValue))
5876 gtk_window_set_default_size_internal (window, TRUE, w, TRUE, h, TRUE);
5880 gtk_window_get_size (window, &w, &h);
5882 grav = GDK_GRAVITY_NORTH_WEST;
5884 if ((result & XNegative) && (result & YNegative))
5885 grav = GDK_GRAVITY_SOUTH_EAST;
5886 else if (result & XNegative)
5887 grav = GDK_GRAVITY_NORTH_EAST;
5888 else if (result & YNegative)
5889 grav = GDK_GRAVITY_SOUTH_WEST;
5891 if ((result & XValue) == 0)
5894 if ((result & YValue) == 0)
5897 if (grav == GDK_GRAVITY_SOUTH_WEST ||
5898 grav == GDK_GRAVITY_SOUTH_EAST)
5899 y = gdk_screen_get_height (window->screen) - h + y;
5901 if (grav == GDK_GRAVITY_SOUTH_EAST ||
5902 grav == GDK_GRAVITY_NORTH_EAST)
5903 x = gdk_screen_get_width (window->screen) - w + x;
5905 /* we don't let you put a window offscreen; maybe some people would
5906 * prefer to be able to, but it's kind of a bogus thing to do.
5915 if ((result & XValue) || (result & YValue))
5917 gtk_window_set_gravity (window, grav);
5918 gtk_window_move (window, x, y);
5922 if (size_set || pos_set)
5924 /* Set USSize, USPosition hints */
5925 GtkWindowGeometryInfo *info;
5927 info = gtk_window_get_geometry_info (window, TRUE);
5930 info->mask |= GDK_HINT_USER_POS;
5932 info->mask |= GDK_HINT_USER_SIZE;
5939 gtk_window_mnemonic_hash_foreach (gpointer key,
5945 GtkWindowKeysForeachFunc func;
5949 GtkWindowMnemonic *mnemonic = value;
5951 if (mnemonic->window == info->window)
5952 (*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
5956 _gtk_window_keys_foreach (GtkWindow *window,
5957 GtkWindowKeysForeachFunc func,
5964 GtkWindowKeysForeachFunc func;
5968 info.window = window;
5970 info.func_data = func_data;
5972 g_hash_table_foreach (mnemonic_hash_table,
5973 gtk_window_mnemonic_hash_foreach,
5976 groups = gtk_accel_groups_from_object (G_OBJECT (window));
5979 GtkAccelGroup *group = groups->data;
5982 for (i = 0; i < group->n_accels; i++)
5984 GtkAccelKey *key = &group->priv_accels[i].key;
5987 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
5990 groups = groups->next;
5995 gtk_window_keys_changed (GtkWindow *window)
5997 gtk_window_free_key_hash (window);
5998 gtk_window_get_key_hash (window);
6001 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
6003 struct _GtkWindowKeyEntry
6007 gboolean is_mnemonic;
6011 add_to_key_hash (GtkWindow *window,
6013 GdkModifierType modifiers,
6014 gboolean is_mnemonic,
6017 GtkKeyHash *key_hash = data;
6019 GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
6021 entry->keyval = keyval;
6022 entry->modifiers = modifiers;
6023 entry->is_mnemonic = is_mnemonic;
6025 /* GtkAccelGroup stores lowercased accelerators. To deal
6026 * with this, if <Shift> was specified, uppercase.
6028 if (modifiers & GDK_SHIFT_MASK)
6030 if (keyval == GDK_Tab)
6031 keyval = GDK_ISO_Left_Tab;
6033 keyval = gdk_keyval_to_upper (keyval);
6036 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
6040 gtk_window_get_key_hash (GtkWindow *window)
6042 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6046 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (window->screen)),
6047 (GDestroyNotify)g_free);
6048 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
6049 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
6055 gtk_window_free_key_hash (GtkWindow *window)
6057 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6060 _gtk_key_hash_free (key_hash);
6061 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
6066 * _gtk_window_activate_key:
6067 * @window: a #GtkWindow
6068 * @event: a #GdkEventKey
6070 * Activates mnemonics and accelerators for this #GtKWindow
6072 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
6075 _gtk_window_activate_key (GtkWindow *window,
6078 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6079 GtkWindowKeyEntry *found_entry = NULL;
6083 gtk_window_keys_changed (window);
6084 key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6089 GSList *entries = _gtk_key_hash_lookup (key_hash,
6090 event->hardware_keycode,
6091 event->state & gtk_accelerator_get_default_mod_mask (),
6095 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
6097 GtkWindowKeyEntry *entry = tmp_list->data;
6098 if (entry->is_mnemonic)
6100 found_entry = entry;
6105 if (!found_entry && entries)
6106 found_entry = entries->data;
6108 g_slist_free (entries);
6113 if (found_entry->is_mnemonic)
6114 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
6116 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
6123 window_update_has_focus (GtkWindow *window)
6125 GtkWidget *widget = GTK_WIDGET (window);
6126 gboolean has_focus = window->has_toplevel_focus && window->is_active;
6128 if (has_focus != window->has_focus)
6130 window->has_focus = has_focus;
6134 if (window->focus_widget &&
6135 window->focus_widget != widget &&
6136 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6137 do_focus_change (window->focus_widget, TRUE);
6141 if (window->focus_widget &&
6142 window->focus_widget != widget &&
6143 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6144 do_focus_change (window->focus_widget, FALSE);
6150 * _gtk_window_set_is_active:
6151 * @window: a #GtkWindow
6152 * @is_active: %TRUE if the window is in the currently active toplevel
6154 * Internal function that sets whether the #GtkWindow is part
6155 * of the currently active toplevel window (taking into account inter-process
6159 _gtk_window_set_is_active (GtkWindow *window,
6162 g_return_if_fail (GTK_IS_WINDOW (window));
6164 is_active = is_active != FALSE;
6166 if (is_active != window->is_active)
6168 window->is_active = is_active;
6169 window_update_has_focus (window);
6171 g_object_notify (G_OBJECT (window), "is_active");
6176 * _gtk_window_set_has_toplevel_focus:
6177 * @window: a #GtkWindow
6178 * @has_toplevel_focus: %TRUE if the in
6180 * Internal function that sets whether the keyboard focus for the
6181 * toplevel window (taking into account inter-process embedding.)
6184 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
6185 gboolean has_toplevel_focus)
6187 g_return_if_fail (GTK_IS_WINDOW (window));
6189 has_toplevel_focus = has_toplevel_focus != FALSE;
6191 if (has_toplevel_focus != window->has_toplevel_focus)
6193 window->has_toplevel_focus = has_toplevel_focus;
6194 window_update_has_focus (window);
6196 g_object_notify (G_OBJECT (window), "has_toplevel_focus");