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 #if defined (GDK_WINDOWING_X11)
34 #elif defined (GDK_WINDOWING_WIN32)
35 #include "win32/gdkwin32.h"
36 #elif defined (GDK_WINDOWING_NANOX)
37 #include "nanox/gdkprivate-nanox.h"
38 #elif defined (GDK_WINDOWING_FB)
39 #include "linux-fb/gdkfb.h"
42 #include "gtkprivate.h"
44 #include "gtksignal.h"
45 #include "gtkwindow.h"
46 #include "gtkwindow-decorate.h"
47 #include "gtkbindings.h"
49 #include "gtkiconfactory.h"
73 PROP_DESTROY_WITH_PARENT,
79 GdkGeometry geometry; /* Last set of geometry hints we set */
83 } GtkWindowLastGeometryInfo;
85 struct _GtkWindowGeometryInfo
87 /* Properties that the app has set on the window
89 GdkGeometry geometry; /* Geometry hints */
91 GtkWidget *widget; /* subwidget to which hints apply */
92 gint width; /* Default size */
94 guint may_shrink : 1; /* one-shot auto_shrink behaviour after set_default_size */
96 GtkWindowLastGeometryInfo last;
107 static void gtk_window_class_init (GtkWindowClass *klass);
108 static void gtk_window_init (GtkWindow *window);
109 static void gtk_window_shutdown (GObject *object);
110 static void gtk_window_destroy (GtkObject *object);
111 static void gtk_window_finalize (GObject *object);
112 static void gtk_window_show (GtkWidget *widget);
113 static void gtk_window_hide (GtkWidget *widget);
114 static void gtk_window_map (GtkWidget *widget);
115 static void gtk_window_unmap (GtkWidget *widget);
116 static void gtk_window_realize (GtkWidget *widget);
117 static void gtk_window_unrealize (GtkWidget *widget);
118 static void gtk_window_size_request (GtkWidget *widget,
119 GtkRequisition *requisition);
120 static void gtk_window_size_allocate (GtkWidget *widget,
121 GtkAllocation *allocation);
122 static gint gtk_window_event (GtkWidget *widget,
124 static gboolean gtk_window_frame_event (GtkWidget *widget,
126 static gint gtk_window_configure_event (GtkWidget *widget,
127 GdkEventConfigure *event);
128 static gint gtk_window_key_press_event (GtkWidget *widget,
130 static gint gtk_window_key_release_event (GtkWidget *widget,
132 static gint gtk_window_enter_notify_event (GtkWidget *widget,
133 GdkEventCrossing *event);
134 static gint gtk_window_leave_notify_event (GtkWidget *widget,
135 GdkEventCrossing *event);
136 static gint gtk_window_focus_in_event (GtkWidget *widget,
137 GdkEventFocus *event);
138 static gint gtk_window_focus_out_event (GtkWidget *widget,
139 GdkEventFocus *event);
140 static gint gtk_window_client_event (GtkWidget *widget,
141 GdkEventClient *event);
142 static void gtk_window_check_resize (GtkContainer *container);
143 static gint gtk_window_focus (GtkContainer *container,
144 GtkDirectionType direction);
145 static void gtk_window_real_set_focus (GtkWindow *window,
148 static void gtk_window_move_resize (GtkWindow *window);
149 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
151 GdkGeometry *geometry_b,
153 static void gtk_window_compute_default_size (GtkWindow *window,
156 static void gtk_window_constrain_size (GtkWindow *window,
157 GdkGeometry *geometry,
163 static void gtk_window_compute_hints (GtkWindow *window,
164 GdkGeometry *new_geometry,
166 static gint gtk_window_compute_reposition (GtkWindow *window,
172 static void gtk_window_read_rcfiles (GtkWidget *widget,
173 GdkEventClient *event);
174 static void gtk_window_paint (GtkWidget *widget,
176 static gint gtk_window_expose (GtkWidget *widget,
177 GdkEventExpose *event);
178 static void gtk_window_unset_transient_for (GtkWindow *window);
179 static void gtk_window_transient_parent_realized (GtkWidget *parent,
181 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
184 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
188 static GSList *toplevel_list = NULL;
189 static GHashTable *mnemonic_hash_table = NULL;
190 static GtkBinClass *parent_class = NULL;
191 static guint window_signals[LAST_SIGNAL] = { 0 };
193 static void gtk_window_set_property (GObject *object,
197 static void gtk_window_get_property (GObject *object,
204 mnemonic_hash (gconstpointer key)
206 const GtkWindowMnemonic *k;
209 k = (GtkWindowMnemonic *)key;
211 h = (gulong) k->window;
212 h ^= k->keyval << 16;
213 h ^= k->keyval >> 16;
219 mnemonic_equal (gconstpointer a, gconstpointer b)
221 const GtkWindowMnemonic *ka;
222 const GtkWindowMnemonic *kb;
224 ka = (GtkWindowMnemonic *)a;
225 kb = (GtkWindowMnemonic *)b;
228 (ka->window == kb->window) &&
229 (ka->keyval == kb->keyval);
233 gtk_window_get_type (void)
235 static GtkType window_type = 0;
239 static const GtkTypeInfo window_info =
243 sizeof (GtkWindowClass),
244 (GtkClassInitFunc) gtk_window_class_init,
245 (GtkObjectInitFunc) gtk_window_init,
246 /* reserved_1 */ NULL,
247 /* reserved_2 */ NULL,
248 (GtkClassInitFunc) NULL,
251 window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
258 gtk_window_class_init (GtkWindowClass *klass)
260 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
261 GtkObjectClass *object_class;
262 GtkWidgetClass *widget_class;
263 GtkContainerClass *container_class;
265 object_class = (GtkObjectClass*) klass;
266 widget_class = (GtkWidgetClass*) klass;
267 container_class = (GtkContainerClass*) klass;
269 parent_class = gtk_type_class (gtk_bin_get_type ());
271 gobject_class->shutdown = gtk_window_shutdown;
272 gobject_class->finalize = gtk_window_finalize;
274 gobject_class->set_property = gtk_window_set_property;
275 gobject_class->get_property = gtk_window_get_property;
277 object_class->destroy = gtk_window_destroy;
279 widget_class->show = gtk_window_show;
280 widget_class->hide = gtk_window_hide;
281 widget_class->map = gtk_window_map;
282 widget_class->unmap = gtk_window_unmap;
283 widget_class->realize = gtk_window_realize;
284 widget_class->unrealize = gtk_window_unrealize;
285 widget_class->size_request = gtk_window_size_request;
286 widget_class->size_allocate = gtk_window_size_allocate;
287 widget_class->configure_event = gtk_window_configure_event;
288 widget_class->key_press_event = gtk_window_key_press_event;
289 widget_class->key_release_event = gtk_window_key_release_event;
290 widget_class->enter_notify_event = gtk_window_enter_notify_event;
291 widget_class->leave_notify_event = gtk_window_leave_notify_event;
292 widget_class->focus_in_event = gtk_window_focus_in_event;
293 widget_class->focus_out_event = gtk_window_focus_out_event;
294 widget_class->client_event = gtk_window_client_event;
296 widget_class->expose_event = gtk_window_expose;
298 container_class->check_resize = gtk_window_check_resize;
299 container_class->focus = gtk_window_focus;
301 klass->set_focus = gtk_window_real_set_focus;
302 klass->frame_event = gtk_window_frame_event;
305 g_object_class_install_property (gobject_class,
307 g_param_spec_enum ("type",
309 _("The type of the window"),
310 GTK_TYPE_WINDOW_TYPE,
312 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
315 g_object_class_install_property (gobject_class,
317 g_param_spec_string ("title",
319 _("The title of the window"),
323 g_object_class_install_property (gobject_class,
325 g_param_spec_boolean ("auto_shrink",
327 _("If TRUE, the window automatically shrinks to its size request anytime a resize occurs. Don't use this feature, it makes no sense."),
331 g_object_class_install_property (gobject_class,
333 g_param_spec_boolean ("allow_shrink",
335 _("If TRUE, the window has no mimimum size. Don't use this feature, it makes no sense."),
339 g_object_class_install_property (gobject_class,
341 g_param_spec_boolean ("allow_grow",
343 _("If TRUE, users can expand the window beyond its minimum size."),
347 g_object_class_install_property (gobject_class,
349 g_param_spec_boolean ("modal",
351 _("If TRUE, the window is modal (other windows are not usable while this one is up)."),
355 g_object_class_install_property (gobject_class,
357 g_param_spec_enum ("window_position",
358 _("Window Position"),
359 _("The initial position of the window."),
360 GTK_TYPE_WINDOW_POSITION,
364 g_object_class_install_property (gobject_class,
366 g_param_spec_int ("default_width",
368 _("The default width of the window, or 0 to use the size request."),
374 g_object_class_install_property (gobject_class,
376 g_param_spec_int ("default_height",
378 _("The default height of the windo, or 0 to use the size request."),
384 g_object_class_install_property (gobject_class,
385 PROP_DESTROY_WITH_PARENT,
386 g_param_spec_boolean ("destroy_with_parent",
387 _("Destroy with Parent"),
388 _("If this window should be destroyed when the parent is destroyed,"),
392 /* Style props are set or not */
394 window_signals[SET_FOCUS] =
395 gtk_signal_new ("set_focus",
397 GTK_CLASS_TYPE (object_class),
398 GTK_SIGNAL_OFFSET (GtkWindowClass, set_focus),
399 gtk_marshal_VOID__OBJECT,
403 window_signals[FRAME_EVENT] =
404 g_signal_newc ("frame_event",
405 G_TYPE_FROM_CLASS(object_class),
407 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
408 _gtk_boolean_handled_accumulator, NULL,
409 gtk_marshal_BOOLEAN__BOXED,
413 if (!mnemonic_hash_table)
414 mnemonic_hash_table = g_hash_table_new (mnemonic_hash,
419 gtk_window_init (GtkWindow *window)
421 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
422 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
424 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
426 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
428 window->title = NULL;
429 window->wmclass_name = g_strdup (g_get_prgname ());
430 window->wmclass_class = g_strdup (gdk_progclass);
431 window->wm_role = NULL;
432 window->geometry_info = NULL;
433 window->type = GTK_WINDOW_TOPLEVEL;
434 window->focus_widget = NULL;
435 window->default_widget = NULL;
436 window->resize_count = 0;
437 window->allow_shrink = FALSE;
438 window->allow_grow = TRUE;
439 window->auto_shrink = FALSE;
440 window->handling_resize = FALSE;
441 window->position = GTK_WIN_POS_NONE;
442 window->use_uposition = TRUE;
443 window->modal = FALSE;
444 window->frame = NULL;
445 window->has_frame = FALSE;
446 window->frame_left = 0;
447 window->frame_right = 0;
448 window->frame_top = 0;
449 window->frame_bottom = 0;
450 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
451 window->gravity = GDK_GRAVITY_NORTH_WEST;
452 window->decorated = TRUE;
453 window->mnemonic_modifier = GDK_MOD1_MASK;
455 gtk_widget_ref (GTK_WIDGET (window));
456 gtk_object_sink (GTK_OBJECT (window));
457 window->has_user_ref_count = TRUE;
458 toplevel_list = g_slist_prepend (toplevel_list, window);
460 gtk_decorated_window_init (window);
462 gtk_signal_connect (GTK_OBJECT (window),
464 GTK_SIGNAL_FUNC (gtk_window_event),
469 gtk_window_set_property (GObject *object,
476 window = GTK_WINDOW (object);
481 window->type = g_value_get_enum (value);
484 gtk_window_set_title (window, g_value_get_string (value));
486 case PROP_AUTO_SHRINK:
487 window->auto_shrink = g_value_get_boolean (value);
488 gtk_widget_queue_resize (GTK_WIDGET (window));
490 case PROP_ALLOW_SHRINK:
491 window->allow_shrink = g_value_get_boolean (value);
492 gtk_widget_queue_resize (GTK_WIDGET (window));
494 case PROP_ALLOW_GROW:
495 window->allow_grow = g_value_get_boolean (value);
496 gtk_widget_queue_resize (GTK_WIDGET (window));
499 gtk_window_set_modal (window, g_value_get_boolean (value));
502 gtk_window_set_position (window, g_value_get_enum (value));
504 case PROP_DEFAULT_WIDTH:
505 gtk_window_set_default_size (window, g_value_get_int (value), -1);
507 case PROP_DEFAULT_HEIGHT:
508 gtk_window_set_default_size (window, -1, g_value_get_int (value));
510 case PROP_DESTROY_WITH_PARENT:
511 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
519 gtk_window_get_property (GObject *object,
526 window = GTK_WINDOW (object);
530 GtkWindowGeometryInfo *info;
532 g_value_set_enum (value, window->type);
535 g_value_set_string (value, window->title);
537 case PROP_AUTO_SHRINK:
538 g_value_set_boolean (value, window->auto_shrink);
540 case PROP_ALLOW_SHRINK:
541 g_value_set_boolean (value, window->allow_shrink);
543 case PROP_ALLOW_GROW:
544 g_value_set_boolean (value, window->allow_grow);
547 g_value_set_boolean (value, window->modal);
550 g_value_set_enum (value, window->position);
552 case PROP_DEFAULT_WIDTH:
553 info = gtk_window_get_geometry_info (window, FALSE);
555 g_value_set_int (value, 0);
557 g_value_set_int (value, info->width);
559 case PROP_DEFAULT_HEIGHT:
560 info = gtk_window_get_geometry_info (window, FALSE);
562 g_value_set_int (value, 0);
564 g_value_set_int (value, info->height);
566 case PROP_DESTROY_WITH_PARENT:
567 g_value_set_boolean (value, window->destroy_with_parent);
570 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
577 * @type: type of window
579 * Creates a new #GtkWindow, which is a toplevel window that can
580 * contain other widgets. Nearly always, the type of the window should
581 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
582 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
583 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
584 * dialogs, though in some other toolkits dialogs are called "popups."
585 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
586 * Popup windows are not controlled by the window manager.
588 * If you simply want an undecorated window (no window borders), use
589 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
591 * Return value: a new #GtkWindow.
594 gtk_window_new (GtkWindowType type)
598 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
600 window = gtk_type_new (GTK_TYPE_WINDOW);
604 return GTK_WIDGET (window);
608 * gtk_window_set_title:
609 * @window: a #GtkWindow
610 * @title: title of the window
612 * Sets the title of the #GtkWindow. The title of a window will be displayed in
613 * its title bar; on the X Window System, the title bar is rendered by the
614 * window manager, so exactly how the title appears to users may vary according
615 * to a user's exact configuration. The title should help a user distinguish
616 * this window from other windows they may have open. A good title might
617 * include the application name and current document filename, for example.
621 gtk_window_set_title (GtkWindow *window,
624 g_return_if_fail (window != NULL);
625 g_return_if_fail (GTK_IS_WINDOW (window));
628 g_free (window->title);
629 window->title = g_strdup (title);
631 if (GTK_WIDGET_REALIZED (window))
633 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
635 gtk_decorated_window_set_title (window, title);
638 g_object_notify (G_OBJECT (window), "title");
642 * gtk_window_set_wmclass:
643 * @window: a #GtkWindow
644 * @wmclass_name: window name hint
645 * @wmclass_class: window class hint
647 * Don't use this function. It sets the X Window System "class" and
648 * "name" hints for a window. According to the ICCCM, you should
649 * always set these to the same value for all windows in an
650 * application, and GTK sets them to that value by default, so calling
651 * this function is sort of pointless. However, you may want to call
652 * gtk_window_set_role() on each window in your application, for the
653 * benefit of the session manager. Setting the role allows the window
654 * manager to restore window positions when loading a saved session.
658 gtk_window_set_wmclass (GtkWindow *window,
659 const gchar *wmclass_name,
660 const gchar *wmclass_class)
662 g_return_if_fail (window != NULL);
663 g_return_if_fail (GTK_IS_WINDOW (window));
665 g_free (window->wmclass_name);
666 window->wmclass_name = g_strdup (wmclass_name);
668 g_free (window->wmclass_class);
669 window->wmclass_class = g_strdup (wmclass_class);
671 if (GTK_WIDGET_REALIZED (window))
672 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
676 * gtk_window_set_role:
677 * @window: a #GtkWindow
678 * @role: unique identifier for the window to be used when restoring a session
680 * In combination with the window title, the window role allows a
681 * window manager to identify "the same" window when an application is
682 * restarted. So for example you might set the "toolbox" role on your
683 * app's toolbox window, so that when the user restarts their session,
684 * the window manager can put the toolbox back in the same place.
686 * If a window already has a unique title, you don't need to set the
687 * role, since the WM can use the title to identify the window when
688 * restoring the session.
692 gtk_window_set_role (GtkWindow *window,
695 g_return_if_fail (GTK_IS_WINDOW (window));
697 if (role == window->wm_role)
700 g_free (window->wm_role);
701 window->wm_role = g_strdup (role);
703 if (GTK_WIDGET_REALIZED (window))
704 g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
708 * gtk_window_set_focus:
709 * @window: a #GtkWindow
710 * @focus: widget to be the new focus widget
712 * If @focus is not the current focus widget, and is focusable, emits
713 * the "set_focus" signal to set @focus as the focus widget for the
714 * window. This function is more or less GTK-internal; to focus an
715 * entry widget or the like, you should use gtk_widget_grab_focus()
716 * instead of this function.
720 gtk_window_set_focus (GtkWindow *window,
723 g_return_if_fail (window != NULL);
724 g_return_if_fail (GTK_IS_WINDOW (window));
727 g_return_if_fail (GTK_IS_WIDGET (focus));
728 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
731 if ((window->focus_widget != focus) ||
732 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
733 gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
737 * gtk_window_set_default:
738 * @window: a #GtkWindow
739 * @default_widget: widget to be the default
741 * The default widget is the widget that's activated when the user
742 * presses Enter in a dialog (for example). This function tells a
743 * #GtkWindow about the current default widget; it's really a GTK
744 * internal function and you shouldn't need it. Instead, to change the
745 * default widget, first set the #GTK_CAN_DEFAULT flag on the widget
746 * you'd like to make the default using GTK_WIDGET_SET_FLAGS(), then
747 * call gtk_widget_grab_default() to move the default.
751 gtk_window_set_default (GtkWindow *window,
752 GtkWidget *default_widget)
754 g_return_if_fail (window != NULL);
755 g_return_if_fail (GTK_IS_WINDOW (window));
758 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
760 if (window->default_widget != default_widget)
762 if (window->default_widget)
764 if (window->focus_widget != window->default_widget ||
765 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
766 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
767 gtk_widget_queue_draw (window->default_widget);
770 window->default_widget = default_widget;
772 if (window->default_widget)
774 if (window->focus_widget == NULL ||
775 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
776 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
777 gtk_widget_queue_draw (window->default_widget);
783 gtk_window_set_policy (GtkWindow *window,
784 gboolean allow_shrink,
786 gboolean auto_shrink)
788 g_return_if_fail (window != NULL);
789 g_return_if_fail (GTK_IS_WINDOW (window));
791 window->allow_shrink = (allow_shrink != FALSE);
792 window->allow_grow = (allow_grow != FALSE);
793 window->auto_shrink = (auto_shrink != FALSE);
795 g_object_notify (G_OBJECT (window), "allow_shrink");
796 g_object_notify (G_OBJECT (window), "allow_grow");
797 g_object_notify (G_OBJECT (window), "auto_shrink");
799 gtk_widget_queue_resize (GTK_WIDGET (window));
803 gtk_window_add_accel_group (GtkWindow *window,
804 GtkAccelGroup *accel_group)
806 g_return_if_fail (window != NULL);
807 g_return_if_fail (GTK_IS_WINDOW (window));
808 g_return_if_fail (accel_group != NULL);
810 gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
814 gtk_window_remove_accel_group (GtkWindow *window,
815 GtkAccelGroup *accel_group)
817 g_return_if_fail (window != NULL);
818 g_return_if_fail (GTK_IS_WINDOW (window));
819 g_return_if_fail (accel_group != NULL);
821 gtk_accel_group_detach (accel_group, GTK_OBJECT (window));
825 gtk_window_add_mnemonic (GtkWindow *window,
829 GtkWindowMnemonic key;
830 GtkWindowMnemonic *mnemonic;
832 g_return_if_fail (GTK_IS_WINDOW (window));
833 g_return_if_fail (GTK_IS_WIDGET (target));
837 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
841 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
842 mnemonic->targets = g_slist_prepend (mnemonic->targets, target);
846 mnemonic = g_new (GtkWindowMnemonic, 1);
848 mnemonic->targets = g_slist_prepend (NULL, target);
849 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
854 gtk_window_remove_mnemonic (GtkWindow *window,
858 GtkWindowMnemonic key;
859 GtkWindowMnemonic *mnemonic;
861 g_return_if_fail (GTK_IS_WINDOW (window));
862 g_return_if_fail (GTK_IS_WIDGET (target));
866 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
868 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
870 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
871 if (mnemonic->targets == NULL)
873 g_hash_table_remove (mnemonic_hash_table, mnemonic);
879 gtk_window_mnemonic_activate (GtkWindow *window,
881 GdkModifierType modifier)
883 GtkWindowMnemonic key;
884 GtkWindowMnemonic *mnemonic;
886 GtkWidget *widget, *chosen_widget;
889 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
891 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
896 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
902 chosen_widget = NULL;
903 list = mnemonic->targets;
906 widget = GTK_WIDGET (list->data);
908 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
909 GTK_WIDGET_MAPPED (widget))
917 chosen_widget = widget;
919 list = g_slist_next (list);
924 /* For round robin we put the activated entry on
925 * the end of the list after activation
927 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
928 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
930 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
936 gtk_window_set_mnemonic_modifier (GtkWindow *window,
937 GdkModifierType modifier)
939 g_return_if_fail (GTK_IS_WINDOW (window));
940 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
942 window->mnemonic_modifier = modifier;
946 gtk_window_set_position (GtkWindow *window,
947 GtkWindowPosition position)
949 g_return_if_fail (GTK_IS_WINDOW (window));
951 window->position = position;
953 g_object_notify (G_OBJECT (window), "window_position");
957 gtk_window_activate_focus (GtkWindow *window)
959 g_return_val_if_fail (window != NULL, FALSE);
960 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
962 if (window->focus_widget)
964 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
965 gtk_widget_activate (window->focus_widget);
973 gtk_window_activate_default (GtkWindow *window)
975 g_return_val_if_fail (window != NULL, FALSE);
976 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
978 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget))
980 gtk_widget_activate (window->default_widget);
988 * gtk_window_set_modal:
989 * @window: a #GtkWindow
990 * @modal: whether the window is modal
992 * Sets a window modal or non-modal. Modal windows prevent interaction
993 * with other windows in the same application. To keep modal dialogs
994 * on top of main application windows, use
995 * gtk_window_set_transient_for() to make the dialog transient for the
996 * parent; most window managers will then disallow lowering the dialog
1002 gtk_window_set_modal (GtkWindow *window,
1005 g_return_if_fail (window != NULL);
1006 g_return_if_fail (GTK_IS_WINDOW (window));
1008 window->modal = modal != FALSE;
1010 /* adjust desired modality state */
1011 if (GTK_WIDGET_VISIBLE (window) && window->modal)
1012 gtk_grab_add (GTK_WIDGET (window));
1014 gtk_grab_remove (GTK_WIDGET (window));
1016 g_object_notify (G_OBJECT (window), "modal");
1020 * gtk_window_list_toplevels:
1022 * Returns a list of all existing toplevel windows. The widgets
1023 * in the list are not individually referenced. If you want
1024 * to iterate through the list and perform actions involving
1025 * callbacks that might destroy the widgets, you MUST call
1026 * g_list_foreach (result, (GFunc)g_object_ref, NULL) first, and
1027 * then unref all the widgets afterwards.
1029 * Return value: list of toplevel widgets
1032 gtk_window_list_toplevels (void)
1037 for (slist = toplevel_list; slist; slist = slist->next)
1038 list = g_list_prepend (list, slist->data);
1044 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1046 GList *embedded_windows;
1048 g_return_if_fail (window != NULL);
1049 g_return_if_fail (GTK_IS_WINDOW (window));
1051 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1052 if (embedded_windows)
1053 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1054 g_quark_from_static_string ("gtk-embedded"));
1055 embedded_windows = g_list_prepend (embedded_windows,
1056 GUINT_TO_POINTER (xid));
1058 gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
1061 (GtkDestroyNotify) g_list_free : NULL);
1065 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1067 GList *embedded_windows;
1070 g_return_if_fail (window != NULL);
1071 g_return_if_fail (GTK_IS_WINDOW (window));
1073 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1074 if (embedded_windows)
1075 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1076 g_quark_from_static_string ("gtk-embedded"));
1078 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1081 embedded_windows = g_list_remove_link (embedded_windows, node);
1082 g_list_free_1 (node);
1085 gtk_object_set_data_full (GTK_OBJECT (window),
1086 "gtk-embedded", embedded_windows,
1088 (GtkDestroyNotify) g_list_free : NULL);
1092 _gtk_window_reposition (GtkWindow *window,
1096 GtkWindowGeometryInfo *info;
1098 g_return_if_fail (window != NULL);
1099 g_return_if_fail (GTK_IS_WINDOW (window));
1101 /* keep this in sync with gtk_window_compute_reposition()
1103 if (GTK_WIDGET_REALIZED (window))
1105 info = gtk_window_get_geometry_info (window, TRUE);
1107 if (!(info->last.flags & GDK_HINT_POS))
1109 info->last.flags |= GDK_HINT_POS;
1110 gdk_window_set_geometry_hints (GTK_WIDGET (window)->window,
1111 &info->last.geometry,
1116 gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
1118 gdk_window_move (GTK_WIDGET (window)->window, x, y);
1123 gtk_window_shutdown (GObject *object)
1127 g_return_if_fail (GTK_IS_WINDOW (object));
1129 window = GTK_WINDOW (object);
1131 gtk_window_set_focus (window, NULL);
1132 gtk_window_set_default (window, NULL);
1134 G_OBJECT_CLASS (parent_class)->shutdown (object);
1138 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1140 gtk_widget_destroy (GTK_WIDGET (child));
1144 connect_parent_destroyed (GtkWindow *window)
1146 if (window->transient_parent)
1148 gtk_signal_connect (GTK_OBJECT (window->transient_parent),
1150 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1156 disconnect_parent_destroyed (GtkWindow *window)
1158 if (window->transient_parent)
1160 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1161 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1167 gtk_window_transient_parent_realized (GtkWidget *parent,
1170 if (GTK_WIDGET_REALIZED (window))
1171 gdk_window_set_transient_for (window->window, parent->window);
1175 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1178 if (GTK_WIDGET_REALIZED (window))
1179 gdk_property_delete (window->window,
1180 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1184 gtk_window_unset_transient_for (GtkWindow *window)
1186 if (window->transient_parent)
1188 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1189 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1191 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1192 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1194 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1195 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1196 &window->transient_parent);
1198 if (window->destroy_with_parent)
1199 disconnect_parent_destroyed (window);
1201 window->transient_parent = NULL;
1206 * gtk_window_set_transient_for:
1207 * @window: a #GtkWindow
1208 * @parent: parent window
1210 * Dialog windows should be set transient for the main application
1211 * window they were spawned from. This allows window managers to
1212 * e.g. keep the dialog on top of the main window, or center the
1213 * dialog over the main window. gtk_dialog_new_with_buttons() and
1214 * other convenience functions in GTK+ will sometimes call
1215 * gtk_window_set_transient_for() on your behalf.
1219 gtk_window_set_transient_for (GtkWindow *window,
1222 g_return_if_fail (GTK_IS_WINDOW (window));
1223 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1224 g_return_if_fail (window != parent);
1227 if (window->transient_parent)
1229 if (GTK_WIDGET_REALIZED (window) &&
1230 GTK_WIDGET_REALIZED (window->transient_parent) &&
1231 (!parent || !GTK_WIDGET_REALIZED (parent)))
1232 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1233 GTK_WIDGET (window));
1235 gtk_window_unset_transient_for (window);
1238 window->transient_parent = parent;
1242 gtk_signal_connect (GTK_OBJECT (parent), "destroy",
1243 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1244 &window->transient_parent);
1245 gtk_signal_connect (GTK_OBJECT (parent), "realize",
1246 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1248 gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
1249 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1252 if (window->destroy_with_parent)
1253 connect_parent_destroyed (window);
1255 if (GTK_WIDGET_REALIZED (window) &&
1256 GTK_WIDGET_REALIZED (parent))
1257 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1258 GTK_WIDGET (window));
1263 * gtk_window_set_type_hint:
1264 * @window: a #GtkWindow
1265 * @hint: the window type
1267 * By setting the type hint for the window, you allow the window
1268 * manager to decorate and handle the window in a way which is
1269 * suitable to the function of the window in your application.
1271 * This function should be called before the window becomes visible.
1273 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1274 * will sometimes call gtk_window_set_type_hint() on your behalf.
1278 gtk_window_set_type_hint (GtkWindow *window,
1279 GdkWindowTypeHint hint)
1281 g_return_if_fail (GTK_IS_WINDOW (window));
1282 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1283 window->type_hint = hint;
1287 * gtk_window_set_destroy_with_parent:
1288 * @window: a #GtkWindow
1289 * @setting: whether to destroy @window with its transient parent
1291 * If @setting is TRUE, then destroying the transient parent of @window
1292 * will also destroy @window itself. This is useful for dialogs that
1293 * shouldn't persist beyond the lifetime of the main window they're
1294 * associated with, for example.
1297 gtk_window_set_destroy_with_parent (GtkWindow *window,
1300 g_return_if_fail (GTK_IS_WINDOW (window));
1302 if (window->destroy_with_parent == (setting != FALSE))
1305 if (window->destroy_with_parent)
1307 disconnect_parent_destroyed (window);
1311 connect_parent_destroyed (window);
1314 window->destroy_with_parent = setting;
1316 g_object_notify (G_OBJECT (window), "destroy_with_parent");
1319 static GtkWindowGeometryInfo*
1320 gtk_window_get_geometry_info (GtkWindow *window,
1323 GtkWindowGeometryInfo *info;
1325 info = window->geometry_info;
1326 if (!info && create)
1328 info = g_new0 (GtkWindowGeometryInfo, 1);
1332 info->last.width = -1;
1333 info->last.height = -1;
1334 info->widget = NULL;
1336 info->may_shrink = FALSE;
1337 window->geometry_info = info;
1344 * gtk_window_set_geometry_hints:
1345 * @window: a #GdkWindow
1346 * @geometry_widget: widget the geometry hints will be applied to
1347 * @geometry: struct containing geometry information
1348 * @geom_mask: mask indicating which struct fields should be paid attention to
1350 * This function sets up hints about how a window can be resized by
1351 * the user. You can set a minimum and maximum size; allowed resize
1352 * increments (e.g. for xterm, you can only resize by the size of a
1353 * character); aspect ratios; and more. See the #GdkGeometry struct.
1357 gtk_window_set_geometry_hints (GtkWindow *window,
1358 GtkWidget *geometry_widget,
1359 GdkGeometry *geometry,
1360 GdkWindowHints geom_mask)
1362 GtkWindowGeometryInfo *info;
1364 g_return_if_fail (window != NULL);
1366 info = gtk_window_get_geometry_info (window, TRUE);
1369 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1370 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1373 info->widget = geometry_widget;
1375 gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
1376 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1380 info->geometry = *geometry;
1382 info->mask = geom_mask;
1384 gtk_widget_queue_resize (GTK_WIDGET (window));
1388 * gtk_window_set_decorated:
1389 * @window: a #GtkWindow
1390 * @setting: %TRUE to decorate the window
1392 * By default, windows are decorated with a title bar, resize
1393 * controls, etc. Some window managers allow GTK+ to disable these
1394 * decorations, creating a borderless window. If you set the decorated
1395 * property to %FALSE using this function, GTK+ will do its best to
1396 * convince the window manager not to decorate the window.
1400 gtk_window_set_decorated (GtkWindow *window,
1403 g_return_if_fail (GTK_IS_WINDOW (window));
1405 setting = setting != FALSE;
1407 if (setting == window->decorated)
1410 if (GTK_WIDGET (window)->window)
1412 if (window->decorated)
1413 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1416 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1422 * gtk_window_set_default_size:
1423 * @window: a #GtkWindow
1424 * @width: width in pixels, 0 to unset, or -1 to leave the width unchanged
1425 * @height: height in pixels, 0 to unset, or -1 to leave the height unchanged
1427 * Sets the default size of a window. If the window's "natural" size
1428 * (its size request) is larger than the default, the default will be
1429 * ignored. So the default size is a minimum initial size. Unlike
1430 * gtk_widget_set_usize(), which sets a size request for a widget and
1431 * thus would keep users from shrinking the window, this function only
1432 * sets the initial size, just as if the user had resized the window
1433 * themselves. Users can still shrink the window again as they
1434 * normally would. Setting a default size of 0 means to use the
1435 * "natural" default size (the size request of the window).
1437 * For more control over a window's initial size and how resizing works,
1438 * investigate gtk_window_set_geometry_hints().
1440 * A useful feature: if you set the "geometry widget" via
1441 * gtk_window_set_geometry_hints(), the default size specified by
1442 * gtk_window_set_default_size() will be the default size of that
1443 * widget, not of the entire window.
1447 gtk_window_set_default_size (GtkWindow *window,
1451 GtkWindowGeometryInfo *info;
1453 g_return_if_fail (GTK_IS_WINDOW (window));
1455 info = gtk_window_get_geometry_info (window, TRUE);
1457 g_object_freeze_notify (G_OBJECT (window));
1460 info->width = width;
1461 g_object_notify (G_OBJECT (window), "default_width");
1462 info->may_shrink = TRUE;
1466 info->height = height;
1467 g_object_notify (G_OBJECT (window), "default_height");
1468 info->may_shrink = TRUE;
1470 g_object_thaw_notify (G_OBJECT (window));
1472 gtk_widget_queue_resize (GTK_WIDGET (window));
1476 gtk_window_destroy (GtkObject *object)
1480 g_return_if_fail (GTK_IS_WINDOW (object));
1482 window = GTK_WINDOW (object);
1484 if (window->transient_parent)
1485 gtk_window_set_transient_for (window, NULL);
1487 if (window->has_user_ref_count)
1489 window->has_user_ref_count = FALSE;
1490 gtk_widget_unref (GTK_WIDGET (window));
1493 GTK_OBJECT_CLASS (parent_class)->destroy (object);
1497 gtk_window_mnemonic_hash_remove (gpointer key,
1501 GtkWindowMnemonic *mnemonic = key;
1502 GtkWindow *window = user;
1504 if (mnemonic->window == window)
1506 if (mnemonic->targets)
1508 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
1510 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
1511 name, mnemonic->targets->data);
1514 g_slist_free (mnemonic->targets);
1523 gtk_window_finalize (GObject *object)
1527 g_return_if_fail (GTK_IS_WINDOW (object));
1529 window = GTK_WINDOW (object);
1531 toplevel_list = g_slist_remove (toplevel_list, window);
1533 g_free (window->title);
1534 g_free (window->wmclass_name);
1535 g_free (window->wmclass_class);
1536 g_free (window->wm_role);
1538 g_hash_table_foreach_remove (mnemonic_hash_table,
1539 gtk_window_mnemonic_hash_remove,
1541 if (window->geometry_info)
1543 if (window->geometry_info->widget)
1544 gtk_signal_disconnect_by_func (GTK_OBJECT (window->geometry_info->widget),
1545 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1546 &window->geometry_info->widget);
1547 g_free (window->geometry_info);
1550 G_OBJECT_CLASS (parent_class)->finalize (object);
1554 gtk_window_show (GtkWidget *widget)
1556 GtkWindow *window = GTK_WINDOW (widget);
1557 GtkContainer *container = GTK_CONTAINER (window);
1558 gboolean need_resize;
1560 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
1562 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
1563 container->need_resize = FALSE;
1567 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
1568 GtkAllocation allocation = { 0, 0 };
1569 GdkGeometry new_geometry;
1570 guint width, height, new_flags;
1571 gboolean was_realized;
1573 /* determine default size to initially show the window with */
1574 gtk_widget_size_request (widget, NULL);
1575 gtk_window_compute_default_size (window, &width, &height);
1577 /* save away the last default size for later comparisions */
1578 info->last.width = width;
1579 info->last.height = height;
1581 /* constrain size to geometry */
1582 gtk_window_compute_hints (window, &new_geometry, &new_flags);
1583 gtk_window_constrain_size (window,
1584 &new_geometry, new_flags,
1588 /* and allocate the window */
1589 allocation.width = width;
1590 allocation.height = height;
1591 gtk_widget_size_allocate (widget, &allocation);
1593 was_realized = FALSE;
1594 if (!GTK_WIDGET_REALIZED (widget))
1596 gtk_widget_realize (widget);
1597 was_realized = TRUE;;
1600 /* Must be done after the windows are realized,
1601 * so that the decorations can be read
1603 gtk_decorated_window_calculate_frame_size (window);
1606 gdk_window_resize (widget->window, width, height);
1609 gtk_container_check_resize (container);
1611 gtk_widget_map (widget);
1614 gtk_grab_add (widget);
1618 gtk_window_hide (GtkWidget *widget)
1622 g_return_if_fail (widget != NULL);
1623 g_return_if_fail (GTK_IS_WINDOW (widget));
1625 window = GTK_WINDOW (widget);
1627 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
1628 gtk_widget_unmap (widget);
1631 gtk_grab_remove (widget);
1635 gtk_window_map (GtkWidget *widget)
1638 GdkWindow *toplevel;
1640 g_return_if_fail (widget != NULL);
1641 g_return_if_fail (GTK_IS_WINDOW (widget));
1643 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1645 window = GTK_WINDOW (widget);
1647 if (window->bin.child &&
1648 GTK_WIDGET_VISIBLE (window->bin.child) &&
1649 !GTK_WIDGET_MAPPED (window->bin.child))
1650 gtk_widget_map (window->bin.child);
1653 toplevel = window->frame;
1655 toplevel = widget->window;
1657 if (window->maximize_initially)
1658 gdk_window_maximize (toplevel);
1660 gdk_window_unmaximize (toplevel);
1662 if (window->stick_initially)
1663 gdk_window_stick (toplevel);
1665 gdk_window_unstick (toplevel);
1667 if (window->iconify_initially)
1668 gdk_window_iconify (toplevel);
1670 gdk_window_deiconify (toplevel);
1672 gdk_window_show (widget->window);
1675 gdk_window_show (window->frame);
1679 gtk_window_unmap (GtkWidget *widget)
1683 g_return_if_fail (widget != NULL);
1684 g_return_if_fail (GTK_IS_WINDOW (widget));
1686 window = GTK_WINDOW (widget);
1688 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1690 gdk_window_withdraw (window->frame);
1692 gdk_window_withdraw (widget->window);
1694 window->use_uposition = TRUE;
1695 window->resize_count = 0;
1696 window->handling_resize = FALSE;
1701 gtk_window_realize (GtkWidget *widget)
1704 GdkWindow *parent_window;
1705 GdkWindowAttr attributes;
1706 gint attributes_mask;
1708 g_return_if_fail (GTK_IS_WINDOW (widget));
1710 window = GTK_WINDOW (widget);
1712 /* ensure widget tree is properly size allocated */
1713 if (widget->allocation.x == -1 &&
1714 widget->allocation.y == -1 &&
1715 widget->allocation.width == 1 &&
1716 widget->allocation.height == 1)
1718 GtkRequisition requisition;
1719 GtkAllocation allocation = { 0, 0, 200, 200 };
1721 gtk_widget_size_request (widget, &requisition);
1722 if (requisition.width || requisition.height)
1724 /* non-empty window */
1725 allocation.width = requisition.width;
1726 allocation.height = requisition.height;
1728 gtk_widget_size_allocate (widget, &allocation);
1730 gtk_container_queue_resize (GTK_CONTAINER (widget));
1732 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
1735 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1737 switch (window->type)
1739 case GTK_WINDOW_TOPLEVEL:
1740 attributes.window_type = GDK_WINDOW_TOPLEVEL;
1742 case GTK_WINDOW_POPUP:
1743 attributes.window_type = GDK_WINDOW_TEMP;
1746 g_warning (G_STRLOC": Unknown window type %d!", window->type);
1750 attributes.title = window->title;
1751 attributes.wmclass_name = window->wmclass_name;
1752 attributes.wmclass_class = window->wmclass_class;
1753 attributes.wclass = GDK_INPUT_OUTPUT;
1754 attributes.visual = gtk_widget_get_visual (widget);
1755 attributes.colormap = gtk_widget_get_colormap (widget);
1757 if (window->has_frame)
1759 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
1760 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
1761 attributes.event_mask = (GDK_EXPOSURE_MASK |
1762 GDK_KEY_PRESS_MASK |
1763 GDK_ENTER_NOTIFY_MASK |
1764 GDK_LEAVE_NOTIFY_MASK |
1765 GDK_FOCUS_CHANGE_MASK |
1766 GDK_STRUCTURE_MASK |
1767 GDK_BUTTON_MOTION_MASK |
1768 GDK_POINTER_MOTION_HINT_MASK |
1769 GDK_BUTTON_PRESS_MASK |
1770 GDK_BUTTON_RELEASE_MASK);
1772 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
1774 window->frame = gdk_window_new (NULL, &attributes, attributes_mask);
1775 gdk_window_set_user_data (window->frame, widget);
1777 attributes.window_type = GDK_WINDOW_CHILD;
1778 attributes.x = window->frame_left;
1779 attributes.y = window->frame_right;
1781 attributes_mask = GDK_WA_X | GDK_WA_Y;
1783 parent_window = window->frame;
1787 attributes_mask = 0;
1788 parent_window = NULL;
1791 attributes.width = widget->allocation.width;
1792 attributes.height = widget->allocation.height;
1793 attributes.event_mask = gtk_widget_get_events (widget);
1794 attributes.event_mask |= (GDK_EXPOSURE_MASK |
1795 GDK_KEY_PRESS_MASK |
1796 GDK_ENTER_NOTIFY_MASK |
1797 GDK_LEAVE_NOTIFY_MASK |
1798 GDK_FOCUS_CHANGE_MASK |
1799 GDK_STRUCTURE_MASK);
1801 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
1802 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
1803 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
1804 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
1805 gdk_window_set_user_data (widget->window, window);
1807 widget->style = gtk_style_attach (widget->style, widget->window);
1808 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
1810 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
1812 /* This is a bad hack to set the window background. */
1813 gtk_window_paint (widget, NULL);
1815 if (window->transient_parent &&
1816 GTK_WIDGET_REALIZED (window->transient_parent))
1817 gdk_window_set_transient_for (widget->window,
1818 GTK_WIDGET (window->transient_parent)->window);
1820 if (window->wm_role)
1821 gdk_window_set_role (widget->window, window->wm_role);
1823 if (!window->decorated)
1824 gdk_window_set_decorations (widget->window, 0);
1826 gdk_window_set_type_hint (widget->window, window->type_hint);
1828 /* transient_for must be set to allow the modal hint */
1829 if (window->transient_parent && window->modal)
1830 gdk_window_set_modal_hint (widget->window, TRUE);
1832 gdk_window_set_modal_hint (widget->window, FALSE);
1836 gtk_window_unrealize (GtkWidget *widget)
1840 g_return_if_fail (widget != NULL);
1841 g_return_if_fail (GTK_IS_WINDOW (widget));
1843 window = GTK_WINDOW (widget);
1847 gdk_window_set_user_data (window->frame, NULL);
1848 gdk_window_destroy (window->frame);
1849 window->frame = NULL;
1852 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1856 gtk_window_size_request (GtkWidget *widget,
1857 GtkRequisition *requisition)
1862 g_return_if_fail (widget != NULL);
1863 g_return_if_fail (GTK_IS_WINDOW (widget));
1864 g_return_if_fail (requisition != NULL);
1866 window = GTK_WINDOW (widget);
1867 bin = GTK_BIN (window);
1869 requisition->width = GTK_CONTAINER (window)->border_width * 2;
1870 requisition->height = GTK_CONTAINER (window)->border_width * 2;
1872 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
1874 GtkRequisition child_requisition;
1876 gtk_widget_size_request (bin->child, &child_requisition);
1878 requisition->width += child_requisition.width;
1879 requisition->height += child_requisition.height;
1884 gtk_window_size_allocate (GtkWidget *widget,
1885 GtkAllocation *allocation)
1888 GtkAllocation child_allocation;
1890 g_return_if_fail (widget != NULL);
1891 g_return_if_fail (GTK_IS_WINDOW (widget));
1892 g_return_if_fail (allocation != NULL);
1894 window = GTK_WINDOW (widget);
1895 widget->allocation = *allocation;
1897 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
1899 child_allocation.x = GTK_CONTAINER (window)->border_width;
1900 child_allocation.y = GTK_CONTAINER (window)->border_width;
1901 child_allocation.width =
1902 MAX (1, (gint)allocation->width - child_allocation.x * 2);
1903 child_allocation.height =
1904 MAX (1, (gint)allocation->height - child_allocation.y * 2);
1906 gtk_widget_size_allocate (window->bin.child, &child_allocation);
1909 if (GTK_WIDGET_REALIZED (widget) && window->frame)
1911 gdk_window_resize (window->frame,
1912 allocation->width + window->frame_left + window->frame_right,
1913 allocation->height + window->frame_top + window->frame_bottom);
1918 gtk_window_event (GtkWidget *widget, GdkEvent *event)
1921 gboolean return_val;
1924 g_return_val_if_fail (widget != NULL, FALSE);
1925 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1926 g_return_val_if_fail (event != NULL, FALSE);
1928 window = GTK_WINDOW (widget);
1930 if (window->frame && (event->any.window == window->frame))
1932 if ((event->type != GDK_KEY_PRESS) &&
1933 (event->type != GDK_KEY_RELEASE) &&
1934 (event->type != GDK_FOCUS_CHANGE))
1936 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
1938 gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
1943 g_object_unref (event->any.window);
1944 event->any.window = g_object_ref (widget->window);
1952 gtk_window_frame_event (GtkWidget *widget, GdkEvent *event)
1954 GdkEventConfigure *configure_event;
1955 GtkWindow *window = GTK_WINDOW (widget);
1958 switch (event->type)
1961 configure_event = (GdkEventConfigure *)event;
1963 /* Invalidate the decorations */
1966 rect.width = configure_event->width;
1967 rect.height = configure_event->height;
1969 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
1971 /* Pass on the (modified) configure event */
1972 configure_event->width -= window->frame_left + window->frame_right;
1973 configure_event->height -= window->frame_top + window->frame_bottom;
1974 return gtk_window_configure_event (widget, configure_event);
1983 gtk_window_configure_event (GtkWidget *widget,
1984 GdkEventConfigure *event)
1988 g_return_val_if_fail (widget != NULL, FALSE);
1989 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1990 g_return_val_if_fail (event != NULL, FALSE);
1992 window = GTK_WINDOW (widget);
1994 /* we got a configure event specifying the new window size and position,
1995 * in principle we have to distinguish 4 cases here:
1996 * 1) the size didn't change and resize_count == 0
1997 * -> the window was merely moved (sometimes not even that)
1998 * 2) the size didn't change and resize_count > 0
1999 * -> we requested a new size, but didn't get it
2000 * 3) the size changed and resize_count > 0
2001 * -> we asked for a new size and we got one
2002 * 4) the size changed and resize_count == 0
2003 * -> we got resized from outside the toolkit, and have to
2004 * accept that size since we don't want to fight neither the
2005 * window manager nor the user
2006 * in the three latter cases we have to reallocate the widget tree,
2007 * which happens in gtk_window_move_resize(), so we set a flag for
2008 * that function and assign the new size. if resize_count > 1,
2009 * we simply do nothing and wait for more configure events.
2012 if (window->resize_count > 0 ||
2013 widget->allocation.width != event->width ||
2014 widget->allocation.height != event->height)
2016 if (window->resize_count > 0)
2017 window->resize_count -= 1;
2019 if (window->resize_count == 0)
2021 window->handling_resize = TRUE;
2023 widget->allocation.width = event->width;
2024 widget->allocation.height = event->height;
2026 gtk_widget_queue_resize (widget);
2034 gtk_window_key_press_event (GtkWidget *widget,
2038 GtkDirectionType direction = 0;
2041 g_return_val_if_fail (widget != NULL, FALSE);
2042 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2043 g_return_val_if_fail (event != NULL, FALSE);
2045 window = GTK_WINDOW (widget);
2049 if (window->focus_widget && window->focus_widget != widget &&
2050 GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
2051 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
2054 handled = gtk_window_mnemonic_activate (window,
2059 handled = gtk_accel_groups_activate (GTK_OBJECT (window), event->keyval, event->state);
2063 switch (event->keyval)
2066 if (window->focus_widget)
2068 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
2069 gtk_widget_activate (window->focus_widget);
2075 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
2076 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
2078 gtk_widget_activate (window->default_widget);
2081 else if (window->focus_widget)
2083 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
2084 gtk_widget_activate (window->focus_widget);
2097 case GDK_ISO_Left_Tab:
2098 switch (event->keyval)
2102 direction = GTK_DIR_UP;
2106 direction = GTK_DIR_DOWN;
2110 direction = GTK_DIR_LEFT;
2114 direction = GTK_DIR_RIGHT;
2117 case GDK_ISO_Left_Tab:
2118 if (event->state & GDK_SHIFT_MASK)
2119 direction = GTK_DIR_TAB_BACKWARD;
2121 direction = GTK_DIR_TAB_FORWARD;
2124 direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
2127 gtk_container_focus (GTK_CONTAINER (widget), direction);
2129 if (!GTK_CONTAINER (window)->focus_child)
2130 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
2137 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
2138 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
2144 gtk_window_key_release_event (GtkWidget *widget,
2150 g_return_val_if_fail (widget != NULL, FALSE);
2151 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2152 g_return_val_if_fail (event != NULL, FALSE);
2154 window = GTK_WINDOW (widget);
2156 if (window->focus_widget &&
2157 window->focus_widget != widget &&
2158 GTK_WIDGET_SENSITIVE (window->focus_widget))
2160 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
2163 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
2164 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
2170 gtk_window_enter_notify_event (GtkWidget *widget,
2171 GdkEventCrossing *event)
2173 g_return_val_if_fail (widget != NULL, FALSE);
2174 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2175 g_return_val_if_fail (event != NULL, FALSE);
2181 gtk_window_leave_notify_event (GtkWidget *widget,
2182 GdkEventCrossing *event)
2184 g_return_val_if_fail (widget != NULL, FALSE);
2185 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2186 g_return_val_if_fail (event != NULL, FALSE);
2192 gtk_window_focus_in_event (GtkWidget *widget,
2193 GdkEventFocus *event)
2196 GdkEventFocus fevent;
2198 g_return_val_if_fail (widget != NULL, FALSE);
2199 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2200 g_return_val_if_fail (event != NULL, FALSE);
2202 /* It appears spurious focus in events can occur when
2203 * the window is hidden. So we'll just check to see if
2204 * the window is visible before actually handling the
2207 if (GTK_WIDGET_VISIBLE (widget))
2209 window = GTK_WINDOW (widget);
2210 if (window->focus_widget &&
2211 window->focus_widget != widget &&
2212 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
2214 fevent.type = GDK_FOCUS_CHANGE;
2215 fevent.window = window->focus_widget->window;
2218 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
2226 gtk_window_focus_out_event (GtkWidget *widget,
2227 GdkEventFocus *event)
2230 GdkEventFocus fevent;
2232 g_return_val_if_fail (widget != NULL, FALSE);
2233 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2234 g_return_val_if_fail (event != NULL, FALSE);
2236 window = GTK_WINDOW (widget);
2237 if (window->focus_widget &&
2238 window->focus_widget != widget &&
2239 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
2241 fevent.type = GDK_FOCUS_CHANGE;
2242 fevent.window = window->focus_widget->window;
2245 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
2251 static GdkAtom atom_rcfiles = GDK_NONE;
2254 gtk_window_read_rcfiles (GtkWidget *widget,
2255 GdkEventClient *event)
2257 GList *embedded_windows;
2259 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
2260 if (embedded_windows)
2265 for(i = 0; i < 5; i++)
2267 sev.data_format = 32;
2268 sev.message_type = atom_rcfiles;
2270 while (embedded_windows)
2272 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
2273 gdk_event_send_client_message ((GdkEvent *) &sev, xid);
2274 embedded_windows = embedded_windows->next;
2278 if (gtk_rc_reparse_all ())
2280 /* If the above returned true, some of our RC files are out
2281 * of date, so we need to reset all our widgets. Our other
2282 * toplevel windows will also get the message, but by
2283 * then, the RC file will up to date, so we have to tell
2284 * them now. Also, we have to invalidate cached icons in
2285 * icon sets so they get re-rendered.
2287 GList *list, *toplevels;
2289 _gtk_icon_set_invalidate_caches ();
2291 toplevels = gtk_window_list_toplevels ();
2292 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
2294 for (list = toplevels; list; list = list->next)
2296 gtk_widget_reset_rc_styles (list->data);
2297 gtk_widget_unref (list->data);
2299 g_list_free (toplevels);
2304 gtk_window_client_event (GtkWidget *widget,
2305 GdkEventClient *event)
2307 g_return_val_if_fail (widget != NULL, FALSE);
2308 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2309 g_return_val_if_fail (event != NULL, FALSE);
2312 atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
2314 if(event->message_type == atom_rcfiles)
2315 gtk_window_read_rcfiles (widget, event);
2321 gtk_window_check_resize (GtkContainer *container)
2325 g_return_if_fail (container != NULL);
2326 g_return_if_fail (GTK_IS_WINDOW (container));
2328 window = GTK_WINDOW (container);
2330 if (GTK_WIDGET_VISIBLE (container))
2331 gtk_window_move_resize (window);
2335 gtk_window_focus (GtkContainer *container,
2336 GtkDirectionType direction)
2338 GtkBin *bin = GTK_BIN (container);
2339 GtkWindow *window = GTK_WINDOW (container);
2340 GtkWidget *old_focus_child = container->focus_child;
2343 /* We need a special implementation here to deal properly with wrapping
2344 * around in the tab chain without the danger of going into an
2347 if (old_focus_child)
2349 if (GTK_IS_CONTAINER (old_focus_child) &&
2350 GTK_WIDGET_DRAWABLE (old_focus_child) &&
2351 GTK_WIDGET_IS_SENSITIVE (old_focus_child) &&
2352 gtk_container_focus (GTK_CONTAINER (old_focus_child), direction))
2356 if (window->focus_widget)
2358 /* Wrapped off the end, clear the focus setting for the toplpevel */
2359 parent = window->focus_widget->parent;
2362 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
2363 parent = GTK_WIDGET (parent)->parent;
2366 gtk_window_set_focus (GTK_WINDOW (container), NULL);
2369 /* Now try to focus the first widget in the window */
2370 if (GTK_WIDGET_DRAWABLE (bin->child) &&
2371 GTK_WIDGET_IS_SENSITIVE (bin->child))
2373 if (GTK_IS_CONTAINER (bin->child))
2375 if (gtk_container_focus (GTK_CONTAINER (bin->child), direction))
2378 else if (GTK_WIDGET_CAN_FOCUS (bin->child))
2380 gtk_widget_grab_focus (bin->child);
2389 gtk_window_real_set_focus (GtkWindow *window,
2392 GdkEventFocus event;
2393 gboolean def_flags = 0;
2395 g_return_if_fail (window != NULL);
2396 g_return_if_fail (GTK_IS_WINDOW (window));
2398 if (window->default_widget)
2399 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
2401 if (window->focus_widget)
2403 event.type = GDK_FOCUS_CHANGE;
2404 event.window = window->focus_widget->window;
2407 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
2408 (window->focus_widget != window->default_widget))
2410 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
2411 /* if any widget had the default set there should be
2412 a default_widget, but might not so this is a sanity
2414 if (window->default_widget)
2415 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
2418 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
2421 window->focus_widget = focus;
2423 if (window->focus_widget)
2425 event.type = GDK_FOCUS_CHANGE;
2426 event.window = window->focus_widget->window;
2429 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
2430 (window->focus_widget != window->default_widget))
2432 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
2433 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
2435 if (window->default_widget)
2436 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
2439 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
2442 if (window->default_widget &&
2443 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
2444 gtk_widget_queue_draw (window->default_widget);
2447 /*********************************
2448 * Functions related to resizing *
2449 *********************************/
2452 gtk_window_move_resize (GtkWindow *window)
2455 GtkContainer *container;
2456 GtkWindowGeometryInfo *info;
2457 GtkWindowLastGeometryInfo saved_last_info;
2458 GdkGeometry new_geometry;
2462 gint new_width, new_height;
2463 gboolean need_reposition;
2464 gboolean default_size_changed = FALSE;
2465 gboolean hints_changed = FALSE;
2466 gboolean may_shrink = window->auto_shrink;
2468 g_return_if_fail (GTK_WIDGET_REALIZED (window));
2470 widget = GTK_WIDGET (window);
2471 container = GTK_CONTAINER (widget);
2472 info = gtk_window_get_geometry_info (window, TRUE);
2473 saved_last_info = info->last;
2475 gtk_widget_size_request (widget, NULL);
2476 gtk_window_compute_default_size (window, &new_width, &new_height);
2478 if (info->last.width < 0 ||
2479 info->last.width != new_width ||
2480 info->last.height != new_height)
2482 default_size_changed = TRUE;
2483 may_shrink |= info->may_shrink;
2484 info->last.width = new_width;
2485 info->last.height = new_height;
2487 /* We need to force a reposition in this case
2489 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
2490 window->use_uposition = TRUE;
2492 info->may_shrink = FALSE;
2494 /* Compute new set of hints for the window
2496 gtk_window_compute_hints (window, &new_geometry, &new_flags);
2497 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
2498 &new_geometry, new_flags))
2500 hints_changed = TRUE;
2501 info->last.geometry = new_geometry;
2502 info->last.flags = new_flags;
2505 /* From the default size and the allocation, figure out the size
2506 * the window should be.
2508 if (!default_size_changed ||
2510 new_width <= widget->allocation.width &&
2511 new_height <= widget->allocation.height))
2513 new_width = widget->allocation.width;
2514 new_height = widget->allocation.height;
2517 /* constrain the window size to the specified geometry */
2518 gtk_window_constrain_size (window,
2519 &new_geometry, new_flags,
2520 new_width, new_height,
2521 &new_width, &new_height);
2523 /* compute new window position if a move is required
2525 need_reposition = gtk_window_compute_reposition (window, new_width, new_height, &x, &y);
2526 if (need_reposition && !(new_flags & GDK_HINT_POS))
2528 new_flags |= GDK_HINT_POS;
2529 hints_changed = TRUE;
2533 /* handle actual resizing:
2534 * - handle reallocations due to configure events
2535 * - figure whether we need to request a new window size
2536 * - handle simple resizes within our widget tree
2537 * - reposition window if neccessary
2539 width = widget->allocation.width;
2540 height = widget->allocation.height;
2542 if (window->handling_resize)
2544 GtkAllocation allocation;
2546 /* if we are just responding to a configure event, which
2547 * might be due to a resize by the window manager, the
2548 * user, or a response to a resizing request we made
2549 * earlier, we go ahead, allocate the new size and we're done
2550 * (see gtk_window_configure_event() for more details).
2553 window->handling_resize = FALSE;
2555 allocation = widget->allocation;
2557 gtk_widget_size_allocate (widget, &allocation);
2558 gtk_widget_queue_draw (widget);
2560 if ((default_size_changed || hints_changed) && (width != new_width || height != new_height))
2562 /* We could be here for two reasons
2563 * 1) We coincidentally got a resize while handling
2565 * 2) Our computation of default_size_changed was completely
2566 * screwed up, probably because one of our children
2567 * is changed requisition during size allocation).
2569 * For 1), we could just go ahead and ask for the
2570 * new size right now, but doing that for 2)
2571 * might well be fighting the user (and can even
2572 * trigger a loop). Since we really don't want to
2573 * do that, we requeue a resize in hopes that
2574 * by the time it gets handled, the child has seen
2575 * the light and is willing to go along with the
2576 * new size. (this happens for the zvt widget, since
2577 * the size_allocate() above will have stored the
2578 * requisition corresponding to the new size in the
2581 * This doesn't buy us anything for 1), but it shouldn't
2582 * hurt us too badly, since it is what would have
2583 * happened if we had gotten the configure event before
2584 * the new size had been set.
2587 if (need_reposition)
2590 gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
2592 gdk_window_move (GTK_WIDGET (window)->window, x, y);
2595 /* we have to preserve the values and flags that are used
2596 * for computation of default_size_changed and hints_changed
2598 info->last = saved_last_info;
2600 gtk_widget_queue_resize (widget);
2606 /* Now set hints if necessary
2609 gdk_window_set_geometry_hints (widget->window,
2613 if ((default_size_changed || hints_changed) &&
2614 (width != new_width || height != new_height))
2616 /* given that (width != new_width || height != new_height), we are in one
2617 * of the following situations:
2619 * default_size_changed
2620 * our requisition has changed and we need a different window size,
2621 * so we request it from the window manager.
2623 * !default_size_changed
2624 * the window manager wouldn't assign us the size we requested, in this
2625 * case we don't try to request a new size with every resize.
2627 * !default_size_changed && hints_changed
2628 * the window manager rejects our size, but we have just changed the
2629 * window manager hints, so there's a certain chance our request will
2630 * be honoured this time, so we try again.
2633 /* request a new window size */
2634 if (need_reposition)
2638 gdk_window_move_resize (window->frame,
2639 x - window->frame_left, y - window->frame_top,
2640 new_width + window->frame_left + window->frame_right,
2641 new_height + window->frame_top + window->frame_bottom);
2642 gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
2645 gdk_window_move_resize (GTK_WIDGET (window)->window, x, y, new_width, new_height);
2650 gdk_window_resize (window->frame,
2651 new_width + window->frame_left + window->frame_right,
2652 new_height + window->frame_top + window->frame_bottom);
2653 gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
2655 window->resize_count += 1;
2657 /* we are now awaiting the new configure event in response to our
2658 * resizing request. the configure event will cause a new resize
2659 * with ->handling_resize=TRUE.
2660 * until then, we want to
2661 * - discard expose events
2662 * - coalesce resizes for our children
2663 * - defer any window resizes until the configure event arrived
2664 * to achive this, we queue a resize for the window, but remove its
2665 * resizing handler, so resizing will not be handled from the next
2666 * idle handler but when the configure event arrives.
2668 * FIXME: we should also dequeue the pending redraws here, since
2669 * we handle those ourselves in ->handling_resize==TRUE.
2671 gtk_widget_queue_resize (GTK_WIDGET (container));
2672 if (container->resize_mode == GTK_RESIZE_QUEUE)
2673 gtk_container_dequeue_resize_handler (container);
2677 if (need_reposition)
2680 gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
2682 gdk_window_move (widget->window, x, y);
2685 if (container->resize_widgets)
2686 gtk_container_resize_children (GTK_CONTAINER (window));
2690 /* Compare two sets of Geometry hints for equality.
2693 gtk_window_compare_hints (GdkGeometry *geometry_a,
2695 GdkGeometry *geometry_b,
2698 if (flags_a != flags_b)
2701 if ((flags_a & GDK_HINT_MIN_SIZE) &&
2702 (geometry_a->min_width != geometry_b->min_width ||
2703 geometry_a->min_height != geometry_b->min_height))
2706 if ((flags_a & GDK_HINT_MAX_SIZE) &&
2707 (geometry_a->max_width != geometry_b->max_width ||
2708 geometry_a->max_height != geometry_b->max_height))
2711 if ((flags_a & GDK_HINT_BASE_SIZE) &&
2712 (geometry_a->base_width != geometry_b->base_width ||
2713 geometry_a->base_height != geometry_b->base_height))
2716 if ((flags_a & GDK_HINT_ASPECT) &&
2717 (geometry_a->min_aspect != geometry_b->min_aspect ||
2718 geometry_a->max_aspect != geometry_b->max_aspect))
2721 if ((flags_a & GDK_HINT_RESIZE_INC) &&
2722 (geometry_a->width_inc != geometry_b->width_inc ||
2723 geometry_a->height_inc != geometry_b->height_inc))
2726 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
2727 geometry_a->win_gravity != geometry_b->win_gravity)
2733 /* Compute the default_size for a window. The result will
2734 * be stored in *width and *height. The default size is
2735 * the size the window should have when initially mapped.
2736 * This routine does not attempt to constrain the size
2737 * to obey the geometry hints - that must be done elsewhere.
2740 gtk_window_compute_default_size (GtkWindow *window,
2744 GtkRequisition requisition;
2745 GtkWindowGeometryInfo *info;
2747 gtk_widget_get_child_requisition (GTK_WIDGET (window), &requisition);
2748 *width = requisition.width;
2749 *height = requisition.height;
2751 info = gtk_window_get_geometry_info (window, FALSE);
2753 if (*width == 0 && *height == 0)
2762 *width = info->width > 0 ? info->width : *width;
2763 *height = info->height > 0 ? info->height : *height;
2768 _gtk_window_constrain_size (GtkWindow *window,
2774 GtkWindowGeometryInfo *info;
2776 g_return_if_fail (GTK_IS_WINDOW (window));
2778 info = window->geometry_info;
2781 GdkWindowHints flags = info->last.flags;
2782 GdkGeometry *geometry = &info->last.geometry;
2784 gtk_window_constrain_size (window,
2795 gtk_window_constrain_size (GtkWindow *window,
2796 GdkGeometry *geometry,
2803 gdk_window_constrain_size (geometry, flags, width, height,
2804 new_width, new_height);
2807 /* Compute the set of geometry hints and flags for a window
2808 * based on the application set geometry, and requisiition
2809 * of the window. gtk_widget_size_request() must have been
2813 gtk_window_compute_hints (GtkWindow *window,
2814 GdkGeometry *new_geometry,
2818 GtkWidgetAuxInfo *aux_info;
2820 gint extra_width = 0;
2821 gint extra_height = 0;
2822 GtkWindowGeometryInfo *geometry_info;
2823 GtkRequisition requisition;
2825 g_return_if_fail (GTK_IS_WINDOW (window));
2827 widget = GTK_WIDGET (window);
2829 gtk_widget_get_child_requisition (widget, &requisition);
2830 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
2832 g_return_if_fail (geometry_info != NULL);
2834 *new_flags = geometry_info->mask;
2835 *new_geometry = geometry_info->geometry;
2837 if (geometry_info->widget)
2839 extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
2840 extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
2846 aux_info = _gtk_widget_get_aux_info (widget, FALSE);
2847 if (aux_info && aux_info->x_set && aux_info->y_set)
2851 *new_flags |= GDK_HINT_POS;
2854 if (*new_flags & GDK_HINT_BASE_SIZE)
2856 new_geometry->base_width += extra_width;
2857 new_geometry->base_height += extra_height;
2859 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
2860 (*new_flags & GDK_HINT_RESIZE_INC) &&
2861 ((extra_width != 0) || (extra_height != 0)))
2863 *new_flags |= GDK_HINT_BASE_SIZE;
2865 new_geometry->base_width = extra_width;
2866 new_geometry->base_height = extra_height;
2869 if (*new_flags & GDK_HINT_MIN_SIZE)
2871 if (new_geometry->min_width < 0)
2872 new_geometry->min_width = requisition.width;
2874 new_geometry->min_width += extra_width;
2876 if (new_geometry->min_height < 0)
2877 new_geometry->min_width = requisition.height;
2879 new_geometry->min_height += extra_height;
2881 else if (!window->allow_shrink)
2883 *new_flags |= GDK_HINT_MIN_SIZE;
2885 new_geometry->min_width = requisition.width;
2886 new_geometry->min_height = requisition.height;
2889 if (*new_flags & GDK_HINT_MAX_SIZE)
2891 if (new_geometry->max_width < 0)
2892 new_geometry->max_width = requisition.width;
2894 new_geometry->max_width += extra_width;
2896 if (new_geometry->max_height < 0)
2897 new_geometry->max_width = requisition.height;
2899 new_geometry->max_height += extra_height;
2901 else if (!window->allow_grow)
2903 *new_flags |= GDK_HINT_MAX_SIZE;
2905 new_geometry->max_width = requisition.width;
2906 new_geometry->max_height = requisition.height;
2909 *new_flags |= GDK_HINT_WIN_GRAVITY;
2910 new_geometry->win_gravity = window->gravity;
2913 /* Compute a new position for the window based on a new
2914 * size. *x and *y will be set to the new coordinates. Returns
2915 * TRUE if the window needs to be moved (and thus x and y got
2919 gtk_window_compute_reposition (GtkWindow *window,
2925 GtkWidget *widget = GTK_WIDGET (window);
2926 GtkWindowPosition pos;
2927 GtkWidget *parent_widget;
2928 gboolean needs_move = FALSE;
2930 parent_widget = (GtkWidget*) window->transient_parent;
2932 pos = window->position;
2933 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
2934 (parent_widget == NULL ||
2935 !GTK_WIDGET_MAPPED (parent_widget)))
2936 pos = GTK_WIN_POS_NONE;
2940 case GTK_WIN_POS_CENTER:
2941 case GTK_WIN_POS_CENTER_ALWAYS:
2942 if (window->use_uposition)
2944 gint screen_width = gdk_screen_width ();
2945 gint screen_height = gdk_screen_height ();
2947 *x = (screen_width - new_width) / 2;
2948 *y = (screen_height - new_height) / 2;
2953 case GTK_WIN_POS_CENTER_ON_PARENT:
2954 if (window->use_uposition)
2957 gdk_window_get_origin (parent_widget->window,
2960 *x = ox + (parent_widget->allocation.width - new_width) / 2;
2961 *y = oy + (parent_widget->allocation.height - new_height) / 2;
2966 case GTK_WIN_POS_MOUSE:
2967 if (window->use_uposition)
2969 gint screen_width = gdk_screen_width ();
2970 gint screen_height = gdk_screen_height ();
2972 gdk_window_get_pointer (NULL, x, y, NULL);
2973 *x -= new_width / 2;
2974 *y -= new_height / 2;
2975 *x = CLAMP (*x, 0, screen_width - new_width);
2976 *y = CLAMP (*y, 0, screen_height - new_height);
2981 if (window->use_uposition)
2983 GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE);
2985 if (aux_info && aux_info->x_set && aux_info->y_set)
2997 GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, TRUE);
2999 /* we handle necessary window positioning by hand here,
3000 * so we can coalesce the window movement with possible
3001 * resizes to get only one configure event.
3003 aux_info->x_set = TRUE;
3004 aux_info->y_set = TRUE;
3007 window->use_uposition = FALSE;
3013 /***********************
3014 * Redrawing functions *
3015 ***********************/
3018 gtk_window_paint (GtkWidget *widget,
3021 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
3022 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
3026 gtk_window_expose (GtkWidget *widget,
3027 GdkEventExpose *event)
3029 g_return_val_if_fail (widget != NULL, FALSE);
3030 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3031 g_return_val_if_fail (event != NULL, FALSE);
3033 if (!GTK_WIDGET_APP_PAINTABLE (widget))
3034 gtk_window_paint (widget, &event->area);
3036 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
3037 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
3043 * gtk_window_set_has_frame:
3044 * @window: a #GtkWindow
3046 * If this function is called on a window before it is realized
3047 * or showed it will have a "frame" window around widget-window,
3048 * accessible in window->frame. Using the signal frame_event
3049 * you can recieve all events targeted at the frame.
3051 * This function is used by the linux-fb port to implement managed
3052 * windows, but it could concievably be used by X-programs that
3053 * want to do their own window decorations.
3056 gtk_window_set_has_frame (GtkWindow *window)
3058 g_return_if_fail (window != NULL);
3059 g_return_if_fail (GTK_IS_WINDOW (window));
3060 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
3062 window->has_frame = TRUE;
3066 * gtk_window_set_frame_dimensions:
3067 * @window: a #GtkWindow that has a frame
3068 * @left: The width of the left border
3069 * @top: The height of the top border
3070 * @right: The width of the right border
3071 * @bottom: The height of the bottom border
3073 * For windows with frames (see #gtk_window_set_has_frame) this function
3074 * can be used to change the size of the frame border.
3077 gtk_window_set_frame_dimensions (GtkWindow *window,
3083 GtkWidget *widget = GTK_WIDGET (window);
3085 g_return_if_fail (window != NULL);
3086 g_return_if_fail (GTK_IS_WINDOW (window));
3088 if (window->frame_left == left &&
3089 window->frame_top == top &&
3090 window->frame_right == right &&
3091 window->frame_bottom == bottom)
3094 window->frame_left = left;
3095 window->frame_top = top;
3096 window->frame_right = right;
3097 window->frame_bottom = bottom;
3099 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3101 gint width = widget->allocation.width + left + right;
3102 gint height = widget->allocation.height + top + bottom;
3103 gdk_window_resize (window->frame, width, height);
3104 gtk_decorated_window_move_resize_window (window,
3106 widget->allocation.width,
3107 widget->allocation.height);
3114 * gtk_window_present:
3115 * @window: a #GtkWindow
3117 * Presents a window to the user. This may mean raising the window
3118 * in the stacking order, deiconifying it, moving it to the current
3119 * desktop, and/or giving it the keyboard focus, possibly dependent
3120 * on the user's platform, window manager, and preferences.
3122 * If @window is hidden, this function calls gtk_widget_show()
3125 * This function should be used when the user tries to open a window
3126 * that's already open. Say for example the preferences dialog is
3127 * currently open, and the user chooses Preferences from the menu
3128 * a second time; use gtk_window_present() to move the already-open dialog
3129 * where the user can see it.
3133 gtk_window_present (GtkWindow *window)
3137 g_return_if_fail (GTK_IS_WINDOW (window));
3139 widget = GTK_WIDGET (window);
3141 if (GTK_WIDGET_VISIBLE (window))
3143 g_assert (widget->window != NULL);
3145 gdk_window_show (widget->window);
3147 /* note that gdk_window_focus() will also move the window to
3148 * the current desktop, for WM spec compliant window managers.
3150 gdk_window_focus (widget->window,
3151 gtk_get_current_event_time ());
3155 gtk_widget_show (widget);
3160 * gtk_window_iconify:
3161 * @window: a #GtkWindow
3163 * Asks to iconify @window. Note that you shouldn't assume the window
3164 * is definitely iconified afterward, because other entities (e.g. the
3165 * user or window manager) could deiconify it again, or there may not
3166 * be a window manager in which case iconification isn't possible,
3167 * etc. But normally the window will end up iconified. Just don't write
3168 * code that crashes if not.
3170 * It's permitted to call this function before showing a window,
3171 * in which case the window will be iconified before it ever appears
3174 * You can track iconification via the "window_state_event" signal
3179 gtk_window_iconify (GtkWindow *window)
3182 GdkWindow *toplevel;
3184 g_return_if_fail (GTK_IS_WINDOW (window));
3186 widget = GTK_WIDGET (window);
3188 window->iconify_initially = TRUE;
3191 toplevel = window->frame;
3193 toplevel = widget->window;
3195 if (toplevel != NULL)
3196 gdk_window_iconify (toplevel);
3200 * gtk_window_deiconify:
3201 * @window: a #GtkWindow
3203 * Asks to deiconify @window. Note that you shouldn't assume the
3204 * window is definitely deiconified afterward, because other entities
3205 * (e.g. the user or window manager) could iconify it again before
3206 * your code which assumes deiconification gets to run.
3208 * You can track iconification via the "window_state_event" signal
3212 gtk_window_deiconify (GtkWindow *window)
3215 GdkWindow *toplevel;
3217 g_return_if_fail (GTK_IS_WINDOW (window));
3219 widget = GTK_WIDGET (window);
3221 window->iconify_initially = FALSE;
3224 toplevel = window->frame;
3226 toplevel = widget->window;
3228 if (toplevel != NULL)
3229 gdk_window_deiconify (toplevel);
3234 * @window: a #GtkWindow
3236 * Asks to stick @window, which means that it will appear on all user
3237 * desktops. Note that you shouldn't assume the window is definitely
3238 * stuck afterward, because other entities (e.g. the user or window
3239 * manager) could unstick it again, and some window managers do not
3240 * support sticking windows. But normally the window will end up
3241 * stuck. Just don't write code that crashes if not.
3243 * It's permitted to call this function before showing a window.
3245 * You can track stickiness via the "window_state_event" signal
3250 gtk_window_stick (GtkWindow *window)
3253 GdkWindow *toplevel;
3255 g_return_if_fail (GTK_IS_WINDOW (window));
3257 widget = GTK_WIDGET (window);
3259 window->stick_initially = TRUE;
3262 toplevel = window->frame;
3264 toplevel = widget->window;
3266 if (toplevel != NULL)
3267 gdk_window_stick (toplevel);
3271 * gtk_window_unstick:
3272 * @window: a #GtkWindow
3274 * Asks to unstick @window, which means that it will appear on only
3275 * one of the user's desktops. Note that you shouldn't assume the
3276 * window is definitely unstuck afterward, because other entities
3277 * (e.g. the user or window manager) could stick it again. But
3278 * normally the window will end up stuck. Just don't write code that
3281 * You can track stickiness via the "window_state_event" signal
3286 gtk_window_unstick (GtkWindow *window)
3289 GdkWindow *toplevel;
3291 g_return_if_fail (GTK_IS_WINDOW (window));
3293 widget = GTK_WIDGET (window);
3295 window->stick_initially = FALSE;
3298 toplevel = window->frame;
3300 toplevel = widget->window;
3302 if (toplevel != NULL)
3303 gdk_window_unstick (toplevel);
3307 * gtk_window_maximize:
3308 * @window: a #GtkWindow
3310 * Asks to maximize @window, so that it becomes full-screen. Note that
3311 * you shouldn't assume the window is definitely maximized afterward,
3312 * because other entities (e.g. the user or window manager) could
3313 * unmaximize it again, and not all window managers support
3314 * maximization. But normally the window will end up maximized. Just
3315 * don't write code that crashes if not.
3317 * It's permitted to call this function before showing a window,
3318 * in which case the window will be maximized when it appears onscreen
3321 * You can track maximization via the "window_state_event" signal
3326 gtk_window_maximize (GtkWindow *window)
3329 GdkWindow *toplevel;
3331 g_return_if_fail (GTK_IS_WINDOW (window));
3333 widget = GTK_WIDGET (window);
3335 window->maximize_initially = TRUE;
3338 toplevel = window->frame;
3340 toplevel = widget->window;
3342 if (toplevel != NULL)
3343 gdk_window_maximize (toplevel);
3347 * gtk_window_unmaximize:
3348 * @window: a #GtkWindow
3350 * Asks to unmaximize @window. Note that you shouldn't assume the
3351 * window is definitely unmaximized afterward, because other entities
3352 * (e.g. the user or window manager) could maximize it again, and not
3353 * all window managers honor requests to unmaximize. But normally the
3354 * window will end up unmaximized. Just don't write code that crashes
3357 * You can track maximization via the "window_state_event" signal
3362 gtk_window_unmaximize (GtkWindow *window)
3365 GdkWindow *toplevel;
3367 g_return_if_fail (GTK_IS_WINDOW (window));
3369 widget = GTK_WIDGET (window);
3371 window->maximize_initially = FALSE;
3374 toplevel = window->frame;
3376 toplevel = widget->window;
3378 if (toplevel != NULL)
3379 gdk_window_unmaximize (toplevel);
3383 * gtk_window_set_resizeable:
3384 * @window: a #GtkWindow
3385 * @resizeable: %TRUE if the user can resize this window
3387 * Sets whether the user can resize a window. Windows are user resizeable
3391 gtk_window_set_resizeable (GtkWindow *window,
3392 gboolean resizeable)
3394 g_return_if_fail (GTK_IS_WINDOW (window));
3396 gtk_window_set_policy (window, FALSE, resizeable, FALSE);
3400 * gtk_window_get_resizeable:
3401 * @window: a #GtkWindow
3403 * Gets the value set by gtk_window_set_resizeable().
3405 * Return value: %TRUE if the user can resize the window
3408 gtk_window_get_resizeable (GtkWindow *window)
3410 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3412 /* allow_grow is most likely to indicate the semantic concept we
3413 * mean by "resizeable" (and will be a reliable indicator if
3414 * set_policy() hasn't been called)
3416 return window->allow_grow;
3420 * gtk_window_set_gravity:
3421 * @window: a #GtkWindow
3422 * @gravity: window gravity
3424 * Window gravity defines the "reference point" to be used when
3425 * positioning or resizing a window. Calls to
3426 * gtk_widget_set_uposition() will position a different point on the
3427 * window depending on the window gravity. When the window changes size
3428 * the reference point determined by the window's gravity will stay in
3431 * See #GdkGravity for full details. To briefly summarize,
3432 * #GDK_GRAVITY_NORTH_WEST means that the reference point is the
3433 * northwest (top left) corner of the window
3434 * frame. #GDK_GRAVITY_SOUTH_EAST would be the bottom right corner of
3435 * the frame, and so on. If you want to position the window contents,
3436 * rather than the window manager's frame, #GDK_GRAVITY_STATIC moves
3437 * the reference point to the northwest corner of the #GtkWindow
3440 * The default window gravity is #GDK_GRAVITY_NORTH_WEST.
3444 gtk_window_set_gravity (GtkWindow *window,
3447 g_return_if_fail (GTK_IS_WINDOW (window));
3449 if (gravity != window->gravity)
3451 window->gravity = gravity;
3453 /* gtk_window_move_resize() will adapt gravity
3455 gtk_widget_queue_resize (GTK_WIDGET (window));
3460 * gtk_window_get_gravity:
3461 * @window: a #GtkWindow
3463 * Gets the value set by gtk_window_set_gravity().
3465 * Return value: window gravity
3468 gtk_window_get_gravity (GtkWindow *window)
3470 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
3472 return window->gravity;
3476 * gtk_window_begin_resize_drag:
3477 * @window: a #GtkWindow
3478 * @button: mouse button that initiated the drag
3479 * @edge: position of the resize control
3480 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
3481 * @root_y: Y position where the user clicked to initiate the drag
3482 * @timestamp: timestamp from the click event that initiated the drag
3484 * Starts resizing a window. This function is used if an application
3485 * has window resizing controls. When GDK can support it, the resize
3486 * will be done using the standard mechanism for the window manager or
3487 * windowing system. Otherwise, GDK will try to emulate window
3488 * resizing, potentially not all that well, depending on the windowing system.
3492 gtk_window_begin_resize_drag (GtkWindow *window,
3500 GdkWindow *toplevel;
3502 g_return_if_fail (GTK_IS_WINDOW (window));
3503 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
3505 widget = GTK_WIDGET (window);
3508 toplevel = window->frame;
3510 toplevel = widget->window;
3512 gdk_window_begin_resize_drag (toplevel,
3520 * gtk_window_begin_move_drag:
3521 * @button: mouse button that initiated the drag
3522 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
3523 * @root_y: Y position where the user clicked to initiate the drag
3524 * @timestamp: timestamp from the click event that initiated the drag
3526 * Starts moving a window. This function is used if an application
3527 * has window movement grips. When GDK can support it, the window movement
3528 * will be done using the standard mechanism for the window manager or
3529 * windowing system. Otherwise, GDK will try to emulate window
3530 * movement, potentially not all that well, depending on the windowing system.
3534 gtk_window_begin_move_drag (GtkWindow *window,
3541 GdkWindow *toplevel;
3543 g_return_if_fail (GTK_IS_WINDOW (window));
3544 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
3546 widget = GTK_WIDGET (window);
3549 toplevel = window->frame;
3551 toplevel = widget->window;
3553 gdk_window_begin_move_drag (toplevel,