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"
52 /* TODO: remove this define and assorted code in 1.3 and fix up the
55 #define FIXME_ZVT_ME_HARDER
78 PROP_DESTROY_WITH_PARENT,
84 GdkGeometry geometry; /* Last set of geometry hints we set */
88 } GtkWindowLastGeometryInfo;
91 /* Properties that the app has set on the window
93 GdkGeometry geometry; /* Geometry hints */
95 GtkWidget *widget; /* subwidget to which hints apply */
96 gint width; /* Default size */
99 GtkWindowLastGeometryInfo last;
100 } GtkWindowGeometryInfo;
102 static void gtk_window_class_init (GtkWindowClass *klass);
103 static void gtk_window_init (GtkWindow *window);
104 static void gtk_window_shutdown (GObject *object);
105 static void gtk_window_destroy (GtkObject *object);
106 static void gtk_window_finalize (GObject *object);
107 static void gtk_window_show (GtkWidget *widget);
108 static void gtk_window_hide (GtkWidget *widget);
109 static void gtk_window_map (GtkWidget *widget);
110 static void gtk_window_unmap (GtkWidget *widget);
111 static void gtk_window_realize (GtkWidget *widget);
112 static void gtk_window_unrealize (GtkWidget *widget);
113 static void gtk_window_size_request (GtkWidget *widget,
114 GtkRequisition *requisition);
115 static void gtk_window_size_allocate (GtkWidget *widget,
116 GtkAllocation *allocation);
117 static gint gtk_window_event (GtkWidget *widget,
119 static gboolean gtk_window_frame_event (GtkWidget *widget,
121 static gint gtk_window_configure_event (GtkWidget *widget,
122 GdkEventConfigure *event);
123 static gint gtk_window_key_press_event (GtkWidget *widget,
125 static gint gtk_window_key_release_event (GtkWidget *widget,
127 static gint gtk_window_enter_notify_event (GtkWidget *widget,
128 GdkEventCrossing *event);
129 static gint gtk_window_leave_notify_event (GtkWidget *widget,
130 GdkEventCrossing *event);
131 static gint gtk_window_focus_in_event (GtkWidget *widget,
132 GdkEventFocus *event);
133 static gint gtk_window_focus_out_event (GtkWidget *widget,
134 GdkEventFocus *event);
135 static gint gtk_window_client_event (GtkWidget *widget,
136 GdkEventClient *event);
137 static void gtk_window_check_resize (GtkContainer *container);
138 static gint gtk_window_focus (GtkContainer *container,
139 GtkDirectionType direction);
140 static void gtk_window_real_set_focus (GtkWindow *window,
143 static void gtk_window_move_resize (GtkWindow *window);
144 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
146 GdkGeometry *geometry_b,
148 static void gtk_window_compute_default_size (GtkWindow *window,
151 static void gtk_window_constrain_size (GtkWindow *window,
152 GdkGeometry *geometry,
158 static void gtk_window_compute_hints (GtkWindow *window,
159 GdkGeometry *new_geometry,
161 static void gtk_window_compute_reposition (GtkWindow *window,
167 static void gtk_window_read_rcfiles (GtkWidget *widget,
168 GdkEventClient *event);
169 static void gtk_window_paint (GtkWidget *widget,
171 static gint gtk_window_expose (GtkWidget *widget,
172 GdkEventExpose *event);
173 static void gtk_window_unset_transient_for (GtkWindow *window);
174 static void gtk_window_transient_parent_realized (GtkWidget *parent,
176 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
179 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
181 static void gtk_window_geometry_destroy (GtkWindowGeometryInfo *info);
184 static GSList *toplevel_list = NULL;
185 static GtkBinClass *parent_class = NULL;
186 static guint window_signals[LAST_SIGNAL] = { 0 };
188 static void gtk_window_set_property (GObject *object,
192 static void gtk_window_get_property (GObject *object,
198 gtk_window_get_type (void)
200 static GtkType window_type = 0;
204 static const GtkTypeInfo window_info =
208 sizeof (GtkWindowClass),
209 (GtkClassInitFunc) gtk_window_class_init,
210 (GtkObjectInitFunc) gtk_window_init,
211 /* reserved_1 */ NULL,
212 /* reserved_2 */ NULL,
213 (GtkClassInitFunc) NULL,
216 window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
223 gtk_window_class_init (GtkWindowClass *klass)
225 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
226 GtkObjectClass *object_class;
227 GtkWidgetClass *widget_class;
228 GtkContainerClass *container_class;
230 object_class = (GtkObjectClass*) klass;
231 widget_class = (GtkWidgetClass*) klass;
232 container_class = (GtkContainerClass*) klass;
234 parent_class = gtk_type_class (gtk_bin_get_type ());
236 gobject_class->shutdown = gtk_window_shutdown;
237 gobject_class->finalize = gtk_window_finalize;
239 gobject_class->set_property = gtk_window_set_property;
240 gobject_class->get_property = gtk_window_get_property;
242 object_class->destroy = gtk_window_destroy;
244 widget_class->show = gtk_window_show;
245 widget_class->hide = gtk_window_hide;
246 widget_class->map = gtk_window_map;
247 widget_class->unmap = gtk_window_unmap;
248 widget_class->realize = gtk_window_realize;
249 widget_class->unrealize = gtk_window_unrealize;
250 widget_class->size_request = gtk_window_size_request;
251 widget_class->size_allocate = gtk_window_size_allocate;
252 widget_class->configure_event = gtk_window_configure_event;
253 widget_class->key_press_event = gtk_window_key_press_event;
254 widget_class->key_release_event = gtk_window_key_release_event;
255 widget_class->enter_notify_event = gtk_window_enter_notify_event;
256 widget_class->leave_notify_event = gtk_window_leave_notify_event;
257 widget_class->focus_in_event = gtk_window_focus_in_event;
258 widget_class->focus_out_event = gtk_window_focus_out_event;
259 widget_class->client_event = gtk_window_client_event;
261 widget_class->expose_event = gtk_window_expose;
263 container_class->check_resize = gtk_window_check_resize;
264 container_class->focus = gtk_window_focus;
266 klass->set_focus = gtk_window_real_set_focus;
267 klass->frame_event = gtk_window_frame_event;
270 g_object_class_install_property (gobject_class,
272 g_param_spec_enum ("type",
274 _("The type of the window"),
275 GTK_TYPE_WINDOW_TYPE,
277 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
280 g_object_class_install_property (gobject_class,
282 g_param_spec_string ("title",
284 _("The title of the window"),
288 g_object_class_install_property (gobject_class,
290 g_param_spec_boolean ("auto_shrink",
292 _("If TRUE, the window automatically shrinks to its size request anytime a resize occurs. Don't use this feature, it makes no sense."),
296 g_object_class_install_property (gobject_class,
298 g_param_spec_boolean ("allow_shrink",
300 _("If TRUE, the window has no mimimum size. Don't use this feature, it makes no sense."),
304 g_object_class_install_property (gobject_class,
306 g_param_spec_boolean ("allow_grow",
308 _("If TRUE, users can expand the window beyond its minimum size."),
312 g_object_class_install_property (gobject_class,
314 g_param_spec_boolean ("modal",
316 _("If TRUE, the window is modal (other windows are not usable while this one is up)."),
320 g_object_class_install_property (gobject_class,
322 g_param_spec_enum ("window_position",
323 _("Window Position"),
324 _("The initial position of the window."),
325 GTK_TYPE_WINDOW_POSITION,
329 g_object_class_install_property (gobject_class,
331 g_param_spec_int ("default_width",
333 _("The default width of the window, or 0 to use the size request."),
339 g_object_class_install_property (gobject_class,
341 g_param_spec_int ("default_height",
343 _("The default height of the windo, or 0 to use the size request."),
349 g_object_class_install_property (gobject_class,
350 PROP_DESTROY_WITH_PARENT,
351 g_param_spec_boolean ("destroy_with_parent",
352 _("Destroy with Parent"),
353 _("If this window should be destroyed when the parent is destroyed,"),
357 /* Style props are set or not */
359 window_signals[SET_FOCUS] =
360 gtk_signal_new ("set_focus",
362 GTK_CLASS_TYPE (object_class),
363 GTK_SIGNAL_OFFSET (GtkWindowClass, set_focus),
364 gtk_marshal_VOID__OBJECT,
368 window_signals[FRAME_EVENT] =
369 gtk_signal_new ("frame_event",
371 GTK_CLASS_TYPE (object_class),
372 GTK_SIGNAL_OFFSET (GtkWindowClass, frame_event),
373 gtk_marshal_BOOLEAN__BOXED,
379 gtk_window_init (GtkWindow *window)
381 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
382 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
384 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
386 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
388 window->title = NULL;
389 window->wmclass_name = g_strdup (g_get_prgname ());
390 window->wmclass_class = g_strdup (gdk_progclass);
391 window->type = GTK_WINDOW_TOPLEVEL;
392 window->focus_widget = NULL;
393 window->default_widget = NULL;
394 window->resize_count = 0;
395 window->allow_shrink = FALSE;
396 window->allow_grow = TRUE;
397 window->auto_shrink = FALSE;
398 window->handling_resize = FALSE;
399 window->position = GTK_WIN_POS_NONE;
400 window->use_uposition = TRUE;
401 window->modal = FALSE;
402 window->frame = NULL;
403 window->has_frame = FALSE;
404 window->frame_left = 0;
405 window->frame_right = 0;
406 window->frame_top = 0;
407 window->frame_bottom = 0;
408 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
409 window->decorated = TRUE;
411 gtk_widget_ref (GTK_WIDGET (window));
412 gtk_object_sink (GTK_OBJECT (window));
413 window->has_user_ref_count = TRUE;
414 toplevel_list = g_slist_prepend (toplevel_list, window);
416 gtk_decorated_window_init (window);
418 gtk_signal_connect (GTK_OBJECT (window),
420 GTK_SIGNAL_FUNC (gtk_window_event),
425 gtk_window_set_property (GObject *object,
432 window = GTK_WINDOW (object);
437 window->type = g_value_get_enum (value);
440 gtk_window_set_title (window, g_value_get_string (value));
442 case PROP_AUTO_SHRINK:
443 window->auto_shrink = g_value_get_boolean (value);
444 gtk_widget_queue_resize (GTK_WIDGET (window));
446 case PROP_ALLOW_SHRINK:
447 window->allow_shrink = g_value_get_boolean (value);
448 gtk_widget_queue_resize (GTK_WIDGET (window));
450 case PROP_ALLOW_GROW:
451 window->allow_grow = g_value_get_boolean (value);
452 gtk_widget_queue_resize (GTK_WIDGET (window));
455 gtk_window_set_modal (window, g_value_get_boolean (value));
458 gtk_window_set_position (window, g_value_get_enum (value));
460 case PROP_DEFAULT_WIDTH:
461 gtk_window_set_default_size (window, g_value_get_int (value), -1);
463 case PROP_DEFAULT_HEIGHT:
464 gtk_window_set_default_size (window, -1, g_value_get_int (value));
466 case PROP_DESTROY_WITH_PARENT:
467 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
475 gtk_window_get_property (GObject *object,
482 window = GTK_WINDOW (object);
486 GtkWindowGeometryInfo *info;
488 g_value_set_enum (value, window->type);
491 g_value_set_string (value, window->title);
493 case PROP_AUTO_SHRINK:
494 g_value_set_boolean (value, window->auto_shrink);
496 case PROP_ALLOW_SHRINK:
497 g_value_set_boolean (value, window->allow_shrink);
499 case PROP_ALLOW_GROW:
500 g_value_set_boolean (value, window->allow_grow);
503 g_value_set_boolean (value, window->modal);
506 g_value_set_enum (value, window->position);
508 case PROP_DEFAULT_WIDTH:
509 info = gtk_window_get_geometry_info (window, FALSE);
511 g_value_set_int (value, 0);
513 g_value_set_int (value, info->width);
515 case PROP_DEFAULT_HEIGHT:
516 info = gtk_window_get_geometry_info (window, FALSE);
518 g_value_set_int (value, 0);
520 g_value_set_int (value, info->height);
522 case PROP_DESTROY_WITH_PARENT:
523 g_value_set_boolean (value, window->destroy_with_parent);
526 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
533 * @type: type of window
535 * Creates a new #GtkWindow, which is a toplevel window that can
536 * contain other widgets. Nearly always, the type of the window should
537 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
538 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
539 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
540 * dialogs, though in some other toolkits dialogs are called "popups."
541 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
542 * Popup windows are not controlled by the window manager.
544 * If you simply want an undecorated window (no window borders), use
545 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
547 * Return value: a new #GtkWindow.
550 gtk_window_new (GtkWindowType type)
554 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
556 window = gtk_type_new (GTK_TYPE_WINDOW);
560 return GTK_WIDGET (window);
564 * gtk_window_set_title:
565 * @window: a #GtkWindow
566 * @title: title of the window
568 * Sets the title of the #GtkWindow. The title of a window will be displayed in
569 * its title bar; on the X Window System, the title bar is rendered by the
570 * window manager, so exactly how the title appears to users may vary according
571 * to a user's exact configuration. The title should help a user distinguish
572 * this window from other windows they may have open. A good title might
573 * include the application name and current document filename, for example.
577 gtk_window_set_title (GtkWindow *window,
580 g_return_if_fail (window != NULL);
581 g_return_if_fail (GTK_IS_WINDOW (window));
584 g_free (window->title);
585 window->title = g_strdup (title);
587 if (GTK_WIDGET_REALIZED (window))
589 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
591 gtk_decorated_window_set_title (window, title);
594 g_object_notify (G_OBJECT (window), "title");
598 * gtk_window_set_wmclass:
599 * @window: a #GtkWindow
600 * @wmclass_name: window name hint
601 * @wmclass_class: window class hint
603 * Don't use this function. It sets the X Window System "class" and
604 * "name" hints for a window. According to the ICCCM, you should
605 * always set these to the same value for all windows in an
606 * application, and GTK sets them to that value by default, so calling
607 * this function is sort of pointless. However, you may want to call
608 * gtk_window_set_role() on each window in your application, for the
609 * benefit of the session manager. Setting the role allows the window
610 * manager to restore window positions when loading a saved session.
614 gtk_window_set_wmclass (GtkWindow *window,
615 const gchar *wmclass_name,
616 const gchar *wmclass_class)
618 g_return_if_fail (window != NULL);
619 g_return_if_fail (GTK_IS_WINDOW (window));
621 g_free (window->wmclass_name);
622 window->wmclass_name = g_strdup (wmclass_name);
624 g_free (window->wmclass_class);
625 window->wmclass_class = g_strdup (wmclass_class);
627 if (GTK_WIDGET_REALIZED (window))
628 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
632 * gtk_window_set_role:
633 * @window: a #GtkWindow
634 * @role: unique identifier for the window to be used when restoring a session
636 * In combination with the window title, the window role allows a
637 * window manager to identify "the same" window when an application is
638 * restarted. So for example you might set the "toolbox" role on your
639 * app's toolbox window, so that when the user restarts their session,
640 * the window manager can put the toolbox back in the same place.
642 * If a window already has a unique title, you don't need to set the
643 * role, since the WM can use the title to identify the window when
644 * restoring the session.
648 gtk_window_set_role (GtkWindow *window,
651 g_return_if_fail (GTK_IS_WINDOW (window));
653 if (role == window->wm_role)
656 g_free (window->wm_role);
657 window->wm_role = g_strdup (role);
659 if (GTK_WIDGET_REALIZED (window))
660 g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
664 * gtk_window_set_focus:
665 * @window: a #GtkWindow
666 * @focus: widget to be the new focus widget
668 * If @focus is not the current focus widget, and is focusable, emits
669 * the "set_focus" signal to set @focus as the focus widget for the
670 * window. This function is more or less GTK-internal; to focus an
671 * entry widget or the like, you should use gtk_widget_grab_focus()
672 * instead of this function.
676 gtk_window_set_focus (GtkWindow *window,
679 g_return_if_fail (window != NULL);
680 g_return_if_fail (GTK_IS_WINDOW (window));
683 g_return_if_fail (GTK_IS_WIDGET (focus));
684 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
687 if ((window->focus_widget != focus) ||
688 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
689 gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
693 * gtk_window_set_default:
694 * @window: a #GtkWindow
695 * @default_widget: widget to be the default
697 * The default widget is the widget that's activated when the user
698 * presses Enter in a dialog (for example). This function tells a
699 * #GtkWindow about the current default widget; it's really a GTK
700 * internal function and you shouldn't need it. Instead, to change the
701 * default widget, first set the #GTK_CAN_DEFAULT flag on the widget
702 * you'd like to make the default using GTK_WIDGET_SET_FLAGS(), then
703 * call gtk_widget_grab_default() to move the default.
707 gtk_window_set_default (GtkWindow *window,
708 GtkWidget *default_widget)
710 g_return_if_fail (window != NULL);
711 g_return_if_fail (GTK_IS_WINDOW (window));
714 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
716 if (window->default_widget != default_widget)
718 if (window->default_widget)
720 if (window->focus_widget != window->default_widget ||
721 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
722 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
723 gtk_widget_queue_draw (window->default_widget);
726 window->default_widget = default_widget;
728 if (window->default_widget)
730 if (window->focus_widget == NULL ||
731 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
732 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
733 gtk_widget_queue_draw (window->default_widget);
739 gtk_window_set_policy (GtkWindow *window,
740 gboolean allow_shrink,
742 gboolean auto_shrink)
744 g_return_if_fail (window != NULL);
745 g_return_if_fail (GTK_IS_WINDOW (window));
747 window->allow_shrink = (allow_shrink != FALSE);
748 window->allow_grow = (allow_grow != FALSE);
749 window->auto_shrink = (auto_shrink != FALSE);
751 g_object_notify (G_OBJECT (window), "allow_shrink");
752 g_object_notify (G_OBJECT (window), "allow_grow");
753 g_object_notify (G_OBJECT (window), "auto_shrink");
755 gtk_widget_queue_resize (GTK_WIDGET (window));
759 gtk_window_add_accel_group (GtkWindow *window,
760 GtkAccelGroup *accel_group)
762 g_return_if_fail (window != NULL);
763 g_return_if_fail (GTK_IS_WINDOW (window));
764 g_return_if_fail (accel_group != NULL);
766 gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
770 gtk_window_remove_accel_group (GtkWindow *window,
771 GtkAccelGroup *accel_group)
773 g_return_if_fail (window != NULL);
774 g_return_if_fail (GTK_IS_WINDOW (window));
775 g_return_if_fail (accel_group != NULL);
777 gtk_accel_group_detach (accel_group, GTK_OBJECT (window));
781 gtk_window_get_default_accel_group (GtkWindow *window)
783 GtkAccelGroup *group;
785 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
787 group = gtk_object_get_data (GTK_OBJECT (window),
792 group = gtk_accel_group_new ();
793 gtk_window_add_accel_group (window, group);
794 gtk_object_set_data (GTK_OBJECT (window),
797 gtk_accel_group_unref (group);
804 gtk_window_set_position (GtkWindow *window,
805 GtkWindowPosition position)
807 g_return_if_fail (window != NULL);
808 g_return_if_fail (GTK_IS_WINDOW (window));
810 window->position = position;
812 g_object_notify (G_OBJECT (window), "window_position");
816 gtk_window_activate_focus (GtkWindow *window)
818 g_return_val_if_fail (window != NULL, FALSE);
819 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
821 if (window->focus_widget)
823 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
824 gtk_widget_activate (window->focus_widget);
832 gtk_window_activate_default (GtkWindow *window)
834 g_return_val_if_fail (window != NULL, FALSE);
835 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
837 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget))
839 gtk_widget_activate (window->default_widget);
847 * gtk_window_set_modal:
848 * @window: a #GtkWindow
849 * @modal: whether the window is modal
851 * Sets a window modal or non-modal. Modal windows prevent interaction
852 * with other windows in the same application. To keep modal dialogs
853 * on top of main application windows, use
854 * gtk_window_set_transient_for() to make the dialog transient for the
855 * parent; most window managers will then disallow lowering the dialog
861 gtk_window_set_modal (GtkWindow *window,
864 g_return_if_fail (window != NULL);
865 g_return_if_fail (GTK_IS_WINDOW (window));
867 window->modal = modal != FALSE;
869 /* adjust desired modality state */
870 if (GTK_WIDGET_VISIBLE (window) && window->modal)
871 gtk_grab_add (GTK_WIDGET (window));
873 gtk_grab_remove (GTK_WIDGET (window));
875 g_object_notify (G_OBJECT (window), "modal");
879 * gtk_window_list_toplevels:
881 * Returns a list of all existing toplevel windows. Each widget
882 * in the list has a reference added to it; to free the
883 * list, first unref each widget in the list, then free the list.
885 * Return value: list of referenced toplevel widgets
888 gtk_window_list_toplevels (void)
893 for (slist = toplevel_list; slist; slist = slist->next)
894 list = g_list_prepend (list, gtk_widget_ref (slist->data));
900 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
902 GList *embedded_windows;
904 g_return_if_fail (window != NULL);
905 g_return_if_fail (GTK_IS_WINDOW (window));
907 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
908 if (embedded_windows)
909 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
910 g_quark_from_static_string ("gtk-embedded"));
911 embedded_windows = g_list_prepend (embedded_windows,
912 GUINT_TO_POINTER (xid));
914 gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
917 (GtkDestroyNotify) g_list_free : NULL);
921 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
923 GList *embedded_windows;
926 g_return_if_fail (window != NULL);
927 g_return_if_fail (GTK_IS_WINDOW (window));
929 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
930 if (embedded_windows)
931 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
932 g_quark_from_static_string ("gtk-embedded"));
934 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
937 embedded_windows = g_list_remove_link (embedded_windows, node);
938 g_list_free_1 (node);
941 gtk_object_set_data_full (GTK_OBJECT (window),
942 "gtk-embedded", embedded_windows,
944 (GtkDestroyNotify) g_list_free : NULL);
948 gtk_window_reposition (GtkWindow *window,
952 GtkWindowGeometryInfo *info;
954 g_return_if_fail (window != NULL);
955 g_return_if_fail (GTK_IS_WINDOW (window));
957 /* keep this in sync with gtk_window_compute_reposition()
959 if (GTK_WIDGET_REALIZED (window))
961 info = gtk_window_get_geometry_info (window, TRUE);
963 if (!(info->last.flags & GDK_HINT_POS))
965 info->last.flags |= GDK_HINT_POS;
966 gdk_window_set_geometry_hints (GTK_WIDGET (window)->window,
967 &info->last.geometry,
972 gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
974 gdk_window_move (GTK_WIDGET (window)->window, x, y);
979 gtk_window_shutdown (GObject *object)
983 g_return_if_fail (GTK_IS_WINDOW (object));
985 window = GTK_WINDOW (object);
987 gtk_window_set_focus (window, NULL);
988 gtk_window_set_default (window, NULL);
990 G_OBJECT_CLASS (parent_class)->shutdown (object);
994 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
996 gtk_widget_destroy (GTK_WIDGET (child));
1000 connect_parent_destroyed (GtkWindow *window)
1002 if (window->transient_parent)
1004 gtk_signal_connect (GTK_OBJECT (window->transient_parent),
1006 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1012 disconnect_parent_destroyed (GtkWindow *window)
1014 if (window->transient_parent)
1016 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1017 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1023 gtk_window_transient_parent_realized (GtkWidget *parent,
1026 if (GTK_WIDGET_REALIZED (window))
1027 gdk_window_set_transient_for (window->window, parent->window);
1031 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1034 if (GTK_WIDGET_REALIZED (window))
1035 gdk_property_delete (window->window,
1036 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1040 gtk_window_unset_transient_for (GtkWindow *window)
1042 if (window->transient_parent)
1044 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1045 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1047 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1048 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1050 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1051 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1052 &window->transient_parent);
1054 if (window->destroy_with_parent)
1055 disconnect_parent_destroyed (window);
1057 window->transient_parent = NULL;
1062 * gtk_window_set_transient_for:
1063 * @window: a #GtkWindow
1064 * @parent: parent window
1066 * Dialog windows should be set transient for the main application
1067 * window they were spawned from. This allows window managers to
1068 * e.g. keep the dialog on top of the main window, or center the
1069 * dialog over the main window. gtk_dialog_new_with_buttons() and
1070 * other convenience functions in GTK+ will sometimes call
1071 * gtk_window_set_transient_for() on your behalf.
1075 gtk_window_set_transient_for (GtkWindow *window,
1078 g_return_if_fail (GTK_IS_WINDOW (window));
1079 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1080 g_return_if_fail (window != parent);
1083 if (window->transient_parent)
1085 if (GTK_WIDGET_REALIZED (window) &&
1086 GTK_WIDGET_REALIZED (window->transient_parent) &&
1087 (!parent || !GTK_WIDGET_REALIZED (parent)))
1088 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1089 GTK_WIDGET (window));
1091 gtk_window_unset_transient_for (window);
1094 window->transient_parent = parent;
1098 gtk_signal_connect (GTK_OBJECT (parent), "destroy",
1099 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1100 &window->transient_parent);
1101 gtk_signal_connect (GTK_OBJECT (parent), "realize",
1102 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1104 gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
1105 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1108 if (window->destroy_with_parent)
1109 connect_parent_destroyed (window);
1111 if (GTK_WIDGET_REALIZED (window) &&
1112 GTK_WIDGET_REALIZED (parent))
1113 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1114 GTK_WIDGET (window));
1119 * gtk_window_set_type_hint:
1120 * @window: a #GtkWindow
1121 * @hint: the window type
1123 * By setting the type hint for the window, you allow the window
1124 * manager to decorate and handle the window in a way which is
1125 * suitable to the function of the window in your application.
1127 * This function should be called before the window becomes visible.
1129 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1130 * will sometimes call gtk_window_set_type_hint() on your behalf.
1134 gtk_window_set_type_hint (GtkWindow *window,
1135 GdkWindowTypeHint hint)
1137 g_return_if_fail (GTK_IS_WINDOW (window));
1138 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1139 window->type_hint = hint;
1143 * gtk_window_set_destroy_with_parent:
1144 * @window: a #GtkWindow
1145 * @setting: whether to destroy @window with its transient parent
1147 * If @setting is TRUE, then destroying the transient parent of @window
1148 * will also destroy @window itself. This is useful for dialogs that
1149 * shouldn't persist beyond the lifetime of the main window they're
1150 * associated with, for example.
1153 gtk_window_set_destroy_with_parent (GtkWindow *window,
1156 g_return_if_fail (GTK_IS_WINDOW (window));
1158 if (window->destroy_with_parent == (setting != FALSE))
1161 if (window->destroy_with_parent)
1163 disconnect_parent_destroyed (window);
1167 connect_parent_destroyed (window);
1170 window->destroy_with_parent = setting;
1172 g_object_notify (G_OBJECT (window), "destroy_with_parent");
1176 gtk_window_geometry_destroy (GtkWindowGeometryInfo *info)
1179 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1180 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1185 static GtkWindowGeometryInfo*
1186 gtk_window_get_geometry_info (GtkWindow *window,
1189 GtkWindowGeometryInfo *info;
1191 info = gtk_object_get_data (GTK_OBJECT (window), "gtk-window-geometry");
1193 if (!info && create)
1195 info = g_new0 (GtkWindowGeometryInfo, 1);
1199 info->last.width = -1;
1200 info->last.height = -1;
1201 info->widget = NULL;
1204 gtk_object_set_data_full (GTK_OBJECT (window),
1205 "gtk-window-geometry",
1207 (GtkDestroyNotify) gtk_window_geometry_destroy);
1214 * gtk_window_set_geometry_hints:
1215 * @window: a #GdkWindow
1216 * @geometry_widget: widget the geometry hints will be applied to
1217 * @geometry: struct containing geometry information
1218 * @geom_mask: mask indicating which struct fields should be paid attention to
1220 * This function sets up hints about how a window can be resized by
1221 * the user. You can set a minimum and maximum size; allowed resize
1222 * increments (e.g. for xterm, you can only resize by the size of a
1223 * character); aspect ratios; and more. See the #GdkGeometry struct.
1227 gtk_window_set_geometry_hints (GtkWindow *window,
1228 GtkWidget *geometry_widget,
1229 GdkGeometry *geometry,
1230 GdkWindowHints geom_mask)
1232 GtkWindowGeometryInfo *info;
1234 g_return_if_fail (window != NULL);
1236 info = gtk_window_get_geometry_info (window, TRUE);
1239 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1240 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1243 info->widget = geometry_widget;
1245 gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
1246 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1250 info->geometry = *geometry;
1252 info->mask = geom_mask;
1254 gtk_widget_queue_resize (GTK_WIDGET (window));
1258 * gtk_window_set_decorated:
1259 * @window: a #GtkWindow
1260 * @setting: %TRUE to decorate the window
1262 * By default, windows are decorated with a title bar, resize
1263 * controls, etc. Some window managers allow GTK+ to disable these
1264 * decorations, creating a borderless window. If you set the decorated
1265 * property to %FALSE using this function, GTK+ will do its best to
1266 * convince the window manager not to decorate the window.
1270 gtk_window_set_decorated (GtkWindow *window,
1273 g_return_if_fail (GTK_IS_WINDOW (window));
1275 setting = setting != FALSE;
1277 if (setting == window->decorated)
1280 if (GTK_WIDGET (window)->window)
1282 if (window->decorated)
1283 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1286 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1292 * gtk_window_set_default_size:
1293 * @window: a #GtkWindow
1294 * @width: width in pixels, 0 to unset, or -1 to leave the width unchanged
1295 * @height: height in pixels, 0 to unset, or -1 to leave the height unchanged
1297 * Sets the default size of a window. If the window's "natural" size
1298 * (its size request) is larger than the default, the default will be
1299 * ignored. So the default size is a minimum initial size. Unlike
1300 * gtk_widget_set_usize(), which sets a size request for a widget and
1301 * thus would keep users from shrinking the window, this function only
1302 * sets the initial size, just as if the user had resized the window
1303 * themselves. Users can still shrink the window again as they
1304 * normally would. Setting a default size of 0 means to use the
1305 * "natural" default size (the size request of the window).
1307 * For more control over a window's initial size and how resizing works,
1308 * investigate gtk_window_set_geometry_hints().
1310 * A useful feature: if you set the "geometry widget" via
1311 * gtk_window_set_geometry_hints(), the default size specified by
1312 * gtk_window_set_default_size() will be the default size of that
1313 * widget, not of the entire window.
1317 gtk_window_set_default_size (GtkWindow *window,
1321 GtkWindowGeometryInfo *info;
1323 g_return_if_fail (GTK_IS_WINDOW (window));
1325 info = gtk_window_get_geometry_info (window, TRUE);
1328 info->width = width;
1330 info->height = height;
1333 g_object_notify (G_OBJECT (window), "width");
1335 g_object_notify (G_OBJECT (window), "height");
1337 gtk_widget_queue_resize (GTK_WIDGET (window));
1341 gtk_window_destroy (GtkObject *object)
1345 g_return_if_fail (GTK_IS_WINDOW (object));
1347 window = GTK_WINDOW (object);
1349 if (window->transient_parent)
1350 gtk_window_set_transient_for (window, NULL);
1352 if (window->has_user_ref_count)
1354 window->has_user_ref_count = FALSE;
1355 gtk_widget_unref (GTK_WIDGET (window));
1358 GTK_OBJECT_CLASS (parent_class)->destroy (object);
1362 gtk_window_finalize (GObject *object)
1366 g_return_if_fail (GTK_IS_WINDOW (object));
1368 window = GTK_WINDOW (object);
1370 toplevel_list = g_slist_remove (toplevel_list, window);
1372 g_free (window->title);
1373 g_free (window->wmclass_name);
1374 g_free (window->wmclass_class);
1376 G_OBJECT_CLASS (parent_class)->finalize (object);
1380 gtk_window_show (GtkWidget *widget)
1382 GtkWindow *window = GTK_WINDOW (widget);
1383 GtkContainer *container = GTK_CONTAINER (window);
1384 gboolean need_resize;
1385 gboolean was_realized;
1387 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
1389 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
1390 container->need_resize = FALSE;
1394 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
1395 GtkAllocation allocation = { 0, 0 };
1396 GdkGeometry new_geometry;
1397 guint width, height, new_flags;
1399 /* determine default size to initially show the window with */
1400 gtk_widget_size_request (widget, NULL);
1401 gtk_window_compute_default_size (window, &width, &height);
1403 /* save away the last default size for later comparisions */
1404 info->last.width = width;
1405 info->last.height = height;
1407 /* constrain size to geometry */
1408 gtk_window_compute_hints (window, &new_geometry, &new_flags);
1409 gtk_window_constrain_size (window,
1410 &new_geometry, new_flags,
1414 /* and allocate the window */
1415 allocation.width = width;
1416 allocation.height = height;
1417 gtk_widget_size_allocate (widget, &allocation);
1419 was_realized = FALSE;
1420 if (!GTK_WIDGET_REALIZED (widget))
1422 gtk_widget_realize (widget);
1423 was_realized = TRUE;;
1426 /* Must be done after the windows are realized,
1427 so that the decorations can be read */
1428 gtk_decorated_window_calculate_frame_size (window);
1431 gdk_window_resize (widget->window, width, height);
1434 gtk_container_check_resize (container);
1436 gtk_widget_map (widget);
1439 gtk_grab_add (widget);
1443 gtk_window_hide (GtkWidget *widget)
1447 g_return_if_fail (widget != NULL);
1448 g_return_if_fail (GTK_IS_WINDOW (widget));
1450 window = GTK_WINDOW (widget);
1452 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
1453 gtk_widget_unmap (widget);
1456 gtk_grab_remove (widget);
1460 gtk_window_map (GtkWidget *widget)
1463 GdkWindow *toplevel;
1465 g_return_if_fail (widget != NULL);
1466 g_return_if_fail (GTK_IS_WINDOW (widget));
1468 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1470 window = GTK_WINDOW (widget);
1472 if (window->bin.child &&
1473 GTK_WIDGET_VISIBLE (window->bin.child) &&
1474 !GTK_WIDGET_MAPPED (window->bin.child))
1475 gtk_widget_map (window->bin.child);
1478 toplevel = window->frame;
1480 toplevel = widget->window;
1482 if (window->maximize_initially)
1483 gdk_window_maximize (toplevel);
1485 gdk_window_unmaximize (toplevel);
1487 if (window->stick_initially)
1488 gdk_window_stick (toplevel);
1490 gdk_window_unstick (toplevel);
1492 if (window->iconify_initially)
1493 gdk_window_iconify (toplevel);
1495 gdk_window_deiconify (toplevel);
1497 gdk_window_show (widget->window);
1500 gdk_window_show (window->frame);
1504 gtk_window_unmap (GtkWidget *widget)
1508 g_return_if_fail (widget != NULL);
1509 g_return_if_fail (GTK_IS_WINDOW (widget));
1511 window = GTK_WINDOW (widget);
1513 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1515 gdk_window_withdraw (window->frame);
1517 gdk_window_withdraw (widget->window);
1519 window->use_uposition = TRUE;
1520 window->resize_count = 0;
1521 window->handling_resize = FALSE;
1526 gtk_window_realize (GtkWidget *widget)
1529 GdkWindow *parent_window;
1530 GdkWindowAttr attributes;
1531 gint attributes_mask;
1533 g_return_if_fail (GTK_IS_WINDOW (widget));
1535 window = GTK_WINDOW (widget);
1537 /* ensure widget tree is properly size allocated */
1538 if (widget->allocation.x == -1 &&
1539 widget->allocation.y == -1 &&
1540 widget->allocation.width == 1 &&
1541 widget->allocation.height == 1)
1543 GtkRequisition requisition;
1544 GtkAllocation allocation = { 0, 0, 200, 200 };
1546 gtk_widget_size_request (widget, &requisition);
1547 if (requisition.width || requisition.height)
1549 /* non-empty window */
1550 allocation.width = requisition.width;
1551 allocation.height = requisition.height;
1553 gtk_widget_size_allocate (widget, &allocation);
1555 gtk_container_queue_resize (GTK_CONTAINER (widget));
1557 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
1560 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1562 switch (window->type)
1564 case GTK_WINDOW_TOPLEVEL:
1565 attributes.window_type = GDK_WINDOW_TOPLEVEL;
1567 case GTK_WINDOW_POPUP:
1568 attributes.window_type = GDK_WINDOW_TEMP;
1571 g_warning (G_STRLOC": Unknown window type %d!", window->type);
1575 attributes.title = window->title;
1576 attributes.wmclass_name = window->wmclass_name;
1577 attributes.wmclass_class = window->wmclass_class;
1578 attributes.wclass = GDK_INPUT_OUTPUT;
1579 attributes.visual = gtk_widget_get_visual (widget);
1580 attributes.colormap = gtk_widget_get_colormap (widget);
1582 if (window->has_frame)
1584 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
1585 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
1586 attributes.event_mask = (GDK_EXPOSURE_MASK |
1587 GDK_KEY_PRESS_MASK |
1588 GDK_ENTER_NOTIFY_MASK |
1589 GDK_LEAVE_NOTIFY_MASK |
1590 GDK_FOCUS_CHANGE_MASK |
1591 GDK_STRUCTURE_MASK |
1592 GDK_BUTTON_MOTION_MASK |
1593 GDK_POINTER_MOTION_HINT_MASK |
1594 GDK_BUTTON_PRESS_MASK |
1595 GDK_BUTTON_RELEASE_MASK);
1597 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
1599 window->frame = gdk_window_new (NULL, &attributes, attributes_mask);
1600 gdk_window_set_user_data (window->frame, widget);
1602 attributes.window_type = GDK_WINDOW_CHILD;
1603 attributes.x = window->frame_left;
1604 attributes.y = window->frame_right;
1606 attributes_mask = GDK_WA_X | GDK_WA_Y;
1608 parent_window = window->frame;
1612 attributes_mask = 0;
1613 parent_window = NULL;
1616 attributes.width = widget->allocation.width;
1617 attributes.height = widget->allocation.height;
1618 attributes.event_mask = gtk_widget_get_events (widget);
1619 attributes.event_mask |= (GDK_EXPOSURE_MASK |
1620 GDK_KEY_PRESS_MASK |
1621 GDK_ENTER_NOTIFY_MASK |
1622 GDK_LEAVE_NOTIFY_MASK |
1623 GDK_FOCUS_CHANGE_MASK |
1624 GDK_STRUCTURE_MASK);
1626 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
1627 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
1628 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
1629 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
1630 gdk_window_set_user_data (widget->window, window);
1632 widget->style = gtk_style_attach (widget->style, widget->window);
1633 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
1635 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
1637 /* This is a bad hack to set the window background. */
1638 gtk_window_paint (widget, NULL);
1640 if (window->transient_parent &&
1641 GTK_WIDGET_REALIZED (window->transient_parent))
1642 gdk_window_set_transient_for (widget->window,
1643 GTK_WIDGET (window->transient_parent)->window);
1645 if (window->wm_role)
1646 gdk_window_set_role (widget->window, window->wm_role);
1648 if (!window->decorated)
1649 gdk_window_set_decorations (widget->window, 0);
1651 gdk_window_set_type_hint (widget->window, window->type_hint);
1653 /* transient_for must be set to allow the modal hint */
1654 if (window->transient_parent && window->modal)
1655 gdk_window_set_modal_hint (widget->window, TRUE);
1657 gdk_window_set_modal_hint (widget->window, FALSE);
1661 gtk_window_unrealize (GtkWidget *widget)
1665 g_return_if_fail (widget != NULL);
1666 g_return_if_fail (GTK_IS_WINDOW (widget));
1668 window = GTK_WINDOW (widget);
1672 gdk_window_set_user_data (window->frame, NULL);
1673 gdk_window_destroy (window->frame);
1674 window->frame = NULL;
1677 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1681 gtk_window_size_request (GtkWidget *widget,
1682 GtkRequisition *requisition)
1687 g_return_if_fail (widget != NULL);
1688 g_return_if_fail (GTK_IS_WINDOW (widget));
1689 g_return_if_fail (requisition != NULL);
1691 window = GTK_WINDOW (widget);
1692 bin = GTK_BIN (window);
1694 requisition->width = GTK_CONTAINER (window)->border_width * 2;
1695 requisition->height = GTK_CONTAINER (window)->border_width * 2;
1697 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
1699 GtkRequisition child_requisition;
1701 gtk_widget_size_request (bin->child, &child_requisition);
1703 requisition->width += child_requisition.width;
1704 requisition->height += child_requisition.height;
1709 gtk_window_size_allocate (GtkWidget *widget,
1710 GtkAllocation *allocation)
1713 GtkAllocation child_allocation;
1715 g_return_if_fail (widget != NULL);
1716 g_return_if_fail (GTK_IS_WINDOW (widget));
1717 g_return_if_fail (allocation != NULL);
1719 window = GTK_WINDOW (widget);
1720 widget->allocation = *allocation;
1722 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
1724 child_allocation.x = GTK_CONTAINER (window)->border_width;
1725 child_allocation.y = GTK_CONTAINER (window)->border_width;
1726 child_allocation.width =
1727 MAX (1, (gint)allocation->width - child_allocation.x * 2);
1728 child_allocation.height =
1729 MAX (1, (gint)allocation->height - child_allocation.y * 2);
1731 gtk_widget_size_allocate (window->bin.child, &child_allocation);
1734 if (GTK_WIDGET_REALIZED (widget) && window->frame)
1736 gdk_window_resize (window->frame,
1737 allocation->width + window->frame_left + window->frame_right,
1738 allocation->height + window->frame_top + window->frame_bottom);
1743 gtk_window_event (GtkWidget *widget, GdkEvent *event)
1746 gboolean return_val;
1749 g_return_val_if_fail (widget != NULL, FALSE);
1750 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1751 g_return_val_if_fail (event != NULL, FALSE);
1753 window = GTK_WINDOW (widget);
1755 if (window->frame && (event->any.window == window->frame))
1757 if ((event->type != GDK_KEY_PRESS) &&
1758 (event->type != GDK_KEY_RELEASE) &&
1759 (event->type != GDK_FOCUS_CHANGE))
1761 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
1763 gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
1768 g_object_unref (event->any.window);
1769 event->any.window = g_object_ref (widget->window);
1777 gtk_window_frame_event (GtkWidget *widget, GdkEvent *event)
1779 GdkEventConfigure *configure_event;
1780 GtkWindow *window = GTK_WINDOW (widget);
1783 switch (event->type)
1786 configure_event = (GdkEventConfigure *)event;
1788 /* Invalidate the decorations */
1791 rect.width = configure_event->width;
1792 rect.height = configure_event->height;
1794 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
1796 /* Pass on the (modified) configure event */
1797 configure_event->width -= window->frame_left + window->frame_right;
1798 configure_event->height -= window->frame_top + window->frame_bottom;
1799 return gtk_window_configure_event (widget, configure_event);
1808 gtk_window_configure_event (GtkWidget *widget,
1809 GdkEventConfigure *event)
1813 g_return_val_if_fail (widget != NULL, FALSE);
1814 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1815 g_return_val_if_fail (event != NULL, FALSE);
1817 window = GTK_WINDOW (widget);
1819 /* we got a configure event specifying the new window size and position,
1820 * in principle we have to distinguish 4 cases here:
1821 * 1) the size didn't change and resize_count == 0
1822 * -> the window was merely moved (sometimes not even that)
1823 * 2) the size didn't change and resize_count > 0
1824 * -> we requested a new size, but didn't get it
1825 * 3) the size changed and resize_count > 0
1826 * -> we asked for a new size and we got one
1827 * 4) the size changed and resize_count == 0
1828 * -> we got resized from outside the toolkit, and have to
1829 * accept that size since we don't want to fight neither the
1830 * window manager nor the user
1831 * in the three latter cases we have to reallocate the widget tree,
1832 * which happens in gtk_window_move_resize(), so we set a flag for
1833 * that function and assign the new size. if resize_count > 1,
1834 * we simply do nothing and wait for more configure events.
1837 if (window->resize_count > 0 ||
1838 widget->allocation.width != event->width ||
1839 widget->allocation.height != event->height)
1841 if (window->resize_count > 0)
1842 window->resize_count -= 1;
1844 if (window->resize_count == 0)
1846 window->handling_resize = TRUE;
1848 widget->allocation.width = event->width;
1849 widget->allocation.height = event->height;
1851 gtk_widget_queue_resize (widget);
1859 gtk_window_key_press_event (GtkWidget *widget,
1863 GtkDirectionType direction = 0;
1866 g_return_val_if_fail (widget != NULL, FALSE);
1867 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1868 g_return_val_if_fail (event != NULL, FALSE);
1870 window = GTK_WINDOW (widget);
1874 if (window->focus_widget &&
1875 window->focus_widget != widget &&
1876 GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1878 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
1882 handled = gtk_accel_groups_activate (GTK_OBJECT (window), event->keyval, event->state);
1886 switch (event->keyval)
1889 if (window->focus_widget)
1891 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1892 gtk_widget_activate (window->focus_widget);
1898 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1899 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1901 gtk_widget_activate (window->default_widget);
1904 else if (window->focus_widget)
1906 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1907 gtk_widget_activate (window->focus_widget);
1920 case GDK_ISO_Left_Tab:
1921 switch (event->keyval)
1925 direction = GTK_DIR_UP;
1929 direction = GTK_DIR_DOWN;
1933 direction = GTK_DIR_LEFT;
1937 direction = GTK_DIR_RIGHT;
1940 case GDK_ISO_Left_Tab:
1941 if (event->state & GDK_SHIFT_MASK)
1942 direction = GTK_DIR_TAB_BACKWARD;
1944 direction = GTK_DIR_TAB_FORWARD;
1947 direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
1950 gtk_container_focus (GTK_CONTAINER (widget), direction);
1952 if (!GTK_CONTAINER (window)->focus_child)
1953 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
1960 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
1961 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
1967 gtk_window_key_release_event (GtkWidget *widget,
1973 g_return_val_if_fail (widget != NULL, FALSE);
1974 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1975 g_return_val_if_fail (event != NULL, FALSE);
1977 window = GTK_WINDOW (widget);
1979 if (window->focus_widget &&
1980 window->focus_widget != widget &&
1981 GTK_WIDGET_SENSITIVE (window->focus_widget))
1983 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
1986 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
1987 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
1993 gtk_window_enter_notify_event (GtkWidget *widget,
1994 GdkEventCrossing *event)
1996 g_return_val_if_fail (widget != NULL, FALSE);
1997 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1998 g_return_val_if_fail (event != NULL, FALSE);
2004 gtk_window_leave_notify_event (GtkWidget *widget,
2005 GdkEventCrossing *event)
2007 g_return_val_if_fail (widget != NULL, FALSE);
2008 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2009 g_return_val_if_fail (event != NULL, FALSE);
2015 gtk_window_focus_in_event (GtkWidget *widget,
2016 GdkEventFocus *event)
2019 GdkEventFocus fevent;
2021 g_return_val_if_fail (widget != NULL, FALSE);
2022 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2023 g_return_val_if_fail (event != NULL, FALSE);
2025 /* It appears spurious focus in events can occur when
2026 * the window is hidden. So we'll just check to see if
2027 * the window is visible before actually handling the
2030 if (GTK_WIDGET_VISIBLE (widget))
2032 window = GTK_WINDOW (widget);
2033 if (window->focus_widget &&
2034 window->focus_widget != widget &&
2035 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
2037 fevent.type = GDK_FOCUS_CHANGE;
2038 fevent.window = window->focus_widget->window;
2041 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
2049 gtk_window_focus_out_event (GtkWidget *widget,
2050 GdkEventFocus *event)
2053 GdkEventFocus fevent;
2055 g_return_val_if_fail (widget != NULL, FALSE);
2056 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2057 g_return_val_if_fail (event != NULL, FALSE);
2059 window = GTK_WINDOW (widget);
2060 if (window->focus_widget &&
2061 window->focus_widget != widget &&
2062 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
2064 fevent.type = GDK_FOCUS_CHANGE;
2065 fevent.window = window->focus_widget->window;
2068 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
2074 static GdkAtom atom_rcfiles = GDK_NONE;
2077 gtk_window_read_rcfiles (GtkWidget *widget,
2078 GdkEventClient *event)
2080 GList *embedded_windows;
2082 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
2083 if (embedded_windows)
2088 for(i = 0; i < 5; i++)
2090 sev.data_format = 32;
2091 sev.message_type = atom_rcfiles;
2093 while (embedded_windows)
2095 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
2096 gdk_event_send_client_message ((GdkEvent *) &sev, xid);
2097 embedded_windows = embedded_windows->next;
2101 if (gtk_rc_reparse_all ())
2103 /* If the above returned true, some of our RC files are out
2104 * of date, so we need to reset all our widgets. Our other
2105 * toplevel windows will also get the message, but by
2106 * then, the RC file will up to date, so we have to tell
2107 * them now. Also, we have to invalidate cached icons in
2108 * icon sets so they get re-rendered.
2110 GList *list, *toplevels;
2112 _gtk_icon_set_invalidate_caches ();
2114 toplevels = gtk_window_list_toplevels ();
2116 for (list = toplevels; list; list = list->next)
2118 gtk_widget_reset_rc_styles (list->data);
2119 gtk_widget_unref (list->data);
2121 g_list_free (toplevels);
2126 gtk_window_client_event (GtkWidget *widget,
2127 GdkEventClient *event)
2129 g_return_val_if_fail (widget != NULL, FALSE);
2130 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2131 g_return_val_if_fail (event != NULL, FALSE);
2134 atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
2136 if(event->message_type == atom_rcfiles)
2137 gtk_window_read_rcfiles (widget, event);
2143 gtk_window_check_resize (GtkContainer *container)
2147 g_return_if_fail (container != NULL);
2148 g_return_if_fail (GTK_IS_WINDOW (container));
2150 window = GTK_WINDOW (container);
2152 if (GTK_WIDGET_VISIBLE (container))
2153 gtk_window_move_resize (window);
2157 gtk_window_focus (GtkContainer *container,
2158 GtkDirectionType direction)
2160 GtkBin *bin = GTK_BIN (container);
2161 GtkWindow *window = GTK_WINDOW (container);
2162 GtkWidget *old_focus_child = container->focus_child;
2165 /* We need a special implementation here to deal properly with wrapping
2166 * around in the tab chain without the danger of going into an
2169 if (old_focus_child)
2171 if (GTK_IS_CONTAINER (old_focus_child) &&
2172 GTK_WIDGET_DRAWABLE (old_focus_child) &&
2173 GTK_WIDGET_IS_SENSITIVE (old_focus_child) &&
2174 gtk_container_focus (GTK_CONTAINER (old_focus_child), direction))
2178 if (window->focus_widget)
2180 /* Wrapped off the end, clear the focus setting for the toplpevel */
2181 parent = window->focus_widget->parent;
2184 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
2185 parent = GTK_WIDGET (parent)->parent;
2188 gtk_window_set_focus (GTK_WINDOW (container), NULL);
2191 /* Now try to focus the first widget in the window */
2192 if (GTK_WIDGET_DRAWABLE (bin->child) &&
2193 GTK_WIDGET_IS_SENSITIVE (bin->child))
2195 if (GTK_IS_CONTAINER (bin->child))
2197 if (gtk_container_focus (GTK_CONTAINER (bin->child), direction))
2200 else if (GTK_WIDGET_CAN_FOCUS (bin->child))
2202 gtk_widget_grab_focus (bin->child);
2211 gtk_window_real_set_focus (GtkWindow *window,
2214 GdkEventFocus event;
2215 gboolean def_flags = 0;
2217 g_return_if_fail (window != NULL);
2218 g_return_if_fail (GTK_IS_WINDOW (window));
2220 if (window->default_widget)
2221 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
2223 if (window->focus_widget)
2225 event.type = GDK_FOCUS_CHANGE;
2226 event.window = window->focus_widget->window;
2229 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
2230 (window->focus_widget != window->default_widget))
2232 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
2233 /* if any widget had the default set there should be
2234 a default_widget, but might not so this is a sanity
2236 if (window->default_widget)
2237 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
2240 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
2243 window->focus_widget = focus;
2245 if (window->focus_widget)
2247 event.type = GDK_FOCUS_CHANGE;
2248 event.window = window->focus_widget->window;
2251 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
2252 (window->focus_widget != window->default_widget))
2254 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
2255 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
2257 if (window->default_widget)
2258 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
2261 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
2264 if (window->default_widget &&
2265 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
2266 gtk_widget_queue_draw (window->default_widget);
2269 /*********************************
2270 * Functions related to resizing *
2271 *********************************/
2274 gtk_window_move_resize (GtkWindow *window)
2277 GtkContainer *container;
2278 GtkWindowGeometryInfo *info;
2279 GtkWindowLastGeometryInfo saved_last_info;
2280 GdkGeometry new_geometry;
2284 gint new_width, new_height;
2285 gboolean default_size_changed = FALSE;
2286 gboolean hints_changed = FALSE;
2288 g_return_if_fail (GTK_IS_WINDOW (window));
2289 g_return_if_fail (GTK_WIDGET_REALIZED (window));
2291 widget = GTK_WIDGET (window);
2292 container = GTK_CONTAINER (widget);
2293 info = gtk_window_get_geometry_info (window, TRUE);
2294 saved_last_info = info->last;
2296 gtk_widget_size_request (widget, NULL);
2297 gtk_window_compute_default_size (window, &new_width, &new_height);
2299 if (info->last.width < 0 ||
2300 info->last.width != new_width ||
2301 info->last.height != new_height)
2303 default_size_changed = TRUE;
2304 info->last.width = new_width;
2305 info->last.height = new_height;
2307 /* We need to force a reposition in this case
2309 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
2310 window->use_uposition = TRUE;
2313 /* Compute new set of hints for the window
2315 gtk_window_compute_hints (window, &new_geometry, &new_flags);
2316 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
2317 &new_geometry, new_flags))
2319 hints_changed = TRUE;
2320 info->last.geometry = new_geometry;
2321 info->last.flags = new_flags;
2324 /* From the default size and the allocation, figure out the size
2325 * the window should be.
2327 if (!default_size_changed ||
2328 (!window->auto_shrink &&
2329 new_width <= widget->allocation.width &&
2330 new_height <= widget->allocation.height))
2332 new_width = widget->allocation.width;
2333 new_height = widget->allocation.height;
2336 /* constrain the window size to the specified geometry */
2337 gtk_window_constrain_size (window,
2338 &new_geometry, new_flags,
2339 new_width, new_height,
2340 &new_width, &new_height);
2342 /* compute new window position if a move is required
2344 gtk_window_compute_reposition (window, new_width, new_height, &x, &y);
2345 if (x != 1 && y != -1 && !(new_flags & GDK_HINT_POS))
2347 new_flags |= GDK_HINT_POS;
2348 hints_changed = TRUE;
2352 /* handle actual resizing:
2353 * - handle reallocations due to configure events
2354 * - figure whether we need to request a new window size
2355 * - handle simple resizes within our widget tree
2356 * - reposition window if neccessary
2358 width = widget->allocation.width;
2359 height = widget->allocation.height;
2361 if (window->handling_resize)
2363 GtkAllocation allocation;
2365 /* if we are just responding to a configure event, which
2366 * might be due to a resize by the window manager, the
2367 * user, or a response to a resizing request we made
2368 * earlier, we go ahead, allocate the new size and we're done
2369 * (see gtk_window_configure_event() for more details).
2372 window->handling_resize = FALSE;
2374 allocation = widget->allocation;
2376 gtk_widget_size_allocate (widget, &allocation);
2377 gtk_widget_queue_draw (widget);
2379 #ifdef FIXME_ZVT_ME_HARDER
2380 if ((default_size_changed || hints_changed) && (width != new_width || height != new_height))
2382 /* We could be here for two reasons
2383 * 1) We coincidentally got a resize while handling
2385 * 2) Our computation of default_size_changed was completely
2386 * screwed up, probably because one of our children
2387 * is broken (i.e. changes requisition during
2388 * size allocation). It's probably a zvt widget.
2390 * For 1), we could just go ahead and ask for the
2391 * new size right now, but doing that for 2)
2392 * might well be fighting the user (and can even
2393 * trigger a loop). Since we really don't want to
2394 * do that, we requeue a resize in hopes that
2395 * by the time it gets handled, the child has seen
2396 * the light and is willing to go along with the
2397 * new size. (this happens for the zvt widget, since
2398 * the size_allocate() above will have stored the
2399 * requisition corresponding to the new size in the
2402 * This doesn't buy us anything for 1), but it shouldn't
2403 * hurt us too badly, since it is what would have
2404 * happened if we had gotten the configure event before
2405 * the new size had been set.
2408 if (x != -1 && y != -1)
2411 gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
2413 gdk_window_move (GTK_WIDGET (window)->window, x, y);
2416 /* we have to preserve the values and flags that are used
2417 * for computation of default_size_changed and hints_changed
2420 info->last = saved_last_info;
2422 gtk_widget_queue_resize (widget);
2426 #endif /* FIXME_ZVT_ME_HARDER */
2429 /* Now set hints if necessary
2432 gdk_window_set_geometry_hints (widget->window,
2436 if ((default_size_changed || hints_changed) &&
2437 (width != new_width || height != new_height))
2439 /* given that (width != new_width || height != new_height), we are in one
2440 * of the following situations:
2442 * default_size_changed
2443 * our requisition has changed and we need a different window size,
2444 * so we request it from the window manager.
2446 * !default_size_changed
2447 * the window manager wouldn't assign us the size we requested, in this
2448 * case we don't try to request a new size with every resize.
2450 * !default_size_changed && hints_changed
2451 * the window manager rejects our size, but we have just changed the
2452 * window manager hints, so there's a certain chance our request will
2453 * be honoured this time, so we try again.
2456 /* request a new window size */
2457 if (x != -1 && y != -1)
2461 gdk_window_move_resize (window->frame,
2462 x - window->frame_left, y - window->frame_top,
2463 new_width + window->frame_left + window->frame_right,
2464 new_height + window->frame_top + window->frame_bottom);
2465 gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
2468 gdk_window_move_resize (GTK_WIDGET (window)->window, x, y, new_width, new_height);
2473 gdk_window_resize (window->frame,
2474 new_width + window->frame_left + window->frame_right,
2475 new_height + window->frame_top + window->frame_bottom);
2476 gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
2478 window->resize_count += 1;
2480 /* we are now awaiting the new configure event in response to our
2481 * resizing request. the configure event will cause a new resize
2482 * with ->handling_resize=TRUE.
2483 * until then, we want to
2484 * - discard expose events
2485 * - coalesce resizes for our children
2486 * - defer any window resizes until the configure event arrived
2487 * to achive this, we queue a resize for the window, but remove its
2488 * resizing handler, so resizing will not be handled from the next
2489 * idle handler but when the configure event arrives.
2491 * FIXME: we should also dequeue the pending redraws here, since
2492 * we handle those ourselves in ->handling_resize==TRUE.
2494 gtk_widget_queue_resize (GTK_WIDGET (container));
2495 if (container->resize_mode == GTK_RESIZE_QUEUE)
2496 gtk_container_dequeue_resize_handler (container);
2500 if (x != -1 && y != -1)
2503 gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
2505 gdk_window_move (widget->window, x, y);
2508 if (container->resize_widgets)
2509 gtk_container_resize_children (GTK_CONTAINER (window));
2513 /* Compare two sets of Geometry hints for equality.
2516 gtk_window_compare_hints (GdkGeometry *geometry_a,
2518 GdkGeometry *geometry_b,
2521 if (flags_a != flags_b)
2524 if ((flags_a & GDK_HINT_MIN_SIZE) &&
2525 (geometry_a->min_width != geometry_b->min_width ||
2526 geometry_a->min_height != geometry_b->min_height))
2529 if ((flags_a & GDK_HINT_MAX_SIZE) &&
2530 (geometry_a->max_width != geometry_b->max_width ||
2531 geometry_a->max_height != geometry_b->max_height))
2534 if ((flags_a & GDK_HINT_BASE_SIZE) &&
2535 (geometry_a->base_width != geometry_b->base_width ||
2536 geometry_a->base_height != geometry_b->base_height))
2539 if ((flags_a & GDK_HINT_ASPECT) &&
2540 (geometry_a->min_aspect != geometry_b->min_aspect ||
2541 geometry_a->max_aspect != geometry_b->max_aspect))
2544 if ((flags_a & GDK_HINT_RESIZE_INC) &&
2545 (geometry_a->width_inc != geometry_b->width_inc ||
2546 geometry_a->height_inc != geometry_b->height_inc))
2552 /* Compute the default_size for a window. The result will
2553 * be stored in *width and *height. The default size is
2554 * the size the window should have when initially mapped.
2555 * This routine does not attempt to constrain the size
2556 * to obey the geometry hints - that must be done elsewhere.
2559 gtk_window_compute_default_size (GtkWindow *window,
2563 GtkRequisition requisition;
2564 GtkWindowGeometryInfo *info;
2566 gtk_widget_get_child_requisition (GTK_WIDGET (window), &requisition);
2567 *width = requisition.width;
2568 *height = requisition.height;
2570 info = gtk_window_get_geometry_info (window, FALSE);
2572 if (*width == 0 && *height == 0)
2581 *width = info->width > 0 ? info->width : *width;
2582 *height = info->height > 0 ? info->height : *height;
2587 _gtk_window_constrain_size (GtkWindow *window,
2593 GtkWindowGeometryInfo *info = (GtkWindowGeometryInfo *)gtk_object_get_data (GTK_OBJECT (window), "gtk-window-geometry");
2597 GdkWindowHints flags = info->last.flags;
2598 GdkGeometry *geometry = &info->last.geometry;
2600 gtk_window_constrain_size (window,
2611 /* Constrain a window size to obey the hints passed in geometry
2612 * and flags. The result will be stored in *new_width and *new_height
2614 * This routine is partially borrowed from fvwm.
2616 * Copyright 1993, Robert Nation
2617 * You may use this code for any purpose, as long as the original
2618 * copyright remains in the source code and all documentation
2620 * which in turn borrows parts of the algorithm from uwm
2623 gtk_window_constrain_size (GtkWindow *window,
2624 GdkGeometry *geometry,
2632 gint min_height = 0;
2633 gint base_width = 0;
2634 gint base_height = 0;
2637 gint max_width = G_MAXINT;
2638 gint max_height = G_MAXINT;
2640 #define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
2642 if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
2644 base_width = geometry->base_width;
2645 base_height = geometry->base_height;
2646 min_width = geometry->min_width;
2647 min_height = geometry->min_height;
2649 else if (flags & GDK_HINT_BASE_SIZE)
2651 base_width = geometry->base_width;
2652 base_height = geometry->base_height;
2653 min_width = geometry->base_width;
2654 min_height = geometry->base_height;
2656 else if (flags & GDK_HINT_MIN_SIZE)
2658 base_width = geometry->min_width;
2659 base_height = geometry->min_height;
2660 min_width = geometry->min_width;
2661 min_height = geometry->min_height;
2664 if (flags & GDK_HINT_MAX_SIZE)
2666 max_width = geometry->max_width ;
2667 max_height = geometry->max_height;
2670 if (flags & GDK_HINT_RESIZE_INC)
2672 xinc = MAX (xinc, geometry->width_inc);
2673 yinc = MAX (yinc, geometry->height_inc);
2676 /* clamp width and height to min and max values
2678 width = CLAMP (width, min_width, max_width);
2679 height = CLAMP (height, min_height, max_height);
2681 /* shrink to base + N * inc
2683 width = base_width + FLOOR (width - base_width, xinc);
2684 height = base_height + FLOOR (height - base_height, yinc);
2686 /* constrain aspect ratio, according to:
2689 * min_aspect <= -------- <= max_aspect
2693 if (flags & GDK_HINT_ASPECT &&
2694 geometry->min_aspect > 0 &&
2695 geometry->max_aspect > 0)
2699 if (geometry->min_aspect * height > width)
2701 delta = FLOOR (height - width * geometry->min_aspect, yinc);
2702 if (height - delta >= min_height)
2706 delta = FLOOR (height * geometry->min_aspect - width, xinc);
2707 if (width + delta <= max_width)
2712 if (geometry->max_aspect * height < width)
2714 delta = FLOOR (width - height * geometry->max_aspect, xinc);
2715 if (width - delta >= min_width)
2719 delta = FLOOR (width / geometry->max_aspect - height, yinc);
2720 if (height + delta <= max_height)
2729 *new_height = height;
2732 /* Compute the set of geometry hints and flags for a window
2733 * based on the application set geometry, and requisiition
2734 * of the window. gtk_widget_size_request() must have been
2738 gtk_window_compute_hints (GtkWindow *window,
2739 GdkGeometry *new_geometry,
2743 GtkWidgetAuxInfo *aux_info;
2745 gint extra_width = 0;
2746 gint extra_height = 0;
2747 GtkWindowGeometryInfo *geometry_info;
2748 GtkRequisition requisition;
2750 g_return_if_fail (GTK_IS_WINDOW (window));
2752 widget = GTK_WIDGET (window);
2754 gtk_widget_get_child_requisition (widget, &requisition);
2755 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
2757 g_return_if_fail (geometry_info != NULL);
2759 *new_flags = geometry_info->mask;
2760 *new_geometry = geometry_info->geometry;
2762 if (geometry_info->widget)
2764 extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
2765 extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
2771 aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
2772 if (aux_info && (aux_info->x != -1) && (aux_info->y != -1))
2776 *new_flags |= GDK_HINT_POS;
2779 if (*new_flags & GDK_HINT_BASE_SIZE)
2781 new_geometry->base_width += extra_width;
2782 new_geometry->base_height += extra_height;
2784 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
2785 (*new_flags & GDK_HINT_RESIZE_INC) &&
2786 ((extra_width != 0) || (extra_height != 0)))
2788 *new_flags |= GDK_HINT_BASE_SIZE;
2790 new_geometry->base_width = extra_width;
2791 new_geometry->base_height = extra_height;
2794 if (*new_flags & GDK_HINT_MIN_SIZE)
2796 if (new_geometry->min_width < 0)
2797 new_geometry->min_width = requisition.width;
2799 new_geometry->min_width += extra_width;
2801 if (new_geometry->min_height < 0)
2802 new_geometry->min_width = requisition.height;
2804 new_geometry->min_height += extra_height;
2806 else if (!window->allow_shrink)
2808 *new_flags |= GDK_HINT_MIN_SIZE;
2810 new_geometry->min_width = requisition.width;
2811 new_geometry->min_height = requisition.height;
2814 if (*new_flags & GDK_HINT_MAX_SIZE)
2816 if (new_geometry->max_width < 0)
2817 new_geometry->max_width = requisition.width;
2819 new_geometry->max_width += extra_width;
2821 if (new_geometry->max_height < 0)
2822 new_geometry->max_width = requisition.height;
2824 new_geometry->max_height += extra_height;
2826 else if (!window->allow_grow)
2828 *new_flags |= GDK_HINT_MAX_SIZE;
2830 new_geometry->max_width = requisition.width;
2831 new_geometry->max_height = requisition.height;
2835 /* Compute a new position for the window based on a new
2836 * size. *x and *y will be set to the new coordinates, or to -1 if the
2837 * window does not need to be moved
2840 gtk_window_compute_reposition (GtkWindow *window,
2847 GtkWindowPosition pos;
2848 GtkWidget *parent_widget;
2850 widget = GTK_WIDGET (window);
2855 parent_widget = (GtkWidget*) window->transient_parent;
2857 pos = window->position;
2858 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
2859 (parent_widget == NULL ||
2860 !GTK_WIDGET_MAPPED (parent_widget)))
2861 pos = GTK_WIN_POS_NONE;
2865 case GTK_WIN_POS_CENTER:
2866 case GTK_WIN_POS_CENTER_ALWAYS:
2867 if (window->use_uposition)
2869 gint screen_width = gdk_screen_width ();
2870 gint screen_height = gdk_screen_height ();
2872 *x = (screen_width - new_width) / 2;
2873 *y = (screen_height - new_height) / 2;
2877 case GTK_WIN_POS_CENTER_ON_PARENT:
2878 if (window->use_uposition)
2881 gdk_window_get_origin (parent_widget->window,
2884 *x = ox + (parent_widget->allocation.width - new_width) / 2;
2885 *y = oy + (parent_widget->allocation.height - new_height) / 2;
2889 case GTK_WIN_POS_MOUSE:
2890 if (window->use_uposition)
2892 gint screen_width = gdk_screen_width ();
2893 gint screen_height = gdk_screen_height ();
2895 gdk_window_get_pointer (NULL, x, y, NULL);
2896 *x -= new_width / 2;
2897 *y -= new_height / 2;
2898 *x = CLAMP (*x, 0, screen_width - new_width);
2899 *y = CLAMP (*y, 0, screen_height - new_height);
2903 if (window->use_uposition)
2905 GtkWidgetAuxInfo *aux_info;
2907 aux_info = gtk_object_get_data (GTK_OBJECT (window), "gtk-aux-info");
2909 aux_info->x != -1 && aux_info->y != -1 &&
2910 aux_info->x != -2 && aux_info->y != -2)
2919 if (*x != -1 && *y != -1)
2921 GtkWidgetAuxInfo *aux_info;
2923 /* we handle necessary window positioning by hand here,
2924 * so we can coalesce the window movement with possible
2925 * resizes to get only one configure event.
2926 * keep this in sync with gtk_widget_set_uposition()
2927 * and gtk_window_reposition().
2929 gtk_widget_set_uposition (widget, -1, -1); /* ensure we have aux_info */
2931 aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
2935 window->use_uposition = FALSE;
2939 /***********************
2940 * Redrawing functions *
2941 ***********************/
2944 gtk_window_paint (GtkWidget *widget,
2947 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
2948 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
2952 gtk_window_expose (GtkWidget *widget,
2953 GdkEventExpose *event)
2955 g_return_val_if_fail (widget != NULL, FALSE);
2956 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2957 g_return_val_if_fail (event != NULL, FALSE);
2959 if (!GTK_WIDGET_APP_PAINTABLE (widget))
2960 gtk_window_paint (widget, &event->area);
2962 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
2963 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
2969 * gtk_window_set_has_frame:
2970 * @window: a #GtkWindow
2972 * If this function is called on a window before it is realized
2973 * or showed it will have a "frame" window around widget-window,
2974 * accessible in window->frame. Using the signal frame_event
2975 * you can recieve all events targeted at the frame.
2977 * This function is used by the linux-fb port to implement managed
2978 * windows, but it could concievably be used by X-programs that
2979 * want to do their own window decorations.
2982 gtk_window_set_has_frame (GtkWindow *window)
2984 g_return_if_fail (window != NULL);
2985 g_return_if_fail (GTK_IS_WINDOW (window));
2986 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
2988 window->has_frame = TRUE;
2992 * gtk_window_set_frame_dimensions:
2993 * @window: a #GtkWindow that has a frame
2994 * @left: The width of the left border
2995 * @top: The height of the top border
2996 * @right: The width of the right border
2997 * @bottom: The height of the bottom border
2999 * For windows with frames (see #gtk_window_set_has_frame) this function
3000 * can be used to change the size of the frame border.
3003 gtk_window_set_frame_dimensions (GtkWindow *window,
3009 GtkWidget *widget = GTK_WIDGET (window);
3011 g_return_if_fail (window != NULL);
3012 g_return_if_fail (GTK_IS_WINDOW (window));
3014 if (window->frame_left == left &&
3015 window->frame_top == top &&
3016 window->frame_right == right &&
3017 window->frame_bottom == bottom)
3020 window->frame_left = left;
3021 window->frame_top = top;
3022 window->frame_right = right;
3023 window->frame_bottom = bottom;
3025 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3027 gint width = widget->allocation.width + left + right;
3028 gint height = widget->allocation.height + top + bottom;
3029 gdk_window_resize (window->frame, width, height);
3030 gtk_decorated_window_move_resize_window (window,
3032 widget->allocation.width,
3033 widget->allocation.height);
3040 * gtk_window_present:
3041 * @window: a #GtkWindow
3043 * Presents a window to the user. This may mean raising the window
3044 * in the stacking order, deiconifying it, moving it to the current
3045 * desktop, and/or giving it the keyboard focus, possibly dependent
3046 * on the user's platform, window manager, and preferences.
3048 * If @window is hidden, this function calls gtk_widget_show()
3051 * This function should be used when the user tries to open a window
3052 * that's already open. Say for example the preferences dialog is
3053 * currently open, and the user chooses Preferences from the menu
3054 * a second time; use gtk_window_present() to move the already-open dialog
3055 * where the user can see it.
3059 gtk_window_present (GtkWindow *window)
3063 g_return_if_fail (GTK_IS_WINDOW (window));
3065 widget = GTK_WIDGET (window);
3067 if (GTK_WIDGET_VISIBLE (window))
3069 g_assert (widget->window != NULL);
3071 gdk_window_show (widget->window);
3073 /* note that gdk_window_focus() will also move the window to
3074 * the current desktop, for WM spec compliant window managers.
3076 gdk_window_focus (widget->window,
3077 gtk_get_current_event_time ());
3081 gtk_widget_show (widget);
3086 * gtk_window_iconify:
3087 * @window: a #GtkWindow
3089 * Asks to iconify @window. Note that you shouldn't assume the window
3090 * is definitely iconified afterward, because other entities (e.g. the
3091 * user or window manager) could deiconify it again, or there may not
3092 * be a window manager in which case iconification isn't possible,
3093 * etc. But normally the window will end up iconified. Just don't write
3094 * code that crashes if not.
3096 * It's permitted to call this function before showing a window,
3097 * in which case the window will be iconified before it ever appears
3100 * You can track iconification via the "window_state_event" signal
3105 gtk_window_iconify (GtkWindow *window)
3108 GdkWindow *toplevel;
3110 g_return_if_fail (GTK_IS_WINDOW (window));
3112 widget = GTK_WIDGET (window);
3114 window->iconify_initially = TRUE;
3117 toplevel = window->frame;
3119 toplevel = widget->window;
3121 if (toplevel != NULL)
3122 gdk_window_iconify (toplevel);
3126 * gtk_window_deiconify:
3127 * @window: a #GtkWindow
3129 * Asks to deiconify @window. Note that you shouldn't assume the
3130 * window is definitely deiconified afterward, because other entities
3131 * (e.g. the user or window manager) could iconify it again before
3132 * your code which assumes deiconification gets to run.
3134 * You can track iconification via the "window_state_event" signal
3138 gtk_window_deiconify (GtkWindow *window)
3141 GdkWindow *toplevel;
3143 g_return_if_fail (GTK_IS_WINDOW (window));
3145 widget = GTK_WIDGET (window);
3147 window->iconify_initially = FALSE;
3150 toplevel = window->frame;
3152 toplevel = widget->window;
3154 if (toplevel != NULL)
3155 gdk_window_deiconify (toplevel);
3160 * @window: a #GtkWindow
3162 * Asks to stick @window, which means that it will appear on all user
3163 * desktops. Note that you shouldn't assume the window is definitely
3164 * stuck afterward, because other entities (e.g. the user or window
3165 * manager) could unstick it again, and some window managers do not
3166 * support sticking windows. But normally the window will end up
3167 * stuck. Just don't write code that crashes if not.
3169 * It's permitted to call this function before showing a window.
3171 * You can track stickiness via the "window_state_event" signal
3176 gtk_window_stick (GtkWindow *window)
3179 GdkWindow *toplevel;
3181 g_return_if_fail (GTK_IS_WINDOW (window));
3183 widget = GTK_WIDGET (window);
3185 window->stick_initially = TRUE;
3188 toplevel = window->frame;
3190 toplevel = widget->window;
3192 if (toplevel != NULL)
3193 gdk_window_stick (toplevel);
3197 * gtk_window_unstick:
3198 * @window: a #GtkWindow
3200 * Asks to unstick @window, which means that it will appear on only
3201 * one of the user's desktops. Note that you shouldn't assume the
3202 * window is definitely unstuck afterward, because other entities
3203 * (e.g. the user or window manager) could stick it again. But
3204 * normally the window will end up stuck. Just don't write code that
3207 * You can track stickiness via the "window_state_event" signal
3212 gtk_window_unstick (GtkWindow *window)
3215 GdkWindow *toplevel;
3217 g_return_if_fail (GTK_IS_WINDOW (window));
3219 widget = GTK_WIDGET (window);
3221 window->stick_initially = FALSE;
3224 toplevel = window->frame;
3226 toplevel = widget->window;
3228 if (toplevel != NULL)
3229 gdk_window_unstick (toplevel);
3233 * gtk_window_maximize:
3234 * @window: a #GtkWindow
3236 * Asks to maximize @window, so that it becomes full-screen. Note that
3237 * you shouldn't assume the window is definitely maximized afterward,
3238 * because other entities (e.g. the user or window manager) could
3239 * unmaximize it again, and not all window managers support
3240 * maximization. But normally the window will end up maximized. Just
3241 * don't write code that crashes if not.
3243 * It's permitted to call this function before showing a window,
3244 * in which case the window will be maximized when it appears onscreen
3247 * You can track maximization via the "window_state_event" signal
3252 gtk_window_maximize (GtkWindow *window)
3255 GdkWindow *toplevel;
3257 g_return_if_fail (GTK_IS_WINDOW (window));
3259 widget = GTK_WIDGET (window);
3261 window->maximize_initially = TRUE;
3264 toplevel = window->frame;
3266 toplevel = widget->window;
3268 if (toplevel != NULL)
3269 gdk_window_maximize (toplevel);
3273 * gtk_window_unmaximize:
3274 * @window: a #GtkWindow
3276 * Asks to unmaximize @window. Note that you shouldn't assume the
3277 * window is definitely unmaximized afterward, because other entities
3278 * (e.g. the user or window manager) could maximize it again, and not
3279 * all window managers honor requests to unmaximize. But normally the
3280 * window will end up unmaximized. Just don't write code that crashes
3283 * You can track maximization via the "window_state_event" signal
3288 gtk_window_unmaximize (GtkWindow *window)
3291 GdkWindow *toplevel;
3293 g_return_if_fail (GTK_IS_WINDOW (window));
3295 widget = GTK_WIDGET (window);
3297 window->maximize_initially = FALSE;
3300 toplevel = window->frame;
3302 toplevel = widget->window;
3304 if (toplevel != NULL)
3305 gdk_window_unmaximize (toplevel);