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"
76 PROP_DESTROY_WITH_PARENT,
85 GdkPixmap *icon_pixmap;
88 guint using_default_icon : 1;
89 guint using_parent_icon : 1;
93 GdkGeometry geometry; /* Last set of geometry hints we set */
95 GdkRectangle configure_request;
96 } GtkWindowLastGeometryInfo;
98 struct _GtkWindowGeometryInfo
100 /* Properties that the app has set on the window
102 GdkGeometry geometry; /* Geometry hints */
104 GtkWidget *widget; /* subwidget to which hints apply */
105 /* from last gtk_window_resize () - if > 0, indicates that
106 * we should resize to this size.
111 /* From last gtk_window_move () prior to mapping -
112 * only used if initial_pos_set
117 /* Default size - used only the FIRST time we map a window,
122 /* whether to use initial_x, initial_y */
123 guint initial_pos_set : 1;
124 /* CENTER_ALWAYS or other position constraint changed since
125 * we sent the last configure request.
127 guint position_constraints_changed : 1;
129 GtkWindowLastGeometryInfo last;
140 static void gtk_window_class_init (GtkWindowClass *klass);
141 static void gtk_window_init (GtkWindow *window);
142 static void gtk_window_dispose (GObject *object);
143 static void gtk_window_destroy (GtkObject *object);
144 static void gtk_window_finalize (GObject *object);
145 static void gtk_window_show (GtkWidget *widget);
146 static void gtk_window_hide (GtkWidget *widget);
147 static void gtk_window_map (GtkWidget *widget);
148 static void gtk_window_unmap (GtkWidget *widget);
149 static void gtk_window_realize (GtkWidget *widget);
150 static void gtk_window_unrealize (GtkWidget *widget);
151 static void gtk_window_size_request (GtkWidget *widget,
152 GtkRequisition *requisition);
153 static void gtk_window_size_allocate (GtkWidget *widget,
154 GtkAllocation *allocation);
155 static gint gtk_window_event (GtkWidget *widget,
157 static gboolean gtk_window_frame_event (GtkWidget *widget,
159 static gint gtk_window_configure_event (GtkWidget *widget,
160 GdkEventConfigure *event);
161 static gint gtk_window_key_press_event (GtkWidget *widget,
163 static gint gtk_window_key_release_event (GtkWidget *widget,
165 static gint gtk_window_enter_notify_event (GtkWidget *widget,
166 GdkEventCrossing *event);
167 static gint gtk_window_leave_notify_event (GtkWidget *widget,
168 GdkEventCrossing *event);
169 static gint gtk_window_focus_in_event (GtkWidget *widget,
170 GdkEventFocus *event);
171 static gint gtk_window_focus_out_event (GtkWidget *widget,
172 GdkEventFocus *event);
173 static gint gtk_window_client_event (GtkWidget *widget,
174 GdkEventClient *event);
175 static void gtk_window_check_resize (GtkContainer *container);
176 static gint gtk_window_focus (GtkWidget *widget,
177 GtkDirectionType direction);
178 static void gtk_window_real_set_focus (GtkWindow *window,
181 static void gtk_window_real_activate_default (GtkWindow *window);
182 static void gtk_window_real_activate_focus (GtkWindow *window);
183 static void gtk_window_move_focus (GtkWindow *window,
184 GtkDirectionType dir);
185 static void gtk_window_read_rcfiles (GtkWidget *widget,
186 GdkEventClient *event);
187 static void gtk_window_paint (GtkWidget *widget,
189 static gint gtk_window_expose (GtkWidget *widget,
190 GdkEventExpose *event);
191 static void gtk_window_unset_transient_for (GtkWindow *window);
192 static void gtk_window_transient_parent_realized (GtkWidget *parent,
194 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
197 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
200 static void gtk_window_move_resize (GtkWindow *window);
201 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
203 GdkGeometry *geometry_b,
205 static void gtk_window_constrain_size (GtkWindow *window,
206 GdkGeometry *geometry,
212 static void gtk_window_constrain_position (GtkWindow *window,
217 static void gtk_window_compute_hints (GtkWindow *window,
218 GdkGeometry *new_geometry,
220 static void gtk_window_compute_configure_request (GtkWindow *window,
221 GdkRectangle *request,
222 GdkGeometry *geometry,
225 static void gtk_window_set_default_size_internal (GtkWindow *window,
226 gboolean change_width,
228 gboolean change_height,
231 static void gtk_window_realize_icon (GtkWindow *window);
232 static void gtk_window_unrealize_icon (GtkWindow *window);
234 static GSList *toplevel_list = NULL;
235 static GHashTable *mnemonic_hash_table = NULL;
236 static GtkBinClass *parent_class = NULL;
237 static guint window_signals[LAST_SIGNAL] = { 0 };
238 static GList *default_icon_list = NULL;
239 /* FIXME need to be per-screen */
240 static GdkPixmap *default_icon_pixmap = NULL;
241 static GdkPixmap *default_icon_mask = NULL;
243 static void gtk_window_set_property (GObject *object,
247 static void gtk_window_get_property (GObject *object,
254 mnemonic_hash (gconstpointer key)
256 const GtkWindowMnemonic *k;
259 k = (GtkWindowMnemonic *)key;
261 h = (gulong) k->window;
262 h ^= k->keyval << 16;
263 h ^= k->keyval >> 16;
269 mnemonic_equal (gconstpointer a, gconstpointer b)
271 const GtkWindowMnemonic *ka;
272 const GtkWindowMnemonic *kb;
274 ka = (GtkWindowMnemonic *)a;
275 kb = (GtkWindowMnemonic *)b;
278 (ka->window == kb->window) &&
279 (ka->keyval == kb->keyval);
283 gtk_window_get_type (void)
285 static GtkType window_type = 0;
289 static const GtkTypeInfo window_info =
293 sizeof (GtkWindowClass),
294 (GtkClassInitFunc) gtk_window_class_init,
295 (GtkObjectInitFunc) gtk_window_init,
296 /* reserved_1 */ NULL,
297 /* reserved_2 */ NULL,
298 (GtkClassInitFunc) NULL,
301 window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
308 gtk_window_class_init (GtkWindowClass *klass)
310 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
311 GtkObjectClass *object_class;
312 GtkWidgetClass *widget_class;
313 GtkContainerClass *container_class;
314 GtkBindingSet *binding_set;
316 object_class = (GtkObjectClass*) klass;
317 widget_class = (GtkWidgetClass*) klass;
318 container_class = (GtkContainerClass*) klass;
320 parent_class = gtk_type_class (gtk_bin_get_type ());
322 gobject_class->dispose = gtk_window_dispose;
323 gobject_class->finalize = gtk_window_finalize;
325 gobject_class->set_property = gtk_window_set_property;
326 gobject_class->get_property = gtk_window_get_property;
328 object_class->destroy = gtk_window_destroy;
330 widget_class->show = gtk_window_show;
331 widget_class->hide = gtk_window_hide;
332 widget_class->map = gtk_window_map;
333 widget_class->unmap = gtk_window_unmap;
334 widget_class->realize = gtk_window_realize;
335 widget_class->unrealize = gtk_window_unrealize;
336 widget_class->size_request = gtk_window_size_request;
337 widget_class->size_allocate = gtk_window_size_allocate;
338 widget_class->configure_event = gtk_window_configure_event;
339 widget_class->key_press_event = gtk_window_key_press_event;
340 widget_class->key_release_event = gtk_window_key_release_event;
341 widget_class->enter_notify_event = gtk_window_enter_notify_event;
342 widget_class->leave_notify_event = gtk_window_leave_notify_event;
343 widget_class->focus_in_event = gtk_window_focus_in_event;
344 widget_class->focus_out_event = gtk_window_focus_out_event;
345 widget_class->client_event = gtk_window_client_event;
346 widget_class->focus = gtk_window_focus;
348 widget_class->expose_event = gtk_window_expose;
350 container_class->check_resize = gtk_window_check_resize;
352 klass->set_focus = gtk_window_real_set_focus;
353 klass->frame_event = gtk_window_frame_event;
355 klass->activate_default = gtk_window_real_activate_default;
356 klass->activate_focus = gtk_window_real_activate_focus;
357 klass->move_focus = gtk_window_move_focus;
360 g_object_class_install_property (gobject_class,
362 g_param_spec_enum ("type",
364 _("The type of the window"),
365 GTK_TYPE_WINDOW_TYPE,
367 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
370 g_object_class_install_property (gobject_class,
372 g_param_spec_string ("title",
374 _("The title of the window"),
378 g_object_class_install_property (gobject_class,
380 g_param_spec_boolean ("allow_shrink",
382 /* xgettext:no-c-format */
383 _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea."),
387 g_object_class_install_property (gobject_class,
389 g_param_spec_boolean ("allow_grow",
391 _("If TRUE, users can expand the window beyond its minimum size."),
395 g_object_class_install_property (gobject_class,
397 g_param_spec_boolean ("resizable",
399 _("If TRUE, users can resize the window."),
403 g_object_class_install_property (gobject_class,
405 g_param_spec_boolean ("modal",
407 _("If TRUE, the window is modal (other windows are not usable while this one is up)."),
411 g_object_class_install_property (gobject_class,
413 g_param_spec_enum ("window_position",
414 _("Window Position"),
415 _("The initial position of the window."),
416 GTK_TYPE_WINDOW_POSITION,
420 g_object_class_install_property (gobject_class,
422 g_param_spec_int ("default_width",
424 _("The default width of the window, used when initially showing the window."),
430 g_object_class_install_property (gobject_class,
432 g_param_spec_int ("default_height",
434 _("The default height of the window, used when initially showing the window."),
440 g_object_class_install_property (gobject_class,
441 PROP_DESTROY_WITH_PARENT,
442 g_param_spec_boolean ("destroy_with_parent",
443 _("Destroy with Parent"),
444 _("If this window should be destroyed when the parent is destroyed"),
448 g_object_class_install_property (gobject_class,
450 g_param_spec_object ("icon",
452 _("Icon for this window"),
456 window_signals[SET_FOCUS] =
457 g_signal_new ("set_focus",
458 G_TYPE_FROM_CLASS (object_class),
460 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
462 gtk_marshal_VOID__OBJECT,
466 window_signals[FRAME_EVENT] =
467 g_signal_new ("frame_event",
468 G_TYPE_FROM_CLASS(object_class),
470 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
471 _gtk_boolean_handled_accumulator, NULL,
472 gtk_marshal_BOOLEAN__BOXED,
476 window_signals[ACTIVATE_FOCUS] =
477 g_signal_new ("activate_focus",
478 G_OBJECT_CLASS_TYPE (object_class),
479 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
480 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_focus),
482 gtk_marshal_VOID__VOID,
486 window_signals[ACTIVATE_DEFAULT] =
487 g_signal_new ("activate_default",
488 G_OBJECT_CLASS_TYPE (object_class),
489 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
490 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_default),
492 gtk_marshal_VOID__VOID,
496 window_signals[MOVE_FOCUS] =
497 g_signal_new ("move_focus",
498 G_OBJECT_CLASS_TYPE (object_class),
499 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
500 GTK_SIGNAL_OFFSET (GtkWindowClass, move_focus),
502 gtk_marshal_VOID__ENUM,
505 GTK_TYPE_DIRECTION_TYPE);
507 if (!mnemonic_hash_table)
508 mnemonic_hash_table = g_hash_table_new (mnemonic_hash,
515 binding_set = gtk_binding_set_by_class (klass);
517 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
518 "activate_focus", 0);
519 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
520 "activate_focus", 0);
522 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
523 "activate_default", 0);
525 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
526 "activate_default", 0);
528 gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
530 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
531 gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
533 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
535 gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
537 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
538 gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
540 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
542 gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
544 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);
545 gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
547 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);
549 gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
551 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);
552 gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
554 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);
556 gtk_binding_entry_add_signal (binding_set, GDK_Tab, 0,
558 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
559 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, 0,
561 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
562 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, 0,
564 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
566 gtk_binding_entry_add_signal (binding_set, GDK_Tab, GDK_SHIFT_MASK,
568 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
569 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, GDK_SHIFT_MASK,
571 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
572 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, GDK_SHIFT_MASK,
574 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
578 gtk_window_init (GtkWindow *window)
580 GdkColormap *colormap;
582 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
583 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
585 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
587 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
589 window->title = NULL;
590 window->wmclass_name = g_strdup (g_get_prgname ());
591 window->wmclass_class = g_strdup (gdk_get_program_class ());
592 window->wm_role = NULL;
593 window->geometry_info = NULL;
594 window->type = GTK_WINDOW_TOPLEVEL;
595 window->focus_widget = NULL;
596 window->default_widget = NULL;
597 window->configure_request_count = 0;
598 window->allow_shrink = FALSE;
599 window->allow_grow = TRUE;
600 window->configure_notify_received = FALSE;
601 window->position = GTK_WIN_POS_NONE;
602 window->need_default_size = TRUE;
603 window->need_default_position = TRUE;
604 window->modal = FALSE;
605 window->frame = NULL;
606 window->has_frame = FALSE;
607 window->frame_left = 0;
608 window->frame_right = 0;
609 window->frame_top = 0;
610 window->frame_bottom = 0;
611 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
612 window->gravity = GDK_GRAVITY_NORTH_WEST;
613 window->decorated = TRUE;
614 window->mnemonic_modifier = GDK_MOD1_MASK;
616 colormap = _gtk_widget_peek_colormap ();
618 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
620 gtk_widget_ref (GTK_WIDGET (window));
621 gtk_object_sink (GTK_OBJECT (window));
622 window->has_user_ref_count = TRUE;
623 toplevel_list = g_slist_prepend (toplevel_list, window);
625 gtk_decorated_window_init (window);
627 gtk_signal_connect (GTK_OBJECT (window),
629 GTK_SIGNAL_FUNC (gtk_window_event),
634 gtk_window_set_property (GObject *object,
641 window = GTK_WINDOW (object);
646 window->type = g_value_get_enum (value);
649 gtk_window_set_title (window, g_value_get_string (value));
651 case PROP_ALLOW_SHRINK:
652 window->allow_shrink = g_value_get_boolean (value);
653 gtk_widget_queue_resize (GTK_WIDGET (window));
655 case PROP_ALLOW_GROW:
656 window->allow_grow = g_value_get_boolean (value);
657 gtk_widget_queue_resize (GTK_WIDGET (window));
658 g_object_notify (G_OBJECT (window), "resizable");
661 window->allow_grow = g_value_get_boolean (value);
662 gtk_widget_queue_resize (GTK_WIDGET (window));
663 g_object_notify (G_OBJECT (window), "allow_grow");
666 gtk_window_set_modal (window, g_value_get_boolean (value));
669 gtk_window_set_position (window, g_value_get_enum (value));
671 case PROP_DEFAULT_WIDTH:
672 gtk_window_set_default_size_internal (window,
673 TRUE, g_value_get_int (value),
676 case PROP_DEFAULT_HEIGHT:
677 gtk_window_set_default_size_internal (window,
679 TRUE, g_value_get_int (value));
681 case PROP_DESTROY_WITH_PARENT:
682 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
685 gtk_window_set_icon (window,
686 g_value_get_object (value));
695 gtk_window_get_property (GObject *object,
702 window = GTK_WINDOW (object);
706 GtkWindowGeometryInfo *info;
708 g_value_set_enum (value, window->type);
711 g_value_set_string (value, window->title);
713 case PROP_ALLOW_SHRINK:
714 g_value_set_boolean (value, window->allow_shrink);
716 case PROP_ALLOW_GROW:
717 g_value_set_boolean (value, window->allow_grow);
720 g_value_set_boolean (value, window->allow_grow);
723 g_value_set_boolean (value, window->modal);
726 g_value_set_enum (value, window->position);
728 case PROP_DEFAULT_WIDTH:
729 info = gtk_window_get_geometry_info (window, FALSE);
731 g_value_set_int (value, -1);
733 g_value_set_int (value, info->default_width);
735 case PROP_DEFAULT_HEIGHT:
736 info = gtk_window_get_geometry_info (window, FALSE);
738 g_value_set_int (value, -1);
740 g_value_set_int (value, info->default_height);
742 case PROP_DESTROY_WITH_PARENT:
743 g_value_set_boolean (value, window->destroy_with_parent);
746 g_value_set_object (value, gtk_window_get_icon (window));
749 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
756 * @type: type of window
758 * Creates a new #GtkWindow, which is a toplevel window that can
759 * contain other widgets. Nearly always, the type of the window should
760 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
761 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
762 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
763 * dialogs, though in some other toolkits dialogs are called "popups."
764 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
765 * Popup windows are not controlled by the window manager.
767 * If you simply want an undecorated window (no window borders), use
768 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
770 * Return value: a new #GtkWindow.
773 gtk_window_new (GtkWindowType type)
777 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
779 window = gtk_type_new (GTK_TYPE_WINDOW);
783 return GTK_WIDGET (window);
787 * gtk_window_set_title:
788 * @window: a #GtkWindow
789 * @title: title of the window
791 * Sets the title of the #GtkWindow. The title of a window will be displayed in
792 * its title bar; on the X Window System, the title bar is rendered by the
793 * window manager, so exactly how the title appears to users may vary according
794 * to a user's exact configuration. The title should help a user distinguish
795 * this window from other windows they may have open. A good title might
796 * include the application name and current document filename, for example.
800 gtk_window_set_title (GtkWindow *window,
803 g_return_if_fail (GTK_IS_WINDOW (window));
806 g_free (window->title);
807 window->title = g_strdup (title);
809 if (GTK_WIDGET_REALIZED (window))
811 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
813 gtk_decorated_window_set_title (window, title);
816 g_object_notify (G_OBJECT (window), "title");
820 * gtk_window_get_title:
821 * @window: a #GtkWindow
823 * Retrieves the title of the window. See gtk_window_set_title().
825 * Return value: the title of the window, or %NULL if none has
826 * been set explicitely. The returned string is owned by the widget
827 * and must not be modified or freed.
829 G_CONST_RETURN gchar *
830 gtk_window_get_title (GtkWindow *window)
832 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
834 return window->title;
838 * gtk_window_set_wmclass:
839 * @window: a #GtkWindow
840 * @wmclass_name: window name hint
841 * @wmclass_class: window class hint
843 * Don't use this function. It sets the X Window System "class" and
844 * "name" hints for a window. According to the ICCCM, you should
845 * always set these to the same value for all windows in an
846 * application, and GTK sets them to that value by default, so calling
847 * this function is sort of pointless. However, you may want to call
848 * gtk_window_set_role() on each window in your application, for the
849 * benefit of the session manager. Setting the role allows the window
850 * manager to restore window positions when loading a saved session.
854 gtk_window_set_wmclass (GtkWindow *window,
855 const gchar *wmclass_name,
856 const gchar *wmclass_class)
858 g_return_if_fail (GTK_IS_WINDOW (window));
860 g_free (window->wmclass_name);
861 window->wmclass_name = g_strdup (wmclass_name);
863 g_free (window->wmclass_class);
864 window->wmclass_class = g_strdup (wmclass_class);
866 if (GTK_WIDGET_REALIZED (window))
867 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
871 * gtk_window_set_role:
872 * @window: a #GtkWindow
873 * @role: unique identifier for the window to be used when restoring a session
875 * In combination with the window title, the window role allows a
876 * window manager to identify "the same" window when an application is
877 * restarted. So for example you might set the "toolbox" role on your
878 * app's toolbox window, so that when the user restarts their session,
879 * the window manager can put the toolbox back in the same place.
881 * If a window already has a unique title, you don't need to set the
882 * role, since the WM can use the title to identify the window when
883 * restoring the session.
887 gtk_window_set_role (GtkWindow *window,
890 g_return_if_fail (GTK_IS_WINDOW (window));
892 if (role == window->wm_role)
895 g_free (window->wm_role);
896 window->wm_role = g_strdup (role);
898 if (GTK_WIDGET_REALIZED (window))
899 g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
903 * gtk_window_get_role:
904 * @window: a #GtkWindow
906 * Returns the role of the window. See gtk_window_set_role() for
907 * further explanation.
909 * Return value: the role of the window if set, or %NULL. The
910 * returned is owned by the widget and must not be modified
913 G_CONST_RETURN gchar *
914 gtk_window_get_role (GtkWindow *window)
916 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
918 return window->wm_role;
922 * gtk_window_set_focus:
923 * @window: a #GtkWindow
924 * @focus: widget to be the new focus widget
926 * If @focus is not the current focus widget, and is focusable, emits
927 * the "set_focus" signal to set @focus as the focus widget for the
928 * window. This function is more or less GTK-internal; to focus an
929 * entry widget or the like, you should use gtk_widget_grab_focus()
930 * instead of this function.
934 gtk_window_set_focus (GtkWindow *window,
937 g_return_if_fail (GTK_IS_WINDOW (window));
940 g_return_if_fail (GTK_IS_WIDGET (focus));
941 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
944 if ((window->focus_widget != focus) ||
945 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
946 gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
950 * gtk_window_set_default:
951 * @window: a #GtkWindow
952 * @default_widget: widget to be the default
954 * The default widget is the widget that's activated when the user
955 * presses Enter in a dialog (for example). This function tells a
956 * #GtkWindow about the current default widget; it's really a GTK
957 * internal function and you shouldn't need it. Instead, to change the
958 * default widget, first set the #GTK_CAN_DEFAULT flag on the widget
959 * you'd like to make the default using GTK_WIDGET_SET_FLAGS(), then
960 * call gtk_widget_grab_default() to move the default.
964 gtk_window_set_default (GtkWindow *window,
965 GtkWidget *default_widget)
967 g_return_if_fail (GTK_IS_WINDOW (window));
970 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
972 if (window->default_widget != default_widget)
974 if (window->default_widget)
976 if (window->focus_widget != window->default_widget ||
977 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
978 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
979 gtk_widget_queue_draw (window->default_widget);
982 window->default_widget = default_widget;
984 if (window->default_widget)
986 if (window->focus_widget == NULL ||
987 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
988 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
989 gtk_widget_queue_draw (window->default_widget);
995 gtk_window_set_policy (GtkWindow *window,
996 gboolean allow_shrink,
998 gboolean auto_shrink)
1000 g_return_if_fail (GTK_IS_WINDOW (window));
1002 window->allow_shrink = (allow_shrink != FALSE);
1003 window->allow_grow = (allow_grow != FALSE);
1005 g_object_freeze_notify (G_OBJECT (window));
1006 g_object_notify (G_OBJECT (window), "allow_shrink");
1007 g_object_notify (G_OBJECT (window), "allow_grow");
1008 g_object_notify (G_OBJECT (window), "resizable");
1009 g_object_thaw_notify (G_OBJECT (window));
1011 gtk_widget_queue_resize (GTK_WIDGET (window));
1015 gtk_window_add_accel_group (GtkWindow *window,
1016 GtkAccelGroup *accel_group)
1018 g_return_if_fail (GTK_IS_WINDOW (window));
1019 g_return_if_fail (accel_group != NULL);
1021 gtk_accel_group_attach (accel_group, G_OBJECT (window));
1025 gtk_window_remove_accel_group (GtkWindow *window,
1026 GtkAccelGroup *accel_group)
1028 g_return_if_fail (GTK_IS_WINDOW (window));
1029 g_return_if_fail (accel_group != NULL);
1031 gtk_accel_group_detach (accel_group, G_OBJECT (window));
1035 gtk_window_add_mnemonic (GtkWindow *window,
1039 GtkWindowMnemonic key;
1040 GtkWindowMnemonic *mnemonic;
1042 g_return_if_fail (GTK_IS_WINDOW (window));
1043 g_return_if_fail (GTK_IS_WIDGET (target));
1045 key.window = window;
1046 key.keyval = keyval;
1047 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1051 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1052 mnemonic->targets = g_slist_prepend (mnemonic->targets, target);
1056 mnemonic = g_new (GtkWindowMnemonic, 1);
1058 mnemonic->targets = g_slist_prepend (NULL, target);
1059 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1064 gtk_window_remove_mnemonic (GtkWindow *window,
1068 GtkWindowMnemonic key;
1069 GtkWindowMnemonic *mnemonic;
1071 g_return_if_fail (GTK_IS_WINDOW (window));
1072 g_return_if_fail (GTK_IS_WIDGET (target));
1074 key.window = window;
1075 key.keyval = keyval;
1076 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1078 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1080 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1081 if (mnemonic->targets == NULL)
1083 g_hash_table_remove (mnemonic_hash_table, mnemonic);
1089 gtk_window_mnemonic_activate (GtkWindow *window,
1091 GdkModifierType modifier)
1093 GtkWindowMnemonic key;
1094 GtkWindowMnemonic *mnemonic;
1096 GtkWidget *widget, *chosen_widget;
1097 gboolean overloaded;
1099 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1101 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1104 key.window = window;
1105 key.keyval = keyval;
1106 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1112 chosen_widget = NULL;
1113 list = mnemonic->targets;
1116 widget = GTK_WIDGET (list->data);
1118 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1119 GTK_WIDGET_MAPPED (widget))
1127 chosen_widget = widget;
1129 list = g_slist_next (list);
1134 /* For round robin we put the activated entry on
1135 * the end of the list after activation
1137 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1138 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1140 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1146 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1147 GdkModifierType modifier)
1149 g_return_if_fail (GTK_IS_WINDOW (window));
1150 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1152 window->mnemonic_modifier = modifier;
1156 * gtk_window_get_mnemonic_modifier:
1157 * @window: a #GtkWindow
1159 * Returns the mnemonic modifier for this window. See
1160 * gtk_window_set_mnemonic_modifier().
1162 * Return value: the modifier mask used to activate
1163 * mnemonics on this window.
1166 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1168 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1170 return window->mnemonic_modifier;
1174 gtk_window_set_position (GtkWindow *window,
1175 GtkWindowPosition position)
1177 g_return_if_fail (GTK_IS_WINDOW (window));
1179 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1180 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1182 GtkWindowGeometryInfo *info;
1184 info = gtk_window_get_geometry_info (window, TRUE);
1186 /* this flag causes us to re-request the CENTER_ALWAYS
1187 * constraint in gtk_window_move_resize(), see
1188 * comment in that function.
1190 info->position_constraints_changed = TRUE;
1192 gtk_widget_queue_resize (GTK_WIDGET (window));
1195 window->position = position;
1197 g_object_notify (G_OBJECT (window), "window_position");
1201 gtk_window_activate_focus (GtkWindow *window)
1203 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1205 if (window->focus_widget)
1207 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1208 gtk_widget_activate (window->focus_widget);
1216 gtk_window_activate_default (GtkWindow *window)
1218 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1220 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1221 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1223 gtk_widget_activate (window->default_widget);
1226 else if (window->focus_widget)
1228 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1229 gtk_widget_activate (window->focus_widget);
1237 * gtk_window_set_modal:
1238 * @window: a #GtkWindow
1239 * @modal: whether the window is modal
1241 * Sets a window modal or non-modal. Modal windows prevent interaction
1242 * with other windows in the same application. To keep modal dialogs
1243 * on top of main application windows, use
1244 * gtk_window_set_transient_for() to make the dialog transient for the
1245 * parent; most window managers will then disallow lowering the dialog
1251 gtk_window_set_modal (GtkWindow *window,
1254 g_return_if_fail (GTK_IS_WINDOW (window));
1256 window->modal = modal != FALSE;
1258 /* adjust desired modality state */
1259 if (GTK_WIDGET_VISIBLE (window) && window->modal)
1260 gtk_grab_add (GTK_WIDGET (window));
1262 gtk_grab_remove (GTK_WIDGET (window));
1264 g_object_notify (G_OBJECT (window), "modal");
1268 * gtk_window_get_modal:
1269 * @window: a #GtkWindow
1271 * Returns whether the window is modal. See gtk_window_set_modal().
1273 * Return value: %TRUE if the window is set to be modal and
1274 * establishes a grab when shown
1277 gtk_window_get_modal (GtkWindow *window)
1279 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1281 return window->modal;
1285 * gtk_window_list_toplevels:
1287 * Returns a list of all existing toplevel windows. The widgets
1288 * in the list are not individually referenced. If you want
1289 * to iterate through the list and perform actions involving
1290 * callbacks that might destroy the widgets, you MUST call
1291 * g_list_foreach (result, (GFunc)g_object_ref, NULL) first, and
1292 * then unref all the widgets afterwards.
1294 * Return value: list of toplevel widgets
1297 gtk_window_list_toplevels (void)
1302 for (slist = toplevel_list; slist; slist = slist->next)
1303 list = g_list_prepend (list, slist->data);
1309 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1311 GList *embedded_windows;
1313 g_return_if_fail (GTK_IS_WINDOW (window));
1315 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1316 if (embedded_windows)
1317 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1318 g_quark_from_static_string ("gtk-embedded"));
1319 embedded_windows = g_list_prepend (embedded_windows,
1320 GUINT_TO_POINTER (xid));
1322 gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
1325 (GtkDestroyNotify) g_list_free : NULL);
1329 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1331 GList *embedded_windows;
1334 g_return_if_fail (GTK_IS_WINDOW (window));
1336 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1337 if (embedded_windows)
1338 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1339 g_quark_from_static_string ("gtk-embedded"));
1341 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1344 embedded_windows = g_list_remove_link (embedded_windows, node);
1345 g_list_free_1 (node);
1348 gtk_object_set_data_full (GTK_OBJECT (window),
1349 "gtk-embedded", embedded_windows,
1351 (GtkDestroyNotify) g_list_free : NULL);
1355 _gtk_window_reposition (GtkWindow *window,
1359 g_return_if_fail (GTK_IS_WINDOW (window));
1361 gtk_window_move (window, x, y);
1365 gtk_window_dispose (GObject *object)
1369 g_return_if_fail (GTK_IS_WINDOW (object));
1371 window = GTK_WINDOW (object);
1373 gtk_window_set_focus (window, NULL);
1374 gtk_window_set_default (window, NULL);
1376 G_OBJECT_CLASS (parent_class)->dispose (object);
1380 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1382 gtk_widget_destroy (GTK_WIDGET (child));
1386 connect_parent_destroyed (GtkWindow *window)
1388 if (window->transient_parent)
1390 gtk_signal_connect (GTK_OBJECT (window->transient_parent),
1392 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1398 disconnect_parent_destroyed (GtkWindow *window)
1400 if (window->transient_parent)
1402 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1403 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1409 gtk_window_transient_parent_realized (GtkWidget *parent,
1412 if (GTK_WIDGET_REALIZED (window))
1413 gdk_window_set_transient_for (window->window, parent->window);
1417 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1420 if (GTK_WIDGET_REALIZED (window))
1421 gdk_property_delete (window->window,
1422 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1426 gtk_window_unset_transient_for (GtkWindow *window)
1428 if (window->transient_parent)
1430 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1431 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1433 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1434 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1436 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1437 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1438 &window->transient_parent);
1440 if (window->destroy_with_parent)
1441 disconnect_parent_destroyed (window);
1443 window->transient_parent = NULL;
1448 * gtk_window_set_transient_for:
1449 * @window: a #GtkWindow
1450 * @parent: parent window
1452 * Dialog windows should be set transient for the main application
1453 * window they were spawned from. This allows window managers to
1454 * e.g. keep the dialog on top of the main window, or center the
1455 * dialog over the main window. gtk_dialog_new_with_buttons() and
1456 * other convenience functions in GTK+ will sometimes call
1457 * gtk_window_set_transient_for() on your behalf.
1461 gtk_window_set_transient_for (GtkWindow *window,
1464 g_return_if_fail (GTK_IS_WINDOW (window));
1465 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1466 g_return_if_fail (window != parent);
1469 if (window->transient_parent)
1471 if (GTK_WIDGET_REALIZED (window) &&
1472 GTK_WIDGET_REALIZED (window->transient_parent) &&
1473 (!parent || !GTK_WIDGET_REALIZED (parent)))
1474 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1475 GTK_WIDGET (window));
1477 gtk_window_unset_transient_for (window);
1480 window->transient_parent = parent;
1484 gtk_signal_connect (GTK_OBJECT (parent), "destroy",
1485 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1486 &window->transient_parent);
1487 gtk_signal_connect (GTK_OBJECT (parent), "realize",
1488 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1490 gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
1491 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1494 if (window->destroy_with_parent)
1495 connect_parent_destroyed (window);
1497 if (GTK_WIDGET_REALIZED (window) &&
1498 GTK_WIDGET_REALIZED (parent))
1499 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1500 GTK_WIDGET (window));
1505 * gtk_window_get_transient_for:
1506 * @window: a #GtkWindow
1508 * Fetches the transient parent for this window. See
1509 * gtk_window_set_transient_for().
1511 * Return value: the transient parent for this window, or %NULL
1512 * if no transient parent has been set.
1515 gtk_window_get_transient_for (GtkWindow *window)
1517 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1519 return window->transient_parent;
1523 * gtk_window_set_type_hint:
1524 * @window: a #GtkWindow
1525 * @hint: the window type
1527 * By setting the type hint for the window, you allow the window
1528 * manager to decorate and handle the window in a way which is
1529 * suitable to the function of the window in your application.
1531 * This function should be called before the window becomes visible.
1533 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1534 * will sometimes call gtk_window_set_type_hint() on your behalf.
1538 gtk_window_set_type_hint (GtkWindow *window,
1539 GdkWindowTypeHint hint)
1541 g_return_if_fail (GTK_IS_WINDOW (window));
1542 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1543 window->type_hint = hint;
1547 * gtk_window_get_type_hint:
1548 * @window: a #GtkWindow
1550 * Gets the type hint for this window. See gtk_window_set_type_hint().
1552 * Return value: the type hint for @window.
1555 gtk_window_get_type_hint (GtkWindow *window)
1557 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1559 return window->type_hint;
1563 * gtk_window_set_destroy_with_parent:
1564 * @window: a #GtkWindow
1565 * @setting: whether to destroy @window with its transient parent
1567 * If @setting is TRUE, then destroying the transient parent of @window
1568 * will also destroy @window itself. This is useful for dialogs that
1569 * shouldn't persist beyond the lifetime of the main window they're
1570 * associated with, for example.
1573 gtk_window_set_destroy_with_parent (GtkWindow *window,
1576 g_return_if_fail (GTK_IS_WINDOW (window));
1578 if (window->destroy_with_parent == (setting != FALSE))
1581 if (window->destroy_with_parent)
1583 disconnect_parent_destroyed (window);
1587 connect_parent_destroyed (window);
1590 window->destroy_with_parent = setting;
1592 g_object_notify (G_OBJECT (window), "destroy_with_parent");
1596 * gtk_window_get_destroy_with_parent:
1597 * @window: a #GtkWindow
1599 * Returns whether the window will be destroyed with its transient parent. See
1600 * gtk_window_set_destroy_with_parent ().
1602 * Return value: %TRUE if the window will be destroyed with its transient parent.
1605 gtk_window_get_destroy_with_parent (GtkWindow *window)
1607 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1609 return window->destroy_with_parent;
1612 static GtkWindowGeometryInfo*
1613 gtk_window_get_geometry_info (GtkWindow *window,
1616 GtkWindowGeometryInfo *info;
1618 info = window->geometry_info;
1619 if (!info && create)
1621 info = g_new0 (GtkWindowGeometryInfo, 1);
1623 info->default_width = -1;
1624 info->default_height = -1;
1625 info->resize_width = -1;
1626 info->resize_height = -1;
1627 info->initial_x = 0;
1628 info->initial_y = 0;
1629 info->initial_pos_set = FALSE;
1630 info->position_constraints_changed = FALSE;
1631 info->last.configure_request.x = 0;
1632 info->last.configure_request.y = 0;
1633 info->last.configure_request.width = -1;
1634 info->last.configure_request.height = -1;
1635 info->widget = NULL;
1637 window->geometry_info = info;
1644 * gtk_window_set_geometry_hints:
1645 * @window: a #GtkWindow
1646 * @geometry_widget: widget the geometry hints will be applied to
1647 * @geometry: struct containing geometry information
1648 * @geom_mask: mask indicating which struct fields should be paid attention to
1650 * This function sets up hints about how a window can be resized by
1651 * the user. You can set a minimum and maximum size; allowed resize
1652 * increments (e.g. for xterm, you can only resize by the size of a
1653 * character); aspect ratios; and more. See the #GdkGeometry struct.
1657 gtk_window_set_geometry_hints (GtkWindow *window,
1658 GtkWidget *geometry_widget,
1659 GdkGeometry *geometry,
1660 GdkWindowHints geom_mask)
1662 GtkWindowGeometryInfo *info;
1664 g_return_if_fail (window != NULL);
1666 info = gtk_window_get_geometry_info (window, TRUE);
1669 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1670 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1673 info->widget = geometry_widget;
1675 gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
1676 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1680 info->geometry = *geometry;
1682 /* We store gravity in window->gravity not in the hints. */
1683 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
1685 if (geom_mask & GDK_HINT_WIN_GRAVITY)
1687 gtk_window_set_gravity (window, geometry->win_gravity);
1690 gtk_widget_queue_resize (GTK_WIDGET (window));
1694 * gtk_window_set_decorated:
1695 * @window: a #GtkWindow
1696 * @setting: %TRUE to decorate the window
1698 * By default, windows are decorated with a title bar, resize
1699 * controls, etc. Some window managers allow GTK+ to disable these
1700 * decorations, creating a borderless window. If you set the decorated
1701 * property to %FALSE using this function, GTK+ will do its best to
1702 * convince the window manager not to decorate the window.
1706 gtk_window_set_decorated (GtkWindow *window,
1709 g_return_if_fail (GTK_IS_WINDOW (window));
1711 setting = setting != FALSE;
1713 if (setting == window->decorated)
1716 window->decorated = setting;
1718 if (GTK_WIDGET (window)->window)
1720 if (window->decorated)
1721 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1724 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1730 * gtk_window_get_decorated:
1731 * @window: a #GtkWindow
1733 * Returns whether the window has been set to have decorations
1734 * such as a title bar via gtk_window_set_decorated().
1736 * Return value: %TRUE if the window has been set to have decorations
1739 gtk_window_get_decorated (GtkWindow *window)
1741 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
1743 return window->decorated;
1746 static GtkWindowIconInfo*
1747 get_icon_info (GtkWindow *window)
1749 return g_object_get_data (G_OBJECT (window),
1750 "gtk-window-icon-info");
1753 static GtkWindowIconInfo*
1754 ensure_icon_info (GtkWindow *window)
1756 GtkWindowIconInfo *info;
1758 info = get_icon_info (window);
1762 info = g_new0 (GtkWindowIconInfo, 1);
1763 g_object_set_data_full (G_OBJECT (window),
1764 "gtk-window-icon-info",
1773 get_pixmap_and_mask (GtkWindowIconInfo *parent_info,
1774 gboolean is_default_list,
1776 GdkPixmap **pmap_return,
1777 GdkBitmap **mask_return)
1779 GdkPixbuf *best_icon;
1783 *pmap_return = NULL;
1784 *mask_return = NULL;
1786 if (is_default_list &&
1787 default_icon_pixmap != NULL)
1789 /* Use shared icon pixmap (eventually will be stored on the
1792 if (default_icon_pixmap)
1793 g_object_ref (G_OBJECT (default_icon_pixmap));
1794 if (default_icon_mask)
1795 g_object_ref (G_OBJECT (default_icon_mask));
1797 *pmap_return = default_icon_pixmap;
1798 *mask_return = default_icon_mask;
1800 else if (parent_info && parent_info->icon_pixmap)
1802 if (parent_info->icon_pixmap)
1803 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1804 if (parent_info->icon_mask)
1805 g_object_ref (G_OBJECT (parent_info->icon_mask));
1807 *pmap_return = parent_info->icon_pixmap;
1808 *mask_return = parent_info->icon_mask;
1812 #define IDEAL_SIZE 48
1814 best_size = G_MAXINT;
1816 tmp_list = icon_list;
1817 while (tmp_list != NULL)
1819 GdkPixbuf *pixbuf = tmp_list->data;
1822 /* average width and height - if someone passes in a rectangular
1823 * icon they deserve what they get.
1825 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
1828 if (best_icon == NULL)
1835 /* icon is better if it's 32 pixels or larger, and closer to
1836 * the ideal size than the current best.
1839 (ABS (best_size - IDEAL_SIZE) <
1840 ABS (this - IDEAL_SIZE)))
1847 tmp_list = tmp_list->next;
1851 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
1852 gdk_colormap_get_system (),
1857 /* Save pmap/mask for others to use if appropriate */
1860 parent_info->icon_pixmap = *pmap_return;
1861 parent_info->icon_mask = *mask_return;
1863 if (parent_info->icon_pixmap)
1864 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1865 if (parent_info->icon_mask)
1866 g_object_ref (G_OBJECT (parent_info->icon_mask));
1868 else if (is_default_list)
1870 default_icon_pixmap = *pmap_return;
1871 default_icon_mask = *mask_return;
1873 if (default_icon_pixmap)
1874 g_object_add_weak_pointer (G_OBJECT (default_icon_pixmap),
1875 (gpointer*)&default_icon_pixmap);
1876 if (default_icon_mask)
1877 g_object_add_weak_pointer (G_OBJECT (default_icon_mask),
1878 (gpointer*)&default_icon_mask);
1884 gtk_window_realize_icon (GtkWindow *window)
1887 GtkWindowIconInfo *info;
1890 widget = GTK_WIDGET (window);
1892 g_return_if_fail (widget->window != NULL);
1894 /* no point setting an icon on override-redirect */
1895 if (window->type == GTK_WINDOW_POPUP)
1900 info = ensure_icon_info (window);
1905 g_return_if_fail (info->icon_pixmap == NULL);
1906 g_return_if_fail (info->icon_mask == NULL);
1908 info->using_default_icon = FALSE;
1909 info->using_parent_icon = FALSE;
1911 icon_list = info->icon_list;
1913 /* Inherit from transient parent */
1914 if (icon_list == NULL && window->transient_parent)
1916 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
1918 info->using_parent_icon = TRUE;
1921 /* Inherit from default */
1922 if (icon_list == NULL)
1924 icon_list = default_icon_list;
1926 info->using_default_icon = TRUE;
1929 gdk_window_set_icon_list (widget->window, icon_list);
1931 get_pixmap_and_mask (info->using_parent_icon ?
1932 ensure_icon_info (window->transient_parent) : NULL,
1933 info->using_default_icon,
1938 /* This is a slight ICCCM violation since it's a color pixmap not
1939 * a bitmap, but everyone does it.
1941 gdk_window_set_icon (widget->window,
1946 info->realized = TRUE;
1950 gtk_window_unrealize_icon (GtkWindow *window)
1952 GtkWindowIconInfo *info;
1955 widget = GTK_WIDGET (window);
1957 info = get_icon_info (window);
1962 if (info->icon_pixmap)
1963 g_object_unref (G_OBJECT (info->icon_pixmap));
1965 if (info->icon_mask)
1966 g_object_unref (G_OBJECT (info->icon_mask));
1968 info->icon_pixmap = NULL;
1969 info->icon_mask = NULL;
1971 /* We don't clear the properties on the window, just figure the
1972 * window is going away.
1975 info->realized = FALSE;
1979 * gtk_window_set_icon_list:
1980 * @window: a #GtkWindow
1981 * @list: list of #GdkPixbuf
1983 * Sets up the icon representing a #GtkWindow. The icon is used when
1984 * the window is minimized (also known as iconified). Some window
1985 * managers or desktop environments may also place it in the window
1986 * frame, or display it in other contexts.
1988 * gtk_window_set_icon_list() allows you to pass in the same icon in
1989 * several hand-drawn sizes. The list should contain the natural sizes
1990 * your icon is available in; that is, don't scale the image before
1991 * passing it to GTK+. Scaling is postponed until the last minute,
1992 * when the desired final size is known, to allow best quality.
1994 * By passing several sizes, you may improve the final image quality
1995 * of the icon, by reducing or eliminating automatic image scaling.
1997 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
1998 * larger images (64x64, 128x128) if you have them.
2000 * See also gtk_window_set_default_icon_list() to set the icon
2001 * for all windows in your application in one go.
2003 * Note that transient windows (those who have been set transient for another
2004 * window using gtk_window_set_transient_for()) will inherit their
2005 * icon from their transient parent. So there's no need to explicitly
2006 * set the icon on transient windows.
2009 gtk_window_set_icon_list (GtkWindow *window,
2012 GtkWindowIconInfo *info;
2014 g_return_if_fail (GTK_IS_WINDOW (window));
2016 info = ensure_icon_info (window);
2018 if (info->icon_list == list) /* check for NULL mostly */
2021 g_list_foreach (info->icon_list,
2022 (GFunc) g_object_unref, NULL);
2024 g_list_free (info->icon_list);
2026 info->icon_list = g_list_copy (list);
2027 g_list_foreach (info->icon_list,
2028 (GFunc) g_object_ref, NULL);
2030 g_object_notify (G_OBJECT (window), "icon");
2032 gtk_window_unrealize_icon (window);
2034 if (GTK_WIDGET_REALIZED (window))
2035 gtk_window_realize_icon (window);
2037 /* We could try to update our transient children, but I don't think
2038 * it's really worth it. If we did it, the best way would probably
2039 * be to have children connect to notify::icon_list
2044 * gtk_window_get_icon_list:
2045 * @window: a #GtkWindow
2047 * Retrieves the list of icons set by gtk_window_set_icon_list().
2048 * The list is copied, but the reference count on each
2049 * member won't be incremented.
2051 * Return value: copy of window's icon list
2054 gtk_window_get_icon_list (GtkWindow *window)
2056 GtkWindowIconInfo *info;
2058 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2060 info = get_icon_info (window);
2063 return g_list_copy (info->icon_list);
2069 * gtk_window_set_icon:
2070 * @window: a #GtkWindow
2071 * @icon: icon image, or %NULL
2073 * Sets up the icon representing a #GtkWindow. This icon is used when
2074 * the window is minimized (also known as iconified). Some window
2075 * managers or desktop environments may also place it in the window
2076 * frame, or display it in other contexts.
2078 * The icon should be provided in whatever size it was naturally
2079 * drawn; that is, don't scale the image before passing it to
2080 * GTK+. Scaling is postponed until the last minute, when the desired
2081 * final size is known, to allow best quality.
2083 * If you have your icon hand-drawn in multiple sizes, use
2084 * gtk_window_set_icon_list(). Then the best size will be used.
2086 * This function is equivalent to calling gtk_window_set_icon_list()
2087 * with a 1-element list.
2089 * See also gtk_window_set_default_icon_list() to set the icon
2090 * for all windows in your application in one go.
2093 gtk_window_set_icon (GtkWindow *window,
2098 g_return_if_fail (GTK_IS_WINDOW (window));
2099 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2102 list = g_list_append (list, icon);
2103 gtk_window_set_icon_list (window, list);
2108 * gtk_window_get_icon:
2109 * @window: a #GtkWindow
2111 * Gets the value set by gtk_window_set_icon() (or if you've
2112 * called gtk_window_set_icon_list(), gets the first icon in
2115 * Return value: icon for window
2118 gtk_window_get_icon (GtkWindow *window)
2120 GtkWindowIconInfo *info;
2122 info = get_icon_info (window);
2123 if (info && info->icon_list)
2124 return GDK_PIXBUF (info->icon_list->data);
2130 * gtk_window_set_default_icon_list:
2131 * @list: a list of #GdkPixbuf
2133 * Sets an icon list to be used as fallback for windows that haven't
2134 * had gtk_window_set_icon_list() called on them to set up a
2135 * window-specific icon list. This function allows you to set up the
2136 * icon for all windows in your app at once.
2138 * See gtk_window_set_icon_list() for more details.
2142 gtk_window_set_default_icon_list (GList *list)
2146 if (list == default_icon_list)
2149 if (default_icon_pixmap)
2150 g_object_unref (G_OBJECT (default_icon_pixmap));
2151 if (default_icon_mask)
2152 g_object_unref (G_OBJECT (default_icon_mask));
2154 default_icon_pixmap = NULL;
2155 default_icon_mask = NULL;
2157 g_list_foreach (default_icon_list,
2158 (GFunc) g_object_unref, NULL);
2160 g_list_free (default_icon_list);
2162 default_icon_list = g_list_copy (list);
2163 g_list_foreach (default_icon_list,
2164 (GFunc) g_object_ref, NULL);
2166 /* Update all toplevels */
2167 toplevels = gtk_window_list_toplevels ();
2168 tmp_list = toplevels;
2169 while (tmp_list != NULL)
2171 GtkWindowIconInfo *info;
2172 GtkWindow *w = tmp_list->data;
2174 info = get_icon_info (w);
2175 if (info && info->using_default_icon)
2177 gtk_window_unrealize_icon (w);
2178 if (GTK_WIDGET_REALIZED (w))
2179 gtk_window_realize_icon (w);
2182 tmp_list = tmp_list->next;
2184 g_list_free (toplevels);
2188 * gtk_window_get_default_icon_list:
2190 * Gets the value set by gtk_window_set_default_icon_list().
2191 * The list is a copy and should be freed with g_list_free(),
2192 * but the pixbufs in the list have not had their reference count
2195 * Return value: copy of default icon list
2198 gtk_window_get_default_icon_list (void)
2200 return g_list_copy (default_icon_list);
2204 gtk_window_set_default_size_internal (GtkWindow *window,
2205 gboolean change_width,
2207 gboolean change_height,
2210 GtkWindowGeometryInfo *info;
2212 g_return_if_fail (GTK_IS_WINDOW (window));
2213 g_return_if_fail (change_width == FALSE || width >= -1);
2214 g_return_if_fail (change_height == FALSE || height >= -1);
2216 info = gtk_window_get_geometry_info (window, TRUE);
2218 g_object_freeze_notify (G_OBJECT (window));
2228 info->default_width = width;
2230 g_object_notify (G_OBJECT (window), "default_width");
2241 info->default_height = height;
2243 g_object_notify (G_OBJECT (window), "default_height");
2246 g_object_thaw_notify (G_OBJECT (window));
2248 gtk_widget_queue_resize (GTK_WIDGET (window));
2252 * gtk_window_set_default_size:
2253 * @window: a #GtkWindow
2254 * @width: width in pixels, or -1 to unset the default width
2255 * @height: height in pixels, or -1 to unset the default height
2257 * Sets the default size of a window. If the window's "natural" size
2258 * (its size request) is larger than the default, the default will be
2259 * ignored. More generally, if the default size does not obey the
2260 * geometry hints for the window (gtk_window_set_geometry_hints() can
2261 * be used to set these explicitly), the default size will be clamped
2262 * to the nearest permitted size.
2264 * Unlike gtk_widget_set_size_request(), which sets a size request for
2265 * a widget and thus would keep users from shrinking the window, this
2266 * function only sets the initial size, just as if the user had
2267 * resized the window themselves. Users can still shrink the window
2268 * again as they normally would. Setting a default size of -1 means to
2269 * use the "natural" default size (the size request of the window).
2271 * For more control over a window's initial size and how resizing works,
2272 * investigate gtk_window_set_geometry_hints().
2274 * A useful feature: if you set the "geometry widget" via
2275 * gtk_window_set_geometry_hints(), the default size specified by
2276 * gtk_window_set_default_size() will be the default size of that
2277 * widget, not of the entire window.
2279 * For some uses, gtk_window_resize() is a more appropriate function.
2280 * gtk_window_resize() changes the current size of the window, rather
2281 * than the size to be used on initial display. gtk_window_resize() always
2282 * affects the window itself, not the geometry widget.
2284 * The default size of a window only affects the first time a window is
2285 * shown; if a window is hidden and re-shown, it will remember the size
2286 * it had prior to hiding, rather than using the default size.
2288 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2289 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2292 gtk_window_set_default_size (GtkWindow *window,
2296 g_return_if_fail (GTK_IS_WINDOW (window));
2297 g_return_if_fail (width >= -1);
2298 g_return_if_fail (height >= -1);
2300 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height);
2304 * gtk_window_get_default_size:
2305 * @window: a #GtkWindow
2306 * @width: location to store the default width, or %NULL
2307 * @height: location to store the default height, or %NULL
2309 * Gets the default size of the window. A value of -1 for the width or
2310 * height indicates that a default size has not been explicitly set
2311 * for that dimension, so the "natural" size of the window will be
2316 gtk_window_get_default_size (GtkWindow *window,
2320 GtkWindowGeometryInfo *info;
2322 g_return_if_fail (GTK_IS_WINDOW (window));
2324 info = gtk_window_get_geometry_info (window, FALSE);
2327 *width = info->default_width;
2330 *height = info->default_height;
2334 * gtk_window_resize:
2335 * @window: a #GtkWindow
2336 * @width: width to resize the window to
2337 * @height: height to resize the window to
2339 * Resizes the window as if the user had done so, obeying geometry
2340 * constraints. The default geometry constraint is that windows may
2341 * not be smaller than their size request; to override this
2342 * constraint, call gtk_widget_set_size_request() to set the window's
2343 * request to a smaller value.
2345 * If gtk_window_resize() is called before showing a window for the
2346 * first time, it overrides any default size set with
2347 * gtk_window_set_default_size().
2349 * Windows may not be resized smaller than 1 by 1 pixels.
2353 gtk_window_resize (GtkWindow *window,
2357 GtkWindowGeometryInfo *info;
2359 g_return_if_fail (GTK_IS_WINDOW (window));
2360 g_return_if_fail (width > 0);
2361 g_return_if_fail (height > 0);
2363 info = gtk_window_get_geometry_info (window, TRUE);
2365 info->resize_width = width;
2366 info->resize_height = height;
2368 gtk_widget_queue_resize (GTK_WIDGET (window));
2372 * gtk_window_get_size:
2373 * @window: a #GtkWindow
2374 * @width: return location for width, or %NULL
2375 * @height: return location for height, or %NULL
2377 * Obtains the current size of @window. If @window is not onscreen,
2378 * it returns the size GTK+ will suggest to the window manager for the
2379 * initial window size (but this is not reliably the same as the size
2380 * the window manager will actually select). The size obtained by
2381 * gtk_window_get_size() is the last size received in a
2382 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2383 * rather than querying the X server for the size. As a result, if you
2384 * call gtk_window_resize() then immediately call
2385 * gtk_window_get_size(), the size won't have taken effect yet. After
2386 * the window manager processes the resize request, GTK+ receives
2387 * notification that the size has changed via a configure event, and
2388 * the size of the window gets updated.
2390 * Note 1: Nearly any use of this function creates a race condition,
2391 * because the size of the window may change between the time that you
2392 * get the size and the time that you perform some action assuming
2393 * that size is the current size. To avoid race conditions, connect to
2394 * "configure_event" on the window and adjust your size-dependent
2395 * state to match the size delivered in the #GdkEventConfigure.
2397 * Note 2: The returned size does NOT include the size of the window
2398 * manager decorations (aka the window frame or border). Those
2399 * are not drawn by GTK+ and GTK+ has no reliable method of
2400 * determining their size.
2402 * Note 3: If you are getting a window size in order to position
2403 * the window onscreen, there may be a better way. The preferred
2404 * way is to simply set the window's semantic type with
2405 * gtk_window_set_type_hint(), which allows the window manager to
2406 * e.g. center dialogs. Also, if you set the transient parent of
2407 * dialogs with gtk_widget_set_transient_for() window managers
2408 * will often center the dialog over its parent window. It's
2409 * much preferred to let the window manager handle these
2410 * things rather than doing it yourself, because all apps will
2411 * behave consistently and according to user prefs if the window
2412 * manager handles it. Also, the window manager can take the size
2413 * of the window decorations/border into account, while your
2414 * application cannot.
2416 * In any case, if you insist on application-specified window
2417 * positioning, there's STILL a better way than doing it yourself -
2418 * gtk_window_set_position() will frequently handle the details
2423 gtk_window_get_size (GtkWindow *window,
2430 g_return_if_fail (GTK_IS_WINDOW (window));
2432 widget = GTK_WIDGET (window);
2434 if (width == NULL && height == NULL)
2437 if (GTK_WIDGET_MAPPED (window))
2439 gdk_drawable_get_size (GTK_WIDGET (window)->window,
2444 GdkRectangle configure_request;
2446 gtk_window_compute_configure_request (window,
2450 w = configure_request.width;
2451 h = configure_request.height;
2462 * @window: a #GtkWindow
2463 * @x: X coordinate to move window to
2464 * @y: Y coordinate to move window to
2466 * Asks the window manager to move @window to the given position.
2467 * Window managers are free to ignore this; most window managers
2468 * ignore requests for initial window positions (instead using a
2469 * user-defined placement algorithm) and honor requests after the
2470 * window has already been shown.
2472 * Note: the position is the position of the gravity-determined
2473 * reference point for the window. The gravity determines two things:
2474 * first, the location of the reference point in root window
2475 * coordinates; and second, which point on the window is positioned at
2476 * the reference point.
2478 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
2479 * point is simply the @x, @y supplied to gtk_window_move(). The
2480 * top-left corner of the window decorations (aka window frame or
2481 * border) will be placed at @x, @y. Therefore, to position a window
2482 * at the top left of the screen, you want to use the default gravity
2483 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
2485 * To position a window at the bottom right corner of the screen, you
2486 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
2487 * point is at @x + the window width and @y + the window height, and
2488 * the bottom-right corner of the window border will be placed at that
2489 * reference point. So, to place a window in the bottom right corner
2490 * you would first set gravity to south east, then write:
2491 * gtk_window_move (window, gdk_screen_width () - window_width,
2492 * gdk_screen_height () - window_height).
2494 * The extended window manager hints specification at
2495 * http://www.freedesktop.org/standards/wm-spec.html has a nice table
2496 * of gravities in the "implementation notes" section.
2498 * The gtk_window_get_position() documentation may also be relevant.
2502 gtk_window_move (GtkWindow *window,
2506 GtkWindowGeometryInfo *info;
2509 g_return_if_fail (GTK_IS_WINDOW (window));
2511 widget = GTK_WIDGET (window);
2513 info = gtk_window_get_geometry_info (window, TRUE);
2515 if (GTK_WIDGET_MAPPED (window))
2517 /* we have now sent a request with this position
2518 * with currently-active constraints, so toggle flag.
2520 info->position_constraints_changed = FALSE;
2522 /* we only constrain if mapped - if not mapped,
2523 * then gtk_window_compute_configure_request()
2524 * will apply the constraints later, and we
2525 * don't want to lose information about
2526 * what position the user set before then.
2527 * i.e. if you do a move() then turn off POS_CENTER
2528 * then show the window, your move() will work.
2530 gtk_window_constrain_position (window,
2531 widget->allocation.width,
2532 widget->allocation.height,
2535 /* Note that this request doesn't go through our standard request
2536 * framework, e.g. doesn't increment configure_request_count,
2537 * doesn't set info->last, etc.; that's because
2538 * we don't save the info needed to arrive at this same request
2541 * To gtk_window_move_resize(), this will end up looking exactly
2542 * the same as the position being changed by the window
2546 /* FIXME are we handling gravity properly for framed windows? */
2548 gdk_window_move (window->frame,
2549 x - window->frame_left,
2550 y - window->frame_top);
2552 gdk_window_move (GTK_WIDGET (window)->window,
2557 /* Save this position to apply on mapping */
2558 info->initial_x = x;
2559 info->initial_y = y;
2560 info->initial_pos_set = TRUE;
2565 * gtk_window_get_position:
2566 * @window: a #GtkWindow
2567 * @root_x: return location for X coordinate of gravity-determined reference p\oint
2568 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
2570 * This function returns the position you need to pass to
2571 * gtk_window_move() to keep @window in its current position. This
2572 * means that the meaning of the returned value varies with window
2573 * gravity. See gtk_window_move() for more details.
2575 * If you haven't changed the window gravity, its gravity will be
2576 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
2577 * gets the position of the top-left corner of the window manager
2578 * frame for the window. gtk_window_move() sets the position of this
2579 * same top-left corner.
2581 * gtk_window_get_position() is not 100% reliable because the X Window System
2582 * does not specify a way to obtain the geometry of the
2583 * decorations placed on a window by the window manager.
2584 * Thus GTK+ is using a "best guess" that works with most
2587 * Moreover, nearly all window managers are broken with respect to
2588 * their handling of window gravity. So moving a window to its current
2589 * position as returned by gtk_window_get_position() tends to
2590 * result in moving the window slightly.
2592 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
2593 * frame is not relevant, and thus gtk_window_get_position() will
2594 * always produce accurate results. However you can't use static
2595 * gravity to do things like place a window in a corner of the screen,
2596 * because static gravity ignores the window manager decorations.
2598 * If you are saving and restoring your application's window
2599 * positions, you should know that it's impossible for applications to
2600 * do this without getting it somewhat wrong because applications do
2601 * not have sufficient knowledge of window manager state. The Correct
2602 * Mechanism is to support the session management protocol (see the
2603 * "GnomeClient" object in the GNOME libraries for example) and allow
2604 * the window manager to save your window sizes and positions.
2609 gtk_window_get_position (GtkWindow *window,
2615 g_return_if_fail (GTK_IS_WINDOW (window));
2617 widget = GTK_WIDGET (window);
2619 if (window->gravity == GDK_GRAVITY_STATIC)
2621 if (GTK_WIDGET_MAPPED (widget))
2623 /* This does a server round-trip, which is sort of wrong;
2624 * but a server round-trip is inevitable for
2625 * gdk_window_get_frame_extents() in the usual
2626 * NorthWestGravity case below, so not sure what else to
2627 * do. We should likely be consistent about whether we get
2628 * the client-side info or the server-side info.
2630 gdk_window_get_origin (widget->window, root_x, root_y);
2634 GdkRectangle configure_request;
2636 gtk_window_compute_configure_request (window,
2640 *root_x = configure_request.x;
2641 *root_y = configure_request.y;
2646 GdkRectangle frame_extents;
2651 if (GTK_WIDGET_MAPPED (widget))
2654 gdk_window_get_frame_extents (window->frame, &frame_extents);
2656 gdk_window_get_frame_extents (widget->window, &frame_extents);
2657 x = frame_extents.x;
2658 y = frame_extents.y;
2659 gtk_window_get_size (window, &w, &h);
2663 /* We just say the frame has 0 size on all sides.
2664 * Not sure what else to do.
2666 gtk_window_compute_configure_request (window,
2669 x = frame_extents.x;
2670 y = frame_extents.y;
2671 w = frame_extents.width;
2672 h = frame_extents.height;
2675 switch (window->gravity)
2677 case GDK_GRAVITY_NORTH:
2678 case GDK_GRAVITY_CENTER:
2679 case GDK_GRAVITY_SOUTH:
2680 /* Find center of frame. */
2681 x += frame_extents.width / 2;
2682 /* Center client window on that point. */
2686 case GDK_GRAVITY_SOUTH_EAST:
2687 case GDK_GRAVITY_EAST:
2688 case GDK_GRAVITY_NORTH_EAST:
2689 /* Find right edge of frame */
2690 x += frame_extents.width;
2691 /* Align left edge of client at that point. */
2698 switch (window->gravity)
2700 case GDK_GRAVITY_WEST:
2701 case GDK_GRAVITY_CENTER:
2702 case GDK_GRAVITY_EAST:
2703 /* Find center of frame. */
2704 y += frame_extents.height / 2;
2705 /* Center client window there. */
2708 case GDK_GRAVITY_SOUTH_WEST:
2709 case GDK_GRAVITY_SOUTH:
2710 case GDK_GRAVITY_SOUTH_EAST:
2711 /* Find south edge of frame */
2712 y += frame_extents.height;
2713 /* Place bottom edge of client there */
2728 * gtk_window_reshow_with_initial_size:
2729 * @window: a #GtkWindow
2731 * Hides @window, then reshows it, resetting the
2732 * default size and position of the window. Used
2733 * by GUI builders only.
2736 gtk_window_reshow_with_initial_size (GtkWindow *window)
2740 g_return_if_fail (GTK_IS_WINDOW (window));
2742 widget = GTK_WIDGET (window);
2744 gtk_widget_hide (widget);
2745 gtk_widget_unrealize (widget);
2746 gtk_widget_show (widget);
2750 gtk_window_destroy (GtkObject *object)
2754 g_return_if_fail (GTK_IS_WINDOW (object));
2756 window = GTK_WINDOW (object);
2758 if (window->transient_parent)
2759 gtk_window_set_transient_for (window, NULL);
2761 /* frees the icons */
2762 gtk_window_set_icon_list (window, NULL);
2764 if (window->has_user_ref_count)
2766 window->has_user_ref_count = FALSE;
2767 gtk_widget_unref (GTK_WIDGET (window));
2771 gtk_window_group_remove_window (window->group, window);
2773 GTK_OBJECT_CLASS (parent_class)->destroy (object);
2777 gtk_window_mnemonic_hash_remove (gpointer key,
2781 GtkWindowMnemonic *mnemonic = key;
2782 GtkWindow *window = user;
2784 if (mnemonic->window == window)
2786 if (mnemonic->targets)
2788 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
2790 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
2791 name, mnemonic->targets->data);
2794 g_slist_free (mnemonic->targets);
2803 gtk_window_finalize (GObject *object)
2807 g_return_if_fail (GTK_IS_WINDOW (object));
2809 window = GTK_WINDOW (object);
2811 toplevel_list = g_slist_remove (toplevel_list, window);
2813 g_free (window->title);
2814 g_free (window->wmclass_name);
2815 g_free (window->wmclass_class);
2816 g_free (window->wm_role);
2818 g_hash_table_foreach_remove (mnemonic_hash_table,
2819 gtk_window_mnemonic_hash_remove,
2821 if (window->geometry_info)
2823 if (window->geometry_info->widget)
2824 gtk_signal_disconnect_by_func (GTK_OBJECT (window->geometry_info->widget),
2825 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
2826 &window->geometry_info->widget);
2827 g_free (window->geometry_info);
2830 G_OBJECT_CLASS (parent_class)->finalize (object);
2834 gtk_window_show (GtkWidget *widget)
2836 GtkWindow *window = GTK_WINDOW (widget);
2837 GtkContainer *container = GTK_CONTAINER (window);
2838 gboolean need_resize;
2840 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
2842 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
2843 container->need_resize = FALSE;
2847 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
2848 GtkAllocation allocation = { 0, 0 };
2849 GdkRectangle configure_request;
2850 GdkGeometry new_geometry;
2852 gboolean was_realized;
2854 /* We are going to go ahead and perform this configure request
2855 * and then emulate a configure notify by going ahead and
2856 * doing a size allocate. Sort of a synchronous
2857 * mini-copy of gtk_window_move_resize() here.
2859 gtk_window_compute_configure_request (window,
2864 /* We update this because we are going to go ahead
2865 * and gdk_window_resize() below, rather than
2868 info->last.configure_request.width = configure_request.width;
2869 info->last.configure_request.height = configure_request.height;
2871 /* and allocate the window - this is normally done
2872 * in move_resize in response to configure notify
2874 allocation.width = configure_request.width;
2875 allocation.height = configure_request.height;
2876 gtk_widget_size_allocate (widget, &allocation);
2878 /* Then we guarantee we have a realize */
2879 was_realized = FALSE;
2880 if (!GTK_WIDGET_REALIZED (widget))
2882 gtk_widget_realize (widget);
2883 was_realized = TRUE;
2886 /* Must be done after the windows are realized,
2887 * so that the decorations can be read
2889 gtk_decorated_window_calculate_frame_size (window);
2891 /* We only send configure request if we didn't just finish
2892 * creating the window; if we just created the window
2893 * then we created it with widget->allocation anyhow.
2896 gdk_window_resize (widget->window,
2897 configure_request.width,
2898 configure_request.height);
2901 gtk_container_check_resize (container);
2903 gtk_widget_map (widget);
2906 gtk_grab_add (widget);
2910 gtk_window_hide (GtkWidget *widget)
2914 g_return_if_fail (GTK_IS_WINDOW (widget));
2916 window = GTK_WINDOW (widget);
2918 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
2919 gtk_widget_unmap (widget);
2922 gtk_grab_remove (widget);
2926 gtk_window_map (GtkWidget *widget)
2929 GdkWindow *toplevel;
2931 g_return_if_fail (GTK_IS_WINDOW (widget));
2933 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
2935 window = GTK_WINDOW (widget);
2937 if (window->bin.child &&
2938 GTK_WIDGET_VISIBLE (window->bin.child) &&
2939 !GTK_WIDGET_MAPPED (window->bin.child))
2940 gtk_widget_map (window->bin.child);
2943 toplevel = window->frame;
2945 toplevel = widget->window;
2947 if (window->maximize_initially)
2948 gdk_window_maximize (toplevel);
2950 gdk_window_unmaximize (toplevel);
2952 if (window->stick_initially)
2953 gdk_window_stick (toplevel);
2955 gdk_window_unstick (toplevel);
2957 if (window->iconify_initially)
2958 gdk_window_iconify (toplevel);
2960 gdk_window_deiconify (toplevel);
2962 /* No longer use the default settings */
2963 window->need_default_size = FALSE;
2964 window->need_default_position = FALSE;
2966 gdk_window_show (widget->window);
2969 gdk_window_show (window->frame);
2973 gtk_window_unmap (GtkWidget *widget)
2976 GtkWindowGeometryInfo *info;
2978 window = GTK_WINDOW (widget);
2980 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
2982 gdk_window_withdraw (window->frame);
2984 gdk_window_withdraw (widget->window);
2986 window->configure_request_count = 0;
2987 window->configure_notify_received = FALSE;
2989 /* on unmap, we reset the default positioning of the window,
2990 * so it's placed again, but we don't reset the default
2991 * size of the window, so it's remembered.
2993 window->need_default_position = TRUE;
2995 info = gtk_window_get_geometry_info (window, FALSE);
2998 info->initial_pos_set = FALSE;
2999 info->position_constraints_changed = FALSE;
3004 gtk_window_realize (GtkWidget *widget)
3007 GdkWindow *parent_window;
3008 GdkWindowAttr attributes;
3009 gint attributes_mask;
3011 g_return_if_fail (GTK_IS_WINDOW (widget));
3013 window = GTK_WINDOW (widget);
3015 /* ensure widget tree is properly size allocated */
3016 if (widget->allocation.x == -1 &&
3017 widget->allocation.y == -1 &&
3018 widget->allocation.width == 1 &&
3019 widget->allocation.height == 1)
3021 GtkRequisition requisition;
3022 GtkAllocation allocation = { 0, 0, 200, 200 };
3024 gtk_widget_size_request (widget, &requisition);
3025 if (requisition.width || requisition.height)
3027 /* non-empty window */
3028 allocation.width = requisition.width;
3029 allocation.height = requisition.height;
3031 gtk_widget_size_allocate (widget, &allocation);
3033 gtk_container_queue_resize (GTK_CONTAINER (widget));
3035 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3038 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3040 switch (window->type)
3042 case GTK_WINDOW_TOPLEVEL:
3043 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3045 case GTK_WINDOW_POPUP:
3046 attributes.window_type = GDK_WINDOW_TEMP;
3049 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3053 attributes.title = window->title;
3054 attributes.wmclass_name = window->wmclass_name;
3055 attributes.wmclass_class = window->wmclass_class;
3056 attributes.wclass = GDK_INPUT_OUTPUT;
3057 attributes.visual = gtk_widget_get_visual (widget);
3058 attributes.colormap = gtk_widget_get_colormap (widget);
3060 if (window->has_frame)
3062 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3063 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3064 attributes.event_mask = (GDK_EXPOSURE_MASK |
3065 GDK_KEY_PRESS_MASK |
3066 GDK_ENTER_NOTIFY_MASK |
3067 GDK_LEAVE_NOTIFY_MASK |
3068 GDK_FOCUS_CHANGE_MASK |
3069 GDK_STRUCTURE_MASK |
3070 GDK_BUTTON_MOTION_MASK |
3071 GDK_POINTER_MOTION_HINT_MASK |
3072 GDK_BUTTON_PRESS_MASK |
3073 GDK_BUTTON_RELEASE_MASK);
3075 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3077 window->frame = gdk_window_new (NULL, &attributes, attributes_mask);
3078 gdk_window_set_user_data (window->frame, widget);
3080 attributes.window_type = GDK_WINDOW_CHILD;
3081 attributes.x = window->frame_left;
3082 attributes.y = window->frame_right;
3084 attributes_mask = GDK_WA_X | GDK_WA_Y;
3086 parent_window = window->frame;
3090 attributes_mask = 0;
3091 parent_window = NULL;
3094 attributes.width = widget->allocation.width;
3095 attributes.height = widget->allocation.height;
3096 attributes.event_mask = gtk_widget_get_events (widget);
3097 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3098 GDK_KEY_PRESS_MASK |
3099 GDK_ENTER_NOTIFY_MASK |
3100 GDK_LEAVE_NOTIFY_MASK |
3101 GDK_FOCUS_CHANGE_MASK |
3102 GDK_STRUCTURE_MASK);
3104 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3105 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3106 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3107 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3108 gdk_window_set_user_data (widget->window, window);
3110 widget->style = gtk_style_attach (widget->style, widget->window);
3111 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3113 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3115 /* This is a bad hack to set the window background. */
3116 gtk_window_paint (widget, NULL);
3118 if (window->transient_parent &&
3119 GTK_WIDGET_REALIZED (window->transient_parent))
3120 gdk_window_set_transient_for (widget->window,
3121 GTK_WIDGET (window->transient_parent)->window);
3123 if (window->wm_role)
3124 gdk_window_set_role (widget->window, window->wm_role);
3126 if (!window->decorated)
3127 gdk_window_set_decorations (widget->window, 0);
3129 gdk_window_set_type_hint (widget->window, window->type_hint);
3131 /* transient_for must be set to allow the modal hint */
3132 if (window->transient_parent && window->modal)
3133 gdk_window_set_modal_hint (widget->window, TRUE);
3135 gdk_window_set_modal_hint (widget->window, FALSE);
3138 gtk_window_realize_icon (window);
3142 gtk_window_unrealize (GtkWidget *widget)
3145 GtkWindowGeometryInfo *info;
3147 window = GTK_WINDOW (widget);
3149 /* On unrealize, we reset the size of the window such
3150 * that we will re-apply the default sizing stuff
3151 * next time we show the window.
3153 * Default positioning is reset on unmap, instead of unrealize.
3155 window->need_default_size = TRUE;
3156 info = gtk_window_get_geometry_info (window, FALSE);
3159 info->resize_width = -1;
3160 info->resize_height = -1;
3161 info->last.configure_request.x = 0;
3162 info->last.configure_request.y = 0;
3163 info->last.configure_request.width = -1;
3164 info->last.configure_request.height = -1;
3165 /* be sure we reset geom hints on re-realize */
3166 info->last.flags = 0;
3171 gdk_window_set_user_data (window->frame, NULL);
3172 gdk_window_destroy (window->frame);
3173 window->frame = NULL;
3177 gtk_window_unrealize_icon (window);
3179 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3183 gtk_window_size_request (GtkWidget *widget,
3184 GtkRequisition *requisition)
3189 g_return_if_fail (GTK_IS_WINDOW (widget));
3190 g_return_if_fail (requisition != NULL);
3192 window = GTK_WINDOW (widget);
3193 bin = GTK_BIN (window);
3195 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3196 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3198 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3200 GtkRequisition child_requisition;
3202 gtk_widget_size_request (bin->child, &child_requisition);
3204 requisition->width += child_requisition.width;
3205 requisition->height += child_requisition.height;
3210 gtk_window_size_allocate (GtkWidget *widget,
3211 GtkAllocation *allocation)
3214 GtkAllocation child_allocation;
3216 g_return_if_fail (GTK_IS_WINDOW (widget));
3217 g_return_if_fail (allocation != NULL);
3219 window = GTK_WINDOW (widget);
3220 widget->allocation = *allocation;
3222 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3224 child_allocation.x = GTK_CONTAINER (window)->border_width;
3225 child_allocation.y = GTK_CONTAINER (window)->border_width;
3226 child_allocation.width =
3227 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3228 child_allocation.height =
3229 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3231 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3234 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3236 gdk_window_resize (window->frame,
3237 allocation->width + window->frame_left + window->frame_right,
3238 allocation->height + window->frame_top + window->frame_bottom);
3243 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3246 gboolean return_val;
3249 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3250 g_return_val_if_fail (event != NULL, FALSE);
3252 window = GTK_WINDOW (widget);
3254 if (window->frame && (event->any.window == window->frame))
3256 if ((event->type != GDK_KEY_PRESS) &&
3257 (event->type != GDK_KEY_RELEASE) &&
3258 (event->type != GDK_FOCUS_CHANGE))
3260 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
3262 gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
3267 g_object_unref (event->any.window);
3268 event->any.window = g_object_ref (widget->window);
3276 gtk_window_frame_event (GtkWidget *widget, GdkEvent *event)
3278 GdkEventConfigure *configure_event;
3279 GtkWindow *window = GTK_WINDOW (widget);
3282 switch (event->type)
3285 configure_event = (GdkEventConfigure *)event;
3287 /* Invalidate the decorations */
3290 rect.width = configure_event->width;
3291 rect.height = configure_event->height;
3293 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3295 /* Pass on the (modified) configure event */
3296 configure_event->width -= window->frame_left + window->frame_right;
3297 configure_event->height -= window->frame_top + window->frame_bottom;
3298 return gtk_window_configure_event (widget, configure_event);
3307 gtk_window_configure_event (GtkWidget *widget,
3308 GdkEventConfigure *event)
3312 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3313 g_return_val_if_fail (event != NULL, FALSE);
3315 window = GTK_WINDOW (widget);
3317 /* window->configure_request_count incremented for each
3318 * configure request, and decremented to a min of 0 for
3319 * each configure notify.
3321 * All it means is that we know we will get at least
3322 * window->configure_request_count more configure notifies.
3323 * We could get more configure notifies than that; some
3324 * of the configure notifies we get may be unrelated to
3325 * the configure requests. But we will get at least
3326 * window->configure_request_count notifies.
3329 if (window->configure_request_count > 0)
3330 window->configure_request_count -= 1;
3332 /* As an optimization, we avoid a resize when possible.
3334 * The only times we can avoid a resize are:
3335 * - we know only the position changed, not the size
3336 * - we know we have made more requests and so will get more
3337 * notifies and can wait to resize when we get them
3340 if (window->configure_request_count > 0 ||
3341 (widget->allocation.width == event->width &&
3342 widget->allocation.height == event->height))
3346 * If we do need to resize, we do that by:
3347 * - filling in widget->allocation with the new size
3348 * - setting configure_notify_received to TRUE
3349 * for use in gtk_window_move_resize()
3350 * - queueing a resize, leading to invocation of
3351 * gtk_window_move_resize() in an idle handler
3355 window->configure_notify_received = TRUE;
3357 widget->allocation.width = event->width;
3358 widget->allocation.height = event->height;
3360 gtk_widget_queue_resize (widget);
3366 gtk_window_key_press_event (GtkWidget *widget,
3372 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3373 g_return_val_if_fail (event != NULL, FALSE);
3375 window = GTK_WINDOW (widget);
3379 if (window->focus_widget && window->focus_widget != widget &&
3380 GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
3381 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
3384 handled = gtk_window_mnemonic_activate (window,
3389 handled = gtk_accel_groups_activate (G_OBJECT (window), event->keyval, event->state);
3391 /* Chain up, invokes binding set */
3392 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
3393 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
3400 gtk_window_real_activate_default (GtkWindow *window)
3402 gtk_window_activate_default (window);
3406 gtk_window_real_activate_focus (GtkWindow *window)
3408 gtk_window_activate_focus (window);
3412 gtk_window_move_focus (GtkWindow *window,
3413 GtkDirectionType dir)
3415 gtk_widget_child_focus (GTK_WIDGET (window), dir);
3417 if (!GTK_CONTAINER (window)->focus_child)
3418 gtk_window_set_focus (window, NULL);
3422 gtk_window_key_release_event (GtkWidget *widget,
3428 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3429 g_return_val_if_fail (event != NULL, FALSE);
3431 window = GTK_WINDOW (widget);
3433 if (window->focus_widget &&
3434 window->focus_widget != widget &&
3435 GTK_WIDGET_SENSITIVE (window->focus_widget))
3437 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
3440 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
3441 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
3447 gtk_window_enter_notify_event (GtkWidget *widget,
3448 GdkEventCrossing *event)
3450 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3451 g_return_val_if_fail (event != NULL, FALSE);
3457 gtk_window_leave_notify_event (GtkWidget *widget,
3458 GdkEventCrossing *event)
3460 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3461 g_return_val_if_fail (event != NULL, FALSE);
3467 gtk_window_focus_in_event (GtkWidget *widget,
3468 GdkEventFocus *event)
3470 GtkWindow *window = GTK_WINDOW (widget);
3471 GdkEventFocus fevent;
3473 /* It appears spurious focus in events can occur when
3474 * the window is hidden. So we'll just check to see if
3475 * the window is visible before actually handling the
3478 if (GTK_WIDGET_VISIBLE (widget))
3480 window->has_focus = TRUE;
3482 if (window->focus_widget &&
3483 window->focus_widget != widget &&
3484 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3486 fevent.type = GDK_FOCUS_CHANGE;
3487 fevent.window = window->focus_widget->window;
3490 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
3498 gtk_window_focus_out_event (GtkWidget *widget,
3499 GdkEventFocus *event)
3501 GtkWindow *window = GTK_WINDOW (widget);
3502 GdkEventFocus fevent;
3504 window->has_focus = FALSE;
3506 if (window->focus_widget &&
3507 window->focus_widget != widget &&
3508 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3510 fevent.type = GDK_FOCUS_CHANGE;
3511 fevent.window = window->focus_widget->window;
3514 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
3520 static GdkAtom atom_rcfiles = GDK_NONE;
3523 gtk_window_read_rcfiles (GtkWidget *widget,
3524 GdkEventClient *event)
3526 GList *embedded_windows;
3528 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
3529 if (embedded_windows)
3534 for (i = 0; i < 5; i++)
3536 sev.data_format = 32;
3537 sev.message_type = atom_rcfiles;
3539 while (embedded_windows)
3541 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
3542 gdk_event_send_client_message ((GdkEvent *) &sev, xid);
3543 embedded_windows = embedded_windows->next;
3547 gtk_rc_reparse_all ();
3551 gtk_window_client_event (GtkWidget *widget,
3552 GdkEventClient *event)
3554 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3555 g_return_val_if_fail (event != NULL, FALSE);
3558 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
3560 if (event->message_type == atom_rcfiles)
3561 gtk_window_read_rcfiles (widget, event);
3567 gtk_window_check_resize (GtkContainer *container)
3571 g_return_if_fail (GTK_IS_WINDOW (container));
3573 window = GTK_WINDOW (container);
3575 if (GTK_WIDGET_VISIBLE (container))
3576 gtk_window_move_resize (window);
3580 gtk_window_focus (GtkWidget *widget,
3581 GtkDirectionType direction)
3585 GtkContainer *container;
3586 GtkWidget *old_focus_child;
3589 container = GTK_CONTAINER (widget);
3590 window = GTK_WINDOW (widget);
3591 bin = GTK_BIN (widget);
3593 old_focus_child = container->focus_child;
3595 /* We need a special implementation here to deal properly with wrapping
3596 * around in the tab chain without the danger of going into an
3599 if (old_focus_child)
3601 if (gtk_widget_child_focus (old_focus_child, direction))
3605 if (window->focus_widget)
3607 /* Wrapped off the end, clear the focus setting for the toplpevel */
3608 parent = window->focus_widget->parent;
3611 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
3612 parent = GTK_WIDGET (parent)->parent;
3615 gtk_window_set_focus (GTK_WINDOW (container), NULL);
3618 /* Now try to focus the first widget in the window */
3621 if (gtk_widget_child_focus (bin->child, direction))
3629 gtk_window_real_set_focus (GtkWindow *window,
3632 GdkEventFocus event;
3633 gboolean def_flags = 0;
3635 g_return_if_fail (GTK_IS_WINDOW (window));
3637 if (window->default_widget)
3638 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
3640 if (window->focus_widget)
3642 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3643 (window->focus_widget != window->default_widget))
3645 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3647 if (window->default_widget)
3648 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3651 if (window->has_focus)
3653 event.type = GDK_FOCUS_CHANGE;
3654 event.window = window->focus_widget->window;
3657 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
3661 window->focus_widget = focus;
3663 if (window->focus_widget)
3665 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3666 (window->focus_widget != window->default_widget))
3668 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
3669 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3671 if (window->default_widget)
3672 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3675 if (window->has_focus)
3677 event.type = GDK_FOCUS_CHANGE;
3678 event.window = window->focus_widget->window;
3681 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
3685 if (window->default_widget &&
3686 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
3687 gtk_widget_queue_draw (window->default_widget);
3690 /*********************************
3691 * Functions related to resizing *
3692 *********************************/
3694 /* This function doesn't constrain to geometry hints */
3696 gtk_window_compute_configure_request_size (GtkWindow *window,
3700 GtkRequisition requisition;
3701 GtkWindowGeometryInfo *info;
3705 * - we've done a size request
3708 widget = GTK_WIDGET (window);
3710 info = gtk_window_get_geometry_info (window, FALSE);
3712 if (window->need_default_size)
3714 gtk_widget_get_child_requisition (widget, &requisition);
3716 /* Default to requisition */
3717 *width = requisition.width;
3718 *height = requisition.height;
3720 /* If window is empty so requests 0, default to random nonzero size */
3721 if (*width == 0 && *height == 0)
3727 /* Override requisition with default size */
3731 if (info->default_width > 0)
3732 *width = info->default_width;
3734 if (info->default_height > 0)
3735 *height = info->default_height;
3740 /* Default to keeping current size */
3741 *width = widget->allocation.width;
3742 *height = widget->allocation.height;
3745 /* Override any size with gtk_window_resize() values */
3748 if (info->resize_width > 0)
3749 *width = info->resize_width;
3751 if (info->resize_height > 0)
3752 *height = info->resize_height;
3757 gtk_window_compute_configure_request (GtkWindow *window,
3758 GdkRectangle *request,
3759 GdkGeometry *geometry,
3762 GdkGeometry new_geometry;
3766 GtkWindowPosition pos;
3767 GtkWidget *parent_widget;
3768 GtkWindowGeometryInfo *info;
3771 widget = GTK_WIDGET (window);
3773 gtk_widget_size_request (widget, NULL);
3774 gtk_window_compute_configure_request_size (window, &w, &h);
3776 gtk_window_compute_hints (window, &new_geometry, &new_flags);
3777 gtk_window_constrain_size (window,
3778 &new_geometry, new_flags,
3782 parent_widget = (GtkWidget*) window->transient_parent;
3784 pos = window->position;
3785 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
3786 (parent_widget == NULL ||
3787 !GTK_WIDGET_MAPPED (parent_widget)))
3788 pos = GTK_WIN_POS_NONE;
3790 info = gtk_window_get_geometry_info (window, TRUE);
3792 /* by default, don't change position requested */
3793 x = info->last.configure_request.x;
3794 y = info->last.configure_request.y;
3796 if (window->need_default_position)
3799 /* FIXME this all interrelates with window gravity.
3800 * For most of them I think we want to set GRAVITY_CENTER.
3802 * Not sure how to go about that.
3807 /* here we are only handling CENTER_ALWAYS
3808 * as it relates to default positioning,
3809 * where it's equivalent to simply CENTER
3811 case GTK_WIN_POS_CENTER_ALWAYS:
3812 case GTK_WIN_POS_CENTER:
3814 gint screen_width = gdk_screen_width ();
3815 gint screen_height = gdk_screen_height ();
3817 x = (screen_width - w) / 2;
3818 y = (screen_height - h) / 2;
3822 case GTK_WIN_POS_CENTER_ON_PARENT:
3826 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
3828 gdk_window_get_origin (parent_widget->window,
3831 x = ox + (parent_widget->allocation.width - w) / 2;
3832 y = oy + (parent_widget->allocation.height - h) / 2;
3836 case GTK_WIN_POS_MOUSE:
3838 gint screen_width = gdk_screen_width ();
3839 gint screen_height = gdk_screen_height ();
3842 gdk_window_get_pointer (NULL, &px, &py, NULL);
3845 x = CLAMP (x, 0, screen_width - w);
3846 y = CLAMP (y, 0, screen_height - h);
3853 } /* if (window->need_default_position) */
3855 if (window->need_default_position &&
3856 info->initial_pos_set)
3858 x = info->initial_x;
3859 y = info->initial_y;
3860 gtk_window_constrain_position (window, w, h, &x, &y);
3866 request->height = h;
3869 *geometry = new_geometry;
3875 gtk_window_constrain_position (GtkWindow *window,
3881 /* See long comments in gtk_window_move_resize()
3882 * on when it's safe to call this function.
3884 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
3886 gint center_x, center_y;
3887 gint screen_width = gdk_screen_width ();
3888 gint screen_height = gdk_screen_height ();
3890 center_x = (screen_width - new_width) / 2;
3891 center_y = (screen_height - new_height) / 2;
3899 gtk_window_move_resize (GtkWindow *window)
3903 * First we determine whether any information has changed that would
3904 * cause us to revise our last configure request. If we would send
3905 * a different configure request from last time, then
3906 * configure_request_size_changed = TRUE or
3907 * configure_request_pos_changed = TRUE. configure_request_size_changed
3908 * may be true due to new hints, a gtk_window_resize(), or whatever.
3909 * configure_request_pos_changed may be true due to gtk_window_set_position()
3910 * or gtk_window_move().
3912 * If the configure request has changed, we send off a new one. To
3913 * ensure GTK invariants are maintained (resize queue does what it
3914 * should), we go ahead and size_allocate the requested size in this
3917 * If the configure request has not changed, we don't ever resend
3918 * it, because it could mean fighting the user or window manager.
3921 * To prepare the configure request, we come up with a base size/pos:
3922 * - the one from gtk_window_move()/gtk_window_resize()
3923 * - else default_width, default_height if we haven't ever
3925 * - else the size request if we haven't ever been mapped,
3926 * as a substitute default size
3927 * - else the current size of the window, as received from
3928 * configure notifies (i.e. the current allocation)
3930 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
3931 * the position request to be centered.
3934 GtkContainer *container;
3935 GtkWindowGeometryInfo *info;
3936 GdkGeometry new_geometry;
3938 GdkRectangle new_request;
3939 gboolean configure_request_size_changed;
3940 gboolean configure_request_pos_changed;
3941 gboolean hints_changed; /* do we need to send these again */
3942 GtkWindowLastGeometryInfo saved_last_info;
3944 widget = GTK_WIDGET (window);
3945 container = GTK_CONTAINER (widget);
3946 info = gtk_window_get_geometry_info (window, TRUE);
3948 configure_request_size_changed = FALSE;
3949 configure_request_pos_changed = FALSE;
3951 gtk_window_compute_configure_request (window, &new_request,
3952 &new_geometry, &new_flags);
3954 /* This check implies the invariant that we never set info->last
3955 * without setting the hints and sending off a configure request.
3957 * If we change info->last without sending the request, we may
3960 if (info->last.configure_request.x != new_request.x ||
3961 info->last.configure_request.y != new_request.y)
3962 configure_request_pos_changed = TRUE;
3964 /* To change, we must be different from BOTH the last request, and
3965 * also our current size as received from the most recent configure
3968 * If different from last request, it means some sizing
3969 * parameters have changed; but one possible such sizing
3970 * parameter could be the current size.
3972 * We never want to re-request our current size, because that could
3973 * lead to some strange infinite loops if a window manager did
3974 * something insane but ICCCM-compliant such as add 2 to all
3975 * requested sizes. (i.e. if the WM always assigned a size that
3976 * was a function of the requested size, rather than a constraint
3977 * applied to requested size - so that requesting current size
3978 * did not result in getting that size back)
3980 * So here we detect and prevent any attempt to set size
3983 * (FIXME I think some race may be possible here, but
3984 * perhaps avoided by configure_request_count?)
3986 if ((info->last.configure_request.width != new_request.width ||
3987 info->last.configure_request.height != new_request.height) &&
3988 (widget->allocation.width != new_request.width ||
3989 widget->allocation.height != new_request.height))
3990 configure_request_size_changed = TRUE;
3993 hints_changed = FALSE;
3995 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
3996 &new_geometry, new_flags))
3998 hints_changed = TRUE;
4001 /* Position Constraints
4002 * ====================
4004 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4005 * a default. The other POS_ values are used only when the
4006 * window is shown, not after that.
4008 * However, we can't implement a position constraint as
4009 * "anytime the window size changes, center the window"
4010 * because this may well end up fighting the WM or user. In
4011 * fact it gets in an infinite loop with at least one WM.
4013 * Basically, applications are in no way in a position to
4014 * constrain the position of a window, with one exception:
4015 * override redirect windows. (Really the intended purpose
4016 * of CENTER_ALWAYS anyhow, I would think.)
4018 * So the way we implement this "constraint" is to say that when WE
4019 * cause a move or resize, i.e. we make a configure request changing
4020 * window size, we recompute the CENTER_ALWAYS position to reflect
4021 * the new window size, and include it in our request. Also, if we
4022 * just turned on CENTER_ALWAYS we snap to center with a new
4023 * request. Otherwise, if we are just NOTIFIED of a move or resize
4024 * done by someone else e.g. the window manager, we do NOT send a
4025 * new configure request.
4027 * For override redirect windows, this works fine; all window
4028 * sizes are from our configure requests. For managed windows,
4029 * it is at least semi-sane, though who knows what the
4030 * app author is thinking.
4033 /* This condition should be kept in sync with the condition later on
4034 * that determines whether we send a configure request. i.e. we
4035 * should do this position constraining anytime we were going to
4036 * send a configure request anyhow, plus when constraints have
4039 if (configure_request_pos_changed ||
4040 configure_request_size_changed ||
4042 info->position_constraints_changed)
4044 /* We request the constrained position if:
4045 * - we were changing position, and need to clamp
4046 * the change to the constraint
4047 * - we're changing the size anyway
4048 * - set_position() was called to toggle CENTER_ALWAYS on
4051 gtk_window_constrain_position (window,
4057 /* Update whether we need to request a move */
4058 if (info->last.configure_request.x != new_request.x ||
4059 info->last.configure_request.y != new_request.y)
4060 configure_request_pos_changed = TRUE;
4062 configure_request_pos_changed = FALSE;
4067 int notify_x, notify_y;
4069 /* this is the position from the last configure notify */
4070 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4072 g_print ("--- %s ---\n"
4073 "last : %d,%d\t%d x %d\n"
4074 "this : %d,%d\t%d x %d\n"
4075 "alloc: %d,%d\t%d x %d\n"
4077 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4078 "configure_notify_received: %d\n"
4079 "configure_request_count: %d\n"
4080 "position_constraints_changed: %d\n",
4081 window->title ? window->title : "(no title)",
4082 info->last.configure_request.x,
4083 info->last.configure_request.y,
4084 info->last.configure_request.width,
4085 info->last.configure_request.height,
4091 widget->allocation.width,
4092 widget->allocation.height,
4093 widget->requisition.width,
4094 widget->requisition.height,
4095 configure_request_pos_changed,
4096 configure_request_size_changed,
4098 window->configure_notify_received,
4099 window->configure_request_count,
4100 info->position_constraints_changed);
4104 saved_last_info = info->last;
4105 info->last.geometry = new_geometry;
4106 info->last.flags = new_flags;
4107 info->last.configure_request = new_request;
4109 /* need to set PPosition so the WM will look at our position,
4110 * but we don't want to count PPosition coming and going as a hints
4111 * change for future iterations. So we saved info->last prior to
4115 /* Also, if the initial position was explicitly set, then we always
4116 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4120 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4121 * this is an initial map
4124 if ((configure_request_pos_changed ||
4125 info->initial_pos_set ||
4126 (window->need_default_position &&
4127 window->position != GTK_WIN_POS_NONE)) &&
4128 (new_flags & GDK_HINT_POS) == 0)
4130 new_flags |= GDK_HINT_POS;
4131 hints_changed = TRUE;
4134 /* Set hints if necessary
4137 gdk_window_set_geometry_hints (widget->window,
4141 /* handle resizing/moving and widget tree allocation
4143 if (window->configure_notify_received)
4145 GtkAllocation allocation;
4147 /* If we have received a configure event since
4148 * the last time in this function, we need to
4149 * accept our new size and size_allocate child widgets.
4150 * (see gtk_window_configure_event() for more details).
4152 * 1 or more configure notifies may have been received.
4153 * Also, configure_notify_received will only be TRUE
4154 * if all expected configure notifies have been received
4155 * (one per configure request), as an optimization.
4158 window->configure_notify_received = FALSE;
4160 /* gtk_window_configure_event() filled in widget->allocation */
4161 allocation = widget->allocation;
4162 gtk_widget_size_allocate (widget, &allocation);
4163 gtk_widget_queue_draw (widget);
4165 /* If the configure request changed, it means that
4167 * 1) coincidentally changed hints or widget properties
4168 * impacting the configure request before getting
4169 * a configure notify, or
4170 * 2) some broken widget is changing its size request
4171 * during size allocation, resulting in
4172 * a false appearance of changed configure request.
4174 * For 1), we could just go ahead and ask for the
4175 * new size right now, but doing that for 2)
4176 * might well be fighting the user (and can even
4177 * trigger a loop). Since we really don't want to
4178 * do that, we requeue a resize in hopes that
4179 * by the time it gets handled, the child has seen
4180 * the light and is willing to go along with the
4181 * new size. (this happens for the zvt widget, since
4182 * the size_allocate() above will have stored the
4183 * requisition corresponding to the new size in the
4186 * This doesn't buy us anything for 1), but it shouldn't
4187 * hurt us too badly, since it is what would have
4188 * happened if we had gotten the configure event before
4189 * the new size had been set.
4192 if (configure_request_size_changed ||
4193 configure_request_pos_changed)
4195 /* Don't change the recorded last info after all, because we
4196 * haven't actually updated to the new info yet - we decided
4197 * to postpone our configure request until later.
4199 info->last = saved_last_info;
4201 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
4204 else if (configure_request_pos_changed ||
4205 configure_request_size_changed ||
4208 /* We are in one of the following situations:
4209 * A. configure_request_size_changed
4210 * our requisition has changed and we need a different window size,
4211 * so we request it from the window manager.
4212 * B. !configure_request_size_changed
4213 * the window manager wouldn't assign us the size we requested, in this
4214 * case we don't try to request a new size with every resize.
4215 * C. !configure_request_size_changed && hints_changed
4216 * the window manager rejects our size, but we have just changed the
4217 * window manager hints, so there's a certain chance our request will
4218 * be honoured this time, so we try again.
4219 * D. configure_request_pos_changed
4220 * we need to move to a new position, in which case we can also request
4221 * a new size since any of A-C might also apply.
4224 /* Now send the configure request */
4225 if (configure_request_pos_changed)
4229 gdk_window_move_resize (window->frame,
4230 new_request.x - window->frame_left,
4231 new_request.y - window->frame_top,
4232 new_request.width + window->frame_left + window->frame_right,
4233 new_request.height + window->frame_top + window->frame_bottom);
4234 gdk_window_resize (GTK_WIDGET (window)->window,
4235 new_request.width, new_request.height);
4238 gdk_window_move_resize (widget->window,
4239 new_request.x, new_request.y,
4240 new_request.width, new_request.height);
4242 else /* only size changed */
4245 gdk_window_resize (window->frame,
4246 new_request.width + window->frame_left + window->frame_right,
4247 new_request.height + window->frame_top + window->frame_bottom);
4248 gdk_window_resize (widget->window,
4249 new_request.width, new_request.height);
4252 /* Increment the number of have-not-yet-received-notify requests */
4253 window->configure_request_count += 1;
4255 /* We have now sent a request since the last position constraint
4256 * change and definitely don't need a an initial size again (not
4257 * resetting this here can lead to infinite loops for
4258 * GTK_RESIZE_IMMEDIATE containers)
4260 info->position_constraints_changed = FALSE;
4261 window->need_default_position = FALSE;
4263 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
4264 * configure event in response to our resizing request.
4265 * the configure event will cause a new resize with
4266 * ->configure_notify_received=TRUE.
4267 * until then, we want to
4268 * - discard expose events
4269 * - coalesce resizes for our children
4270 * - defer any window resizes until the configure event arrived
4271 * to achieve this, we queue a resize for the window, but remove its
4272 * resizing handler, so resizing will not be handled from the next
4273 * idle handler but when the configure event arrives.
4275 * FIXME: we should also dequeue the pending redraws here, since
4276 * we handle those ourselves upon ->configure_notify_received==TRUE.
4278 if (container->resize_mode == GTK_RESIZE_QUEUE)
4280 gtk_widget_queue_resize (widget);
4281 _gtk_container_dequeue_resize_handler (container);
4286 /* Not requesting anything new from WM, just had a queue resize
4287 * for some reason, so handle the resize queue
4289 if (container->resize_widgets)
4290 gtk_container_resize_children (container);
4294 /* Compare two sets of Geometry hints for equality.
4297 gtk_window_compare_hints (GdkGeometry *geometry_a,
4299 GdkGeometry *geometry_b,
4302 if (flags_a != flags_b)
4305 if ((flags_a & GDK_HINT_MIN_SIZE) &&
4306 (geometry_a->min_width != geometry_b->min_width ||
4307 geometry_a->min_height != geometry_b->min_height))
4310 if ((flags_a & GDK_HINT_MAX_SIZE) &&
4311 (geometry_a->max_width != geometry_b->max_width ||
4312 geometry_a->max_height != geometry_b->max_height))
4315 if ((flags_a & GDK_HINT_BASE_SIZE) &&
4316 (geometry_a->base_width != geometry_b->base_width ||
4317 geometry_a->base_height != geometry_b->base_height))
4320 if ((flags_a & GDK_HINT_ASPECT) &&
4321 (geometry_a->min_aspect != geometry_b->min_aspect ||
4322 geometry_a->max_aspect != geometry_b->max_aspect))
4325 if ((flags_a & GDK_HINT_RESIZE_INC) &&
4326 (geometry_a->width_inc != geometry_b->width_inc ||
4327 geometry_a->height_inc != geometry_b->height_inc))
4330 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
4331 geometry_a->win_gravity != geometry_b->win_gravity)
4338 _gtk_window_constrain_size (GtkWindow *window,
4344 GtkWindowGeometryInfo *info;
4346 g_return_if_fail (GTK_IS_WINDOW (window));
4348 info = window->geometry_info;
4351 GdkWindowHints flags = info->last.flags;
4352 GdkGeometry *geometry = &info->last.geometry;
4354 gtk_window_constrain_size (window,
4365 gtk_window_constrain_size (GtkWindow *window,
4366 GdkGeometry *geometry,
4373 gdk_window_constrain_size (geometry, flags, width, height,
4374 new_width, new_height);
4377 /* Compute the set of geometry hints and flags for a window
4378 * based on the application set geometry, and requisiition
4379 * of the window. gtk_widget_size_request() must have been
4383 gtk_window_compute_hints (GtkWindow *window,
4384 GdkGeometry *new_geometry,
4388 gint extra_width = 0;
4389 gint extra_height = 0;
4390 GtkWindowGeometryInfo *geometry_info;
4391 GtkRequisition requisition;
4393 g_return_if_fail (GTK_IS_WINDOW (window));
4395 widget = GTK_WIDGET (window);
4397 gtk_widget_get_child_requisition (widget, &requisition);
4398 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
4402 *new_flags = geometry_info->mask;
4403 *new_geometry = geometry_info->geometry;
4410 if (geometry_info && geometry_info->widget)
4412 extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
4413 extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
4416 /* We don't want to set GDK_HINT_POS in here, we just set it
4417 * in gtk_window_move_resize() when we want the position
4421 if (*new_flags & GDK_HINT_BASE_SIZE)
4423 new_geometry->base_width += extra_width;
4424 new_geometry->base_height += extra_height;
4426 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
4427 (*new_flags & GDK_HINT_RESIZE_INC) &&
4428 ((extra_width != 0) || (extra_height != 0)))
4430 *new_flags |= GDK_HINT_BASE_SIZE;
4432 new_geometry->base_width = extra_width;
4433 new_geometry->base_height = extra_height;
4436 if (*new_flags & GDK_HINT_MIN_SIZE)
4438 if (new_geometry->min_width < 0)
4439 new_geometry->min_width = requisition.width;
4441 new_geometry->min_width += extra_width;
4443 if (new_geometry->min_height < 0)
4444 new_geometry->min_height = requisition.height;
4446 new_geometry->min_height += extra_height;
4448 else if (!window->allow_shrink)
4450 *new_flags |= GDK_HINT_MIN_SIZE;
4452 new_geometry->min_width = requisition.width;
4453 new_geometry->min_height = requisition.height;
4456 if (*new_flags & GDK_HINT_MAX_SIZE)
4458 if (new_geometry->max_width < 0)
4459 new_geometry->max_width = requisition.width;
4461 new_geometry->max_width += extra_width;
4463 if (new_geometry->max_height < 0)
4464 new_geometry->max_width = requisition.height;
4466 new_geometry->max_height += extra_height;
4468 else if (!window->allow_grow)
4470 *new_flags |= GDK_HINT_MAX_SIZE;
4472 new_geometry->max_width = requisition.width;
4473 new_geometry->max_height = requisition.height;
4476 *new_flags |= GDK_HINT_WIN_GRAVITY;
4477 new_geometry->win_gravity = window->gravity;
4480 /***********************
4481 * Redrawing functions *
4482 ***********************/
4485 gtk_window_paint (GtkWidget *widget,
4488 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
4489 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
4493 gtk_window_expose (GtkWidget *widget,
4494 GdkEventExpose *event)
4496 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
4497 g_return_val_if_fail (event != NULL, FALSE);
4499 if (!GTK_WIDGET_APP_PAINTABLE (widget))
4500 gtk_window_paint (widget, &event->area);
4502 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
4503 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
4509 * gtk_window_set_has_frame:
4510 * @window: a #GtkWindow
4511 * @setting: a boolean
4513 * If this function is called on a window with setting of TRUE, before
4514 * it is realized or showed, it will have a "frame" window around
4515 * widget->window, accessible in window->frame. Using the signal
4516 * frame_event you can recieve all events targeted at the frame.
4518 * This function is used by the linux-fb port to implement managed
4519 * windows, but it could concievably be used by X-programs that
4520 * want to do their own window decorations.
4523 gtk_window_set_has_frame (GtkWindow *window,
4526 g_return_if_fail (GTK_IS_WINDOW (window));
4527 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
4529 window->has_frame = setting != FALSE;
4533 * gtk_window_get_has_frame:
4534 * @window: a #GtkWindow
4536 * Accessor for whether the window has a frame window exterior to
4537 * widget->window. See gtk_window_set_has_frame ().
4539 * Return value: %TRUE if a frame has been added to the window
4540 * via gtk_widow_has_frame
4543 gtk_window_get_has_frame (GtkWindow *window)
4545 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4547 return window->has_frame;
4551 * gtk_window_set_frame_dimensions:
4552 * @window: a #GtkWindow that has a frame
4553 * @left: The width of the left border
4554 * @top: The height of the top border
4555 * @right: The width of the right border
4556 * @bottom: The height of the bottom border
4558 * For windows with frames (see #gtk_window_set_has_frame) this function
4559 * can be used to change the size of the frame border.
4562 gtk_window_set_frame_dimensions (GtkWindow *window,
4568 GtkWidget *widget = GTK_WIDGET (window);
4570 g_return_if_fail (GTK_IS_WINDOW (window));
4572 if (window->frame_left == left &&
4573 window->frame_top == top &&
4574 window->frame_right == right &&
4575 window->frame_bottom == bottom)
4578 window->frame_left = left;
4579 window->frame_top = top;
4580 window->frame_right = right;
4581 window->frame_bottom = bottom;
4583 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4585 gint width = widget->allocation.width + left + right;
4586 gint height = widget->allocation.height + top + bottom;
4587 gdk_window_resize (window->frame, width, height);
4588 gtk_decorated_window_move_resize_window (window,
4590 widget->allocation.width,
4591 widget->allocation.height);
4596 * gtk_window_present:
4597 * @window: a #GtkWindow
4599 * Presents a window to the user. This may mean raising the window
4600 * in the stacking order, deiconifying it, moving it to the current
4601 * desktop, and/or giving it the keyboard focus, possibly dependent
4602 * on the user's platform, window manager, and preferences.
4604 * If @window is hidden, this function calls gtk_widget_show()
4607 * This function should be used when the user tries to open a window
4608 * that's already open. Say for example the preferences dialog is
4609 * currently open, and the user chooses Preferences from the menu
4610 * a second time; use gtk_window_present() to move the already-open dialog
4611 * where the user can see it.
4615 gtk_window_present (GtkWindow *window)
4619 g_return_if_fail (GTK_IS_WINDOW (window));
4621 widget = GTK_WIDGET (window);
4623 if (GTK_WIDGET_VISIBLE (window))
4625 g_assert (widget->window != NULL);
4627 gdk_window_show (widget->window);
4629 /* note that gdk_window_focus() will also move the window to
4630 * the current desktop, for WM spec compliant window managers.
4632 gdk_window_focus (widget->window,
4633 gtk_get_current_event_time ());
4637 gtk_widget_show (widget);
4642 * gtk_window_iconify:
4643 * @window: a #GtkWindow
4645 * Asks to iconify (i.e. minimize) the specified @window. Note that you
4646 * shouldn't assume the window is definitely iconified afterward,
4647 * because other entities (e.g. the user or window manager) could
4648 * deiconify it again, or there may not be a window manager in which
4649 * case iconification isn't possible, etc. But normally the window
4650 * will end up iconified. Just don't write code that crashes if not.
4652 * It's permitted to call this function before showing a window,
4653 * in which case the window will be iconified before it ever appears
4656 * You can track iconification via the "window_state_event" signal
4661 gtk_window_iconify (GtkWindow *window)
4664 GdkWindow *toplevel;
4666 g_return_if_fail (GTK_IS_WINDOW (window));
4668 widget = GTK_WIDGET (window);
4670 window->iconify_initially = TRUE;
4673 toplevel = window->frame;
4675 toplevel = widget->window;
4677 if (toplevel != NULL)
4678 gdk_window_iconify (toplevel);
4682 * gtk_window_deiconify:
4683 * @window: a #GtkWindow
4685 * Asks to deiconify (i.e. unminimize) the specified @window. Note
4686 * that you shouldn't assume the window is definitely deiconified
4687 * afterward, because other entities (e.g. the user or window manager)
4688 * could iconify it again before your code which assumes
4689 * deiconification gets to run.
4691 * You can track iconification via the "window_state_event" signal
4695 gtk_window_deiconify (GtkWindow *window)
4698 GdkWindow *toplevel;
4700 g_return_if_fail (GTK_IS_WINDOW (window));
4702 widget = GTK_WIDGET (window);
4704 window->iconify_initially = FALSE;
4707 toplevel = window->frame;
4709 toplevel = widget->window;
4711 if (toplevel != NULL)
4712 gdk_window_deiconify (toplevel);
4717 * @window: a #GtkWindow
4719 * Asks to stick @window, which means that it will appear on all user
4720 * desktops. Note that you shouldn't assume the window is definitely
4721 * stuck afterward, because other entities (e.g. the user or window
4722 * manager) could unstick it again, and some window managers do not
4723 * support sticking windows. But normally the window will end up
4724 * stuck. Just don't write code that crashes if not.
4726 * It's permitted to call this function before showing a window.
4728 * You can track stickiness via the "window_state_event" signal
4733 gtk_window_stick (GtkWindow *window)
4736 GdkWindow *toplevel;
4738 g_return_if_fail (GTK_IS_WINDOW (window));
4740 widget = GTK_WIDGET (window);
4742 window->stick_initially = TRUE;
4745 toplevel = window->frame;
4747 toplevel = widget->window;
4749 if (toplevel != NULL)
4750 gdk_window_stick (toplevel);
4754 * gtk_window_unstick:
4755 * @window: a #GtkWindow
4757 * Asks to unstick @window, which means that it will appear on only
4758 * one of the user's desktops. Note that you shouldn't assume the
4759 * window is definitely unstuck afterward, because other entities
4760 * (e.g. the user or window manager) could stick it again. But
4761 * normally the window will end up stuck. Just don't write code that
4764 * You can track stickiness via the "window_state_event" signal
4769 gtk_window_unstick (GtkWindow *window)
4772 GdkWindow *toplevel;
4774 g_return_if_fail (GTK_IS_WINDOW (window));
4776 widget = GTK_WIDGET (window);
4778 window->stick_initially = FALSE;
4781 toplevel = window->frame;
4783 toplevel = widget->window;
4785 if (toplevel != NULL)
4786 gdk_window_unstick (toplevel);
4790 * gtk_window_maximize:
4791 * @window: a #GtkWindow
4793 * Asks to maximize @window, so that it becomes full-screen. Note that
4794 * you shouldn't assume the window is definitely maximized afterward,
4795 * because other entities (e.g. the user or window manager) could
4796 * unmaximize it again, and not all window managers support
4797 * maximization. But normally the window will end up maximized. Just
4798 * don't write code that crashes if not.
4800 * It's permitted to call this function before showing a window,
4801 * in which case the window will be maximized when it appears onscreen
4804 * You can track maximization via the "window_state_event" signal
4809 gtk_window_maximize (GtkWindow *window)
4812 GdkWindow *toplevel;
4814 g_return_if_fail (GTK_IS_WINDOW (window));
4816 widget = GTK_WIDGET (window);
4818 window->maximize_initially = TRUE;
4821 toplevel = window->frame;
4823 toplevel = widget->window;
4825 if (toplevel != NULL)
4826 gdk_window_maximize (toplevel);
4830 * gtk_window_unmaximize:
4831 * @window: a #GtkWindow
4833 * Asks to unmaximize @window. Note that you shouldn't assume the
4834 * window is definitely unmaximized afterward, because other entities
4835 * (e.g. the user or window manager) could maximize it again, and not
4836 * all window managers honor requests to unmaximize. But normally the
4837 * window will end up unmaximized. Just don't write code that crashes
4840 * You can track maximization via the "window_state_event" signal
4845 gtk_window_unmaximize (GtkWindow *window)
4848 GdkWindow *toplevel;
4850 g_return_if_fail (GTK_IS_WINDOW (window));
4852 widget = GTK_WIDGET (window);
4854 window->maximize_initially = FALSE;
4857 toplevel = window->frame;
4859 toplevel = widget->window;
4861 if (toplevel != NULL)
4862 gdk_window_unmaximize (toplevel);
4866 * gtk_window_set_resizable:
4867 * @window: a #GtkWindow
4868 * @resizable: %TRUE if the user can resize this window
4870 * Sets whether the user can resize a window. Windows are user resizable
4874 gtk_window_set_resizable (GtkWindow *window,
4877 g_return_if_fail (GTK_IS_WINDOW (window));
4879 gtk_window_set_policy (window, FALSE, resizable, FALSE);
4883 * gtk_window_get_resizable:
4884 * @window: a #GtkWindow
4886 * Gets the value set by gtk_window_set_resizable().
4888 * Return value: %TRUE if the user can resize the window
4891 gtk_window_get_resizable (GtkWindow *window)
4893 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4895 /* allow_grow is most likely to indicate the semantic concept we
4896 * mean by "resizable" (and will be a reliable indicator if
4897 * set_policy() hasn't been called)
4899 return window->allow_grow;
4903 * gtk_window_set_gravity:
4904 * @window: a #GtkWindow
4905 * @gravity: window gravity
4907 * Window gravity defines the meaning of coordinates passed to
4908 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
4911 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
4912 * typically "do what you mean."
4916 gtk_window_set_gravity (GtkWindow *window,
4919 g_return_if_fail (GTK_IS_WINDOW (window));
4921 if (gravity != window->gravity)
4923 window->gravity = gravity;
4925 /* gtk_window_move_resize() will adapt gravity
4927 gtk_widget_queue_resize (GTK_WIDGET (window));
4932 * gtk_window_get_gravity:
4933 * @window: a #GtkWindow
4935 * Gets the value set by gtk_window_set_gravity().
4937 * Return value: window gravity
4940 gtk_window_get_gravity (GtkWindow *window)
4942 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
4944 return window->gravity;
4948 * gtk_window_begin_resize_drag:
4949 * @window: a #GtkWindow
4950 * @button: mouse button that initiated the drag
4951 * @edge: position of the resize control
4952 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
4953 * @root_y: Y position where the user clicked to initiate the drag
4954 * @timestamp: timestamp from the click event that initiated the drag
4956 * Starts resizing a window. This function is used if an application
4957 * has window resizing controls. When GDK can support it, the resize
4958 * will be done using the standard mechanism for the window manager or
4959 * windowing system. Otherwise, GDK will try to emulate window
4960 * resizing, potentially not all that well, depending on the windowing system.
4964 gtk_window_begin_resize_drag (GtkWindow *window,
4972 GdkWindow *toplevel;
4974 g_return_if_fail (GTK_IS_WINDOW (window));
4975 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
4977 widget = GTK_WIDGET (window);
4980 toplevel = window->frame;
4982 toplevel = widget->window;
4984 gdk_window_begin_resize_drag (toplevel,
4991 * gtk_window_get_frame_dimensions:
4992 * @window: a #GtkWindow
4993 * @left: location to store the width of the frame at the left, or %NULL
4994 * @top: location to store the height of the frame at the top, or %NULL
4995 * @right: location to store the width of the frame at the returns, or %NULL
4996 * @bottom: location to store the height of the frame at the bottom, or %NULL
4998 * Retrieves the dimensions of the frame window for this toplevel.
4999 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5002 gtk_window_get_frame_dimensions (GtkWindow *window,
5008 g_return_if_fail (GTK_IS_WINDOW (window));
5011 *left = window->frame_left;
5013 *top = window->frame_top;
5015 *right = window->frame_right;
5017 *bottom = window->frame_bottom;
5021 * gtk_window_begin_move_drag:
5022 * @window: a #GtkWindow
5023 * @button: mouse button that initiated the drag
5024 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5025 * @root_y: Y position where the user clicked to initiate the drag
5026 * @timestamp: timestamp from the click event that initiated the drag
5028 * Starts moving a window. This function is used if an application
5029 * has window movement grips. When GDK can support it, the window movement
5030 * will be done using the standard mechanism for the window manager or
5031 * windowing system. Otherwise, GDK will try to emulate window
5032 * movement, potentially not all that well, depending on the windowing system.
5036 gtk_window_begin_move_drag (GtkWindow *window,
5043 GdkWindow *toplevel;
5045 g_return_if_fail (GTK_IS_WINDOW (window));
5046 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5048 widget = GTK_WIDGET (window);
5051 toplevel = window->frame;
5053 toplevel = widget->window;
5055 gdk_window_begin_move_drag (toplevel,
5063 gtk_window_group_class_init (GtkWindowGroupClass *klass)
5068 gtk_window_group_get_type (void)
5070 static GtkType window_group_type = 0;
5072 if (!window_group_type)
5074 static const GTypeInfo window_group_info =
5076 sizeof (GtkWindowGroupClass),
5077 NULL, /* base_init */
5078 NULL, /* base_finalize */
5079 (GClassInitFunc) gtk_window_group_class_init,
5080 NULL, /* class_finalize */
5081 NULL, /* class_data */
5082 sizeof (GtkWindowGroup),
5083 16, /* n_preallocs */
5084 (GInstanceInitFunc) NULL,
5087 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
5090 return window_group_type;
5094 * gtk_window_group_new:
5096 * Create a new #GtkWindowGroup object. Grabs added with
5097 * gtk_window_grab_add() only affect windows within the
5098 * same #GtkWindowGroup
5103 gtk_window_group_new (void)
5105 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
5109 window_group_cleanup_grabs (GtkWindowGroup *group,
5113 GSList *to_remove = NULL;
5115 tmp_list = group->grabs;
5118 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
5119 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
5120 tmp_list = tmp_list->next;
5125 gtk_grab_remove (to_remove->data);
5126 g_object_unref (to_remove->data);
5127 to_remove = g_slist_delete_link (to_remove, to_remove);
5132 * gtk_window_group_add_widget:
5133 * @window_group: a #GtkWindowGroup
5134 * @window: the #GtkWindow to add
5136 * Add a window to a #GtkWindowGroup.
5139 gtk_window_group_add_window (GtkWindowGroup *window_group,
5142 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5143 g_return_if_fail (GTK_IS_WINDOW (window));
5145 if (window->group != window_group)
5147 g_object_ref (window);
5148 g_object_ref (window_group);
5151 gtk_window_group_remove_window (window->group, window);
5153 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
5155 window->group = window_group;
5157 g_object_unref (window);
5162 * gtk_window_group_remove_window:
5163 * @window_group: a #GtkWindowGroup
5164 * @window: the #GtkWindow to remove
5166 * Removes a window from a #GtkWindowGroup.
5169 gtk_window_group_remove_window (GtkWindowGroup *window_group,
5172 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5173 g_return_if_fail (GTK_IS_WIDGET (window));
5174 g_return_if_fail (window->group == window_group);
5176 g_object_ref (window);
5178 window_group_cleanup_grabs (window_group, window);
5179 window->group = NULL;
5181 g_object_unref (G_OBJECT (window_group));
5182 g_object_unref (window);
5185 /* Return the group for the window or the default group
5188 _gtk_window_get_group (GtkWindow *window)
5190 if (window && window->group)
5191 return window->group;
5194 static GtkWindowGroup *default_group = NULL;
5197 default_group = gtk_window_group_new ();
5199 return default_group;
5205 Derived from XParseGeometry() in XFree86
5207 Copyright 1985, 1986, 1987,1998 The Open Group
5209 All Rights Reserved.
5211 The above copyright notice and this permission notice shall be included
5212 in all copies or substantial portions of the Software.
5214 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5215 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5216 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
5217 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
5218 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
5219 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
5220 OTHER DEALINGS IN THE SOFTWARE.
5222 Except as contained in this notice, the name of The Open Group shall
5223 not be used in advertising or otherwise to promote the sale, use or
5224 other dealings in this Software without prior written authorization
5225 from The Open Group.
5230 * XParseGeometry parses strings of the form
5231 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5232 * width, height, xoffset, and yoffset are unsigned integers.
5233 * Example: "=80x24+300-49"
5234 * The equal sign is optional.
5235 * It returns a bitmask that indicates which of the four values
5236 * were actually found in the string. For each value found,
5237 * the corresponding argument is updated; for each value
5238 * not found, the corresponding argument is left unchanged.
5241 /* The following code is from Xlib, and is minimally modified, so we
5242 * can track any upstream changes if required. Don't change this
5243 * code. Or if you do, put in a huge comment marking which thing
5248 read_int (gchar *string,
5256 else if (*string == '-')
5262 for (; (*string >= '0') && (*string <= '9'); string++)
5264 result = (result * 10) + (*string - '0');
5276 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
5277 * value (x, y, width, height) was found in the parsed string.
5279 #define NoValue 0x0000
5280 #define XValue 0x0001
5281 #define YValue 0x0002
5282 #define WidthValue 0x0004
5283 #define HeightValue 0x0008
5284 #define AllValues 0x000F
5285 #define XNegative 0x0010
5286 #define YNegative 0x0020
5288 /* Try not to reformat/modify, so we can compare/sync with X sources */
5290 gtk_XParseGeometry (const char *string,
5293 unsigned int *width,
5294 unsigned int *height)
5298 unsigned int tempWidth, tempHeight;
5300 char *nextCharacter;
5302 /* These initializations are just to silence gcc */
5308 if ( (string == NULL) || (*string == '\0')) return(mask);
5310 string++; /* ignore possible '=' at beg of geometry spec */
5312 strind = (char *)string;
5313 if (*strind != '+' && *strind != '-' && *strind != 'x') {
5314 tempWidth = read_int(strind, &nextCharacter);
5315 if (strind == nextCharacter)
5317 strind = nextCharacter;
5321 if (*strind == 'x' || *strind == 'X') {
5323 tempHeight = read_int(strind, &nextCharacter);
5324 if (strind == nextCharacter)
5326 strind = nextCharacter;
5327 mask |= HeightValue;
5330 if ((*strind == '+') || (*strind == '-')) {
5331 if (*strind == '-') {
5333 tempX = -read_int(strind, &nextCharacter);
5334 if (strind == nextCharacter)
5336 strind = nextCharacter;
5342 tempX = read_int(strind, &nextCharacter);
5343 if (strind == nextCharacter)
5345 strind = nextCharacter;
5348 if ((*strind == '+') || (*strind == '-')) {
5349 if (*strind == '-') {
5351 tempY = -read_int(strind, &nextCharacter);
5352 if (strind == nextCharacter)
5354 strind = nextCharacter;
5361 tempY = read_int(strind, &nextCharacter);
5362 if (strind == nextCharacter)
5364 strind = nextCharacter;
5370 /* If strind isn't at the end of the string the it's an invalid
5371 geometry specification. */
5373 if (*strind != '\0') return (0);
5379 if (mask & WidthValue)
5381 if (mask & HeightValue)
5382 *height = tempHeight;
5387 * gtk_window_parse_geometry:
5388 * @window: a #GtkWindow
5389 * @geometry: geometry string
5391 * Parses a standard X Window System geometry string - see the
5392 * manual page for X (type 'man X') for details on this.
5393 * gtk_window_parse_geometry() does work on all GTK+ ports
5394 * including Win32 but is primarily intended for an X environment.
5396 * If either a size or a position can be extracted from the
5397 * geometry string, gtk_window_parse_geometry() returns %TRUE
5398 * and calls gtk_window_set_default_size() and/or gtk_window_move()
5399 * to resize/move the window.
5401 * If gtk_window_parse_geometry() returns %TRUE, it will also
5402 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
5403 * indicating to the window manager that the size/position of
5404 * the window was user-specified. This causes most window
5405 * managers to honor the geometry.
5407 * Return value: %TRUE if string was parsed successfully
5410 gtk_window_parse_geometry (GtkWindow *window,
5411 const gchar *geometry)
5416 gboolean size_set, pos_set;
5418 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5419 g_return_val_if_fail (geometry != NULL, FALSE);
5421 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
5423 if ((result & WidthValue) == 0 ||
5426 if ((result & HeightValue) == 0 ||
5431 if ((result & WidthValue) || (result & HeightValue))
5433 gtk_window_set_default_size (window, w, h);
5437 gtk_window_get_size (window, &w, &h);
5439 grav = GDK_GRAVITY_NORTH_WEST;
5441 if ((result & XNegative) && (result & YNegative))
5442 grav = GDK_GRAVITY_SOUTH_EAST;
5443 else if (result & XNegative)
5444 grav = GDK_GRAVITY_NORTH_EAST;
5445 else if (result & YNegative)
5446 grav = GDK_GRAVITY_SOUTH_WEST;
5448 if ((result & XValue) == 0)
5451 if ((result & YValue) == 0)
5454 if (grav == GDK_GRAVITY_SOUTH_WEST ||
5455 grav == GDK_GRAVITY_SOUTH_EAST)
5456 y = gdk_screen_height () - h;
5458 if (grav == GDK_GRAVITY_SOUTH_EAST ||
5459 grav == GDK_GRAVITY_NORTH_EAST)
5460 x = gdk_screen_width () - w;
5469 if ((result & XValue) || (result & YValue))
5471 gtk_window_set_gravity (window, grav);
5472 gtk_window_move (window, x, y);
5476 if (size_set || pos_set)
5478 /* Set USSize, USPosition hints */
5479 GtkWindowGeometryInfo *info;
5481 info = gtk_window_get_geometry_info (window, TRUE);
5484 info->mask |= GDK_HINT_USER_POS;
5486 info->mask |= GDK_HINT_USER_SIZE;