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"
51 /* TODO: remove this define and assorted code in 1.3 and fix up the
54 #define FIXME_ZVT_ME_HARDER
73 ARG_DESTROY_WITH_PARENT
77 GdkGeometry geometry; /* Last set of geometry hints we set */
81 } GtkWindowLastGeometryInfo;
84 /* Properties that the app has set on the window
86 GdkGeometry geometry; /* Geometry hints */
88 GtkWidget *widget; /* subwidget to which hints apply */
89 gint width; /* Default size */
92 GtkWindowLastGeometryInfo last;
93 } GtkWindowGeometryInfo;
95 static void gtk_window_class_init (GtkWindowClass *klass);
96 static void gtk_window_init (GtkWindow *window);
97 static void gtk_window_set_arg (GtkObject *object,
100 static void gtk_window_get_arg (GtkObject *object,
103 static void gtk_window_shutdown (GObject *object);
104 static void gtk_window_destroy (GtkObject *object);
105 static void gtk_window_finalize (GObject *object);
106 static void gtk_window_show (GtkWidget *widget);
107 static void gtk_window_hide (GtkWidget *widget);
108 static void gtk_window_map (GtkWidget *widget);
109 static void gtk_window_unmap (GtkWidget *widget);
110 static void gtk_window_realize (GtkWidget *widget);
111 static void gtk_window_unrealize (GtkWidget *widget);
112 static void gtk_window_size_request (GtkWidget *widget,
113 GtkRequisition *requisition);
114 static void gtk_window_size_allocate (GtkWidget *widget,
115 GtkAllocation *allocation);
116 static gint gtk_window_event (GtkWidget *widget,
118 static gboolean gtk_window_frame_event (GtkWidget *widget,
120 static gint gtk_window_configure_event (GtkWidget *widget,
121 GdkEventConfigure *event);
122 static gint gtk_window_key_press_event (GtkWidget *widget,
124 static gint gtk_window_key_release_event (GtkWidget *widget,
126 static gint gtk_window_enter_notify_event (GtkWidget *widget,
127 GdkEventCrossing *event);
128 static gint gtk_window_leave_notify_event (GtkWidget *widget,
129 GdkEventCrossing *event);
130 static gint gtk_window_focus_in_event (GtkWidget *widget,
131 GdkEventFocus *event);
132 static gint gtk_window_focus_out_event (GtkWidget *widget,
133 GdkEventFocus *event);
134 static gint gtk_window_client_event (GtkWidget *widget,
135 GdkEventClient *event);
136 static void gtk_window_check_resize (GtkContainer *container);
137 static gint gtk_window_focus (GtkContainer *container,
138 GtkDirectionType direction);
139 static void gtk_window_real_set_focus (GtkWindow *window,
142 static void gtk_window_move_resize (GtkWindow *window);
143 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
145 GdkGeometry *geometry_b,
147 static void gtk_window_compute_default_size (GtkWindow *window,
150 static void gtk_window_constrain_size (GtkWindow *window,
151 GdkGeometry *geometry,
157 static void gtk_window_compute_hints (GtkWindow *window,
158 GdkGeometry *new_geometry,
160 static void gtk_window_compute_reposition (GtkWindow *window,
166 static void gtk_window_read_rcfiles (GtkWidget *widget,
167 GdkEventClient *event);
168 static void gtk_window_paint (GtkWidget *widget,
170 static gint gtk_window_expose (GtkWidget *widget,
171 GdkEventExpose *event);
172 static void gtk_window_unset_transient_for (GtkWindow *window);
173 static void gtk_window_transient_parent_realized (GtkWidget *parent,
175 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
178 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
180 static void gtk_window_geometry_destroy (GtkWindowGeometryInfo *info);
183 static GSList *toplevel_list = NULL;
184 static GtkBinClass *parent_class = NULL;
185 static guint window_signals[LAST_SIGNAL] = { 0 };
189 gtk_window_get_type (void)
191 static GtkType window_type = 0;
195 static const GtkTypeInfo window_info =
199 sizeof (GtkWindowClass),
200 (GtkClassInitFunc) gtk_window_class_init,
201 (GtkObjectInitFunc) gtk_window_init,
202 /* reserved_1 */ NULL,
203 /* reserved_2 */ NULL,
204 (GtkClassInitFunc) NULL,
207 window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
214 gtk_window_class_init (GtkWindowClass *klass)
216 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
217 GtkObjectClass *object_class;
218 GtkWidgetClass *widget_class;
219 GtkContainerClass *container_class;
221 object_class = (GtkObjectClass*) klass;
222 widget_class = (GtkWidgetClass*) klass;
223 container_class = (GtkContainerClass*) klass;
225 parent_class = gtk_type_class (gtk_bin_get_type ());
227 gobject_class->shutdown = gtk_window_shutdown;
228 gobject_class->finalize = gtk_window_finalize;
230 object_class->set_arg = gtk_window_set_arg;
231 object_class->get_arg = gtk_window_get_arg;
232 object_class->destroy = gtk_window_destroy;
234 widget_class->show = gtk_window_show;
235 widget_class->hide = gtk_window_hide;
236 widget_class->map = gtk_window_map;
237 widget_class->unmap = gtk_window_unmap;
238 widget_class->realize = gtk_window_realize;
239 widget_class->unrealize = gtk_window_unrealize;
240 widget_class->size_request = gtk_window_size_request;
241 widget_class->size_allocate = gtk_window_size_allocate;
242 widget_class->configure_event = gtk_window_configure_event;
243 widget_class->key_press_event = gtk_window_key_press_event;
244 widget_class->key_release_event = gtk_window_key_release_event;
245 widget_class->enter_notify_event = gtk_window_enter_notify_event;
246 widget_class->leave_notify_event = gtk_window_leave_notify_event;
247 widget_class->focus_in_event = gtk_window_focus_in_event;
248 widget_class->focus_out_event = gtk_window_focus_out_event;
249 widget_class->client_event = gtk_window_client_event;
251 widget_class->expose_event = gtk_window_expose;
253 container_class->check_resize = gtk_window_check_resize;
254 container_class->focus = gtk_window_focus;
256 klass->set_focus = gtk_window_real_set_focus;
257 klass->frame_event = gtk_window_frame_event;
259 gtk_object_add_arg_type ("GtkWindow::type", GTK_TYPE_WINDOW_TYPE, GTK_ARG_READWRITE, ARG_TYPE);
260 gtk_object_add_arg_type ("GtkWindow::title", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_TITLE);
261 gtk_object_add_arg_type ("GtkWindow::auto_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_AUTO_SHRINK);
262 gtk_object_add_arg_type ("GtkWindow::allow_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_SHRINK);
263 gtk_object_add_arg_type ("GtkWindow::allow_grow", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_GROW);
264 gtk_object_add_arg_type ("GtkWindow::modal", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_MODAL);
265 gtk_object_add_arg_type ("GtkWindow::window_position", GTK_TYPE_WINDOW_POSITION, GTK_ARG_READWRITE, ARG_WIN_POS);
266 gtk_object_add_arg_type ("GtkWindow::default_width", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_DEFAULT_WIDTH);
267 gtk_object_add_arg_type ("GtkWindow::default_height", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_DEFAULT_HEIGHT);
268 gtk_object_add_arg_type ("GtkWindow::destroy_with_parent", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_DESTROY_WITH_PARENT);
270 window_signals[SET_FOCUS] =
271 gtk_signal_new ("set_focus",
273 GTK_CLASS_TYPE (object_class),
274 GTK_SIGNAL_OFFSET (GtkWindowClass, set_focus),
275 gtk_marshal_VOID__POINTER,
279 window_signals[FRAME_EVENT] =
280 gtk_signal_new ("frame_event",
282 GTK_CLASS_TYPE (object_class),
283 GTK_SIGNAL_OFFSET (GtkWindowClass, frame_event),
284 gtk_marshal_BOOLEAN__POINTER,
290 gtk_window_init (GtkWindow *window)
292 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
293 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
295 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
297 window->title = NULL;
298 window->wmclass_name = g_strdup (g_get_prgname ());
299 window->wmclass_class = g_strdup (gdk_progclass);
300 window->type = GTK_WINDOW_TOPLEVEL;
301 window->focus_widget = NULL;
302 window->default_widget = NULL;
303 window->resize_count = 0;
304 window->allow_shrink = FALSE;
305 window->allow_grow = TRUE;
306 window->auto_shrink = FALSE;
307 window->handling_resize = FALSE;
308 window->position = GTK_WIN_POS_NONE;
309 window->use_uposition = TRUE;
310 window->modal = FALSE;
311 window->frame = NULL;
312 window->has_frame = FALSE;
313 window->frame_left = 0;
314 window->frame_right = 0;
315 window->frame_top = 0;
316 window->frame_bottom = 0;
318 gtk_widget_ref (GTK_WIDGET (window));
319 gtk_object_sink (GTK_OBJECT (window));
320 window->has_user_ref_count = TRUE;
321 toplevel_list = g_slist_prepend (toplevel_list, window);
323 gtk_decorated_window_init (window);
325 gtk_signal_connect (GTK_OBJECT (window),
327 GTK_SIGNAL_FUNC (gtk_window_event),
332 gtk_window_set_arg (GtkObject *object,
338 window = GTK_WINDOW (object);
343 window->type = GTK_VALUE_ENUM (*arg);
346 gtk_window_set_title (window, GTK_VALUE_STRING (*arg));
348 case ARG_AUTO_SHRINK:
349 window->auto_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
350 gtk_widget_queue_resize (GTK_WIDGET (window));
352 case ARG_ALLOW_SHRINK:
353 window->allow_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
354 gtk_widget_queue_resize (GTK_WIDGET (window));
357 window->allow_grow = (GTK_VALUE_BOOL (*arg) != FALSE);
358 gtk_widget_queue_resize (GTK_WIDGET (window));
361 gtk_window_set_modal (window, GTK_VALUE_BOOL (*arg));
364 gtk_window_set_position (window, GTK_VALUE_ENUM (*arg));
366 case ARG_DEFAULT_WIDTH:
367 gtk_window_set_default_size (window, GTK_VALUE_INT (*arg), -2);
369 case ARG_DEFAULT_HEIGHT:
370 gtk_window_set_default_size (window, -2, GTK_VALUE_INT (*arg));
372 case ARG_DESTROY_WITH_PARENT:
373 gtk_window_set_destroy_with_parent (window, GTK_VALUE_BOOL (*arg));
381 gtk_window_get_arg (GtkObject *object,
387 window = GTK_WINDOW (object);
391 GtkWindowGeometryInfo *info;
393 GTK_VALUE_ENUM (*arg) = window->type;
396 GTK_VALUE_STRING (*arg) = g_strdup (window->title);
398 case ARG_AUTO_SHRINK:
399 GTK_VALUE_BOOL (*arg) = window->auto_shrink;
401 case ARG_ALLOW_SHRINK:
402 GTK_VALUE_BOOL (*arg) = window->allow_shrink;
405 GTK_VALUE_BOOL (*arg) = window->allow_grow;
408 GTK_VALUE_BOOL (*arg) = window->modal;
411 GTK_VALUE_ENUM (*arg) = window->position;
413 case ARG_DEFAULT_WIDTH:
414 info = gtk_window_get_geometry_info (window, FALSE);
416 GTK_VALUE_INT (*arg) = -1;
418 GTK_VALUE_INT (*arg) = info->width;
420 case ARG_DEFAULT_HEIGHT:
421 info = gtk_window_get_geometry_info (window, FALSE);
423 GTK_VALUE_INT (*arg) = -1;
425 GTK_VALUE_INT (*arg) = info->height;
427 case ARG_DESTROY_WITH_PARENT:
428 GTK_VALUE_BOOL (*arg) = window->destroy_with_parent;
431 arg->type = GTK_TYPE_INVALID;
438 * @type: type of window
440 * Creates a new #GtkWindow, which is a toplevel window that can
441 * contain other widgets. Nearly always, the type of the window should
442 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
443 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
444 * you might use #GTK_WINDOW_TOPLEVEL. #GTK_WINDOW_DIALOG is not
445 * useful; dialogs should be of type #GTK_WINDOW_TOPLEVEL. (Probably
446 * you want to use the #GtkDialog widget for dialogs anyway).
448 * Return value: a new #GtkWindow.
451 gtk_window_new (GtkWindowType type)
455 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
457 window = gtk_type_new (GTK_TYPE_WINDOW);
461 return GTK_WIDGET (window);
465 * gtk_window_set_title:
466 * @window: a #GtkWindow
467 * @title: title of the window
469 * Sets the title of the #GtkWindow. The title of a window will be displayed in
470 * its title bar; on the X Window System, the title bar is rendered by the
471 * window manager, so exactly how the title appears to users may vary according
472 * to a user's exact configuration. The title should help a user distinguish
473 * this window from other windows they may have open. A good title might
474 * include the application name and current document filename, for example.
478 gtk_window_set_title (GtkWindow *window,
481 g_return_if_fail (window != NULL);
482 g_return_if_fail (GTK_IS_WINDOW (window));
485 g_free (window->title);
486 window->title = g_strdup (title);
488 if (GTK_WIDGET_REALIZED (window))
490 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
492 gtk_decorated_window_set_title (window, title);
497 * gtk_window_set_wmclass:
498 * @window: a #GtkWindow
499 * @wmclass_name: window name hint
500 * @wmclass_class: window class hint
502 * This function sets the X Window System "class" and "name" hints for a window.
503 * According to the ICCCM, you should always set these to the same value for
504 * all windows in an application, and GTK sets them to that value by default,
505 * so calling this function is sort of pointless. However, you may want to
506 * call gtk_window_set_role() on each window in your application, for the
507 * benefit of the session manager. Setting the role allows the window manager
508 * to restore window positions when loading a saved session.
512 gtk_window_set_wmclass (GtkWindow *window,
513 const gchar *wmclass_name,
514 const gchar *wmclass_class)
516 g_return_if_fail (window != NULL);
517 g_return_if_fail (GTK_IS_WINDOW (window));
519 g_free (window->wmclass_name);
520 window->wmclass_name = g_strdup (wmclass_name);
522 g_free (window->wmclass_class);
523 window->wmclass_class = g_strdup (wmclass_class);
525 if (GTK_WIDGET_REALIZED (window))
526 g_warning ("shouldn't set wmclass after window is realized!\n");
530 * gtk_window_set_focus:
531 * @window: a #GtkWindow
532 * @focus: widget to be the new focus widget
534 * If @focus is not the current focus widget, and is focusable, emits
535 * the "set_focus" signal to set @focus as the focus widget for the
536 * window. This function is more or less GTK-internal; to focus an
537 * entry widget or the like, you should use gtk_widget_grab_focus()
538 * instead of this function.
542 gtk_window_set_focus (GtkWindow *window,
545 g_return_if_fail (window != NULL);
546 g_return_if_fail (GTK_IS_WINDOW (window));
549 g_return_if_fail (GTK_IS_WIDGET (focus));
550 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
553 if ((window->focus_widget != focus) ||
554 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
555 gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
559 * gtk_window_set_default:
560 * @window: a #GtkWindow
561 * @default_widget: widget to be the default
563 * The default widget is the widget that's activated when the user
564 * presses Enter in a dialog (for example). This function tells a
565 * #GtkWindow about the current default widget; it's really a GTK
566 * internal function and you shouldn't need it. Instead, to change the
567 * default widget, first set the #GTK_CAN_DEFAULT flag on the widget
568 * you'd like to make the default using GTK_WIDGET_SET_FLAGS(), then
569 * call gtk_widget_grab_default() to move the default.
573 gtk_window_set_default (GtkWindow *window,
574 GtkWidget *default_widget)
576 g_return_if_fail (window != NULL);
577 g_return_if_fail (GTK_IS_WINDOW (window));
580 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
582 if (window->default_widget != default_widget)
584 if (window->default_widget)
586 if (window->focus_widget != window->default_widget ||
587 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
588 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
589 gtk_widget_queue_draw (window->default_widget);
592 window->default_widget = default_widget;
594 if (window->default_widget)
596 if (window->focus_widget == NULL ||
597 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
598 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
599 gtk_widget_queue_draw (window->default_widget);
605 gtk_window_set_policy (GtkWindow *window,
610 g_return_if_fail (window != NULL);
611 g_return_if_fail (GTK_IS_WINDOW (window));
613 window->allow_shrink = (allow_shrink != FALSE);
614 window->allow_grow = (allow_grow != FALSE);
615 window->auto_shrink = (auto_shrink != FALSE);
617 gtk_widget_queue_resize (GTK_WIDGET (window));
621 gtk_window_add_accel_group (GtkWindow *window,
622 GtkAccelGroup *accel_group)
624 g_return_if_fail (window != NULL);
625 g_return_if_fail (GTK_IS_WINDOW (window));
626 g_return_if_fail (accel_group != NULL);
628 gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
632 gtk_window_remove_accel_group (GtkWindow *window,
633 GtkAccelGroup *accel_group)
635 g_return_if_fail (window != NULL);
636 g_return_if_fail (GTK_IS_WINDOW (window));
637 g_return_if_fail (accel_group != NULL);
639 gtk_accel_group_detach (accel_group, GTK_OBJECT (window));
643 gtk_window_get_default_accel_group (GtkWindow *window)
645 GtkAccelGroup *group;
647 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
649 group = gtk_object_get_data (GTK_OBJECT (window),
654 group = gtk_accel_group_new ();
655 gtk_window_add_accel_group (window, group);
656 gtk_object_set_data (GTK_OBJECT (window),
659 gtk_accel_group_unref (group);
666 gtk_window_set_position (GtkWindow *window,
667 GtkWindowPosition position)
669 g_return_if_fail (window != NULL);
670 g_return_if_fail (GTK_IS_WINDOW (window));
672 window->position = position;
676 gtk_window_activate_focus (GtkWindow *window)
678 g_return_val_if_fail (window != NULL, FALSE);
679 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
681 if (window->focus_widget)
683 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
684 gtk_widget_activate (window->focus_widget);
692 gtk_window_activate_default (GtkWindow *window)
694 g_return_val_if_fail (window != NULL, FALSE);
695 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
697 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget))
699 gtk_widget_activate (window->default_widget);
707 * gtk_window_set_modal:
708 * @window: a #GtkWindow
709 * @modal: whether the window is modal
711 * Sets a window modal or non-modal. Modal windows prevent interaction
712 * with other windows in the same application. To keep modal dialogs
713 * on top of main application windows, use
714 * gtk_window_set_transient_for() to make the dialog transient for the
715 * parent; most window managers will then disallow lowering the dialog
721 gtk_window_set_modal (GtkWindow *window,
724 g_return_if_fail (window != NULL);
725 g_return_if_fail (GTK_IS_WINDOW (window));
727 window->modal = modal != FALSE;
729 /* adjust desired modality state */
730 if (GTK_WIDGET_VISIBLE (window) && window->modal)
731 gtk_grab_add (GTK_WIDGET (window));
733 gtk_grab_remove (GTK_WIDGET (window));
737 * gtk_window_list_toplevels:
739 * Returns a list of all existing toplevel windows. Each widget
740 * in the list has a reference added to it; to free the
741 * list, first unref each widget in the list, then free the list.
743 * Return value: list of referenced toplevel widgets
746 gtk_window_list_toplevels (void)
751 for (slist = toplevel_list; slist; slist = slist->next)
752 list = g_list_prepend (list, gtk_widget_ref (slist->data));
758 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
760 GList *embedded_windows;
762 g_return_if_fail (window != NULL);
763 g_return_if_fail (GTK_IS_WINDOW (window));
765 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
766 if (embedded_windows)
767 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
768 g_quark_from_static_string ("gtk-embedded"));
769 embedded_windows = g_list_prepend (embedded_windows,
770 GUINT_TO_POINTER (xid));
772 gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
775 (GtkDestroyNotify) g_list_free : NULL);
779 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
781 GList *embedded_windows;
784 g_return_if_fail (window != NULL);
785 g_return_if_fail (GTK_IS_WINDOW (window));
787 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
788 if (embedded_windows)
789 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
790 g_quark_from_static_string ("gtk-embedded"));
792 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
795 embedded_windows = g_list_remove_link (embedded_windows, node);
796 g_list_free_1 (node);
799 gtk_object_set_data_full (GTK_OBJECT (window),
800 "gtk-embedded", embedded_windows,
802 (GtkDestroyNotify) g_list_free : NULL);
806 gtk_window_reposition (GtkWindow *window,
810 GtkWindowGeometryInfo *info;
812 g_return_if_fail (window != NULL);
813 g_return_if_fail (GTK_IS_WINDOW (window));
815 /* keep this in sync with gtk_window_compute_reposition()
817 if (GTK_WIDGET_REALIZED (window))
819 info = gtk_window_get_geometry_info (window, TRUE);
821 if (!(info->last.flags & GDK_HINT_POS))
823 info->last.flags |= GDK_HINT_POS;
824 gdk_window_set_geometry_hints (GTK_WIDGET (window)->window,
825 &info->last.geometry,
830 gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
832 gdk_window_move (GTK_WIDGET (window)->window, x, y);
837 gtk_window_shutdown (GObject *object)
841 g_return_if_fail (GTK_IS_WINDOW (object));
843 window = GTK_WINDOW (object);
845 gtk_window_set_focus (window, NULL);
846 gtk_window_set_default (window, NULL);
848 G_OBJECT_CLASS (parent_class)->shutdown (object);
852 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
854 gtk_widget_destroy (GTK_WIDGET (child));
858 connect_parent_destroyed (GtkWindow *window)
860 if (window->transient_parent)
862 gtk_signal_connect (GTK_OBJECT (window->transient_parent),
864 GTK_SIGNAL_FUNC (parent_destroyed_callback),
870 disconnect_parent_destroyed (GtkWindow *window)
872 if (window->transient_parent)
874 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
875 GTK_SIGNAL_FUNC (parent_destroyed_callback),
881 gtk_window_transient_parent_realized (GtkWidget *parent,
884 if (GTK_WIDGET_REALIZED (window))
885 gdk_window_set_transient_for (window->window, parent->window);
889 gtk_window_transient_parent_unrealized (GtkWidget *parent,
892 if (GTK_WIDGET_REALIZED (window))
893 gdk_property_delete (window->window,
894 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
898 gtk_window_unset_transient_for (GtkWindow *window)
900 if (window->transient_parent)
902 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
903 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
905 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
906 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
908 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
909 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
910 &window->transient_parent);
912 if (window->destroy_with_parent)
913 disconnect_parent_destroyed (window);
915 window->transient_parent = NULL;
920 * gtk_window_set_transient_for:
921 * @window: a #GtkWindow
922 * @parent: parent window
924 * Dialog windows should be set transient for the main application
925 * window they were spawned from. This allows window managers to
926 * e.g. keep the dialog on top of the main window, or center the
927 * dialog over the main window. gtk_dialog_new_with_buttons() and
928 * other convenience functions in GTK+ will sometimes call
929 * gtk_window_set_transient_for() on yoru behalf.
933 gtk_window_set_transient_for (GtkWindow *window,
936 g_return_if_fail (GTK_IS_WINDOW (window));
937 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
938 g_return_if_fail (window != parent);
941 if (window->transient_parent)
943 if (GTK_WIDGET_REALIZED (window) &&
944 GTK_WIDGET_REALIZED (window->transient_parent) &&
945 (!parent || !GTK_WIDGET_REALIZED (parent)))
946 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
947 GTK_WIDGET (window));
949 gtk_window_unset_transient_for (window);
952 window->transient_parent = parent;
956 gtk_signal_connect (GTK_OBJECT (parent), "destroy",
957 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
958 &window->transient_parent);
959 gtk_signal_connect (GTK_OBJECT (parent), "realize",
960 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
962 gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
963 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
966 if (window->destroy_with_parent)
967 connect_parent_destroyed (window);
969 if (GTK_WIDGET_REALIZED (window) &&
970 GTK_WIDGET_REALIZED (parent))
971 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
972 GTK_WIDGET (window));
977 * gtk_window_set_destroy_with_parent:
978 * @window: a #GtkWindow
979 * @setting: whether to destroy @window with its transient parent
981 * If @setting is TRUE, then destroying the transient parent of @window
982 * will also destroy @window itself. This is useful for dialogs that
983 * shouldn't persist beyond the lifetime of the main window they're
984 * associated with, for example.
987 gtk_window_set_destroy_with_parent (GtkWindow *window,
990 g_return_if_fail (GTK_IS_WINDOW (window));
992 if (window->destroy_with_parent == (setting != FALSE))
995 if (window->destroy_with_parent)
997 disconnect_parent_destroyed (window);
1001 connect_parent_destroyed (window);
1004 window->destroy_with_parent = setting;
1008 gtk_window_geometry_destroy (GtkWindowGeometryInfo *info)
1011 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1012 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1017 static GtkWindowGeometryInfo*
1018 gtk_window_get_geometry_info (GtkWindow *window,
1021 GtkWindowGeometryInfo *info;
1023 info = gtk_object_get_data (GTK_OBJECT (window), "gtk-window-geometry");
1025 if (!info && create)
1027 info = g_new0 (GtkWindowGeometryInfo, 1);
1031 info->last.width = -1;
1032 info->last.height = -1;
1033 info->widget = NULL;
1036 gtk_object_set_data_full (GTK_OBJECT (window),
1037 "gtk-window-geometry",
1039 (GtkDestroyNotify) gtk_window_geometry_destroy);
1046 * gtk_window_set_geometry_hints:
1047 * @window: a #GdkWindow
1048 * @geometry_widget: widget the geometry hints will be applied to
1049 * @geometry: struct containing geometry information
1050 * @geom_mask: mask indicating which struct fields should be paid attention to
1052 * This function sets up hints about how a window can be resized by
1053 * the user. You can set a minimum and maximum size; allowed resize
1054 * increments (e.g. for xterm, you can only resize by the size of a
1055 * character); aspect ratios; and more. See the #GdkGeometry struct.
1059 gtk_window_set_geometry_hints (GtkWindow *window,
1060 GtkWidget *geometry_widget,
1061 GdkGeometry *geometry,
1062 GdkWindowHints geom_mask)
1064 GtkWindowGeometryInfo *info;
1066 g_return_if_fail (window != NULL);
1068 info = gtk_window_get_geometry_info (window, TRUE);
1071 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1072 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1075 info->widget = geometry_widget;
1077 gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
1078 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1082 info->geometry = *geometry;
1084 info->mask = geom_mask;
1086 gtk_widget_queue_resize (GTK_WIDGET (window));
1090 * gtk_window_set_default_size:
1091 * @window: a #GtkWindow
1092 * @width: width in pixels, or -1 to leave the default width unchanged
1093 * @height: height in pixels, or -1 to leave the default height unchanged
1095 * Sets the default size of a window. If the window's "natural" size
1096 * (its size request) is larger than the default, the default will be
1097 * ignored. So the default size is a minimum initial size. Unlike
1098 * gtk_widget_set_usize(), which sets a size request for a widget and
1099 * thus would keep users from shrinking the window, this function only
1100 * sets the initial size, just as if the user had resized the window
1101 * themselves. Users can still shrink the window again as they
1104 * For more control over a window's initial size and how resizing works,
1105 * investigate gtk_window_set_geometry_hints().
1109 gtk_window_set_default_size (GtkWindow *window,
1113 GtkWindowGeometryInfo *info;
1115 g_return_if_fail (GTK_IS_WINDOW (window));
1117 info = gtk_window_get_geometry_info (window, TRUE);
1120 info->width = width;
1122 info->height = height;
1124 gtk_widget_queue_resize (GTK_WIDGET (window));
1128 gtk_window_destroy (GtkObject *object)
1132 g_return_if_fail (GTK_IS_WINDOW (object));
1134 window = GTK_WINDOW (object);
1136 if (window->transient_parent)
1137 gtk_window_set_transient_for (window, NULL);
1139 if (window->has_user_ref_count)
1141 window->has_user_ref_count = FALSE;
1142 gtk_widget_unref (GTK_WIDGET (window));
1145 GTK_OBJECT_CLASS (parent_class)->destroy (object);
1149 gtk_window_finalize (GObject *object)
1153 g_return_if_fail (GTK_IS_WINDOW (object));
1155 window = GTK_WINDOW (object);
1157 toplevel_list = g_slist_remove (toplevel_list, window);
1159 g_free (window->title);
1160 g_free (window->wmclass_name);
1161 g_free (window->wmclass_class);
1163 G_OBJECT_CLASS(parent_class)->finalize (object);
1167 gtk_window_show (GtkWidget *widget)
1169 GtkWindow *window = GTK_WINDOW (widget);
1170 GtkContainer *container = GTK_CONTAINER (window);
1171 gboolean need_resize;
1172 gboolean was_realized;
1174 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
1176 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
1177 container->need_resize = FALSE;
1181 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
1182 GtkAllocation allocation = { 0, 0 };
1183 GdkGeometry new_geometry;
1184 guint width, height, new_flags;
1186 /* determine default size to initially show the window with */
1187 gtk_widget_size_request (widget, NULL);
1188 gtk_window_compute_default_size (window, &width, &height);
1190 /* save away the last default size for later comparisions */
1191 info->last.width = width;
1192 info->last.height = height;
1194 /* constrain size to geometry */
1195 gtk_window_compute_hints (window, &new_geometry, &new_flags);
1196 gtk_window_constrain_size (window,
1197 &new_geometry, new_flags,
1201 /* and allocate the window */
1202 allocation.width = width;
1203 allocation.height = height;
1204 gtk_widget_size_allocate (widget, &allocation);
1206 was_realized = FALSE;
1207 if (!GTK_WIDGET_REALIZED (widget))
1209 gtk_widget_realize (widget);
1210 was_realized = TRUE;;
1213 /* Must be done after the windows are realized,
1214 so that the decorations can be read */
1215 gtk_decorated_window_calculate_frame_size (window);
1218 gdk_window_resize (widget->window, width, height);
1221 gtk_container_check_resize (container);
1223 gtk_widget_map (widget);
1226 gtk_grab_add (widget);
1230 gtk_window_hide (GtkWidget *widget)
1234 g_return_if_fail (widget != NULL);
1235 g_return_if_fail (GTK_IS_WINDOW (widget));
1237 window = GTK_WINDOW (widget);
1239 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
1240 gtk_widget_unmap (widget);
1243 gtk_grab_remove (widget);
1247 gtk_window_map (GtkWidget *widget)
1250 GdkWindow *toplevel;
1252 g_return_if_fail (widget != NULL);
1253 g_return_if_fail (GTK_IS_WINDOW (widget));
1255 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1257 window = GTK_WINDOW (widget);
1259 if (window->bin.child &&
1260 GTK_WIDGET_VISIBLE (window->bin.child) &&
1261 !GTK_WIDGET_MAPPED (window->bin.child))
1262 gtk_widget_map (window->bin.child);
1265 toplevel = window->frame;
1267 toplevel = widget->window;
1269 if (window->maximize_initially)
1270 gdk_window_maximize (toplevel);
1272 gdk_window_unmaximize (toplevel);
1274 if (window->stick_initially)
1275 gdk_window_stick (toplevel);
1277 gdk_window_unstick (toplevel);
1279 if (window->iconify_initially)
1280 gdk_window_iconify (toplevel);
1282 gdk_window_deiconify (toplevel);
1284 gdk_window_show (widget->window);
1287 gdk_window_show (window->frame);
1291 gtk_window_unmap (GtkWidget *widget)
1295 g_return_if_fail (widget != NULL);
1296 g_return_if_fail (GTK_IS_WINDOW (widget));
1298 window = GTK_WINDOW (widget);
1300 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1302 gdk_window_withdraw (window->frame);
1304 gdk_window_withdraw (widget->window);
1306 window->use_uposition = TRUE;
1307 window->resize_count = 0;
1308 window->handling_resize = FALSE;
1313 gtk_window_realize (GtkWidget *widget)
1316 GdkWindow *parent_window;
1317 GdkWindowAttr attributes;
1318 gint attributes_mask;
1320 g_return_if_fail (GTK_IS_WINDOW (widget));
1322 window = GTK_WINDOW (widget);
1324 /* ensure widget tree is properly size allocated */
1325 if (widget->allocation.x == -1 &&
1326 widget->allocation.y == -1 &&
1327 widget->allocation.width == 1 &&
1328 widget->allocation.height == 1)
1330 GtkRequisition requisition;
1331 GtkAllocation allocation = { 0, 0, 200, 200 };
1333 gtk_widget_size_request (widget, &requisition);
1334 if (requisition.width || requisition.height)
1336 /* non-empty window */
1337 allocation.width = requisition.width;
1338 allocation.height = requisition.height;
1340 gtk_widget_size_allocate (widget, &allocation);
1342 gtk_container_queue_resize (GTK_CONTAINER (widget));
1344 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
1347 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1349 switch (window->type)
1351 case GTK_WINDOW_TOPLEVEL:
1352 attributes.window_type = GDK_WINDOW_TOPLEVEL;
1354 case GTK_WINDOW_DIALOG:
1355 attributes.window_type = GDK_WINDOW_DIALOG;
1357 case GTK_WINDOW_POPUP:
1358 attributes.window_type = GDK_WINDOW_TEMP;
1362 attributes.title = window->title;
1363 attributes.wmclass_name = window->wmclass_name;
1364 attributes.wmclass_class = window->wmclass_class;
1365 attributes.wclass = GDK_INPUT_OUTPUT;
1366 attributes.visual = gtk_widget_get_visual (widget);
1367 attributes.colormap = gtk_widget_get_colormap (widget);
1369 if (window->has_frame)
1371 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
1372 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
1373 attributes.event_mask = (GDK_EXPOSURE_MASK |
1374 GDK_KEY_PRESS_MASK |
1375 GDK_ENTER_NOTIFY_MASK |
1376 GDK_LEAVE_NOTIFY_MASK |
1377 GDK_FOCUS_CHANGE_MASK |
1378 GDK_STRUCTURE_MASK |
1379 GDK_BUTTON_MOTION_MASK |
1380 GDK_POINTER_MOTION_HINT_MASK |
1381 GDK_BUTTON_PRESS_MASK |
1382 GDK_BUTTON_RELEASE_MASK);
1384 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
1386 window->frame = gdk_window_new (NULL, &attributes, attributes_mask);
1387 gdk_window_set_user_data (window->frame, widget);
1389 attributes.window_type = GDK_WINDOW_CHILD;
1390 attributes.x = window->frame_left;
1391 attributes.y = window->frame_right;
1393 attributes_mask = GDK_WA_X | GDK_WA_Y;
1395 parent_window = window->frame;
1399 attributes_mask = 0;
1400 parent_window = NULL;
1403 attributes.width = widget->allocation.width;
1404 attributes.height = widget->allocation.height;
1405 attributes.event_mask = gtk_widget_get_events (widget);
1406 attributes.event_mask |= (GDK_EXPOSURE_MASK |
1407 GDK_KEY_PRESS_MASK |
1408 GDK_ENTER_NOTIFY_MASK |
1409 GDK_LEAVE_NOTIFY_MASK |
1410 GDK_FOCUS_CHANGE_MASK |
1411 GDK_STRUCTURE_MASK);
1413 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
1414 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
1415 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
1416 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
1417 gdk_window_set_user_data (widget->window, window);
1419 widget->style = gtk_style_attach (widget->style, widget->window);
1420 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
1422 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
1424 /* This is a bad hack to set the window background. */
1425 gtk_window_paint (widget, NULL);
1427 if (window->transient_parent &&
1428 GTK_WIDGET_REALIZED (window->transient_parent))
1429 gdk_window_set_transient_for (widget->window,
1430 GTK_WIDGET (window->transient_parent)->window);
1434 gtk_window_unrealize (GtkWidget *widget)
1438 g_return_if_fail (widget != NULL);
1439 g_return_if_fail (GTK_IS_WINDOW (widget));
1441 window = GTK_WINDOW (widget);
1445 gdk_window_set_user_data (window->frame, NULL);
1446 gdk_window_destroy (window->frame);
1447 window->frame = NULL;
1450 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1454 gtk_window_size_request (GtkWidget *widget,
1455 GtkRequisition *requisition)
1460 g_return_if_fail (widget != NULL);
1461 g_return_if_fail (GTK_IS_WINDOW (widget));
1462 g_return_if_fail (requisition != NULL);
1464 window = GTK_WINDOW (widget);
1465 bin = GTK_BIN (window);
1467 requisition->width = GTK_CONTAINER (window)->border_width * 2;
1468 requisition->height = GTK_CONTAINER (window)->border_width * 2;
1470 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
1472 GtkRequisition child_requisition;
1474 gtk_widget_size_request (bin->child, &child_requisition);
1476 requisition->width += child_requisition.width;
1477 requisition->height += child_requisition.height;
1482 gtk_window_size_allocate (GtkWidget *widget,
1483 GtkAllocation *allocation)
1486 GtkAllocation child_allocation;
1488 g_return_if_fail (widget != NULL);
1489 g_return_if_fail (GTK_IS_WINDOW (widget));
1490 g_return_if_fail (allocation != NULL);
1492 window = GTK_WINDOW (widget);
1493 widget->allocation = *allocation;
1495 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
1497 child_allocation.x = GTK_CONTAINER (window)->border_width;
1498 child_allocation.y = GTK_CONTAINER (window)->border_width;
1499 child_allocation.width =
1500 MAX (1, (gint)allocation->width - child_allocation.x * 2);
1501 child_allocation.height =
1502 MAX (1, (gint)allocation->height - child_allocation.y * 2);
1504 gtk_widget_size_allocate (window->bin.child, &child_allocation);
1507 if (GTK_WIDGET_REALIZED (widget) && window->frame)
1509 gdk_window_resize (window->frame,
1510 allocation->width + window->frame_left + window->frame_right,
1511 allocation->height + window->frame_top + window->frame_bottom);
1516 gtk_window_event (GtkWidget *widget, GdkEvent *event)
1519 gboolean return_val;
1522 g_return_val_if_fail (widget != NULL, FALSE);
1523 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1524 g_return_val_if_fail (event != NULL, FALSE);
1526 window = GTK_WINDOW (widget);
1528 if (window->frame && (event->any.window == window->frame))
1530 if ((event->type != GDK_KEY_PRESS) &&
1531 (event->type != GDK_KEY_RELEASE) &&
1532 (event->type != GDK_FOCUS_CHANGE))
1534 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
1536 gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
1541 g_object_unref (event->any.window);
1542 event->any.window = g_object_ref (widget->window);
1550 gtk_window_frame_event (GtkWidget *widget, GdkEvent *event)
1552 GdkEventConfigure *configure_event;
1553 GtkWindow *window = GTK_WINDOW (widget);
1556 switch (event->type)
1559 configure_event = (GdkEventConfigure *)event;
1561 /* Invalidate the decorations */
1564 rect.width = configure_event->width;
1565 rect.height = configure_event->height;
1567 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
1569 /* Pass on the (modified) configure event */
1570 configure_event->width -= window->frame_left + window->frame_right;
1571 configure_event->height -= window->frame_top + window->frame_bottom;
1572 return gtk_window_configure_event (widget, configure_event);
1581 gtk_window_configure_event (GtkWidget *widget,
1582 GdkEventConfigure *event)
1586 g_return_val_if_fail (widget != NULL, FALSE);
1587 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1588 g_return_val_if_fail (event != NULL, FALSE);
1590 window = GTK_WINDOW (widget);
1592 /* we got a configure event specifying the new window size and position,
1593 * in principle we have to distinguish 4 cases here:
1594 * 1) the size didn't change and resize_count == 0
1595 * -> the window was merely moved (sometimes not even that)
1596 * 2) the size didn't change and resize_count > 0
1597 * -> we requested a new size, but didn't get it
1598 * 3) the size changed and resize_count > 0
1599 * -> we asked for a new size and we got one
1600 * 4) the size changed and resize_count == 0
1601 * -> we got resized from outside the toolkit, and have to
1602 * accept that size since we don't want to fight neither the
1603 * window manager nor the user
1604 * in the three latter cases we have to reallocate the widget tree,
1605 * which happens in gtk_window_move_resize(), so we set a flag for
1606 * that function and assign the new size. if resize_count > 1,
1607 * we simply do nothing and wait for more configure events.
1610 if (window->resize_count > 0 ||
1611 widget->allocation.width != event->width ||
1612 widget->allocation.height != event->height)
1614 if (window->resize_count > 0)
1615 window->resize_count -= 1;
1617 if (window->resize_count == 0)
1619 window->handling_resize = TRUE;
1621 widget->allocation.width = event->width;
1622 widget->allocation.height = event->height;
1624 gtk_widget_queue_resize (widget);
1632 gtk_window_key_press_event (GtkWidget *widget,
1636 GtkDirectionType direction = 0;
1639 g_return_val_if_fail (widget != NULL, FALSE);
1640 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1641 g_return_val_if_fail (event != NULL, FALSE);
1643 window = GTK_WINDOW (widget);
1647 if (window->focus_widget &&
1648 window->focus_widget != widget &&
1649 GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1651 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
1655 handled = gtk_accel_groups_activate (GTK_OBJECT (window), event->keyval, event->state);
1659 switch (event->keyval)
1662 if (window->focus_widget)
1664 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1665 gtk_widget_activate (window->focus_widget);
1671 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1672 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1674 gtk_widget_activate (window->default_widget);
1677 else if (window->focus_widget)
1679 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1680 gtk_widget_activate (window->focus_widget);
1693 case GDK_ISO_Left_Tab:
1694 switch (event->keyval)
1698 direction = GTK_DIR_UP;
1702 direction = GTK_DIR_DOWN;
1706 direction = GTK_DIR_LEFT;
1710 direction = GTK_DIR_RIGHT;
1713 case GDK_ISO_Left_Tab:
1714 if (event->state & GDK_SHIFT_MASK)
1715 direction = GTK_DIR_TAB_BACKWARD;
1717 direction = GTK_DIR_TAB_FORWARD;
1720 direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
1723 gtk_container_focus (GTK_CONTAINER (widget), direction);
1725 if (!GTK_CONTAINER (window)->focus_child)
1726 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
1733 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
1734 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
1740 gtk_window_key_release_event (GtkWidget *widget,
1746 g_return_val_if_fail (widget != NULL, FALSE);
1747 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1748 g_return_val_if_fail (event != NULL, FALSE);
1750 window = GTK_WINDOW (widget);
1752 if (window->focus_widget &&
1753 window->focus_widget != widget &&
1754 GTK_WIDGET_SENSITIVE (window->focus_widget))
1756 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
1759 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
1760 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
1766 gtk_window_enter_notify_event (GtkWidget *widget,
1767 GdkEventCrossing *event)
1769 g_return_val_if_fail (widget != NULL, FALSE);
1770 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1771 g_return_val_if_fail (event != NULL, FALSE);
1777 gtk_window_leave_notify_event (GtkWidget *widget,
1778 GdkEventCrossing *event)
1780 g_return_val_if_fail (widget != NULL, FALSE);
1781 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1782 g_return_val_if_fail (event != NULL, FALSE);
1788 gtk_window_focus_in_event (GtkWidget *widget,
1789 GdkEventFocus *event)
1792 GdkEventFocus fevent;
1794 g_return_val_if_fail (widget != NULL, FALSE);
1795 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1796 g_return_val_if_fail (event != NULL, FALSE);
1798 /* It appears spurious focus in events can occur when
1799 * the window is hidden. So we'll just check to see if
1800 * the window is visible before actually handling the
1803 if (GTK_WIDGET_VISIBLE (widget))
1805 window = GTK_WINDOW (widget);
1806 if (window->focus_widget &&
1807 window->focus_widget != widget &&
1808 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
1810 fevent.type = GDK_FOCUS_CHANGE;
1811 fevent.window = window->focus_widget->window;
1814 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
1822 gtk_window_focus_out_event (GtkWidget *widget,
1823 GdkEventFocus *event)
1826 GdkEventFocus fevent;
1828 g_return_val_if_fail (widget != NULL, FALSE);
1829 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1830 g_return_val_if_fail (event != NULL, FALSE);
1832 window = GTK_WINDOW (widget);
1833 if (window->focus_widget &&
1834 window->focus_widget != widget &&
1835 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
1837 fevent.type = GDK_FOCUS_CHANGE;
1838 fevent.window = window->focus_widget->window;
1841 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
1847 static GdkAtom atom_rcfiles = GDK_NONE;
1850 gtk_window_read_rcfiles (GtkWidget *widget,
1851 GdkEventClient *event)
1853 GList *embedded_windows;
1855 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
1856 if (embedded_windows)
1861 for(i = 0; i < 5; i++)
1863 sev.data_format = 32;
1864 sev.message_type = atom_rcfiles;
1866 while (embedded_windows)
1868 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
1869 gdk_event_send_client_message ((GdkEvent *) &sev, xid);
1870 embedded_windows = embedded_windows->next;
1874 if (gtk_rc_reparse_all ())
1876 /* If the above returned true, some of our RC files are out
1877 * of date, so we need to reset all our widgets. Our other
1878 * toplevel windows will also get the message, but by
1879 * then, the RC file will up to date, so we have to tell
1880 * them now. Also, we have to invalidate cached icons in
1881 * icon sets so they get re-rendered.
1883 GList *list, *toplevels;
1885 _gtk_icon_set_invalidate_caches ();
1887 toplevels = gtk_window_list_toplevels ();
1889 for (list = toplevels; list; list = list->next)
1891 gtk_widget_reset_rc_styles (list->data);
1892 gtk_widget_unref (list->data);
1894 g_list_free (toplevels);
1899 gtk_window_client_event (GtkWidget *widget,
1900 GdkEventClient *event)
1902 g_return_val_if_fail (widget != NULL, FALSE);
1903 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1904 g_return_val_if_fail (event != NULL, FALSE);
1907 atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
1909 if(event->message_type == atom_rcfiles)
1910 gtk_window_read_rcfiles (widget, event);
1916 gtk_window_check_resize (GtkContainer *container)
1920 g_return_if_fail (container != NULL);
1921 g_return_if_fail (GTK_IS_WINDOW (container));
1923 window = GTK_WINDOW (container);
1925 if (GTK_WIDGET_VISIBLE (container))
1926 gtk_window_move_resize (window);
1930 gtk_window_focus (GtkContainer *container,
1931 GtkDirectionType direction)
1933 GtkBin *bin = GTK_BIN (container);
1934 GtkWindow *window = GTK_WINDOW (container);
1935 GtkWidget *old_focus_child = container->focus_child;
1938 /* We need a special implementation here to deal properly with wrapping
1939 * around in the tab chain without the danger of going into an
1942 if (old_focus_child)
1944 if (GTK_IS_CONTAINER (old_focus_child) &&
1945 GTK_WIDGET_DRAWABLE (old_focus_child) &&
1946 GTK_WIDGET_IS_SENSITIVE (old_focus_child) &&
1947 gtk_container_focus (GTK_CONTAINER (old_focus_child), direction))
1951 if (window->focus_widget)
1953 /* Wrapped off the end, clear the focus setting for the toplpevel */
1954 parent = window->focus_widget->parent;
1957 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
1958 parent = GTK_WIDGET (parent)->parent;
1961 gtk_window_set_focus (GTK_WINDOW (container), NULL);
1964 /* Now try to focus the first widget in the window */
1965 if (GTK_WIDGET_DRAWABLE (bin->child) &&
1966 GTK_WIDGET_IS_SENSITIVE (bin->child))
1968 if (GTK_IS_CONTAINER (bin->child))
1970 if (gtk_container_focus (GTK_CONTAINER (bin->child), direction))
1973 else if (GTK_WIDGET_CAN_FOCUS (bin->child))
1975 gtk_widget_grab_focus (bin->child);
1984 gtk_window_real_set_focus (GtkWindow *window,
1987 GdkEventFocus event;
1988 gboolean def_flags = 0;
1990 g_return_if_fail (window != NULL);
1991 g_return_if_fail (GTK_IS_WINDOW (window));
1993 if (window->default_widget)
1994 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
1996 if (window->focus_widget)
1998 event.type = GDK_FOCUS_CHANGE;
1999 event.window = window->focus_widget->window;
2002 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
2003 (window->focus_widget != window->default_widget))
2005 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
2006 /* if any widget had the default set there should be
2007 a default_widget, but might not so this is a sanity
2009 if (window->default_widget)
2010 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
2013 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
2016 window->focus_widget = focus;
2018 if (window->focus_widget)
2020 event.type = GDK_FOCUS_CHANGE;
2021 event.window = window->focus_widget->window;
2024 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
2025 (window->focus_widget != window->default_widget))
2027 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
2028 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
2030 if (window->default_widget)
2031 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
2034 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
2037 if (window->default_widget &&
2038 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
2039 gtk_widget_queue_draw (window->default_widget);
2042 /*********************************
2043 * Functions related to resizing *
2044 *********************************/
2047 gtk_window_move_resize (GtkWindow *window)
2050 GtkContainer *container;
2051 GtkWindowGeometryInfo *info;
2052 GtkWindowLastGeometryInfo saved_last_info;
2053 GdkGeometry new_geometry;
2057 gint new_width, new_height;
2058 gboolean default_size_changed = FALSE;
2059 gboolean hints_changed = FALSE;
2061 g_return_if_fail (GTK_IS_WINDOW (window));
2062 g_return_if_fail (GTK_WIDGET_REALIZED (window));
2064 widget = GTK_WIDGET (window);
2065 container = GTK_CONTAINER (widget);
2066 info = gtk_window_get_geometry_info (window, TRUE);
2067 saved_last_info = info->last;
2069 gtk_widget_size_request (widget, NULL);
2070 gtk_window_compute_default_size (window, &new_width, &new_height);
2072 if (info->last.width < 0 ||
2073 info->last.width != new_width ||
2074 info->last.height != new_height)
2076 default_size_changed = TRUE;
2077 info->last.width = new_width;
2078 info->last.height = new_height;
2080 /* We need to force a reposition in this case
2082 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
2083 window->use_uposition = TRUE;
2086 /* Compute new set of hints for the window
2088 gtk_window_compute_hints (window, &new_geometry, &new_flags);
2089 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
2090 &new_geometry, new_flags))
2092 hints_changed = TRUE;
2093 info->last.geometry = new_geometry;
2094 info->last.flags = new_flags;
2097 /* From the default size and the allocation, figure out the size
2098 * the window should be.
2100 if (!default_size_changed ||
2101 (!window->auto_shrink &&
2102 new_width <= widget->allocation.width &&
2103 new_height <= widget->allocation.height))
2105 new_width = widget->allocation.width;
2106 new_height = widget->allocation.height;
2109 /* constrain the window size to the specified geometry */
2110 gtk_window_constrain_size (window,
2111 &new_geometry, new_flags,
2112 new_width, new_height,
2113 &new_width, &new_height);
2115 /* compute new window position if a move is required
2117 gtk_window_compute_reposition (window, new_width, new_height, &x, &y);
2118 if (x != 1 && y != -1 && !(new_flags & GDK_HINT_POS))
2120 new_flags |= GDK_HINT_POS;
2121 hints_changed = TRUE;
2125 /* handle actual resizing:
2126 * - handle reallocations due to configure events
2127 * - figure whether we need to request a new window size
2128 * - handle simple resizes within our widget tree
2129 * - reposition window if neccessary
2131 width = widget->allocation.width;
2132 height = widget->allocation.height;
2134 if (window->handling_resize)
2136 GtkAllocation allocation;
2138 /* if we are just responding to a configure event, which
2139 * might be due to a resize by the window manager, the
2140 * user, or a response to a resizing request we made
2141 * earlier, we go ahead, allocate the new size and we're done
2142 * (see gtk_window_configure_event() for more details).
2145 window->handling_resize = FALSE;
2147 allocation = widget->allocation;
2149 gtk_widget_size_allocate (widget, &allocation);
2150 gtk_widget_queue_draw (widget);
2152 #ifdef FIXME_ZVT_ME_HARDER
2153 if ((default_size_changed || hints_changed) && (width != new_width || height != new_height))
2155 /* We could be here for two reasons
2156 * 1) We coincidentally got a resize while handling
2158 * 2) Our computation of default_size_changed was completely
2159 * screwed up, probably because one of our children
2160 * is broken (i.e. changes requisition during
2161 * size allocation). It's probably a zvt widget.
2163 * For 1), we could just go ahead and ask for the
2164 * new size right now, but doing that for 2)
2165 * might well be fighting the user (and can even
2166 * trigger a loop). Since we really don't want to
2167 * do that, we requeue a resize in hopes that
2168 * by the time it gets handled, the child has seen
2169 * the light and is willing to go along with the
2170 * new size. (this happens for the zvt widget, since
2171 * the size_allocate() above will have stored the
2172 * requisition corresponding to the new size in the
2175 * This doesn't buy us anything for 1), but it shouldn't
2176 * hurt us too badly, since it is what would have
2177 * happened if we had gotten the configure event before
2178 * the new size had been set.
2181 if (x != -1 && y != -1)
2184 gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
2186 gdk_window_move (GTK_WIDGET (window)->window, x, y);
2189 /* we have to preserve the values and flags that are used
2190 * for computation of default_size_changed and hints_changed
2193 info->last = saved_last_info;
2195 gtk_widget_queue_resize (widget);
2199 #endif /* FIXME_ZVT_ME_HARDER */
2202 /* Now set hints if necessary
2205 gdk_window_set_geometry_hints (widget->window,
2209 if ((default_size_changed || hints_changed) &&
2210 (width != new_width || height != new_height))
2212 /* given that (width != new_width || height != new_height), we are in one
2213 * of the following situations:
2215 * default_size_changed
2216 * our requisition has changed and we need a different window size,
2217 * so we request it from the window manager.
2219 * !default_size_changed
2220 * the window manager wouldn't assign us the size we requested, in this
2221 * case we don't try to request a new size with every resize.
2223 * !default_size_changed && hints_changed
2224 * the window manager rejects our size, but we have just changed the
2225 * window manager hints, so there's a certain chance our request will
2226 * be honoured this time, so we try again.
2229 /* request a new window size */
2230 if (x != -1 && y != -1)
2234 gdk_window_move_resize (window->frame,
2235 x - window->frame_left, y - window->frame_top,
2236 new_width + window->frame_left + window->frame_right,
2237 new_height + window->frame_top + window->frame_bottom);
2238 gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
2241 gdk_window_move_resize (GTK_WIDGET (window)->window, x, y, new_width, new_height);
2246 gdk_window_resize (window->frame,
2247 new_width + window->frame_left + window->frame_right,
2248 new_height + window->frame_top + window->frame_bottom);
2249 gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
2251 window->resize_count += 1;
2253 /* we are now awaiting the new configure event in response to our
2254 * resizing request. the configure event will cause a new resize
2255 * with ->handling_resize=TRUE.
2256 * until then, we want to
2257 * - discard expose events
2258 * - coalesce resizes for our children
2259 * - defer any window resizes until the configure event arrived
2260 * to achive this, we queue a resize for the window, but remove its
2261 * resizing handler, so resizing will not be handled from the next
2262 * idle handler but when the configure event arrives.
2264 * FIXME: we should also dequeue the pending redraws here, since
2265 * we handle those ourselves in ->handling_resize==TRUE.
2267 gtk_widget_queue_resize (GTK_WIDGET (container));
2268 if (container->resize_mode == GTK_RESIZE_QUEUE)
2269 gtk_container_dequeue_resize_handler (container);
2273 if (x != -1 && y != -1)
2276 gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
2278 gdk_window_move (widget->window, x, y);
2281 if (container->resize_widgets)
2282 gtk_container_resize_children (GTK_CONTAINER (window));
2286 /* Compare two sets of Geometry hints for equality.
2289 gtk_window_compare_hints (GdkGeometry *geometry_a,
2291 GdkGeometry *geometry_b,
2294 if (flags_a != flags_b)
2297 if ((flags_a & GDK_HINT_MIN_SIZE) &&
2298 (geometry_a->min_width != geometry_b->min_width ||
2299 geometry_a->min_height != geometry_b->min_height))
2302 if ((flags_a & GDK_HINT_MAX_SIZE) &&
2303 (geometry_a->max_width != geometry_b->max_width ||
2304 geometry_a->max_height != geometry_b->max_height))
2307 if ((flags_a & GDK_HINT_BASE_SIZE) &&
2308 (geometry_a->base_width != geometry_b->base_width ||
2309 geometry_a->base_height != geometry_b->base_height))
2312 if ((flags_a & GDK_HINT_ASPECT) &&
2313 (geometry_a->min_aspect != geometry_b->min_aspect ||
2314 geometry_a->max_aspect != geometry_b->max_aspect))
2317 if ((flags_a & GDK_HINT_RESIZE_INC) &&
2318 (geometry_a->width_inc != geometry_b->width_inc ||
2319 geometry_a->height_inc != geometry_b->height_inc))
2325 /* Compute the default_size for a window. The result will
2326 * be stored in *width and *height. The default size is
2327 * the size the window should have when initially mapped.
2328 * This routine does not attempt to constrain the size
2329 * to obey the geometry hints - that must be done elsewhere.
2332 gtk_window_compute_default_size (GtkWindow *window,
2336 GtkRequisition requisition;
2337 GtkWindowGeometryInfo *info;
2339 gtk_widget_get_child_requisition (GTK_WIDGET (window), &requisition);
2340 *width = requisition.width;
2341 *height = requisition.height;
2343 info = gtk_window_get_geometry_info (window, FALSE);
2345 if (*width == 0 && *height == 0)
2354 *width = info->width > 0 ? info->width : *width;
2355 *height = info->height > 0 ? info->height : *height;
2360 _gtk_window_constrain_size (GtkWindow *window,
2366 GtkWindowGeometryInfo *info = (GtkWindowGeometryInfo *)gtk_object_get_data (GTK_OBJECT (window), "gtk-window-geometry");
2370 GdkWindowHints flags = info->last.flags;
2371 GdkGeometry *geometry = &info->last.geometry;
2373 gtk_window_constrain_size (window,
2384 /* Constrain a window size to obey the hints passed in geometry
2385 * and flags. The result will be stored in *new_width and *new_height
2387 * This routine is partially borrowed from fvwm.
2389 * Copyright 1993, Robert Nation
2390 * You may use this code for any purpose, as long as the original
2391 * copyright remains in the source code and all documentation
2393 * which in turn borrows parts of the algorithm from uwm
2396 gtk_window_constrain_size (GtkWindow *window,
2397 GdkGeometry *geometry,
2405 gint min_height = 0;
2406 gint base_width = 0;
2407 gint base_height = 0;
2410 gint max_width = G_MAXINT;
2411 gint max_height = G_MAXINT;
2413 #define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
2415 if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
2417 base_width = geometry->base_width;
2418 base_height = geometry->base_height;
2419 min_width = geometry->min_width;
2420 min_height = geometry->min_height;
2422 else if (flags & GDK_HINT_BASE_SIZE)
2424 base_width = geometry->base_width;
2425 base_height = geometry->base_height;
2426 min_width = geometry->base_width;
2427 min_height = geometry->base_height;
2429 else if (flags & GDK_HINT_MIN_SIZE)
2431 base_width = geometry->min_width;
2432 base_height = geometry->min_height;
2433 min_width = geometry->min_width;
2434 min_height = geometry->min_height;
2437 if (flags & GDK_HINT_MAX_SIZE)
2439 max_width = geometry->max_width ;
2440 max_height = geometry->max_height;
2443 if (flags & GDK_HINT_RESIZE_INC)
2445 xinc = MAX (xinc, geometry->width_inc);
2446 yinc = MAX (yinc, geometry->height_inc);
2449 /* clamp width and height to min and max values
2451 width = CLAMP (width, min_width, max_width);
2452 height = CLAMP (height, min_height, max_height);
2454 /* shrink to base + N * inc
2456 width = base_width + FLOOR (width - base_width, xinc);
2457 height = base_height + FLOOR (height - base_height, yinc);
2459 /* constrain aspect ratio, according to:
2462 * min_aspect <= -------- <= max_aspect
2466 if (flags & GDK_HINT_ASPECT &&
2467 geometry->min_aspect > 0 &&
2468 geometry->max_aspect > 0)
2472 if (geometry->min_aspect * height > width)
2474 delta = FLOOR (height - width * geometry->min_aspect, yinc);
2475 if (height - delta >= min_height)
2479 delta = FLOOR (height * geometry->min_aspect - width, xinc);
2480 if (width + delta <= max_width)
2485 if (geometry->max_aspect * height < width)
2487 delta = FLOOR (width - height * geometry->max_aspect, xinc);
2488 if (width - delta >= min_width)
2492 delta = FLOOR (width / geometry->max_aspect - height, yinc);
2493 if (height + delta <= max_height)
2502 *new_height = height;
2505 /* Compute the set of geometry hints and flags for a window
2506 * based on the application set geometry, and requisiition
2507 * of the window. gtk_widget_size_request() must have been
2511 gtk_window_compute_hints (GtkWindow *window,
2512 GdkGeometry *new_geometry,
2516 GtkWidgetAuxInfo *aux_info;
2518 gint extra_width = 0;
2519 gint extra_height = 0;
2520 GtkWindowGeometryInfo *geometry_info;
2521 GtkRequisition requisition;
2523 g_return_if_fail (GTK_IS_WINDOW (window));
2525 widget = GTK_WIDGET (window);
2527 gtk_widget_get_child_requisition (widget, &requisition);
2528 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
2530 g_return_if_fail (geometry_info != NULL);
2532 *new_flags = geometry_info->mask;
2533 *new_geometry = geometry_info->geometry;
2535 if (geometry_info->widget)
2537 extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
2538 extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
2544 aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
2545 if (aux_info && (aux_info->x != -1) && (aux_info->y != -1))
2549 *new_flags |= GDK_HINT_POS;
2552 if (*new_flags & GDK_HINT_BASE_SIZE)
2554 new_geometry->base_width += extra_width;
2555 new_geometry->base_height += extra_height;
2557 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
2558 (*new_flags & GDK_HINT_RESIZE_INC) &&
2559 ((extra_width != 0) || (extra_height != 0)))
2561 *new_flags |= GDK_HINT_BASE_SIZE;
2563 new_geometry->base_width = extra_width;
2564 new_geometry->base_height = extra_height;
2567 if (*new_flags & GDK_HINT_MIN_SIZE)
2569 if (new_geometry->min_width < 0)
2570 new_geometry->min_width = requisition.width;
2572 new_geometry->min_width += extra_width;
2574 if (new_geometry->min_height < 0)
2575 new_geometry->min_width = requisition.height;
2577 new_geometry->min_height += extra_height;
2579 else if (!window->allow_shrink)
2581 *new_flags |= GDK_HINT_MIN_SIZE;
2583 new_geometry->min_width = requisition.width;
2584 new_geometry->min_height = requisition.height;
2587 if (*new_flags & GDK_HINT_MAX_SIZE)
2589 if (new_geometry->max_width < 0)
2590 new_geometry->max_width = requisition.width;
2592 new_geometry->max_width += extra_width;
2594 if (new_geometry->max_height < 0)
2595 new_geometry->max_width = requisition.height;
2597 new_geometry->max_height += extra_height;
2599 else if (!window->allow_grow)
2601 *new_flags |= GDK_HINT_MAX_SIZE;
2603 new_geometry->max_width = requisition.width;
2604 new_geometry->max_height = requisition.height;
2608 /* Compute a new position for the window based on a new
2609 * size. *x and *y will be set to the new coordinates, or to -1 if the
2610 * window does not need to be moved
2613 gtk_window_compute_reposition (GtkWindow *window,
2620 GtkWindowPosition pos;
2621 GtkWidget *parent_widget;
2623 widget = GTK_WIDGET (window);
2628 parent_widget = (GtkWidget*) window->transient_parent;
2630 pos = window->position;
2631 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
2632 (parent_widget == NULL ||
2633 !GTK_WIDGET_MAPPED (parent_widget)))
2634 pos = GTK_WIN_POS_NONE;
2638 case GTK_WIN_POS_CENTER:
2639 case GTK_WIN_POS_CENTER_ALWAYS:
2640 if (window->use_uposition)
2642 gint screen_width = gdk_screen_width ();
2643 gint screen_height = gdk_screen_height ();
2645 *x = (screen_width - new_width) / 2;
2646 *y = (screen_height - new_height) / 2;
2650 case GTK_WIN_POS_CENTER_ON_PARENT:
2651 if (window->use_uposition)
2654 gdk_window_get_origin (parent_widget->window,
2657 *x = ox + (parent_widget->allocation.width - new_width) / 2;
2658 *y = oy + (parent_widget->allocation.height - new_height) / 2;
2662 case GTK_WIN_POS_MOUSE:
2663 if (window->use_uposition)
2665 gint screen_width = gdk_screen_width ();
2666 gint screen_height = gdk_screen_height ();
2668 gdk_window_get_pointer (NULL, x, y, NULL);
2669 *x -= new_width / 2;
2670 *y -= new_height / 2;
2671 *x = CLAMP (*x, 0, screen_width - new_width);
2672 *y = CLAMP (*y, 0, screen_height - new_height);
2676 if (window->use_uposition)
2678 GtkWidgetAuxInfo *aux_info;
2680 aux_info = gtk_object_get_data (GTK_OBJECT (window), "gtk-aux-info");
2682 aux_info->x != -1 && aux_info->y != -1 &&
2683 aux_info->x != -2 && aux_info->y != -2)
2692 if (*x != -1 && *y != -1)
2694 GtkWidgetAuxInfo *aux_info;
2696 /* we handle necessary window positioning by hand here,
2697 * so we can coalesce the window movement with possible
2698 * resizes to get only one configure event.
2699 * keep this in sync with gtk_widget_set_uposition()
2700 * and gtk_window_reposition().
2702 gtk_widget_set_uposition (widget, -1, -1); /* ensure we have aux_info */
2704 aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
2708 window->use_uposition = FALSE;
2712 /***********************
2713 * Redrawing functions *
2714 ***********************/
2717 gtk_window_paint (GtkWidget *widget,
2720 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
2721 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
2725 gtk_window_expose (GtkWidget *widget,
2726 GdkEventExpose *event)
2728 g_return_val_if_fail (widget != NULL, FALSE);
2729 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2730 g_return_val_if_fail (event != NULL, FALSE);
2732 if (!GTK_WIDGET_APP_PAINTABLE (widget))
2733 gtk_window_paint (widget, &event->area);
2735 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
2736 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
2742 * gtk_window_set_has_frame:
2743 * @window: a #GtkWindow
2745 * If this function is called on a window before it is realized
2746 * or showed it will have a "frame" window around widget-window,
2747 * accessible in window->frame. Using the signal frame_event
2748 * you can recieve all events targeted at the frame.
2750 * This function is used by the linux-fb port to implement managed
2751 * windows, but it could concievably be used by X-programs that
2752 * want to do their own window decorations.
2755 gtk_window_set_has_frame (GtkWindow *window)
2757 g_return_if_fail (window != NULL);
2758 g_return_if_fail (GTK_IS_WINDOW (window));
2759 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
2761 window->has_frame = TRUE;
2765 * gtk_window_set_frame_dimensions:
2766 * @window: a #GtkWindow that has a frame
2767 * @left: The width of the left border
2768 * @top: The height of the top border
2769 * @right: The width of the right border
2770 * @bottom: The height of the bottom border
2772 * For windows with frames (see #gtk_window_set_has_frame) this function
2773 * can be used to change the size of the frame border.
2776 gtk_window_set_frame_dimensions (GtkWindow *window,
2782 GtkWidget *widget = GTK_WIDGET (window);
2784 g_return_if_fail (window != NULL);
2785 g_return_if_fail (GTK_IS_WINDOW (window));
2787 if (window->frame_left == left &&
2788 window->frame_top == top &&
2789 window->frame_right == right &&
2790 window->frame_bottom == bottom)
2793 window->frame_left = left;
2794 window->frame_top = top;
2795 window->frame_right = right;
2796 window->frame_bottom = bottom;
2798 if (GTK_WIDGET_REALIZED (widget) && window->frame)
2800 gint width = widget->allocation.width + left + right;
2801 gint height = widget->allocation.height + top + bottom;
2802 gdk_window_resize (window->frame, width, height);
2803 gtk_decorated_window_move_resize_window (window,
2805 widget->allocation.width,
2806 widget->allocation.height);
2813 * gtk_window_present:
2814 * @window: a #GtkWindow
2816 * Presents a window to the user. This may mean raising the window
2817 * in the stacking order, deiconifying it, moving it to the current
2818 * desktop, and/or giving it the keyboard focus, possibly dependent
2819 * on the user's platform, window manager, and preferences.
2821 * If @window is hidden, this function calls gtk_widget_show()
2824 * This function should be used when the user tries to open a window
2825 * that's already open. Say for example the preferences dialog is
2826 * currently open, and the user chooses Preferences from the menu
2827 * a second time; use gtk_window_present() to move the already-open dialog
2828 * where the user can see it.
2832 gtk_window_present (GtkWindow *window)
2836 g_return_if_fail (GTK_IS_WINDOW (window));
2838 widget = GTK_WIDGET (window);
2840 if (GTK_WIDGET_VISIBLE (window))
2842 g_assert (widget->window != NULL);
2844 gdk_window_show (widget->window);
2846 /* note that gdk_window_focus() will also move the window to
2847 * the current desktop, for WM spec compliant window managers.
2849 gdk_window_focus (widget->window,
2850 gtk_get_current_event_time ());
2854 gtk_widget_show (widget);
2859 * gtk_window_iconify:
2860 * @window: a #GtkWindow
2862 * Asks to iconify @window. Note that you shouldn't assume the window
2863 * is definitely iconified afterward, because other entities (e.g. the
2864 * user or window manager) could deiconify it again, or there may not
2865 * be a window manager in which case iconification isn't possible,
2866 * etc. But normally the window will end up iconified. Just don't write
2867 * code that crashes if not.
2869 * It's permitted to call this function before showing a window,
2870 * in which case the window will be iconified before it ever appears
2873 * You can track iconification via the "window_state_event" signal
2878 gtk_window_iconify (GtkWindow *window)
2881 GdkWindow *toplevel;
2883 g_return_if_fail (GTK_IS_WINDOW (window));
2885 widget = GTK_WIDGET (window);
2887 window->iconify_initially = TRUE;
2890 toplevel = window->frame;
2892 toplevel = widget->window;
2894 if (toplevel != NULL)
2895 gdk_window_iconify (toplevel);
2899 * gtk_window_deiconify:
2900 * @window: a #GtkWindow
2902 * Asks to deiconify @window. Note that you shouldn't assume the
2903 * window is definitely deiconified afterward, because other entities
2904 * (e.g. the user or window manager) could iconify it again before
2905 * your code which assumes deiconification gets to run.
2907 * You can track iconification via the "window_state_event" signal
2911 gtk_window_deiconify (GtkWindow *window)
2914 GdkWindow *toplevel;
2916 g_return_if_fail (GTK_IS_WINDOW (window));
2918 widget = GTK_WIDGET (window);
2920 window->iconify_initially = FALSE;
2923 toplevel = window->frame;
2925 toplevel = widget->window;
2927 if (toplevel != NULL)
2928 gdk_window_deiconify (toplevel);
2933 * @window: a #GtkWindow
2935 * Asks to stick @window, which means that it will appear on all user
2936 * desktops. Note that you shouldn't assume the window is definitely
2937 * stuck afterward, because other entities (e.g. the user or window
2938 * manager) could unstick it again, and some window managers do not
2939 * support sticking windows. But normally the window will end up
2940 * stuck. Just don't write code that crashes if not.
2942 * It's permitted to call this function before showing a window.
2944 * You can track stickiness via the "window_state_event" signal
2949 gtk_window_stick (GtkWindow *window)
2952 GdkWindow *toplevel;
2954 g_return_if_fail (GTK_IS_WINDOW (window));
2956 widget = GTK_WIDGET (window);
2958 window->stick_initially = TRUE;
2961 toplevel = window->frame;
2963 toplevel = widget->window;
2965 if (toplevel != NULL)
2966 gdk_window_stick (toplevel);
2970 * gtk_window_unstick:
2971 * @window: a #GtkWindow
2973 * Asks to unstick @window, which means that it will appear on only
2974 * one of the user's desktops. Note that you shouldn't assume the
2975 * window is definitely unstuck afterward, because other entities
2976 * (e.g. the user or window manager) could stick it again. But
2977 * normally the window will end up stuck. Just don't write code that
2980 * You can track stickiness via the "window_state_event" signal
2985 gtk_window_unstick (GtkWindow *window)
2988 GdkWindow *toplevel;
2990 g_return_if_fail (GTK_IS_WINDOW (window));
2992 widget = GTK_WIDGET (window);
2994 window->stick_initially = FALSE;
2997 toplevel = window->frame;
2999 toplevel = widget->window;
3001 if (toplevel != NULL)
3002 gdk_window_unstick (toplevel);
3006 * gtk_window_maximize:
3007 * @window: a #GtkWindow
3009 * Asks to maximize @window, so that it becomes full-screen. Note that
3010 * you shouldn't assume the window is definitely maximized afterward,
3011 * because other entities (e.g. the user or window manager) could
3012 * unmaximize it again, and not all window managers support
3013 * maximization. But normally the window will end up maximized. Just
3014 * don't write code that crashes if not.
3016 * It's permitted to call this function before showing a window,
3017 * in which case the window will be maximized when it appears onscreen
3020 * You can track maximization via the "window_state_event" signal
3025 gtk_window_maximize (GtkWindow *window)
3028 GdkWindow *toplevel;
3030 g_return_if_fail (GTK_IS_WINDOW (window));
3032 widget = GTK_WIDGET (window);
3034 window->maximize_initially = TRUE;
3037 toplevel = window->frame;
3039 toplevel = widget->window;
3041 if (toplevel != NULL)
3042 gdk_window_maximize (toplevel);
3046 * gtk_window_unmaximize:
3047 * @window: a #GtkWindow
3049 * Asks to unmaximize @window. Note that you shouldn't assume the
3050 * window is definitely unmaximized afterward, because other entities
3051 * (e.g. the user or window manager) could maximize it again, and not
3052 * all window managers honor requests to unmaximize. But normally the
3053 * window will end up unmaximized. Just don't write code that crashes
3056 * You can track maximization via the "window_state_event" signal
3061 gtk_window_unmaximize (GtkWindow *window)
3064 GdkWindow *toplevel;
3066 g_return_if_fail (GTK_IS_WINDOW (window));
3068 widget = GTK_WIDGET (window);
3070 window->maximize_initially = FALSE;
3073 toplevel = window->frame;
3075 toplevel = widget->window;
3077 if (toplevel != NULL)
3078 gdk_window_unmaximize (toplevel);