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_FB)
37 #include "linux-fb/gdkfb.h"
40 #include "gtkprivate.h"
42 #include "gtksignal.h"
43 #include "gtkwindow.h"
44 #include "gtkwindow-decorate.h"
45 #include "gtkbindings.h"
47 #include "gtkiconfactory.h"
74 PROP_DESTROY_WITH_PARENT,
83 GdkPixmap *icon_pixmap;
86 guint using_default_icon : 1;
87 guint using_parent_icon : 1;
91 GdkGeometry geometry; /* Last set of geometry hints we set */
93 GdkRectangle configure_request;
94 } GtkWindowLastGeometryInfo;
96 struct _GtkWindowGeometryInfo
98 /* Properties that the app has set on the window
100 GdkGeometry geometry; /* Geometry hints */
102 GtkWidget *widget; /* subwidget to which hints apply */
103 /* from last gtk_window_resize () - if > 0, indicates that
104 * we should resize to this size.
109 /* From last gtk_window_move () prior to mapping -
110 * only used if initial_pos_set
115 /* Default size - used only the FIRST time we map a window,
120 /* whether to use initial_x, initial_y */
121 guint initial_pos_set : 1;
122 /* CENTER_ALWAYS or other position constraint changed since
123 * we sent the last configure request.
125 guint position_constraints_changed : 1;
127 GtkWindowLastGeometryInfo last;
138 static void gtk_window_class_init (GtkWindowClass *klass);
139 static void gtk_window_init (GtkWindow *window);
140 static void gtk_window_dispose (GObject *object);
141 static void gtk_window_destroy (GtkObject *object);
142 static void gtk_window_finalize (GObject *object);
143 static void gtk_window_show (GtkWidget *widget);
144 static void gtk_window_hide (GtkWidget *widget);
145 static void gtk_window_map (GtkWidget *widget);
146 static void gtk_window_unmap (GtkWidget *widget);
147 static void gtk_window_realize (GtkWidget *widget);
148 static void gtk_window_unrealize (GtkWidget *widget);
149 static void gtk_window_size_request (GtkWidget *widget,
150 GtkRequisition *requisition);
151 static void gtk_window_size_allocate (GtkWidget *widget,
152 GtkAllocation *allocation);
153 static gint gtk_window_event (GtkWidget *widget,
155 static gboolean gtk_window_frame_event (GtkWidget *widget,
157 static gint gtk_window_configure_event (GtkWidget *widget,
158 GdkEventConfigure *event);
159 static gint gtk_window_key_press_event (GtkWidget *widget,
161 static gint gtk_window_key_release_event (GtkWidget *widget,
163 static gint gtk_window_enter_notify_event (GtkWidget *widget,
164 GdkEventCrossing *event);
165 static gint gtk_window_leave_notify_event (GtkWidget *widget,
166 GdkEventCrossing *event);
167 static gint gtk_window_focus_in_event (GtkWidget *widget,
168 GdkEventFocus *event);
169 static gint gtk_window_focus_out_event (GtkWidget *widget,
170 GdkEventFocus *event);
171 static gint gtk_window_client_event (GtkWidget *widget,
172 GdkEventClient *event);
173 static void gtk_window_check_resize (GtkContainer *container);
174 static gint gtk_window_focus (GtkWidget *widget,
175 GtkDirectionType direction);
176 static void gtk_window_real_set_focus (GtkWindow *window,
179 static void gtk_window_real_activate_default (GtkWindow *window);
180 static void gtk_window_real_activate_focus (GtkWindow *window);
181 static void gtk_window_move_focus (GtkWindow *window,
182 GtkDirectionType dir);
183 static void gtk_window_read_rcfiles (GtkWidget *widget,
184 GdkEventClient *event);
185 static void gtk_window_paint (GtkWidget *widget,
187 static gint gtk_window_expose (GtkWidget *widget,
188 GdkEventExpose *event);
189 static void gtk_window_unset_transient_for (GtkWindow *window);
190 static void gtk_window_transient_parent_realized (GtkWidget *parent,
192 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
195 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
198 static void gtk_window_move_resize (GtkWindow *window);
199 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
201 GdkGeometry *geometry_b,
203 static void gtk_window_constrain_size (GtkWindow *window,
204 GdkGeometry *geometry,
210 static void gtk_window_constrain_position (GtkWindow *window,
215 static void gtk_window_compute_hints (GtkWindow *window,
216 GdkGeometry *new_geometry,
218 static void gtk_window_compute_configure_request (GtkWindow *window,
219 GdkRectangle *request,
220 GdkGeometry *geometry,
223 static void gtk_window_set_default_size_internal (GtkWindow *window,
224 gboolean change_width,
226 gboolean change_height,
229 static void gtk_window_realize_icon (GtkWindow *window);
230 static void gtk_window_unrealize_icon (GtkWindow *window);
232 static GSList *toplevel_list = NULL;
233 static GHashTable *mnemonic_hash_table = NULL;
234 static GtkBinClass *parent_class = NULL;
235 static guint window_signals[LAST_SIGNAL] = { 0 };
236 static GList *default_icon_list = NULL;
237 /* FIXME need to be per-screen */
238 static GdkPixmap *default_icon_pixmap = NULL;
239 static GdkPixmap *default_icon_mask = NULL;
241 static void gtk_window_set_property (GObject *object,
245 static void gtk_window_get_property (GObject *object,
252 mnemonic_hash (gconstpointer key)
254 const GtkWindowMnemonic *k;
257 k = (GtkWindowMnemonic *)key;
259 h = (gulong) k->window;
260 h ^= k->keyval << 16;
261 h ^= k->keyval >> 16;
267 mnemonic_equal (gconstpointer a, gconstpointer b)
269 const GtkWindowMnemonic *ka;
270 const GtkWindowMnemonic *kb;
272 ka = (GtkWindowMnemonic *)a;
273 kb = (GtkWindowMnemonic *)b;
276 (ka->window == kb->window) &&
277 (ka->keyval == kb->keyval);
281 gtk_window_get_type (void)
283 static GtkType window_type = 0;
287 static const GtkTypeInfo window_info =
291 sizeof (GtkWindowClass),
292 (GtkClassInitFunc) gtk_window_class_init,
293 (GtkObjectInitFunc) gtk_window_init,
294 /* reserved_1 */ NULL,
295 /* reserved_2 */ NULL,
296 (GtkClassInitFunc) NULL,
299 window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
306 gtk_window_class_init (GtkWindowClass *klass)
308 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
309 GtkObjectClass *object_class;
310 GtkWidgetClass *widget_class;
311 GtkContainerClass *container_class;
312 GtkBindingSet *binding_set;
314 object_class = (GtkObjectClass*) klass;
315 widget_class = (GtkWidgetClass*) klass;
316 container_class = (GtkContainerClass*) klass;
318 parent_class = gtk_type_class (gtk_bin_get_type ());
320 gobject_class->dispose = gtk_window_dispose;
321 gobject_class->finalize = gtk_window_finalize;
323 gobject_class->set_property = gtk_window_set_property;
324 gobject_class->get_property = gtk_window_get_property;
326 object_class->destroy = gtk_window_destroy;
328 widget_class->show = gtk_window_show;
329 widget_class->hide = gtk_window_hide;
330 widget_class->map = gtk_window_map;
331 widget_class->unmap = gtk_window_unmap;
332 widget_class->realize = gtk_window_realize;
333 widget_class->unrealize = gtk_window_unrealize;
334 widget_class->size_request = gtk_window_size_request;
335 widget_class->size_allocate = gtk_window_size_allocate;
336 widget_class->configure_event = gtk_window_configure_event;
337 widget_class->key_press_event = gtk_window_key_press_event;
338 widget_class->key_release_event = gtk_window_key_release_event;
339 widget_class->enter_notify_event = gtk_window_enter_notify_event;
340 widget_class->leave_notify_event = gtk_window_leave_notify_event;
341 widget_class->focus_in_event = gtk_window_focus_in_event;
342 widget_class->focus_out_event = gtk_window_focus_out_event;
343 widget_class->client_event = gtk_window_client_event;
344 widget_class->focus = gtk_window_focus;
346 widget_class->expose_event = gtk_window_expose;
348 container_class->check_resize = gtk_window_check_resize;
350 klass->set_focus = gtk_window_real_set_focus;
351 klass->frame_event = gtk_window_frame_event;
353 klass->activate_default = gtk_window_real_activate_default;
354 klass->activate_focus = gtk_window_real_activate_focus;
355 klass->move_focus = gtk_window_move_focus;
358 g_object_class_install_property (gobject_class,
360 g_param_spec_enum ("type",
362 _("The type of the window"),
363 GTK_TYPE_WINDOW_TYPE,
365 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
368 g_object_class_install_property (gobject_class,
370 g_param_spec_string ("title",
372 _("The title of the window"),
376 g_object_class_install_property (gobject_class,
378 g_param_spec_boolean ("allow_shrink",
380 /* xgettext:no-c-format */
381 _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea."),
385 g_object_class_install_property (gobject_class,
387 g_param_spec_boolean ("allow_grow",
389 _("If TRUE, users can expand the window beyond its minimum size."),
393 g_object_class_install_property (gobject_class,
395 g_param_spec_boolean ("resizable",
397 _("If TRUE, users can resize the window."),
401 g_object_class_install_property (gobject_class,
403 g_param_spec_boolean ("modal",
405 _("If TRUE, the window is modal (other windows are not usable while this one is up)."),
409 g_object_class_install_property (gobject_class,
411 g_param_spec_enum ("window_position",
412 _("Window Position"),
413 _("The initial position of the window."),
414 GTK_TYPE_WINDOW_POSITION,
418 g_object_class_install_property (gobject_class,
420 g_param_spec_int ("default_width",
422 _("The default width of the window, used when initially showing the window."),
428 g_object_class_install_property (gobject_class,
430 g_param_spec_int ("default_height",
432 _("The default height of the window, used when initially showing the window."),
438 g_object_class_install_property (gobject_class,
439 PROP_DESTROY_WITH_PARENT,
440 g_param_spec_boolean ("destroy_with_parent",
441 _("Destroy with Parent"),
442 _("If this window should be destroyed when the parent is destroyed"),
446 g_object_class_install_property (gobject_class,
448 g_param_spec_object ("icon",
450 _("Icon for this window"),
454 window_signals[SET_FOCUS] =
455 g_signal_new ("set_focus",
456 G_TYPE_FROM_CLASS (object_class),
458 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
460 gtk_marshal_VOID__OBJECT,
464 window_signals[FRAME_EVENT] =
465 g_signal_new ("frame_event",
466 G_TYPE_FROM_CLASS(object_class),
468 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
469 _gtk_boolean_handled_accumulator, NULL,
470 gtk_marshal_BOOLEAN__BOXED,
474 window_signals[ACTIVATE_FOCUS] =
475 g_signal_new ("activate_focus",
476 G_OBJECT_CLASS_TYPE (object_class),
477 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
478 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_focus),
480 gtk_marshal_VOID__VOID,
484 window_signals[ACTIVATE_DEFAULT] =
485 g_signal_new ("activate_default",
486 G_OBJECT_CLASS_TYPE (object_class),
487 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
488 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_default),
490 gtk_marshal_VOID__VOID,
494 window_signals[MOVE_FOCUS] =
495 g_signal_new ("move_focus",
496 G_OBJECT_CLASS_TYPE (object_class),
497 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
498 GTK_SIGNAL_OFFSET (GtkWindowClass, move_focus),
500 gtk_marshal_VOID__ENUM,
503 GTK_TYPE_DIRECTION_TYPE);
505 if (!mnemonic_hash_table)
506 mnemonic_hash_table = g_hash_table_new (mnemonic_hash,
513 binding_set = gtk_binding_set_by_class (klass);
515 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
516 "activate_focus", 0);
517 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
518 "activate_focus", 0);
520 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
521 "activate_default", 0);
523 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
524 "activate_default", 0);
526 gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
528 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
529 gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
531 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
533 gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
535 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
536 gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
538 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
540 gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
542 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);
543 gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
545 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);
547 gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
549 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);
550 gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
552 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);
554 gtk_binding_entry_add_signal (binding_set, GDK_Tab, 0,
556 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
557 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, 0,
559 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
560 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, 0,
562 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
564 gtk_binding_entry_add_signal (binding_set, GDK_Tab, GDK_SHIFT_MASK,
566 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
567 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, GDK_SHIFT_MASK,
569 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
570 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, GDK_SHIFT_MASK,
572 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
576 gtk_window_init (GtkWindow *window)
578 GdkColormap *colormap;
580 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
581 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
583 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
585 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
587 window->title = NULL;
588 window->wmclass_name = g_strdup (g_get_prgname ());
589 window->wmclass_class = g_strdup (gdk_get_program_class ());
590 window->wm_role = NULL;
591 window->geometry_info = NULL;
592 window->type = GTK_WINDOW_TOPLEVEL;
593 window->focus_widget = NULL;
594 window->default_widget = NULL;
595 window->configure_request_count = 0;
596 window->allow_shrink = FALSE;
597 window->allow_grow = TRUE;
598 window->configure_notify_received = FALSE;
599 window->position = GTK_WIN_POS_NONE;
600 window->need_default_size = TRUE;
601 window->need_default_position = TRUE;
602 window->modal = FALSE;
603 window->frame = NULL;
604 window->has_frame = FALSE;
605 window->frame_left = 0;
606 window->frame_right = 0;
607 window->frame_top = 0;
608 window->frame_bottom = 0;
609 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
610 window->gravity = GDK_GRAVITY_NORTH_WEST;
611 window->decorated = TRUE;
612 window->mnemonic_modifier = GDK_MOD1_MASK;
614 colormap = _gtk_widget_peek_colormap ();
616 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
618 gtk_widget_ref (GTK_WIDGET (window));
619 gtk_object_sink (GTK_OBJECT (window));
620 window->has_user_ref_count = TRUE;
621 toplevel_list = g_slist_prepend (toplevel_list, window);
623 gtk_decorated_window_init (window);
625 gtk_signal_connect (GTK_OBJECT (window),
627 GTK_SIGNAL_FUNC (gtk_window_event),
632 gtk_window_set_property (GObject *object,
639 window = GTK_WINDOW (object);
644 window->type = g_value_get_enum (value);
647 gtk_window_set_title (window, g_value_get_string (value));
649 case PROP_ALLOW_SHRINK:
650 window->allow_shrink = g_value_get_boolean (value);
651 gtk_widget_queue_resize (GTK_WIDGET (window));
653 case PROP_ALLOW_GROW:
654 window->allow_grow = g_value_get_boolean (value);
655 gtk_widget_queue_resize (GTK_WIDGET (window));
656 g_object_notify (G_OBJECT (window), "resizable");
659 window->allow_grow = g_value_get_boolean (value);
660 gtk_widget_queue_resize (GTK_WIDGET (window));
661 g_object_notify (G_OBJECT (window), "allow_grow");
664 gtk_window_set_modal (window, g_value_get_boolean (value));
667 gtk_window_set_position (window, g_value_get_enum (value));
669 case PROP_DEFAULT_WIDTH:
670 gtk_window_set_default_size_internal (window,
671 TRUE, g_value_get_int (value),
674 case PROP_DEFAULT_HEIGHT:
675 gtk_window_set_default_size_internal (window,
677 TRUE, g_value_get_int (value));
679 case PROP_DESTROY_WITH_PARENT:
680 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
683 gtk_window_set_icon (window,
684 g_value_get_object (value));
693 gtk_window_get_property (GObject *object,
700 window = GTK_WINDOW (object);
704 GtkWindowGeometryInfo *info;
706 g_value_set_enum (value, window->type);
709 g_value_set_string (value, window->title);
711 case PROP_ALLOW_SHRINK:
712 g_value_set_boolean (value, window->allow_shrink);
714 case PROP_ALLOW_GROW:
715 g_value_set_boolean (value, window->allow_grow);
718 g_value_set_boolean (value, window->allow_grow);
721 g_value_set_boolean (value, window->modal);
724 g_value_set_enum (value, window->position);
726 case PROP_DEFAULT_WIDTH:
727 info = gtk_window_get_geometry_info (window, FALSE);
729 g_value_set_int (value, -1);
731 g_value_set_int (value, info->default_width);
733 case PROP_DEFAULT_HEIGHT:
734 info = gtk_window_get_geometry_info (window, FALSE);
736 g_value_set_int (value, -1);
738 g_value_set_int (value, info->default_height);
740 case PROP_DESTROY_WITH_PARENT:
741 g_value_set_boolean (value, window->destroy_with_parent);
744 g_value_set_object (value, gtk_window_get_icon (window));
747 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
754 * @type: type of window
756 * Creates a new #GtkWindow, which is a toplevel window that can
757 * contain other widgets. Nearly always, the type of the window should
758 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
759 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
760 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
761 * dialogs, though in some other toolkits dialogs are called "popups."
762 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
763 * Popup windows are not controlled by the window manager.
765 * If you simply want an undecorated window (no window borders), use
766 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
768 * Return value: a new #GtkWindow.
771 gtk_window_new (GtkWindowType type)
775 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
777 window = gtk_type_new (GTK_TYPE_WINDOW);
781 return GTK_WIDGET (window);
785 * gtk_window_set_title:
786 * @window: a #GtkWindow
787 * @title: title of the window
789 * Sets the title of the #GtkWindow. The title of a window will be displayed in
790 * its title bar; on the X Window System, the title bar is rendered by the
791 * window manager, so exactly how the title appears to users may vary according
792 * to a user's exact configuration. The title should help a user distinguish
793 * this window from other windows they may have open. A good title might
794 * include the application name and current document filename, for example.
798 gtk_window_set_title (GtkWindow *window,
801 g_return_if_fail (GTK_IS_WINDOW (window));
804 g_free (window->title);
805 window->title = g_strdup (title);
807 if (GTK_WIDGET_REALIZED (window))
809 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
811 gtk_decorated_window_set_title (window, title);
814 g_object_notify (G_OBJECT (window), "title");
818 * gtk_window_get_title:
819 * @window: a #GtkWindow
821 * Retrieves the title of the window. See gtk_window_set_title().
823 * Return value: the title of the window, or %NULL if none has
824 * been set explicitely. The returned string is owned by the widget
825 * and must not be modified or freed.
827 G_CONST_RETURN gchar *
828 gtk_window_get_title (GtkWindow *window)
830 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
832 return window->title;
836 * gtk_window_set_wmclass:
837 * @window: a #GtkWindow
838 * @wmclass_name: window name hint
839 * @wmclass_class: window class hint
841 * Don't use this function. It sets the X Window System "class" and
842 * "name" hints for a window. According to the ICCCM, you should
843 * always set these to the same value for all windows in an
844 * application, and GTK sets them to that value by default, so calling
845 * this function is sort of pointless. However, you may want to call
846 * gtk_window_set_role() on each window in your application, for the
847 * benefit of the session manager. Setting the role allows the window
848 * manager to restore window positions when loading a saved session.
852 gtk_window_set_wmclass (GtkWindow *window,
853 const gchar *wmclass_name,
854 const gchar *wmclass_class)
856 g_return_if_fail (GTK_IS_WINDOW (window));
858 g_free (window->wmclass_name);
859 window->wmclass_name = g_strdup (wmclass_name);
861 g_free (window->wmclass_class);
862 window->wmclass_class = g_strdup (wmclass_class);
864 if (GTK_WIDGET_REALIZED (window))
865 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
869 * gtk_window_set_role:
870 * @window: a #GtkWindow
871 * @role: unique identifier for the window to be used when restoring a session
873 * In combination with the window title, the window role allows a
874 * window manager to identify "the same" window when an application is
875 * restarted. So for example you might set the "toolbox" role on your
876 * app's toolbox window, so that when the user restarts their session,
877 * the window manager can put the toolbox back in the same place.
879 * If a window already has a unique title, you don't need to set the
880 * role, since the WM can use the title to identify the window when
881 * restoring the session.
885 gtk_window_set_role (GtkWindow *window,
888 g_return_if_fail (GTK_IS_WINDOW (window));
890 if (role == window->wm_role)
893 g_free (window->wm_role);
894 window->wm_role = g_strdup (role);
896 if (GTK_WIDGET_REALIZED (window))
897 g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
901 * gtk_window_get_role:
902 * @window: a #GtkWindow
904 * Returns the role of the window. See gtk_window_set_role() for
905 * further explanation.
907 * Return value: the role of the window if set, or %NULL. The
908 * returned is owned by the widget and must not be modified
911 G_CONST_RETURN gchar *
912 gtk_window_get_role (GtkWindow *window)
914 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
916 return window->wm_role;
920 * gtk_window_set_focus:
921 * @window: a #GtkWindow
922 * @focus: widget to be the new focus widget
924 * If @focus is not the current focus widget, and is focusable, emits
925 * the "set_focus" signal to set @focus as the focus widget for the
926 * window. This function is more or less GTK-internal; to focus an
927 * entry widget or the like, you should use gtk_widget_grab_focus()
928 * instead of this function.
932 gtk_window_set_focus (GtkWindow *window,
935 g_return_if_fail (GTK_IS_WINDOW (window));
938 g_return_if_fail (GTK_IS_WIDGET (focus));
939 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
942 if ((window->focus_widget != focus) ||
943 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
944 gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
948 * gtk_window_set_default:
949 * @window: a #GtkWindow
950 * @default_widget: widget to be the default
952 * The default widget is the widget that's activated when the user
953 * presses Enter in a dialog (for example). This function tells a
954 * #GtkWindow about the current default widget; it's really a GTK
955 * internal function and you shouldn't need it. Instead, to change the
956 * default widget, first set the #GTK_CAN_DEFAULT flag on the widget
957 * you'd like to make the default using GTK_WIDGET_SET_FLAGS(), then
958 * call gtk_widget_grab_default() to move the default.
962 gtk_window_set_default (GtkWindow *window,
963 GtkWidget *default_widget)
965 g_return_if_fail (GTK_IS_WINDOW (window));
968 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
970 if (window->default_widget != default_widget)
972 if (window->default_widget)
974 if (window->focus_widget != window->default_widget ||
975 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
976 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
977 gtk_widget_queue_draw (window->default_widget);
980 window->default_widget = default_widget;
982 if (window->default_widget)
984 if (window->focus_widget == NULL ||
985 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
986 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
987 gtk_widget_queue_draw (window->default_widget);
993 gtk_window_set_policy (GtkWindow *window,
994 gboolean allow_shrink,
996 gboolean auto_shrink)
998 g_return_if_fail (GTK_IS_WINDOW (window));
1000 window->allow_shrink = (allow_shrink != FALSE);
1001 window->allow_grow = (allow_grow != FALSE);
1003 g_object_freeze_notify (G_OBJECT (window));
1004 g_object_notify (G_OBJECT (window), "allow_shrink");
1005 g_object_notify (G_OBJECT (window), "allow_grow");
1006 g_object_notify (G_OBJECT (window), "resizable");
1007 g_object_thaw_notify (G_OBJECT (window));
1009 gtk_widget_queue_resize (GTK_WIDGET (window));
1013 gtk_window_add_accel_group (GtkWindow *window,
1014 GtkAccelGroup *accel_group)
1016 g_return_if_fail (GTK_IS_WINDOW (window));
1017 g_return_if_fail (accel_group != NULL);
1019 gtk_accel_group_attach (accel_group, G_OBJECT (window));
1023 gtk_window_remove_accel_group (GtkWindow *window,
1024 GtkAccelGroup *accel_group)
1026 g_return_if_fail (GTK_IS_WINDOW (window));
1027 g_return_if_fail (accel_group != NULL);
1029 gtk_accel_group_detach (accel_group, G_OBJECT (window));
1033 gtk_window_add_mnemonic (GtkWindow *window,
1037 GtkWindowMnemonic key;
1038 GtkWindowMnemonic *mnemonic;
1040 g_return_if_fail (GTK_IS_WINDOW (window));
1041 g_return_if_fail (GTK_IS_WIDGET (target));
1043 key.window = window;
1044 key.keyval = keyval;
1045 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1049 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1050 mnemonic->targets = g_slist_prepend (mnemonic->targets, target);
1054 mnemonic = g_new (GtkWindowMnemonic, 1);
1056 mnemonic->targets = g_slist_prepend (NULL, target);
1057 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1062 gtk_window_remove_mnemonic (GtkWindow *window,
1066 GtkWindowMnemonic key;
1067 GtkWindowMnemonic *mnemonic;
1069 g_return_if_fail (GTK_IS_WINDOW (window));
1070 g_return_if_fail (GTK_IS_WIDGET (target));
1072 key.window = window;
1073 key.keyval = keyval;
1074 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1076 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1078 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1079 if (mnemonic->targets == NULL)
1081 g_hash_table_remove (mnemonic_hash_table, mnemonic);
1087 gtk_window_mnemonic_activate (GtkWindow *window,
1089 GdkModifierType modifier)
1091 GtkWindowMnemonic key;
1092 GtkWindowMnemonic *mnemonic;
1094 GtkWidget *widget, *chosen_widget;
1095 gboolean overloaded;
1097 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1099 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1102 key.window = window;
1103 key.keyval = keyval;
1104 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1110 chosen_widget = NULL;
1111 list = mnemonic->targets;
1114 widget = GTK_WIDGET (list->data);
1116 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1117 GTK_WIDGET_MAPPED (widget))
1125 chosen_widget = widget;
1127 list = g_slist_next (list);
1132 /* For round robin we put the activated entry on
1133 * the end of the list after activation
1135 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1136 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1138 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1144 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1145 GdkModifierType modifier)
1147 g_return_if_fail (GTK_IS_WINDOW (window));
1148 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1150 window->mnemonic_modifier = modifier;
1154 * gtk_window_get_mnemonic_modifier:
1155 * @window: a #GtkWindow
1157 * Returns the mnemonic modifier for this window. See
1158 * gtk_window_set_mnemonic_modifier().
1160 * Return value: the modifier mask used to activate
1161 * mnemonics on this window.
1164 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1166 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1168 return window->mnemonic_modifier;
1172 gtk_window_set_position (GtkWindow *window,
1173 GtkWindowPosition position)
1175 g_return_if_fail (GTK_IS_WINDOW (window));
1177 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1178 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1180 GtkWindowGeometryInfo *info;
1182 info = gtk_window_get_geometry_info (window, TRUE);
1184 /* this flag causes us to re-request the CENTER_ALWAYS
1185 * constraint in gtk_window_move_resize(), see
1186 * comment in that function.
1188 info->position_constraints_changed = TRUE;
1190 gtk_widget_queue_resize (GTK_WIDGET (window));
1193 window->position = position;
1195 g_object_notify (G_OBJECT (window), "window_position");
1199 gtk_window_activate_focus (GtkWindow *window)
1201 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1203 if (window->focus_widget)
1205 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1206 gtk_widget_activate (window->focus_widget);
1214 gtk_window_activate_default (GtkWindow *window)
1216 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1218 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1219 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1221 gtk_widget_activate (window->default_widget);
1224 else if (window->focus_widget)
1226 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1227 gtk_widget_activate (window->focus_widget);
1235 * gtk_window_set_modal:
1236 * @window: a #GtkWindow
1237 * @modal: whether the window is modal
1239 * Sets a window modal or non-modal. Modal windows prevent interaction
1240 * with other windows in the same application. To keep modal dialogs
1241 * on top of main application windows, use
1242 * gtk_window_set_transient_for() to make the dialog transient for the
1243 * parent; most window managers will then disallow lowering the dialog
1249 gtk_window_set_modal (GtkWindow *window,
1252 g_return_if_fail (GTK_IS_WINDOW (window));
1254 window->modal = modal != FALSE;
1256 /* adjust desired modality state */
1257 if (GTK_WIDGET_VISIBLE (window) && window->modal)
1258 gtk_grab_add (GTK_WIDGET (window));
1260 gtk_grab_remove (GTK_WIDGET (window));
1262 g_object_notify (G_OBJECT (window), "modal");
1266 * gtk_window_get_modal:
1267 * @window: a #GtkWindow
1269 * Returns whether the window is modal. See gtk_window_set_modal().
1271 * Return value: %TRUE if the window is set to be modal and
1272 * establishes a grab when shown
1275 gtk_window_get_modal (GtkWindow *window)
1277 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1279 return window->modal;
1283 * gtk_window_list_toplevels:
1285 * Returns a list of all existing toplevel windows. The widgets
1286 * in the list are not individually referenced. If you want
1287 * to iterate through the list and perform actions involving
1288 * callbacks that might destroy the widgets, you MUST call
1289 * g_list_foreach (result, (GFunc)g_object_ref, NULL) first, and
1290 * then unref all the widgets afterwards.
1292 * Return value: list of toplevel widgets
1295 gtk_window_list_toplevels (void)
1300 for (slist = toplevel_list; slist; slist = slist->next)
1301 list = g_list_prepend (list, slist->data);
1307 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1309 GList *embedded_windows;
1311 g_return_if_fail (GTK_IS_WINDOW (window));
1313 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1314 if (embedded_windows)
1315 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1316 g_quark_from_static_string ("gtk-embedded"));
1317 embedded_windows = g_list_prepend (embedded_windows,
1318 GUINT_TO_POINTER (xid));
1320 gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
1323 (GtkDestroyNotify) g_list_free : NULL);
1327 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1329 GList *embedded_windows;
1332 g_return_if_fail (GTK_IS_WINDOW (window));
1334 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1335 if (embedded_windows)
1336 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1337 g_quark_from_static_string ("gtk-embedded"));
1339 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1342 embedded_windows = g_list_remove_link (embedded_windows, node);
1343 g_list_free_1 (node);
1346 gtk_object_set_data_full (GTK_OBJECT (window),
1347 "gtk-embedded", embedded_windows,
1349 (GtkDestroyNotify) g_list_free : NULL);
1353 _gtk_window_reposition (GtkWindow *window,
1357 g_return_if_fail (GTK_IS_WINDOW (window));
1359 gtk_window_move (window, x, y);
1363 gtk_window_dispose (GObject *object)
1367 g_return_if_fail (GTK_IS_WINDOW (object));
1369 window = GTK_WINDOW (object);
1371 gtk_window_set_focus (window, NULL);
1372 gtk_window_set_default (window, NULL);
1374 G_OBJECT_CLASS (parent_class)->dispose (object);
1378 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1380 gtk_widget_destroy (GTK_WIDGET (child));
1384 connect_parent_destroyed (GtkWindow *window)
1386 if (window->transient_parent)
1388 gtk_signal_connect (GTK_OBJECT (window->transient_parent),
1390 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1396 disconnect_parent_destroyed (GtkWindow *window)
1398 if (window->transient_parent)
1400 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1401 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1407 gtk_window_transient_parent_realized (GtkWidget *parent,
1410 if (GTK_WIDGET_REALIZED (window))
1411 gdk_window_set_transient_for (window->window, parent->window);
1415 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1418 if (GTK_WIDGET_REALIZED (window))
1419 gdk_property_delete (window->window,
1420 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1424 gtk_window_unset_transient_for (GtkWindow *window)
1426 if (window->transient_parent)
1428 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1429 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1431 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1432 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1434 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1435 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1436 &window->transient_parent);
1438 if (window->destroy_with_parent)
1439 disconnect_parent_destroyed (window);
1441 window->transient_parent = NULL;
1446 * gtk_window_set_transient_for:
1447 * @window: a #GtkWindow
1448 * @parent: parent window
1450 * Dialog windows should be set transient for the main application
1451 * window they were spawned from. This allows window managers to
1452 * e.g. keep the dialog on top of the main window, or center the
1453 * dialog over the main window. gtk_dialog_new_with_buttons() and
1454 * other convenience functions in GTK+ will sometimes call
1455 * gtk_window_set_transient_for() on your behalf.
1459 gtk_window_set_transient_for (GtkWindow *window,
1462 g_return_if_fail (GTK_IS_WINDOW (window));
1463 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1464 g_return_if_fail (window != parent);
1467 if (window->transient_parent)
1469 if (GTK_WIDGET_REALIZED (window) &&
1470 GTK_WIDGET_REALIZED (window->transient_parent) &&
1471 (!parent || !GTK_WIDGET_REALIZED (parent)))
1472 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1473 GTK_WIDGET (window));
1475 gtk_window_unset_transient_for (window);
1478 window->transient_parent = parent;
1482 gtk_signal_connect (GTK_OBJECT (parent), "destroy",
1483 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1484 &window->transient_parent);
1485 gtk_signal_connect (GTK_OBJECT (parent), "realize",
1486 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1488 gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
1489 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1492 if (window->destroy_with_parent)
1493 connect_parent_destroyed (window);
1495 if (GTK_WIDGET_REALIZED (window) &&
1496 GTK_WIDGET_REALIZED (parent))
1497 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1498 GTK_WIDGET (window));
1503 * gtk_window_get_transient_for:
1504 * @window: a #GtkWindow
1506 * Fetches the transient parent for this window. See
1507 * gtk_window_set_transient_for().
1509 * Return value: the transient parent for this window, or %NULL
1510 * if no transient parent has been set.
1513 gtk_window_get_transient_for (GtkWindow *window)
1515 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1517 return window->transient_parent;
1521 * gtk_window_set_type_hint:
1522 * @window: a #GtkWindow
1523 * @hint: the window type
1525 * By setting the type hint for the window, you allow the window
1526 * manager to decorate and handle the window in a way which is
1527 * suitable to the function of the window in your application.
1529 * This function should be called before the window becomes visible.
1531 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1532 * will sometimes call gtk_window_set_type_hint() on your behalf.
1536 gtk_window_set_type_hint (GtkWindow *window,
1537 GdkWindowTypeHint hint)
1539 g_return_if_fail (GTK_IS_WINDOW (window));
1540 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1541 window->type_hint = hint;
1545 * gtk_window_get_type_hint:
1546 * @window: a #GtkWindow
1548 * Gets the type hint for this window. See gtk_window_set_type_hint().
1550 * Return value: the type hint for @window.
1553 gtk_window_get_type_hint (GtkWindow *window)
1555 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1557 return window->type_hint;
1561 * gtk_window_set_destroy_with_parent:
1562 * @window: a #GtkWindow
1563 * @setting: whether to destroy @window with its transient parent
1565 * If @setting is TRUE, then destroying the transient parent of @window
1566 * will also destroy @window itself. This is useful for dialogs that
1567 * shouldn't persist beyond the lifetime of the main window they're
1568 * associated with, for example.
1571 gtk_window_set_destroy_with_parent (GtkWindow *window,
1574 g_return_if_fail (GTK_IS_WINDOW (window));
1576 if (window->destroy_with_parent == (setting != FALSE))
1579 if (window->destroy_with_parent)
1581 disconnect_parent_destroyed (window);
1585 connect_parent_destroyed (window);
1588 window->destroy_with_parent = setting;
1590 g_object_notify (G_OBJECT (window), "destroy_with_parent");
1594 * gtk_window_get_destroy_with_parent:
1595 * @window: a #GtkWindow
1597 * Returns whether the window will be destroyed with its transient parent. See
1598 * gtk_window_set_destroy_with_parent ().
1600 * Return value: %TRUE if the window will be destroyed with its transient parent.
1603 gtk_window_get_destroy_with_parent (GtkWindow *window)
1605 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1607 return window->destroy_with_parent;
1610 static GtkWindowGeometryInfo*
1611 gtk_window_get_geometry_info (GtkWindow *window,
1614 GtkWindowGeometryInfo *info;
1616 info = window->geometry_info;
1617 if (!info && create)
1619 info = g_new0 (GtkWindowGeometryInfo, 1);
1621 info->default_width = -1;
1622 info->default_height = -1;
1623 info->resize_width = -1;
1624 info->resize_height = -1;
1625 info->initial_x = 0;
1626 info->initial_y = 0;
1627 info->initial_pos_set = FALSE;
1628 info->position_constraints_changed = FALSE;
1629 info->last.configure_request.x = 0;
1630 info->last.configure_request.y = 0;
1631 info->last.configure_request.width = -1;
1632 info->last.configure_request.height = -1;
1633 info->widget = NULL;
1635 window->geometry_info = info;
1642 * gtk_window_set_geometry_hints:
1643 * @window: a #GtkWindow
1644 * @geometry_widget: widget the geometry hints will be applied to
1645 * @geometry: struct containing geometry information
1646 * @geom_mask: mask indicating which struct fields should be paid attention to
1648 * This function sets up hints about how a window can be resized by
1649 * the user. You can set a minimum and maximum size; allowed resize
1650 * increments (e.g. for xterm, you can only resize by the size of a
1651 * character); aspect ratios; and more. See the #GdkGeometry struct.
1655 gtk_window_set_geometry_hints (GtkWindow *window,
1656 GtkWidget *geometry_widget,
1657 GdkGeometry *geometry,
1658 GdkWindowHints geom_mask)
1660 GtkWindowGeometryInfo *info;
1662 g_return_if_fail (window != NULL);
1664 info = gtk_window_get_geometry_info (window, TRUE);
1667 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1668 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1671 info->widget = geometry_widget;
1673 gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
1674 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1678 info->geometry = *geometry;
1680 /* We store gravity in window->gravity not in the hints. */
1681 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
1683 if (geom_mask & GDK_HINT_WIN_GRAVITY)
1685 gtk_window_set_gravity (window, geometry->win_gravity);
1688 gtk_widget_queue_resize (GTK_WIDGET (window));
1692 * gtk_window_set_decorated:
1693 * @window: a #GtkWindow
1694 * @setting: %TRUE to decorate the window
1696 * By default, windows are decorated with a title bar, resize
1697 * controls, etc. Some window managers allow GTK+ to disable these
1698 * decorations, creating a borderless window. If you set the decorated
1699 * property to %FALSE using this function, GTK+ will do its best to
1700 * convince the window manager not to decorate the window.
1704 gtk_window_set_decorated (GtkWindow *window,
1707 g_return_if_fail (GTK_IS_WINDOW (window));
1709 setting = setting != FALSE;
1711 if (setting == window->decorated)
1714 window->decorated = setting;
1716 if (GTK_WIDGET (window)->window)
1718 if (window->decorated)
1719 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1722 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1728 * gtk_window_get_decorated:
1729 * @window: a #GtkWindow
1731 * Returns whether the window has been set to have decorations
1732 * such as a title bar via gtk_window_set_decorated().
1734 * Return value: %TRUE if the window has been set to have decorations
1737 gtk_window_get_decorated (GtkWindow *window)
1739 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
1741 return window->decorated;
1744 static GtkWindowIconInfo*
1745 get_icon_info (GtkWindow *window)
1747 return g_object_get_data (G_OBJECT (window),
1748 "gtk-window-icon-info");
1751 static GtkWindowIconInfo*
1752 ensure_icon_info (GtkWindow *window)
1754 GtkWindowIconInfo *info;
1756 info = get_icon_info (window);
1760 info = g_new0 (GtkWindowIconInfo, 1);
1761 g_object_set_data_full (G_OBJECT (window),
1762 "gtk-window-icon-info",
1771 get_pixmap_and_mask (GtkWindowIconInfo *parent_info,
1772 gboolean is_default_list,
1774 GdkPixmap **pmap_return,
1775 GdkBitmap **mask_return)
1777 GdkPixbuf *best_icon;
1781 *pmap_return = NULL;
1782 *mask_return = NULL;
1784 if (is_default_list &&
1785 default_icon_pixmap != NULL)
1787 /* Use shared icon pixmap (eventually will be stored on the
1790 if (default_icon_pixmap)
1791 g_object_ref (G_OBJECT (default_icon_pixmap));
1792 if (default_icon_mask)
1793 g_object_ref (G_OBJECT (default_icon_mask));
1795 *pmap_return = default_icon_pixmap;
1796 *mask_return = default_icon_mask;
1798 else if (parent_info && parent_info->icon_pixmap)
1800 if (parent_info->icon_pixmap)
1801 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1802 if (parent_info->icon_mask)
1803 g_object_ref (G_OBJECT (parent_info->icon_mask));
1805 *pmap_return = parent_info->icon_pixmap;
1806 *mask_return = parent_info->icon_mask;
1810 #define IDEAL_SIZE 48
1812 best_size = G_MAXINT;
1814 tmp_list = icon_list;
1815 while (tmp_list != NULL)
1817 GdkPixbuf *pixbuf = tmp_list->data;
1820 /* average width and height - if someone passes in a rectangular
1821 * icon they deserve what they get.
1823 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
1826 if (best_icon == NULL)
1833 /* icon is better if it's 32 pixels or larger, and closer to
1834 * the ideal size than the current best.
1837 (ABS (best_size - IDEAL_SIZE) <
1838 ABS (this - IDEAL_SIZE)))
1845 tmp_list = tmp_list->next;
1849 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
1850 gdk_colormap_get_system (),
1855 /* Save pmap/mask for others to use if appropriate */
1858 parent_info->icon_pixmap = *pmap_return;
1859 parent_info->icon_mask = *mask_return;
1861 if (parent_info->icon_pixmap)
1862 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1863 if (parent_info->icon_mask)
1864 g_object_ref (G_OBJECT (parent_info->icon_mask));
1866 else if (is_default_list)
1868 default_icon_pixmap = *pmap_return;
1869 default_icon_mask = *mask_return;
1871 if (default_icon_pixmap)
1872 g_object_add_weak_pointer (G_OBJECT (default_icon_pixmap),
1873 (gpointer*)&default_icon_pixmap);
1874 if (default_icon_mask)
1875 g_object_add_weak_pointer (G_OBJECT (default_icon_mask),
1876 (gpointer*)&default_icon_mask);
1882 gtk_window_realize_icon (GtkWindow *window)
1885 GtkWindowIconInfo *info;
1888 widget = GTK_WIDGET (window);
1890 g_return_if_fail (widget->window != NULL);
1892 /* no point setting an icon on override-redirect */
1893 if (window->type == GTK_WINDOW_POPUP)
1898 info = ensure_icon_info (window);
1903 g_return_if_fail (info->icon_pixmap == NULL);
1904 g_return_if_fail (info->icon_mask == NULL);
1906 info->using_default_icon = FALSE;
1907 info->using_parent_icon = FALSE;
1909 icon_list = info->icon_list;
1911 /* Inherit from transient parent */
1912 if (icon_list == NULL && window->transient_parent)
1914 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
1916 info->using_parent_icon = TRUE;
1919 /* Inherit from default */
1920 if (icon_list == NULL)
1922 icon_list = default_icon_list;
1924 info->using_default_icon = TRUE;
1927 gdk_window_set_icon_list (widget->window, icon_list);
1929 get_pixmap_and_mask (info->using_parent_icon ?
1930 ensure_icon_info (window->transient_parent) : NULL,
1931 info->using_default_icon,
1936 /* This is a slight ICCCM violation since it's a color pixmap not
1937 * a bitmap, but everyone does it.
1939 gdk_window_set_icon (widget->window,
1944 info->realized = TRUE;
1948 gtk_window_unrealize_icon (GtkWindow *window)
1950 GtkWindowIconInfo *info;
1953 widget = GTK_WIDGET (window);
1955 info = get_icon_info (window);
1960 if (info->icon_pixmap)
1961 g_object_unref (G_OBJECT (info->icon_pixmap));
1963 if (info->icon_mask)
1964 g_object_unref (G_OBJECT (info->icon_mask));
1966 info->icon_pixmap = NULL;
1967 info->icon_mask = NULL;
1969 /* We don't clear the properties on the window, just figure the
1970 * window is going away.
1973 info->realized = FALSE;
1977 * gtk_window_set_icon_list:
1978 * @window: a #GtkWindow
1979 * @list: list of #GdkPixbuf
1981 * Sets up the icon representing a #GtkWindow. The icon is used when
1982 * the window is minimized (also known as iconified). Some window
1983 * managers or desktop environments may also place it in the window
1984 * frame, or display it in other contexts.
1986 * gtk_window_set_icon_list() allows you to pass in the same icon in
1987 * several hand-drawn sizes. The list should contain the natural sizes
1988 * your icon is available in; that is, don't scale the image before
1989 * passing it to GTK+. Scaling is postponed until the last minute,
1990 * when the desired final size is known, to allow best quality.
1992 * By passing several sizes, you may improve the final image quality
1993 * of the icon, by reducing or eliminating automatic image scaling.
1995 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
1996 * larger images (64x64, 128x128) if you have them.
1998 * See also gtk_window_set_default_icon_list() to set the icon
1999 * for all windows in your application in one go.
2001 * Note that transient windows (those who have been set transient for another
2002 * window using gtk_window_set_transient_for()) will inherit their
2003 * icon from their transient parent. So there's no need to explicitly
2004 * set the icon on transient windows.
2007 gtk_window_set_icon_list (GtkWindow *window,
2010 GtkWindowIconInfo *info;
2012 g_return_if_fail (GTK_IS_WINDOW (window));
2014 info = ensure_icon_info (window);
2016 if (info->icon_list == list) /* check for NULL mostly */
2019 g_list_foreach (info->icon_list,
2020 (GFunc) g_object_unref, NULL);
2022 g_list_free (info->icon_list);
2024 info->icon_list = g_list_copy (list);
2025 g_list_foreach (info->icon_list,
2026 (GFunc) g_object_ref, NULL);
2028 g_object_notify (G_OBJECT (window), "icon");
2030 gtk_window_unrealize_icon (window);
2032 if (GTK_WIDGET_REALIZED (window))
2033 gtk_window_realize_icon (window);
2035 /* We could try to update our transient children, but I don't think
2036 * it's really worth it. If we did it, the best way would probably
2037 * be to have children connect to notify::icon_list
2042 * gtk_window_get_icon_list:
2043 * @window: a #GtkWindow
2045 * Retrieves the list of icons set by gtk_window_set_icon_list().
2046 * The list is copied, but the reference count on each
2047 * member won't be incremented.
2049 * Return value: copy of window's icon list
2052 gtk_window_get_icon_list (GtkWindow *window)
2054 GtkWindowIconInfo *info;
2056 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2058 info = get_icon_info (window);
2061 return g_list_copy (info->icon_list);
2067 * gtk_window_set_icon:
2068 * @window: a #GtkWindow
2069 * @icon: icon image, or %NULL
2071 * Sets up the icon representing a #GtkWindow. This icon is used when
2072 * the window is minimized (also known as iconified). Some window
2073 * managers or desktop environments may also place it in the window
2074 * frame, or display it in other contexts.
2076 * The icon should be provided in whatever size it was naturally
2077 * drawn; that is, don't scale the image before passing it to
2078 * GTK+. Scaling is postponed until the last minute, when the desired
2079 * final size is known, to allow best quality.
2081 * If you have your icon hand-drawn in multiple sizes, use
2082 * gtk_window_set_icon_list(). Then the best size will be used.
2084 * This function is equivalent to calling gtk_window_set_icon_list()
2085 * with a 1-element list.
2087 * See also gtk_window_set_default_icon_list() to set the icon
2088 * for all windows in your application in one go.
2091 gtk_window_set_icon (GtkWindow *window,
2096 g_return_if_fail (GTK_IS_WINDOW (window));
2097 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2100 list = g_list_append (list, icon);
2101 gtk_window_set_icon_list (window, list);
2106 * gtk_window_get_icon:
2107 * @window: a #GtkWindow
2109 * Gets the value set by gtk_window_set_icon() (or if you've
2110 * called gtk_window_set_icon_list(), gets the first icon in
2113 * Return value: icon for window
2116 gtk_window_get_icon (GtkWindow *window)
2118 GtkWindowIconInfo *info;
2120 info = get_icon_info (window);
2121 if (info && info->icon_list)
2122 return GDK_PIXBUF (info->icon_list->data);
2128 * gtk_window_set_default_icon_list:
2129 * @list: a list of #GdkPixbuf
2131 * Sets an icon list to be used as fallback for windows that haven't
2132 * had gtk_window_set_icon_list() called on them to set up a
2133 * window-specific icon list. This function allows you to set up the
2134 * icon for all windows in your app at once.
2136 * See gtk_window_set_icon_list() for more details.
2140 gtk_window_set_default_icon_list (GList *list)
2144 if (list == default_icon_list)
2147 if (default_icon_pixmap)
2148 g_object_unref (G_OBJECT (default_icon_pixmap));
2149 if (default_icon_mask)
2150 g_object_unref (G_OBJECT (default_icon_mask));
2152 default_icon_pixmap = NULL;
2153 default_icon_mask = NULL;
2155 g_list_foreach (default_icon_list,
2156 (GFunc) g_object_unref, NULL);
2158 g_list_free (default_icon_list);
2160 default_icon_list = g_list_copy (list);
2161 g_list_foreach (default_icon_list,
2162 (GFunc) g_object_ref, NULL);
2164 /* Update all toplevels */
2165 toplevels = gtk_window_list_toplevels ();
2166 tmp_list = toplevels;
2167 while (tmp_list != NULL)
2169 GtkWindowIconInfo *info;
2170 GtkWindow *w = tmp_list->data;
2172 info = get_icon_info (w);
2173 if (info && info->using_default_icon)
2175 gtk_window_unrealize_icon (w);
2176 if (GTK_WIDGET_REALIZED (w))
2177 gtk_window_realize_icon (w);
2180 tmp_list = tmp_list->next;
2182 g_list_free (toplevels);
2186 * gtk_window_get_default_icon_list:
2188 * Gets the value set by gtk_window_set_default_icon_list().
2189 * The list is a copy and should be freed with g_list_free(),
2190 * but the pixbufs in the list have not had their reference count
2193 * Return value: copy of default icon list
2196 gtk_window_get_default_icon_list (void)
2198 return g_list_copy (default_icon_list);
2202 gtk_window_set_default_size_internal (GtkWindow *window,
2203 gboolean change_width,
2205 gboolean change_height,
2208 GtkWindowGeometryInfo *info;
2210 g_return_if_fail (GTK_IS_WINDOW (window));
2211 g_return_if_fail (change_width == FALSE || width >= -1);
2212 g_return_if_fail (change_height == FALSE || height >= -1);
2214 info = gtk_window_get_geometry_info (window, TRUE);
2216 g_object_freeze_notify (G_OBJECT (window));
2226 info->default_width = width;
2228 g_object_notify (G_OBJECT (window), "default_width");
2239 info->default_height = height;
2241 g_object_notify (G_OBJECT (window), "default_height");
2244 g_object_thaw_notify (G_OBJECT (window));
2246 gtk_widget_queue_resize (GTK_WIDGET (window));
2250 * gtk_window_set_default_size:
2251 * @window: a #GtkWindow
2252 * @width: width in pixels, or -1 to unset the default width
2253 * @height: height in pixels, or -1 to unset the default height
2255 * Sets the default size of a window. If the window's "natural" size
2256 * (its size request) is larger than the default, the default will be
2257 * ignored. More generally, if the default size does not obey the
2258 * geometry hints for the window (gtk_window_set_geometry_hints() can
2259 * be used to set these explicitly), the default size will be clamped
2260 * to the nearest permitted size.
2262 * Unlike gtk_widget_set_size_request(), which sets a size request for
2263 * a widget and thus would keep users from shrinking the window, this
2264 * function only sets the initial size, just as if the user had
2265 * resized the window themselves. Users can still shrink the window
2266 * again as they normally would. Setting a default size of -1 means to
2267 * use the "natural" default size (the size request of the window).
2269 * For more control over a window's initial size and how resizing works,
2270 * investigate gtk_window_set_geometry_hints().
2272 * A useful feature: if you set the "geometry widget" via
2273 * gtk_window_set_geometry_hints(), the default size specified by
2274 * gtk_window_set_default_size() will be the default size of that
2275 * widget, not of the entire window.
2277 * For some uses, gtk_window_resize() is a more appropriate function.
2278 * gtk_window_resize() changes the current size of the window, rather
2279 * than the size to be used on initial display. gtk_window_resize() always
2280 * affects the window itself, not the geometry widget.
2282 * The default size of a window only affects the first time a window is
2283 * shown; if a window is hidden and re-shown, it will remember the size
2284 * it had prior to hiding, rather than using the default size.
2286 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2287 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2290 gtk_window_set_default_size (GtkWindow *window,
2294 g_return_if_fail (GTK_IS_WINDOW (window));
2295 g_return_if_fail (width >= -1);
2296 g_return_if_fail (height >= -1);
2298 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height);
2302 * gtk_window_get_default_size:
2303 * @window: a #GtkWindow
2304 * @width: location to store the default width, or %NULL
2305 * @height: location to store the default height, or %NULL
2307 * Gets the default size of the window. A value of -1 for the width or
2308 * height indicates that a default size has not been explicitly set
2309 * for that dimension, so the "natural" size of the window will be
2314 gtk_window_get_default_size (GtkWindow *window,
2318 GtkWindowGeometryInfo *info;
2320 g_return_if_fail (GTK_IS_WINDOW (window));
2322 info = gtk_window_get_geometry_info (window, FALSE);
2325 *width = info->default_width;
2328 *height = info->default_height;
2332 * gtk_window_resize:
2333 * @window: a #GtkWindow
2334 * @width: width to resize the window to
2335 * @height: height to resize the window to
2337 * Resizes the window as if the user had done so, obeying geometry
2338 * constraints. The default geometry constraint is that windows may
2339 * not be smaller than their size request; to override this
2340 * constraint, call gtk_widget_set_size_request() to set the window's
2341 * request to a smaller value.
2343 * If gtk_window_resize() is called before showing a window for the
2344 * first time, it overrides any default size set with
2345 * gtk_window_set_default_size().
2347 * Windows may not be resized smaller than 1 by 1 pixels.
2351 gtk_window_resize (GtkWindow *window,
2355 GtkWindowGeometryInfo *info;
2357 g_return_if_fail (GTK_IS_WINDOW (window));
2358 g_return_if_fail (width > 0);
2359 g_return_if_fail (height > 0);
2361 info = gtk_window_get_geometry_info (window, TRUE);
2363 info->resize_width = width;
2364 info->resize_height = height;
2366 gtk_widget_queue_resize (GTK_WIDGET (window));
2370 * gtk_window_get_size:
2371 * @window: a #GtkWindow
2372 * @width: return location for width, or %NULL
2373 * @height: return location for height, or %NULL
2375 * Obtains the current size of @window. If @window is not onscreen,
2376 * it returns the size GTK+ will suggest to the window manager for the
2377 * initial window size (but this is not reliably the same as the size
2378 * the window manager will actually select). The size obtained by
2379 * gtk_window_get_size() is the last size received in a
2380 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2381 * rather than querying the X server for the size. As a result, if you
2382 * call gtk_window_resize() then immediately call
2383 * gtk_window_get_size(), the size won't have taken effect yet. After
2384 * the window manager processes the resize request, GTK+ receives
2385 * notification that the size has changed via a configure event, and
2386 * the size of the window gets updated.
2388 * Note 1: Nearly any use of this function creates a race condition,
2389 * because the size of the window may change between the time that you
2390 * get the size and the time that you perform some action assuming
2391 * that size is the current size. To avoid race conditions, connect to
2392 * "configure_event" on the window and adjust your size-dependent
2393 * state to match the size delivered in the #GdkEventConfigure.
2395 * Note 2: The returned size does NOT include the size of the window
2396 * manager decorations (aka the window frame or border). Those
2397 * are not drawn by GTK+ and GTK+ has no reliable method of
2398 * determining their size.
2400 * Note 3: If you are getting a window size in order to position
2401 * the window onscreen, there may be a better way. The preferred
2402 * way is to simply set the window's semantic type with
2403 * gtk_window_set_type_hint(), which allows the window manager to
2404 * e.g. center dialogs. Also, if you set the transient parent of
2405 * dialogs with gtk_widget_set_transient_for() window managers
2406 * will often center the dialog over its parent window. It's
2407 * much preferred to let the window manager handle these
2408 * things rather than doing it yourself, because all apps will
2409 * behave consistently and according to user prefs if the window
2410 * manager handles it. Also, the window manager can take the size
2411 * of the window decorations/border into account, while your
2412 * application cannot.
2414 * In any case, if you insist on application-specified window
2415 * positioning, there's STILL a better way than doing it yourself -
2416 * gtk_window_set_position() will frequently handle the details
2421 gtk_window_get_size (GtkWindow *window,
2428 g_return_if_fail (GTK_IS_WINDOW (window));
2430 widget = GTK_WIDGET (window);
2432 if (width == NULL && height == NULL)
2435 if (GTK_WIDGET_MAPPED (window))
2437 gdk_drawable_get_size (GTK_WIDGET (window)->window,
2442 GdkRectangle configure_request;
2444 gtk_window_compute_configure_request (window,
2448 w = configure_request.width;
2449 h = configure_request.height;
2460 * @window: a #GtkWindow
2461 * @x: X coordinate to move window to
2462 * @y: Y coordinate to move window to
2464 * Asks the window manager to move @window to the given position.
2465 * Window managers are free to ignore this; most window managers
2466 * ignore requests for initial window positions (instead using a
2467 * user-defined placement algorithm) and honor requests after the
2468 * window has already been shown.
2470 * Note: the position is the position of the gravity-determined
2471 * reference point for the window. The gravity determines two things:
2472 * first, the location of the reference point in root window
2473 * coordinates; and second, which point on the window is positioned at
2474 * the reference point.
2476 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
2477 * point is simply the @x, @y supplied to gtk_window_move(). The
2478 * top-left corner of the window decorations (aka window frame or
2479 * border) will be placed at @x, @y. Therefore, to position a window
2480 * at the top left of the screen, you want to use the default gravity
2481 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
2483 * To position a window at the bottom right corner of the screen, you
2484 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
2485 * point is at @x + the window width and @y + the window height, and
2486 * the bottom-right corner of the window border will be placed at that
2487 * reference point. So, to place a window in the bottom right corner
2488 * you would first set gravity to south east, then write:
2489 * gtk_window_move (window, gdk_screen_width () - window_width,
2490 * gdk_screen_height () - window_height).
2492 * The extended window manager hints specification at
2493 * http://www.freedesktop.org/standards/wm-spec.html has a nice table
2494 * of gravities in the "implementation notes" section.
2496 * The gtk_window_get_position() documentation may also be relevant.
2500 gtk_window_move (GtkWindow *window,
2504 GtkWindowGeometryInfo *info;
2507 g_return_if_fail (GTK_IS_WINDOW (window));
2509 widget = GTK_WIDGET (window);
2511 info = gtk_window_get_geometry_info (window, TRUE);
2513 if (GTK_WIDGET_MAPPED (window))
2515 /* we have now sent a request with this position
2516 * with currently-active constraints, so toggle flag.
2518 info->position_constraints_changed = FALSE;
2520 /* we only constrain if mapped - if not mapped,
2521 * then gtk_window_compute_configure_request()
2522 * will apply the constraints later, and we
2523 * don't want to lose information about
2524 * what position the user set before then.
2525 * i.e. if you do a move() then turn off POS_CENTER
2526 * then show the window, your move() will work.
2528 gtk_window_constrain_position (window,
2529 widget->allocation.width,
2530 widget->allocation.height,
2533 /* Note that this request doesn't go through our standard request
2534 * framework, e.g. doesn't increment configure_request_count,
2535 * doesn't set info->last, etc.; that's because
2536 * we don't save the info needed to arrive at this same request
2539 * To gtk_window_move_resize(), this will end up looking exactly
2540 * the same as the position being changed by the window
2544 /* FIXME are we handling gravity properly for framed windows? */
2546 gdk_window_move (window->frame,
2547 x - window->frame_left,
2548 y - window->frame_top);
2550 gdk_window_move (GTK_WIDGET (window)->window,
2555 /* Save this position to apply on mapping */
2556 info->initial_x = x;
2557 info->initial_y = y;
2558 info->initial_pos_set = TRUE;
2563 * gtk_window_get_position:
2564 * @window: a #GtkWindow
2565 * @root_x: return location for X coordinate of gravity-determined reference p\oint
2566 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
2568 * This function returns the position you need to pass to
2569 * gtk_window_move() to keep @window in its current position. This
2570 * means that the meaning of the returned value varies with window
2571 * gravity. See gtk_window_move() for more details.
2573 * If you haven't changed the window gravity, its gravity will be
2574 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
2575 * gets the position of the top-left corner of the window manager
2576 * frame for the window. gtk_window_move() sets the position of this
2577 * same top-left corner.
2579 * gtk_window_get_position() is not 100% reliable because the X Window System
2580 * does not specify a way to obtain the geometry of the
2581 * decorations placed on a window by the window manager.
2582 * Thus GTK+ is using a "best guess" that works with most
2585 * Moreover, nearly all window managers are broken with respect to
2586 * their handling of window gravity. So moving a window to its current
2587 * position as returned by gtk_window_get_position() tends to
2588 * result in moving the window slightly.
2590 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
2591 * frame is not relevant, and thus gtk_window_get_position() will
2592 * always produce accurate results. However you can't use static
2593 * gravity to do things like place a window in a corner of the screen,
2594 * because static gravity ignores the window manager decorations.
2596 * If you are saving and restoring your application's window
2597 * positions, you should know that it's impossible for applications to
2598 * do this without getting it somewhat wrong because applications do
2599 * not have sufficient knowledge of window manager state. The Correct
2600 * Mechanism is to support the session management protocol (see the
2601 * "GnomeClient" object in the GNOME libraries for example) and allow
2602 * the window manager to save your window sizes and positions.
2607 gtk_window_get_position (GtkWindow *window,
2613 g_return_if_fail (GTK_IS_WINDOW (window));
2615 widget = GTK_WIDGET (window);
2617 if (window->gravity == GDK_GRAVITY_STATIC)
2619 if (GTK_WIDGET_MAPPED (widget))
2621 /* This does a server round-trip, which is sort of wrong;
2622 * but a server round-trip is inevitable for
2623 * gdk_window_get_frame_extents() in the usual
2624 * NorthWestGravity case below, so not sure what else to
2625 * do. We should likely be consistent about whether we get
2626 * the client-side info or the server-side info.
2628 gdk_window_get_origin (widget->window, root_x, root_y);
2632 GdkRectangle configure_request;
2634 gtk_window_compute_configure_request (window,
2638 *root_x = configure_request.x;
2639 *root_y = configure_request.y;
2644 GdkRectangle frame_extents;
2649 if (GTK_WIDGET_MAPPED (widget))
2652 gdk_window_get_frame_extents (window->frame, &frame_extents);
2654 gdk_window_get_frame_extents (widget->window, &frame_extents);
2655 x = frame_extents.x;
2656 y = frame_extents.y;
2657 gtk_window_get_size (window, &w, &h);
2661 /* We just say the frame has 0 size on all sides.
2662 * Not sure what else to do.
2664 gtk_window_compute_configure_request (window,
2667 x = frame_extents.x;
2668 y = frame_extents.y;
2669 w = frame_extents.width;
2670 h = frame_extents.height;
2673 switch (window->gravity)
2675 case GDK_GRAVITY_NORTH:
2676 case GDK_GRAVITY_CENTER:
2677 case GDK_GRAVITY_SOUTH:
2678 /* Find center of frame. */
2679 x += frame_extents.width / 2;
2680 /* Center client window on that point. */
2684 case GDK_GRAVITY_SOUTH_EAST:
2685 case GDK_GRAVITY_EAST:
2686 case GDK_GRAVITY_NORTH_EAST:
2687 /* Find right edge of frame */
2688 x += frame_extents.width;
2689 /* Align left edge of client at that point. */
2696 switch (window->gravity)
2698 case GDK_GRAVITY_WEST:
2699 case GDK_GRAVITY_CENTER:
2700 case GDK_GRAVITY_EAST:
2701 /* Find center of frame. */
2702 y += frame_extents.height / 2;
2703 /* Center client window there. */
2706 case GDK_GRAVITY_SOUTH_WEST:
2707 case GDK_GRAVITY_SOUTH:
2708 case GDK_GRAVITY_SOUTH_EAST:
2709 /* Find south edge of frame */
2710 y += frame_extents.height;
2711 /* Place bottom edge of client there */
2726 * gtk_window_reshow_with_initial_size:
2727 * @window: a #GtkWindow
2729 * Hides @window, then reshows it, resetting the
2730 * default size and position of the window. Used
2731 * by GUI builders only.
2734 gtk_window_reshow_with_initial_size (GtkWindow *window)
2738 g_return_if_fail (GTK_IS_WINDOW (window));
2740 widget = GTK_WIDGET (window);
2742 gtk_widget_hide (widget);
2743 gtk_widget_unrealize (widget);
2744 gtk_widget_show (widget);
2748 gtk_window_destroy (GtkObject *object)
2752 g_return_if_fail (GTK_IS_WINDOW (object));
2754 window = GTK_WINDOW (object);
2756 if (window->transient_parent)
2757 gtk_window_set_transient_for (window, NULL);
2759 /* frees the icons */
2760 gtk_window_set_icon_list (window, NULL);
2762 if (window->has_user_ref_count)
2764 window->has_user_ref_count = FALSE;
2765 gtk_widget_unref (GTK_WIDGET (window));
2769 gtk_window_group_remove_window (window->group, window);
2771 GTK_OBJECT_CLASS (parent_class)->destroy (object);
2775 gtk_window_mnemonic_hash_remove (gpointer key,
2779 GtkWindowMnemonic *mnemonic = key;
2780 GtkWindow *window = user;
2782 if (mnemonic->window == window)
2784 if (mnemonic->targets)
2786 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
2788 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
2789 name, mnemonic->targets->data);
2792 g_slist_free (mnemonic->targets);
2801 gtk_window_finalize (GObject *object)
2805 g_return_if_fail (GTK_IS_WINDOW (object));
2807 window = GTK_WINDOW (object);
2809 toplevel_list = g_slist_remove (toplevel_list, window);
2811 g_free (window->title);
2812 g_free (window->wmclass_name);
2813 g_free (window->wmclass_class);
2814 g_free (window->wm_role);
2816 g_hash_table_foreach_remove (mnemonic_hash_table,
2817 gtk_window_mnemonic_hash_remove,
2819 if (window->geometry_info)
2821 if (window->geometry_info->widget)
2822 gtk_signal_disconnect_by_func (GTK_OBJECT (window->geometry_info->widget),
2823 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
2824 &window->geometry_info->widget);
2825 g_free (window->geometry_info);
2828 G_OBJECT_CLASS (parent_class)->finalize (object);
2832 gtk_window_show (GtkWidget *widget)
2834 GtkWindow *window = GTK_WINDOW (widget);
2835 GtkContainer *container = GTK_CONTAINER (window);
2836 gboolean need_resize;
2838 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
2840 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
2841 container->need_resize = FALSE;
2845 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
2846 GtkAllocation allocation = { 0, 0 };
2847 GdkRectangle configure_request;
2848 GdkGeometry new_geometry;
2850 gboolean was_realized;
2852 /* We are going to go ahead and perform this configure request
2853 * and then emulate a configure notify by going ahead and
2854 * doing a size allocate. Sort of a synchronous
2855 * mini-copy of gtk_window_move_resize() here.
2857 gtk_window_compute_configure_request (window,
2862 /* We update this because we are going to go ahead
2863 * and gdk_window_resize() below, rather than
2866 info->last.configure_request.width = configure_request.width;
2867 info->last.configure_request.height = configure_request.height;
2869 /* and allocate the window - this is normally done
2870 * in move_resize in response to configure notify
2872 allocation.width = configure_request.width;
2873 allocation.height = configure_request.height;
2874 gtk_widget_size_allocate (widget, &allocation);
2876 /* Then we guarantee we have a realize */
2877 was_realized = FALSE;
2878 if (!GTK_WIDGET_REALIZED (widget))
2880 gtk_widget_realize (widget);
2881 was_realized = TRUE;
2884 /* Must be done after the windows are realized,
2885 * so that the decorations can be read
2887 gtk_decorated_window_calculate_frame_size (window);
2889 /* We only send configure request if we didn't just finish
2890 * creating the window; if we just created the window
2891 * then we created it with widget->allocation anyhow.
2894 gdk_window_resize (widget->window,
2895 configure_request.width,
2896 configure_request.height);
2899 gtk_container_check_resize (container);
2901 gtk_widget_map (widget);
2904 gtk_grab_add (widget);
2908 gtk_window_hide (GtkWidget *widget)
2912 g_return_if_fail (GTK_IS_WINDOW (widget));
2914 window = GTK_WINDOW (widget);
2916 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
2917 gtk_widget_unmap (widget);
2920 gtk_grab_remove (widget);
2924 gtk_window_map (GtkWidget *widget)
2927 GdkWindow *toplevel;
2929 g_return_if_fail (GTK_IS_WINDOW (widget));
2931 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
2933 window = GTK_WINDOW (widget);
2935 if (window->bin.child &&
2936 GTK_WIDGET_VISIBLE (window->bin.child) &&
2937 !GTK_WIDGET_MAPPED (window->bin.child))
2938 gtk_widget_map (window->bin.child);
2941 toplevel = window->frame;
2943 toplevel = widget->window;
2945 if (window->maximize_initially)
2946 gdk_window_maximize (toplevel);
2948 gdk_window_unmaximize (toplevel);
2950 if (window->stick_initially)
2951 gdk_window_stick (toplevel);
2953 gdk_window_unstick (toplevel);
2955 if (window->iconify_initially)
2956 gdk_window_iconify (toplevel);
2958 gdk_window_deiconify (toplevel);
2960 /* No longer use the default settings */
2961 window->need_default_size = FALSE;
2962 window->need_default_position = FALSE;
2964 gdk_window_show (widget->window);
2967 gdk_window_show (window->frame);
2971 gtk_window_unmap (GtkWidget *widget)
2974 GtkWindowGeometryInfo *info;
2976 window = GTK_WINDOW (widget);
2978 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
2980 gdk_window_withdraw (window->frame);
2982 gdk_window_withdraw (widget->window);
2984 window->configure_request_count = 0;
2985 window->configure_notify_received = FALSE;
2987 /* on unmap, we reset the default positioning of the window,
2988 * so it's placed again, but we don't reset the default
2989 * size of the window, so it's remembered.
2991 window->need_default_position = TRUE;
2993 info = gtk_window_get_geometry_info (window, FALSE);
2996 info->initial_pos_set = FALSE;
2997 info->position_constraints_changed = FALSE;
3002 gtk_window_realize (GtkWidget *widget)
3005 GdkWindow *parent_window;
3006 GdkWindowAttr attributes;
3007 gint attributes_mask;
3009 g_return_if_fail (GTK_IS_WINDOW (widget));
3011 window = GTK_WINDOW (widget);
3013 /* ensure widget tree is properly size allocated */
3014 if (widget->allocation.x == -1 &&
3015 widget->allocation.y == -1 &&
3016 widget->allocation.width == 1 &&
3017 widget->allocation.height == 1)
3019 GtkRequisition requisition;
3020 GtkAllocation allocation = { 0, 0, 200, 200 };
3022 gtk_widget_size_request (widget, &requisition);
3023 if (requisition.width || requisition.height)
3025 /* non-empty window */
3026 allocation.width = requisition.width;
3027 allocation.height = requisition.height;
3029 gtk_widget_size_allocate (widget, &allocation);
3031 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3033 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3036 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3038 switch (window->type)
3040 case GTK_WINDOW_TOPLEVEL:
3041 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3043 case GTK_WINDOW_POPUP:
3044 attributes.window_type = GDK_WINDOW_TEMP;
3047 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3051 attributes.title = window->title;
3052 attributes.wmclass_name = window->wmclass_name;
3053 attributes.wmclass_class = window->wmclass_class;
3054 attributes.wclass = GDK_INPUT_OUTPUT;
3055 attributes.visual = gtk_widget_get_visual (widget);
3056 attributes.colormap = gtk_widget_get_colormap (widget);
3058 if (window->has_frame)
3060 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3061 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3062 attributes.event_mask = (GDK_EXPOSURE_MASK |
3063 GDK_KEY_PRESS_MASK |
3064 GDK_ENTER_NOTIFY_MASK |
3065 GDK_LEAVE_NOTIFY_MASK |
3066 GDK_FOCUS_CHANGE_MASK |
3067 GDK_STRUCTURE_MASK |
3068 GDK_BUTTON_MOTION_MASK |
3069 GDK_POINTER_MOTION_HINT_MASK |
3070 GDK_BUTTON_PRESS_MASK |
3071 GDK_BUTTON_RELEASE_MASK);
3073 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3075 window->frame = gdk_window_new (NULL, &attributes, attributes_mask);
3076 gdk_window_set_user_data (window->frame, widget);
3078 attributes.window_type = GDK_WINDOW_CHILD;
3079 attributes.x = window->frame_left;
3080 attributes.y = window->frame_right;
3082 attributes_mask = GDK_WA_X | GDK_WA_Y;
3084 parent_window = window->frame;
3088 attributes_mask = 0;
3089 parent_window = NULL;
3092 attributes.width = widget->allocation.width;
3093 attributes.height = widget->allocation.height;
3094 attributes.event_mask = gtk_widget_get_events (widget);
3095 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3096 GDK_KEY_PRESS_MASK |
3097 GDK_ENTER_NOTIFY_MASK |
3098 GDK_LEAVE_NOTIFY_MASK |
3099 GDK_FOCUS_CHANGE_MASK |
3100 GDK_STRUCTURE_MASK);
3102 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3103 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3104 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3105 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3106 gdk_window_set_user_data (widget->window, window);
3108 widget->style = gtk_style_attach (widget->style, widget->window);
3109 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3111 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3113 /* This is a bad hack to set the window background. */
3114 gtk_window_paint (widget, NULL);
3116 if (window->transient_parent &&
3117 GTK_WIDGET_REALIZED (window->transient_parent))
3118 gdk_window_set_transient_for (widget->window,
3119 GTK_WIDGET (window->transient_parent)->window);
3121 if (window->wm_role)
3122 gdk_window_set_role (widget->window, window->wm_role);
3124 if (!window->decorated)
3125 gdk_window_set_decorations (widget->window, 0);
3127 gdk_window_set_type_hint (widget->window, window->type_hint);
3129 /* transient_for must be set to allow the modal hint */
3130 if (window->transient_parent && window->modal)
3131 gdk_window_set_modal_hint (widget->window, TRUE);
3133 gdk_window_set_modal_hint (widget->window, FALSE);
3136 gtk_window_realize_icon (window);
3140 gtk_window_unrealize (GtkWidget *widget)
3143 GtkWindowGeometryInfo *info;
3145 window = GTK_WINDOW (widget);
3147 /* On unrealize, we reset the size of the window such
3148 * that we will re-apply the default sizing stuff
3149 * next time we show the window.
3151 * Default positioning is reset on unmap, instead of unrealize.
3153 window->need_default_size = TRUE;
3154 info = gtk_window_get_geometry_info (window, FALSE);
3157 info->resize_width = -1;
3158 info->resize_height = -1;
3159 info->last.configure_request.x = 0;
3160 info->last.configure_request.y = 0;
3161 info->last.configure_request.width = -1;
3162 info->last.configure_request.height = -1;
3163 /* be sure we reset geom hints on re-realize */
3164 info->last.flags = 0;
3169 gdk_window_set_user_data (window->frame, NULL);
3170 gdk_window_destroy (window->frame);
3171 window->frame = NULL;
3175 gtk_window_unrealize_icon (window);
3177 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3181 gtk_window_size_request (GtkWidget *widget,
3182 GtkRequisition *requisition)
3187 g_return_if_fail (GTK_IS_WINDOW (widget));
3188 g_return_if_fail (requisition != NULL);
3190 window = GTK_WINDOW (widget);
3191 bin = GTK_BIN (window);
3193 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3194 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3196 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3198 GtkRequisition child_requisition;
3200 gtk_widget_size_request (bin->child, &child_requisition);
3202 requisition->width += child_requisition.width;
3203 requisition->height += child_requisition.height;
3208 gtk_window_size_allocate (GtkWidget *widget,
3209 GtkAllocation *allocation)
3212 GtkAllocation child_allocation;
3214 g_return_if_fail (GTK_IS_WINDOW (widget));
3215 g_return_if_fail (allocation != NULL);
3217 window = GTK_WINDOW (widget);
3218 widget->allocation = *allocation;
3220 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3222 child_allocation.x = GTK_CONTAINER (window)->border_width;
3223 child_allocation.y = GTK_CONTAINER (window)->border_width;
3224 child_allocation.width =
3225 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3226 child_allocation.height =
3227 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3229 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3232 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3234 gdk_window_resize (window->frame,
3235 allocation->width + window->frame_left + window->frame_right,
3236 allocation->height + window->frame_top + window->frame_bottom);
3241 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3244 gboolean return_val;
3247 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3248 g_return_val_if_fail (event != NULL, FALSE);
3250 window = GTK_WINDOW (widget);
3252 if (window->frame && (event->any.window == window->frame))
3254 if ((event->type != GDK_KEY_PRESS) &&
3255 (event->type != GDK_KEY_RELEASE) &&
3256 (event->type != GDK_FOCUS_CHANGE))
3258 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
3260 gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
3265 g_object_unref (event->any.window);
3266 event->any.window = g_object_ref (widget->window);
3274 gtk_window_frame_event (GtkWidget *widget, GdkEvent *event)
3276 GdkEventConfigure *configure_event;
3277 GtkWindow *window = GTK_WINDOW (widget);
3280 switch (event->type)
3283 configure_event = (GdkEventConfigure *)event;
3285 /* Invalidate the decorations */
3288 rect.width = configure_event->width;
3289 rect.height = configure_event->height;
3291 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3293 /* Pass on the (modified) configure event */
3294 configure_event->width -= window->frame_left + window->frame_right;
3295 configure_event->height -= window->frame_top + window->frame_bottom;
3296 return gtk_window_configure_event (widget, configure_event);
3305 gtk_window_configure_event (GtkWidget *widget,
3306 GdkEventConfigure *event)
3310 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3311 g_return_val_if_fail (event != NULL, FALSE);
3313 window = GTK_WINDOW (widget);
3315 /* window->configure_request_count incremented for each
3316 * configure request, and decremented to a min of 0 for
3317 * each configure notify.
3319 * All it means is that we know we will get at least
3320 * window->configure_request_count more configure notifies.
3321 * We could get more configure notifies than that; some
3322 * of the configure notifies we get may be unrelated to
3323 * the configure requests. But we will get at least
3324 * window->configure_request_count notifies.
3327 if (window->configure_request_count > 0)
3328 window->configure_request_count -= 1;
3330 /* As an optimization, we avoid a resize when possible.
3332 * The only times we can avoid a resize are:
3333 * - we know only the position changed, not the size
3334 * - we know we have made more requests and so will get more
3335 * notifies and can wait to resize when we get them
3338 if (window->configure_request_count > 0 ||
3339 (widget->allocation.width == event->width &&
3340 widget->allocation.height == event->height))
3344 * If we do need to resize, we do that by:
3345 * - filling in widget->allocation with the new size
3346 * - setting configure_notify_received to TRUE
3347 * for use in gtk_window_move_resize()
3348 * - queueing a resize, leading to invocation of
3349 * gtk_window_move_resize() in an idle handler
3353 window->configure_notify_received = TRUE;
3355 widget->allocation.width = event->width;
3356 widget->allocation.height = event->height;
3358 gtk_widget_queue_resize (widget);
3364 gtk_window_key_press_event (GtkWidget *widget,
3370 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3371 g_return_val_if_fail (event != NULL, FALSE);
3373 window = GTK_WINDOW (widget);
3377 if (window->focus_widget && window->focus_widget != widget &&
3378 GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
3379 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
3382 handled = gtk_window_mnemonic_activate (window,
3387 handled = gtk_accel_groups_activate (G_OBJECT (window), event->keyval, event->state);
3389 /* Chain up, invokes binding set */
3390 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
3391 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
3398 gtk_window_real_activate_default (GtkWindow *window)
3400 gtk_window_activate_default (window);
3404 gtk_window_real_activate_focus (GtkWindow *window)
3406 gtk_window_activate_focus (window);
3410 gtk_window_move_focus (GtkWindow *window,
3411 GtkDirectionType dir)
3413 gtk_widget_child_focus (GTK_WIDGET (window), dir);
3415 if (!GTK_CONTAINER (window)->focus_child)
3416 gtk_window_set_focus (window, NULL);
3420 gtk_window_key_release_event (GtkWidget *widget,
3426 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3427 g_return_val_if_fail (event != NULL, FALSE);
3429 window = GTK_WINDOW (widget);
3431 if (window->focus_widget &&
3432 window->focus_widget != widget &&
3433 GTK_WIDGET_SENSITIVE (window->focus_widget))
3435 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
3438 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
3439 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
3445 gtk_window_enter_notify_event (GtkWidget *widget,
3446 GdkEventCrossing *event)
3448 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3449 g_return_val_if_fail (event != NULL, FALSE);
3455 gtk_window_leave_notify_event (GtkWidget *widget,
3456 GdkEventCrossing *event)
3458 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3459 g_return_val_if_fail (event != NULL, FALSE);
3465 gtk_window_focus_in_event (GtkWidget *widget,
3466 GdkEventFocus *event)
3468 GtkWindow *window = GTK_WINDOW (widget);
3469 GdkEventFocus fevent;
3471 /* It appears spurious focus in events can occur when
3472 * the window is hidden. So we'll just check to see if
3473 * the window is visible before actually handling the
3476 if (GTK_WIDGET_VISIBLE (widget))
3478 window->has_focus = TRUE;
3480 if (window->focus_widget &&
3481 window->focus_widget != widget &&
3482 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3484 fevent.type = GDK_FOCUS_CHANGE;
3485 fevent.window = window->focus_widget->window;
3488 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
3496 gtk_window_focus_out_event (GtkWidget *widget,
3497 GdkEventFocus *event)
3499 GtkWindow *window = GTK_WINDOW (widget);
3500 GdkEventFocus fevent;
3502 window->has_focus = FALSE;
3504 if (window->focus_widget &&
3505 window->focus_widget != widget &&
3506 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3508 fevent.type = GDK_FOCUS_CHANGE;
3509 fevent.window = window->focus_widget->window;
3512 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
3518 static GdkAtom atom_rcfiles = GDK_NONE;
3521 gtk_window_read_rcfiles (GtkWidget *widget,
3522 GdkEventClient *event)
3524 GList *embedded_windows;
3526 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
3527 if (embedded_windows)
3532 for (i = 0; i < 5; i++)
3534 sev.data_format = 32;
3535 sev.message_type = atom_rcfiles;
3537 while (embedded_windows)
3539 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
3540 gdk_event_send_client_message ((GdkEvent *) &sev, xid);
3541 embedded_windows = embedded_windows->next;
3545 gtk_rc_reparse_all ();
3549 gtk_window_client_event (GtkWidget *widget,
3550 GdkEventClient *event)
3552 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3553 g_return_val_if_fail (event != NULL, FALSE);
3556 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
3558 if (event->message_type == atom_rcfiles)
3559 gtk_window_read_rcfiles (widget, event);
3565 gtk_window_check_resize (GtkContainer *container)
3569 g_return_if_fail (GTK_IS_WINDOW (container));
3571 window = GTK_WINDOW (container);
3573 if (GTK_WIDGET_VISIBLE (container))
3574 gtk_window_move_resize (window);
3578 gtk_window_focus (GtkWidget *widget,
3579 GtkDirectionType direction)
3583 GtkContainer *container;
3584 GtkWidget *old_focus_child;
3587 container = GTK_CONTAINER (widget);
3588 window = GTK_WINDOW (widget);
3589 bin = GTK_BIN (widget);
3591 old_focus_child = container->focus_child;
3593 /* We need a special implementation here to deal properly with wrapping
3594 * around in the tab chain without the danger of going into an
3597 if (old_focus_child)
3599 if (gtk_widget_child_focus (old_focus_child, direction))
3603 if (window->focus_widget)
3605 /* Wrapped off the end, clear the focus setting for the toplpevel */
3606 parent = window->focus_widget->parent;
3609 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
3610 parent = GTK_WIDGET (parent)->parent;
3613 gtk_window_set_focus (GTK_WINDOW (container), NULL);
3616 /* Now try to focus the first widget in the window */
3619 if (gtk_widget_child_focus (bin->child, direction))
3627 gtk_window_real_set_focus (GtkWindow *window,
3630 GdkEventFocus event;
3631 gboolean def_flags = 0;
3633 g_return_if_fail (GTK_IS_WINDOW (window));
3635 if (window->default_widget)
3636 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
3638 if (window->focus_widget)
3640 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3641 (window->focus_widget != window->default_widget))
3643 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3645 if (window->default_widget)
3646 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3649 if (window->has_focus)
3651 event.type = GDK_FOCUS_CHANGE;
3652 event.window = window->focus_widget->window;
3655 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
3659 window->focus_widget = focus;
3661 if (window->focus_widget)
3663 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3664 (window->focus_widget != window->default_widget))
3666 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
3667 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3669 if (window->default_widget)
3670 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3673 if (window->has_focus)
3675 event.type = GDK_FOCUS_CHANGE;
3676 event.window = window->focus_widget->window;
3679 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
3683 if (window->default_widget &&
3684 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
3685 gtk_widget_queue_draw (window->default_widget);
3688 /*********************************
3689 * Functions related to resizing *
3690 *********************************/
3692 /* This function doesn't constrain to geometry hints */
3694 gtk_window_compute_configure_request_size (GtkWindow *window,
3698 GtkRequisition requisition;
3699 GtkWindowGeometryInfo *info;
3703 * - we've done a size request
3706 widget = GTK_WIDGET (window);
3708 info = gtk_window_get_geometry_info (window, FALSE);
3710 if (window->need_default_size)
3712 gtk_widget_get_child_requisition (widget, &requisition);
3714 /* Default to requisition */
3715 *width = requisition.width;
3716 *height = requisition.height;
3718 /* If window is empty so requests 0, default to random nonzero size */
3719 if (*width == 0 && *height == 0)
3725 /* Override requisition with default size */
3729 if (info->default_width > 0)
3730 *width = info->default_width;
3732 if (info->default_height > 0)
3733 *height = info->default_height;
3738 /* Default to keeping current size */
3739 *width = widget->allocation.width;
3740 *height = widget->allocation.height;
3743 /* Override any size with gtk_window_resize() values */
3746 if (info->resize_width > 0)
3747 *width = info->resize_width;
3749 if (info->resize_height > 0)
3750 *height = info->resize_height;
3755 gtk_window_compute_configure_request (GtkWindow *window,
3756 GdkRectangle *request,
3757 GdkGeometry *geometry,
3760 GdkGeometry new_geometry;
3764 GtkWindowPosition pos;
3765 GtkWidget *parent_widget;
3766 GtkWindowGeometryInfo *info;
3769 widget = GTK_WIDGET (window);
3771 gtk_widget_size_request (widget, NULL);
3772 gtk_window_compute_configure_request_size (window, &w, &h);
3774 gtk_window_compute_hints (window, &new_geometry, &new_flags);
3775 gtk_window_constrain_size (window,
3776 &new_geometry, new_flags,
3780 parent_widget = (GtkWidget*) window->transient_parent;
3782 pos = window->position;
3783 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
3784 (parent_widget == NULL ||
3785 !GTK_WIDGET_MAPPED (parent_widget)))
3786 pos = GTK_WIN_POS_NONE;
3788 info = gtk_window_get_geometry_info (window, TRUE);
3790 /* by default, don't change position requested */
3791 x = info->last.configure_request.x;
3792 y = info->last.configure_request.y;
3794 if (window->need_default_position)
3797 /* FIXME this all interrelates with window gravity.
3798 * For most of them I think we want to set GRAVITY_CENTER.
3800 * Not sure how to go about that.
3805 /* here we are only handling CENTER_ALWAYS
3806 * as it relates to default positioning,
3807 * where it's equivalent to simply CENTER
3809 case GTK_WIN_POS_CENTER_ALWAYS:
3810 case GTK_WIN_POS_CENTER:
3812 gint screen_width = gdk_screen_width ();
3813 gint screen_height = gdk_screen_height ();
3815 x = (screen_width - w) / 2;
3816 y = (screen_height - h) / 2;
3820 case GTK_WIN_POS_CENTER_ON_PARENT:
3824 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
3826 gdk_window_get_origin (parent_widget->window,
3829 x = ox + (parent_widget->allocation.width - w) / 2;
3830 y = oy + (parent_widget->allocation.height - h) / 2;
3834 case GTK_WIN_POS_MOUSE:
3836 gint screen_width = gdk_screen_width ();
3837 gint screen_height = gdk_screen_height ();
3840 gdk_window_get_pointer (NULL, &px, &py, NULL);
3843 x = CLAMP (x, 0, screen_width - w);
3844 y = CLAMP (y, 0, screen_height - h);
3851 } /* if (window->need_default_position) */
3853 if (window->need_default_position &&
3854 info->initial_pos_set)
3856 x = info->initial_x;
3857 y = info->initial_y;
3858 gtk_window_constrain_position (window, w, h, &x, &y);
3864 request->height = h;
3867 *geometry = new_geometry;
3873 gtk_window_constrain_position (GtkWindow *window,
3879 /* See long comments in gtk_window_move_resize()
3880 * on when it's safe to call this function.
3882 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
3884 gint center_x, center_y;
3885 gint screen_width = gdk_screen_width ();
3886 gint screen_height = gdk_screen_height ();
3888 center_x = (screen_width - new_width) / 2;
3889 center_y = (screen_height - new_height) / 2;
3897 gtk_window_move_resize (GtkWindow *window)
3901 * First we determine whether any information has changed that would
3902 * cause us to revise our last configure request. If we would send
3903 * a different configure request from last time, then
3904 * configure_request_size_changed = TRUE or
3905 * configure_request_pos_changed = TRUE. configure_request_size_changed
3906 * may be true due to new hints, a gtk_window_resize(), or whatever.
3907 * configure_request_pos_changed may be true due to gtk_window_set_position()
3908 * or gtk_window_move().
3910 * If the configure request has changed, we send off a new one. To
3911 * ensure GTK invariants are maintained (resize queue does what it
3912 * should), we go ahead and size_allocate the requested size in this
3915 * If the configure request has not changed, we don't ever resend
3916 * it, because it could mean fighting the user or window manager.
3919 * To prepare the configure request, we come up with a base size/pos:
3920 * - the one from gtk_window_move()/gtk_window_resize()
3921 * - else default_width, default_height if we haven't ever
3923 * - else the size request if we haven't ever been mapped,
3924 * as a substitute default size
3925 * - else the current size of the window, as received from
3926 * configure notifies (i.e. the current allocation)
3928 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
3929 * the position request to be centered.
3932 GtkContainer *container;
3933 GtkWindowGeometryInfo *info;
3934 GdkGeometry new_geometry;
3936 GdkRectangle new_request;
3937 gboolean configure_request_size_changed;
3938 gboolean configure_request_pos_changed;
3939 gboolean hints_changed; /* do we need to send these again */
3940 GtkWindowLastGeometryInfo saved_last_info;
3942 widget = GTK_WIDGET (window);
3943 container = GTK_CONTAINER (widget);
3944 info = gtk_window_get_geometry_info (window, TRUE);
3946 configure_request_size_changed = FALSE;
3947 configure_request_pos_changed = FALSE;
3949 gtk_window_compute_configure_request (window, &new_request,
3950 &new_geometry, &new_flags);
3952 /* This check implies the invariant that we never set info->last
3953 * without setting the hints and sending off a configure request.
3955 * If we change info->last without sending the request, we may
3958 if (info->last.configure_request.x != new_request.x ||
3959 info->last.configure_request.y != new_request.y)
3960 configure_request_pos_changed = TRUE;
3962 if ((info->last.configure_request.width != new_request.width ||
3963 info->last.configure_request.height != new_request.height))
3964 configure_request_size_changed = TRUE;
3966 hints_changed = FALSE;
3968 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
3969 &new_geometry, new_flags))
3971 hints_changed = TRUE;
3974 /* Position Constraints
3975 * ====================
3977 * POS_CENTER_ALWAYS is conceptually a constraint rather than
3978 * a default. The other POS_ values are used only when the
3979 * window is shown, not after that.
3981 * However, we can't implement a position constraint as
3982 * "anytime the window size changes, center the window"
3983 * because this may well end up fighting the WM or user. In
3984 * fact it gets in an infinite loop with at least one WM.
3986 * Basically, applications are in no way in a position to
3987 * constrain the position of a window, with one exception:
3988 * override redirect windows. (Really the intended purpose
3989 * of CENTER_ALWAYS anyhow, I would think.)
3991 * So the way we implement this "constraint" is to say that when WE
3992 * cause a move or resize, i.e. we make a configure request changing
3993 * window size, we recompute the CENTER_ALWAYS position to reflect
3994 * the new window size, and include it in our request. Also, if we
3995 * just turned on CENTER_ALWAYS we snap to center with a new
3996 * request. Otherwise, if we are just NOTIFIED of a move or resize
3997 * done by someone else e.g. the window manager, we do NOT send a
3998 * new configure request.
4000 * For override redirect windows, this works fine; all window
4001 * sizes are from our configure requests. For managed windows,
4002 * it is at least semi-sane, though who knows what the
4003 * app author is thinking.
4006 /* This condition should be kept in sync with the condition later on
4007 * that determines whether we send a configure request. i.e. we
4008 * should do this position constraining anytime we were going to
4009 * send a configure request anyhow, plus when constraints have
4012 if (configure_request_pos_changed ||
4013 configure_request_size_changed ||
4015 info->position_constraints_changed)
4017 /* We request the constrained position if:
4018 * - we were changing position, and need to clamp
4019 * the change to the constraint
4020 * - we're changing the size anyway
4021 * - set_position() was called to toggle CENTER_ALWAYS on
4024 gtk_window_constrain_position (window,
4030 /* Update whether we need to request a move */
4031 if (info->last.configure_request.x != new_request.x ||
4032 info->last.configure_request.y != new_request.y)
4033 configure_request_pos_changed = TRUE;
4035 configure_request_pos_changed = FALSE;
4040 int notify_x, notify_y;
4042 /* this is the position from the last configure notify */
4043 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4045 g_print ("--- %s ---\n"
4046 "last : %d,%d\t%d x %d\n"
4047 "this : %d,%d\t%d x %d\n"
4048 "alloc: %d,%d\t%d x %d\n"
4050 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4051 "configure_notify_received: %d\n"
4052 "configure_request_count: %d\n"
4053 "position_constraints_changed: %d\n",
4054 window->title ? window->title : "(no title)",
4055 info->last.configure_request.x,
4056 info->last.configure_request.y,
4057 info->last.configure_request.width,
4058 info->last.configure_request.height,
4064 widget->allocation.width,
4065 widget->allocation.height,
4066 widget->requisition.width,
4067 widget->requisition.height,
4068 configure_request_pos_changed,
4069 configure_request_size_changed,
4071 window->configure_notify_received,
4072 window->configure_request_count,
4073 info->position_constraints_changed);
4077 saved_last_info = info->last;
4078 info->last.geometry = new_geometry;
4079 info->last.flags = new_flags;
4080 info->last.configure_request = new_request;
4082 /* need to set PPosition so the WM will look at our position,
4083 * but we don't want to count PPosition coming and going as a hints
4084 * change for future iterations. So we saved info->last prior to
4088 /* Also, if the initial position was explicitly set, then we always
4089 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4093 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4094 * this is an initial map
4097 if ((configure_request_pos_changed ||
4098 info->initial_pos_set ||
4099 (window->need_default_position &&
4100 window->position != GTK_WIN_POS_NONE)) &&
4101 (new_flags & GDK_HINT_POS) == 0)
4103 new_flags |= GDK_HINT_POS;
4104 hints_changed = TRUE;
4107 /* Set hints if necessary
4110 gdk_window_set_geometry_hints (widget->window,
4114 /* handle resizing/moving and widget tree allocation
4116 if (window->configure_notify_received)
4118 GtkAllocation allocation;
4120 /* If we have received a configure event since
4121 * the last time in this function, we need to
4122 * accept our new size and size_allocate child widgets.
4123 * (see gtk_window_configure_event() for more details).
4125 * 1 or more configure notifies may have been received.
4126 * Also, configure_notify_received will only be TRUE
4127 * if all expected configure notifies have been received
4128 * (one per configure request), as an optimization.
4131 window->configure_notify_received = FALSE;
4133 /* gtk_window_configure_event() filled in widget->allocation */
4134 allocation = widget->allocation;
4135 gtk_widget_size_allocate (widget, &allocation);
4136 gtk_widget_queue_draw (widget);
4138 /* If the configure request changed, it means that
4140 * 1) coincidentally changed hints or widget properties
4141 * impacting the configure request before getting
4142 * a configure notify, or
4143 * 2) some broken widget is changing its size request
4144 * during size allocation, resulting in
4145 * a false appearance of changed configure request.
4147 * For 1), we could just go ahead and ask for the
4148 * new size right now, but doing that for 2)
4149 * might well be fighting the user (and can even
4150 * trigger a loop). Since we really don't want to
4151 * do that, we requeue a resize in hopes that
4152 * by the time it gets handled, the child has seen
4153 * the light and is willing to go along with the
4154 * new size. (this happens for the zvt widget, since
4155 * the size_allocate() above will have stored the
4156 * requisition corresponding to the new size in the
4159 * This doesn't buy us anything for 1), but it shouldn't
4160 * hurt us too badly, since it is what would have
4161 * happened if we had gotten the configure event before
4162 * the new size had been set.
4165 if (configure_request_size_changed ||
4166 configure_request_pos_changed)
4168 /* Don't change the recorded last info after all, because we
4169 * haven't actually updated to the new info yet - we decided
4170 * to postpone our configure request until later.
4172 info->last = saved_last_info;
4174 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
4177 else if ((configure_request_size_changed || hints_changed) &&
4178 (widget->allocation.width != new_request.width ||
4179 widget->allocation.height != new_request.height))
4182 /* We are in one of the following situations:
4183 * A. configure_request_size_changed
4184 * our requisition has changed and we need a different window size,
4185 * so we request it from the window manager.
4186 * B. !configure_request_size_changed && hints_changed
4187 * the window manager rejects our size, but we have just changed the
4188 * window manager hints, so there's a chance our request will
4189 * be honoured this time, so we try again.
4191 * However, if the new requisition is the same as the current allocation,
4192 * we don't request it again, since we won't get a ConfigureNotify back from
4193 * the window manager unless it decides to change our requisition. If
4194 * we don't get the ConfigureNotify back, the resize queue will never be run.
4197 /* Now send the configure request */
4198 if (configure_request_pos_changed)
4202 gdk_window_move_resize (window->frame,
4203 new_request.x - window->frame_left,
4204 new_request.y - window->frame_top,
4205 new_request.width + window->frame_left + window->frame_right,
4206 new_request.height + window->frame_top + window->frame_bottom);
4207 gdk_window_resize (GTK_WIDGET (window)->window,
4208 new_request.width, new_request.height);
4211 gdk_window_move_resize (widget->window,
4212 new_request.x, new_request.y,
4213 new_request.width, new_request.height);
4215 else /* only size changed */
4218 gdk_window_resize (window->frame,
4219 new_request.width + window->frame_left + window->frame_right,
4220 new_request.height + window->frame_top + window->frame_bottom);
4221 gdk_window_resize (widget->window,
4222 new_request.width, new_request.height);
4225 /* Increment the number of have-not-yet-received-notify requests */
4226 window->configure_request_count += 1;
4228 /* We have now sent a request since the last position constraint
4229 * change and definitely don't need a an initial size again (not
4230 * resetting this here can lead to infinite loops for
4231 * GTK_RESIZE_IMMEDIATE containers)
4233 info->position_constraints_changed = FALSE;
4234 window->need_default_position = FALSE;
4236 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
4237 * configure event in response to our resizing request.
4238 * the configure event will cause a new resize with
4239 * ->configure_notify_received=TRUE.
4240 * until then, we want to
4241 * - discard expose events
4242 * - coalesce resizes for our children
4243 * - defer any window resizes until the configure event arrived
4244 * to achieve this, we queue a resize for the window, but remove its
4245 * resizing handler, so resizing will not be handled from the next
4246 * idle handler but when the configure event arrives.
4248 * FIXME: we should also dequeue the pending redraws here, since
4249 * we handle those ourselves upon ->configure_notify_received==TRUE.
4251 if (container->resize_mode == GTK_RESIZE_QUEUE)
4253 gtk_widget_queue_resize (widget);
4254 _gtk_container_dequeue_resize_handler (container);
4259 /* Handle any position changes.
4261 if (configure_request_pos_changed)
4265 gdk_window_move (window->frame,
4266 new_request.x - window->frame_left,
4267 new_request.y - window->frame_top);
4270 gdk_window_move (widget->window,
4271 new_request.x, new_request.y);
4274 /* And run the resize queue.
4276 if (container->resize_widgets)
4277 gtk_container_resize_children (container);
4281 /* Compare two sets of Geometry hints for equality.
4284 gtk_window_compare_hints (GdkGeometry *geometry_a,
4286 GdkGeometry *geometry_b,
4289 if (flags_a != flags_b)
4292 if ((flags_a & GDK_HINT_MIN_SIZE) &&
4293 (geometry_a->min_width != geometry_b->min_width ||
4294 geometry_a->min_height != geometry_b->min_height))
4297 if ((flags_a & GDK_HINT_MAX_SIZE) &&
4298 (geometry_a->max_width != geometry_b->max_width ||
4299 geometry_a->max_height != geometry_b->max_height))
4302 if ((flags_a & GDK_HINT_BASE_SIZE) &&
4303 (geometry_a->base_width != geometry_b->base_width ||
4304 geometry_a->base_height != geometry_b->base_height))
4307 if ((flags_a & GDK_HINT_ASPECT) &&
4308 (geometry_a->min_aspect != geometry_b->min_aspect ||
4309 geometry_a->max_aspect != geometry_b->max_aspect))
4312 if ((flags_a & GDK_HINT_RESIZE_INC) &&
4313 (geometry_a->width_inc != geometry_b->width_inc ||
4314 geometry_a->height_inc != geometry_b->height_inc))
4317 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
4318 geometry_a->win_gravity != geometry_b->win_gravity)
4325 _gtk_window_constrain_size (GtkWindow *window,
4331 GtkWindowGeometryInfo *info;
4333 g_return_if_fail (GTK_IS_WINDOW (window));
4335 info = window->geometry_info;
4338 GdkWindowHints flags = info->last.flags;
4339 GdkGeometry *geometry = &info->last.geometry;
4341 gtk_window_constrain_size (window,
4352 gtk_window_constrain_size (GtkWindow *window,
4353 GdkGeometry *geometry,
4360 gdk_window_constrain_size (geometry, flags, width, height,
4361 new_width, new_height);
4364 /* Compute the set of geometry hints and flags for a window
4365 * based on the application set geometry, and requisiition
4366 * of the window. gtk_widget_size_request() must have been
4370 gtk_window_compute_hints (GtkWindow *window,
4371 GdkGeometry *new_geometry,
4375 gint extra_width = 0;
4376 gint extra_height = 0;
4377 GtkWindowGeometryInfo *geometry_info;
4378 GtkRequisition requisition;
4380 g_return_if_fail (GTK_IS_WINDOW (window));
4382 widget = GTK_WIDGET (window);
4384 gtk_widget_get_child_requisition (widget, &requisition);
4385 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
4389 *new_flags = geometry_info->mask;
4390 *new_geometry = geometry_info->geometry;
4397 if (geometry_info && geometry_info->widget)
4399 extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
4400 extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
4403 /* We don't want to set GDK_HINT_POS in here, we just set it
4404 * in gtk_window_move_resize() when we want the position
4408 if (*new_flags & GDK_HINT_BASE_SIZE)
4410 new_geometry->base_width += extra_width;
4411 new_geometry->base_height += extra_height;
4413 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
4414 (*new_flags & GDK_HINT_RESIZE_INC) &&
4415 ((extra_width != 0) || (extra_height != 0)))
4417 *new_flags |= GDK_HINT_BASE_SIZE;
4419 new_geometry->base_width = extra_width;
4420 new_geometry->base_height = extra_height;
4423 if (*new_flags & GDK_HINT_MIN_SIZE)
4425 if (new_geometry->min_width < 0)
4426 new_geometry->min_width = requisition.width;
4428 new_geometry->min_width += extra_width;
4430 if (new_geometry->min_height < 0)
4431 new_geometry->min_height = requisition.height;
4433 new_geometry->min_height += extra_height;
4435 else if (!window->allow_shrink)
4437 *new_flags |= GDK_HINT_MIN_SIZE;
4439 new_geometry->min_width = requisition.width;
4440 new_geometry->min_height = requisition.height;
4443 if (*new_flags & GDK_HINT_MAX_SIZE)
4445 if (new_geometry->max_width < 0)
4446 new_geometry->max_width = requisition.width;
4448 new_geometry->max_width += extra_width;
4450 if (new_geometry->max_height < 0)
4451 new_geometry->max_width = requisition.height;
4453 new_geometry->max_height += extra_height;
4455 else if (!window->allow_grow)
4457 *new_flags |= GDK_HINT_MAX_SIZE;
4459 new_geometry->max_width = requisition.width;
4460 new_geometry->max_height = requisition.height;
4463 *new_flags |= GDK_HINT_WIN_GRAVITY;
4464 new_geometry->win_gravity = window->gravity;
4467 /***********************
4468 * Redrawing functions *
4469 ***********************/
4472 gtk_window_paint (GtkWidget *widget,
4475 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
4476 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
4480 gtk_window_expose (GtkWidget *widget,
4481 GdkEventExpose *event)
4483 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
4484 g_return_val_if_fail (event != NULL, FALSE);
4486 if (!GTK_WIDGET_APP_PAINTABLE (widget))
4487 gtk_window_paint (widget, &event->area);
4489 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
4490 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
4496 * gtk_window_set_has_frame:
4497 * @window: a #GtkWindow
4498 * @setting: a boolean
4500 * (Note: this is a special-purpose function for the framebuffer port,
4501 * that causes GTK+ to draw its own window border. For most applications,
4502 * you want gtk_window_set_decorated() instead, which tells the window
4503 * manager whether to draw the window border.)
4505 * If this function is called on a window with setting of TRUE, before
4506 * it is realized or showed, it will have a "frame" window around
4507 * widget->window, accessible in window->frame. Using the signal
4508 * frame_event you can recieve all events targeted at the frame.
4510 * This function is used by the linux-fb port to implement managed
4511 * windows, but it could concievably be used by X-programs that
4512 * want to do their own window decorations.
4516 gtk_window_set_has_frame (GtkWindow *window,
4519 g_return_if_fail (GTK_IS_WINDOW (window));
4520 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
4522 window->has_frame = setting != FALSE;
4526 * gtk_window_get_has_frame:
4527 * @window: a #GtkWindow
4529 * Accessor for whether the window has a frame window exterior to
4530 * widget->window. Gets the value set by gtk_window_set_has_frame ().
4532 * Return value: %TRUE if a frame has been added to the window
4533 * via gtk_widow_has_frame
4536 gtk_window_get_has_frame (GtkWindow *window)
4538 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4540 return window->has_frame;
4544 * gtk_window_set_frame_dimensions:
4545 * @window: a #GtkWindow that has a frame
4546 * @left: The width of the left border
4547 * @top: The height of the top border
4548 * @right: The width of the right border
4549 * @bottom: The height of the bottom border
4551 * (Note: this is a special-purpose function intended for the framebuffer
4552 * port; see gtk_window_set_has_frame(). It will have no effect on the
4553 * window border drawn by the window manager, which is the normal
4554 * case when using the X Window system.)
4556 * For windows with frames (see #gtk_window_set_has_frame) this function
4557 * can be used to change the size of the frame border.
4560 gtk_window_set_frame_dimensions (GtkWindow *window,
4566 GtkWidget *widget = GTK_WIDGET (window);
4568 g_return_if_fail (GTK_IS_WINDOW (window));
4570 if (window->frame_left == left &&
4571 window->frame_top == top &&
4572 window->frame_right == right &&
4573 window->frame_bottom == bottom)
4576 window->frame_left = left;
4577 window->frame_top = top;
4578 window->frame_right = right;
4579 window->frame_bottom = bottom;
4581 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4583 gint width = widget->allocation.width + left + right;
4584 gint height = widget->allocation.height + top + bottom;
4585 gdk_window_resize (window->frame, width, height);
4586 gtk_decorated_window_move_resize_window (window,
4588 widget->allocation.width,
4589 widget->allocation.height);
4594 * gtk_window_present:
4595 * @window: a #GtkWindow
4597 * Presents a window to the user. This may mean raising the window
4598 * in the stacking order, deiconifying it, moving it to the current
4599 * desktop, and/or giving it the keyboard focus, possibly dependent
4600 * on the user's platform, window manager, and preferences.
4602 * If @window is hidden, this function calls gtk_widget_show()
4605 * This function should be used when the user tries to open a window
4606 * that's already open. Say for example the preferences dialog is
4607 * currently open, and the user chooses Preferences from the menu
4608 * a second time; use gtk_window_present() to move the already-open dialog
4609 * where the user can see it.
4613 gtk_window_present (GtkWindow *window)
4617 g_return_if_fail (GTK_IS_WINDOW (window));
4619 widget = GTK_WIDGET (window);
4621 if (GTK_WIDGET_VISIBLE (window))
4623 g_assert (widget->window != NULL);
4625 gdk_window_show (widget->window);
4627 /* note that gdk_window_focus() will also move the window to
4628 * the current desktop, for WM spec compliant window managers.
4630 gdk_window_focus (widget->window,
4631 gtk_get_current_event_time ());
4635 gtk_widget_show (widget);
4640 * gtk_window_iconify:
4641 * @window: a #GtkWindow
4643 * Asks to iconify (i.e. minimize) the specified @window. Note that you
4644 * shouldn't assume the window is definitely iconified afterward,
4645 * because other entities (e.g. the user or window manager) could
4646 * deiconify it again, or there may not be a window manager in which
4647 * case iconification isn't possible, etc. But normally the window
4648 * will end up iconified. Just don't write code that crashes if not.
4650 * It's permitted to call this function before showing a window,
4651 * in which case the window will be iconified before it ever appears
4654 * You can track iconification via the "window_state_event" signal
4659 gtk_window_iconify (GtkWindow *window)
4662 GdkWindow *toplevel;
4664 g_return_if_fail (GTK_IS_WINDOW (window));
4666 widget = GTK_WIDGET (window);
4668 window->iconify_initially = TRUE;
4671 toplevel = window->frame;
4673 toplevel = widget->window;
4675 if (toplevel != NULL)
4676 gdk_window_iconify (toplevel);
4680 * gtk_window_deiconify:
4681 * @window: a #GtkWindow
4683 * Asks to deiconify (i.e. unminimize) the specified @window. Note
4684 * that you shouldn't assume the window is definitely deiconified
4685 * afterward, because other entities (e.g. the user or window manager)
4686 * could iconify it again before your code which assumes
4687 * deiconification gets to run.
4689 * You can track iconification via the "window_state_event" signal
4693 gtk_window_deiconify (GtkWindow *window)
4696 GdkWindow *toplevel;
4698 g_return_if_fail (GTK_IS_WINDOW (window));
4700 widget = GTK_WIDGET (window);
4702 window->iconify_initially = FALSE;
4705 toplevel = window->frame;
4707 toplevel = widget->window;
4709 if (toplevel != NULL)
4710 gdk_window_deiconify (toplevel);
4715 * @window: a #GtkWindow
4717 * Asks to stick @window, which means that it will appear on all user
4718 * desktops. Note that you shouldn't assume the window is definitely
4719 * stuck afterward, because other entities (e.g. the user or window
4720 * manager) could unstick it again, and some window managers do not
4721 * support sticking windows. But normally the window will end up
4722 * stuck. Just don't write code that crashes if not.
4724 * It's permitted to call this function before showing a window.
4726 * You can track stickiness via the "window_state_event" signal
4731 gtk_window_stick (GtkWindow *window)
4734 GdkWindow *toplevel;
4736 g_return_if_fail (GTK_IS_WINDOW (window));
4738 widget = GTK_WIDGET (window);
4740 window->stick_initially = TRUE;
4743 toplevel = window->frame;
4745 toplevel = widget->window;
4747 if (toplevel != NULL)
4748 gdk_window_stick (toplevel);
4752 * gtk_window_unstick:
4753 * @window: a #GtkWindow
4755 * Asks to unstick @window, which means that it will appear on only
4756 * one of the user's desktops. Note that you shouldn't assume the
4757 * window is definitely unstuck afterward, because other entities
4758 * (e.g. the user or window manager) could stick it again. But
4759 * normally the window will end up stuck. Just don't write code that
4762 * You can track stickiness via the "window_state_event" signal
4767 gtk_window_unstick (GtkWindow *window)
4770 GdkWindow *toplevel;
4772 g_return_if_fail (GTK_IS_WINDOW (window));
4774 widget = GTK_WIDGET (window);
4776 window->stick_initially = FALSE;
4779 toplevel = window->frame;
4781 toplevel = widget->window;
4783 if (toplevel != NULL)
4784 gdk_window_unstick (toplevel);
4788 * gtk_window_maximize:
4789 * @window: a #GtkWindow
4791 * Asks to maximize @window, so that it becomes full-screen. Note that
4792 * you shouldn't assume the window is definitely maximized afterward,
4793 * because other entities (e.g. the user or window manager) could
4794 * unmaximize it again, and not all window managers support
4795 * maximization. But normally the window will end up maximized. Just
4796 * don't write code that crashes if not.
4798 * It's permitted to call this function before showing a window,
4799 * in which case the window will be maximized when it appears onscreen
4802 * You can track maximization via the "window_state_event" signal
4807 gtk_window_maximize (GtkWindow *window)
4810 GdkWindow *toplevel;
4812 g_return_if_fail (GTK_IS_WINDOW (window));
4814 widget = GTK_WIDGET (window);
4816 window->maximize_initially = TRUE;
4819 toplevel = window->frame;
4821 toplevel = widget->window;
4823 if (toplevel != NULL)
4824 gdk_window_maximize (toplevel);
4828 * gtk_window_unmaximize:
4829 * @window: a #GtkWindow
4831 * Asks to unmaximize @window. Note that you shouldn't assume the
4832 * window is definitely unmaximized afterward, because other entities
4833 * (e.g. the user or window manager) could maximize it again, and not
4834 * all window managers honor requests to unmaximize. But normally the
4835 * window will end up unmaximized. Just don't write code that crashes
4838 * You can track maximization via the "window_state_event" signal
4843 gtk_window_unmaximize (GtkWindow *window)
4846 GdkWindow *toplevel;
4848 g_return_if_fail (GTK_IS_WINDOW (window));
4850 widget = GTK_WIDGET (window);
4852 window->maximize_initially = FALSE;
4855 toplevel = window->frame;
4857 toplevel = widget->window;
4859 if (toplevel != NULL)
4860 gdk_window_unmaximize (toplevel);
4864 * gtk_window_set_resizable:
4865 * @window: a #GtkWindow
4866 * @resizable: %TRUE if the user can resize this window
4868 * Sets whether the user can resize a window. Windows are user resizable
4872 gtk_window_set_resizable (GtkWindow *window,
4875 g_return_if_fail (GTK_IS_WINDOW (window));
4877 gtk_window_set_policy (window, FALSE, resizable, FALSE);
4881 * gtk_window_get_resizable:
4882 * @window: a #GtkWindow
4884 * Gets the value set by gtk_window_set_resizable().
4886 * Return value: %TRUE if the user can resize the window
4889 gtk_window_get_resizable (GtkWindow *window)
4891 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4893 /* allow_grow is most likely to indicate the semantic concept we
4894 * mean by "resizable" (and will be a reliable indicator if
4895 * set_policy() hasn't been called)
4897 return window->allow_grow;
4901 * gtk_window_set_gravity:
4902 * @window: a #GtkWindow
4903 * @gravity: window gravity
4905 * Window gravity defines the meaning of coordinates passed to
4906 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
4909 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
4910 * typically "do what you mean."
4914 gtk_window_set_gravity (GtkWindow *window,
4917 g_return_if_fail (GTK_IS_WINDOW (window));
4919 if (gravity != window->gravity)
4921 window->gravity = gravity;
4923 /* gtk_window_move_resize() will adapt gravity
4925 gtk_widget_queue_resize (GTK_WIDGET (window));
4930 * gtk_window_get_gravity:
4931 * @window: a #GtkWindow
4933 * Gets the value set by gtk_window_set_gravity().
4935 * Return value: window gravity
4938 gtk_window_get_gravity (GtkWindow *window)
4940 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
4942 return window->gravity;
4946 * gtk_window_begin_resize_drag:
4947 * @window: a #GtkWindow
4948 * @button: mouse button that initiated the drag
4949 * @edge: position of the resize control
4950 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
4951 * @root_y: Y position where the user clicked to initiate the drag
4952 * @timestamp: timestamp from the click event that initiated the drag
4954 * Starts resizing a window. This function is used if an application
4955 * has window resizing controls. When GDK can support it, the resize
4956 * will be done using the standard mechanism for the window manager or
4957 * windowing system. Otherwise, GDK will try to emulate window
4958 * resizing, potentially not all that well, depending on the windowing system.
4962 gtk_window_begin_resize_drag (GtkWindow *window,
4970 GdkWindow *toplevel;
4972 g_return_if_fail (GTK_IS_WINDOW (window));
4973 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
4975 widget = GTK_WIDGET (window);
4978 toplevel = window->frame;
4980 toplevel = widget->window;
4982 gdk_window_begin_resize_drag (toplevel,
4989 * gtk_window_get_frame_dimensions:
4990 * @window: a #GtkWindow
4991 * @left: location to store the width of the frame at the left, or %NULL
4992 * @top: location to store the height of the frame at the top, or %NULL
4993 * @right: location to store the width of the frame at the returns, or %NULL
4994 * @bottom: location to store the height of the frame at the bottom, or %NULL
4996 * (Note: this is a special-purpose function intended for the
4997 * framebuffer port; see gtk_window_set_has_frame(). It will not
4998 * return the size of the window border drawn by the window manager,
4999 * which is the normal case when using a windowing system.
5000 * See gdk_window_get_frame_extents() to get the standard
5001 * window border extents.)
5003 * Retrieves the dimensions of the frame window for this toplevel.
5004 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5007 gtk_window_get_frame_dimensions (GtkWindow *window,
5013 g_return_if_fail (GTK_IS_WINDOW (window));
5016 *left = window->frame_left;
5018 *top = window->frame_top;
5020 *right = window->frame_right;
5022 *bottom = window->frame_bottom;
5026 * gtk_window_begin_move_drag:
5027 * @window: a #GtkWindow
5028 * @button: mouse button that initiated the drag
5029 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5030 * @root_y: Y position where the user clicked to initiate the drag
5031 * @timestamp: timestamp from the click event that initiated the drag
5033 * Starts moving a window. This function is used if an application
5034 * has window movement grips. When GDK can support it, the window movement
5035 * will be done using the standard mechanism for the window manager or
5036 * windowing system. Otherwise, GDK will try to emulate window
5037 * movement, potentially not all that well, depending on the windowing system.
5041 gtk_window_begin_move_drag (GtkWindow *window,
5048 GdkWindow *toplevel;
5050 g_return_if_fail (GTK_IS_WINDOW (window));
5051 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5053 widget = GTK_WIDGET (window);
5056 toplevel = window->frame;
5058 toplevel = widget->window;
5060 gdk_window_begin_move_drag (toplevel,
5068 gtk_window_group_class_init (GtkWindowGroupClass *klass)
5073 gtk_window_group_get_type (void)
5075 static GtkType window_group_type = 0;
5077 if (!window_group_type)
5079 static const GTypeInfo window_group_info =
5081 sizeof (GtkWindowGroupClass),
5082 NULL, /* base_init */
5083 NULL, /* base_finalize */
5084 (GClassInitFunc) gtk_window_group_class_init,
5085 NULL, /* class_finalize */
5086 NULL, /* class_data */
5087 sizeof (GtkWindowGroup),
5088 16, /* n_preallocs */
5089 (GInstanceInitFunc) NULL,
5092 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
5095 return window_group_type;
5099 * gtk_window_group_new:
5101 * Create a new #GtkWindowGroup object. Grabs added with
5102 * gtk_window_grab_add() only affect windows within the
5103 * same #GtkWindowGroup
5108 gtk_window_group_new (void)
5110 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
5114 window_group_cleanup_grabs (GtkWindowGroup *group,
5118 GSList *to_remove = NULL;
5120 tmp_list = group->grabs;
5123 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
5124 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
5125 tmp_list = tmp_list->next;
5130 gtk_grab_remove (to_remove->data);
5131 g_object_unref (to_remove->data);
5132 to_remove = g_slist_delete_link (to_remove, to_remove);
5137 * gtk_window_group_add_widget:
5138 * @window_group: a #GtkWindowGroup
5139 * @window: the #GtkWindow to add
5141 * Add a window to a #GtkWindowGroup.
5144 gtk_window_group_add_window (GtkWindowGroup *window_group,
5147 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5148 g_return_if_fail (GTK_IS_WINDOW (window));
5150 if (window->group != window_group)
5152 g_object_ref (window);
5153 g_object_ref (window_group);
5156 gtk_window_group_remove_window (window->group, window);
5158 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
5160 window->group = window_group;
5162 g_object_unref (window);
5167 * gtk_window_group_remove_window:
5168 * @window_group: a #GtkWindowGroup
5169 * @window: the #GtkWindow to remove
5171 * Removes a window from a #GtkWindowGroup.
5174 gtk_window_group_remove_window (GtkWindowGroup *window_group,
5177 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5178 g_return_if_fail (GTK_IS_WIDGET (window));
5179 g_return_if_fail (window->group == window_group);
5181 g_object_ref (window);
5183 window_group_cleanup_grabs (window_group, window);
5184 window->group = NULL;
5186 g_object_unref (G_OBJECT (window_group));
5187 g_object_unref (window);
5190 /* Return the group for the window or the default group
5193 _gtk_window_get_group (GtkWindow *window)
5195 if (window && window->group)
5196 return window->group;
5199 static GtkWindowGroup *default_group = NULL;
5202 default_group = gtk_window_group_new ();
5204 return default_group;
5210 Derived from XParseGeometry() in XFree86
5212 Copyright 1985, 1986, 1987,1998 The Open Group
5214 All Rights Reserved.
5216 The above copyright notice and this permission notice shall be included
5217 in all copies or substantial portions of the Software.
5219 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5220 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5221 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
5222 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
5223 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
5224 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
5225 OTHER DEALINGS IN THE SOFTWARE.
5227 Except as contained in this notice, the name of The Open Group shall
5228 not be used in advertising or otherwise to promote the sale, use or
5229 other dealings in this Software without prior written authorization
5230 from The Open Group.
5235 * XParseGeometry parses strings of the form
5236 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5237 * width, height, xoffset, and yoffset are unsigned integers.
5238 * Example: "=80x24+300-49"
5239 * The equal sign is optional.
5240 * It returns a bitmask that indicates which of the four values
5241 * were actually found in the string. For each value found,
5242 * the corresponding argument is updated; for each value
5243 * not found, the corresponding argument is left unchanged.
5246 /* The following code is from Xlib, and is minimally modified, so we
5247 * can track any upstream changes if required. Don't change this
5248 * code. Or if you do, put in a huge comment marking which thing
5253 read_int (gchar *string,
5261 else if (*string == '-')
5267 for (; (*string >= '0') && (*string <= '9'); string++)
5269 result = (result * 10) + (*string - '0');
5281 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
5282 * value (x, y, width, height) was found in the parsed string.
5284 #define NoValue 0x0000
5285 #define XValue 0x0001
5286 #define YValue 0x0002
5287 #define WidthValue 0x0004
5288 #define HeightValue 0x0008
5289 #define AllValues 0x000F
5290 #define XNegative 0x0010
5291 #define YNegative 0x0020
5293 /* Try not to reformat/modify, so we can compare/sync with X sources */
5295 gtk_XParseGeometry (const char *string,
5298 unsigned int *width,
5299 unsigned int *height)
5303 unsigned int tempWidth, tempHeight;
5305 char *nextCharacter;
5307 /* These initializations are just to silence gcc */
5313 if ( (string == NULL) || (*string == '\0')) return(mask);
5315 string++; /* ignore possible '=' at beg of geometry spec */
5317 strind = (char *)string;
5318 if (*strind != '+' && *strind != '-' && *strind != 'x') {
5319 tempWidth = read_int(strind, &nextCharacter);
5320 if (strind == nextCharacter)
5322 strind = nextCharacter;
5326 if (*strind == 'x' || *strind == 'X') {
5328 tempHeight = read_int(strind, &nextCharacter);
5329 if (strind == nextCharacter)
5331 strind = nextCharacter;
5332 mask |= HeightValue;
5335 if ((*strind == '+') || (*strind == '-')) {
5336 if (*strind == '-') {
5338 tempX = -read_int(strind, &nextCharacter);
5339 if (strind == nextCharacter)
5341 strind = nextCharacter;
5347 tempX = read_int(strind, &nextCharacter);
5348 if (strind == nextCharacter)
5350 strind = nextCharacter;
5353 if ((*strind == '+') || (*strind == '-')) {
5354 if (*strind == '-') {
5356 tempY = -read_int(strind, &nextCharacter);
5357 if (strind == nextCharacter)
5359 strind = nextCharacter;
5366 tempY = read_int(strind, &nextCharacter);
5367 if (strind == nextCharacter)
5369 strind = nextCharacter;
5375 /* If strind isn't at the end of the string the it's an invalid
5376 geometry specification. */
5378 if (*strind != '\0') return (0);
5384 if (mask & WidthValue)
5386 if (mask & HeightValue)
5387 *height = tempHeight;
5392 * gtk_window_parse_geometry:
5393 * @window: a #GtkWindow
5394 * @geometry: geometry string
5396 * Parses a standard X Window System geometry string - see the
5397 * manual page for X (type 'man X') for details on this.
5398 * gtk_window_parse_geometry() does work on all GTK+ ports
5399 * including Win32 but is primarily intended for an X environment.
5401 * If either a size or a position can be extracted from the
5402 * geometry string, gtk_window_parse_geometry() returns %TRUE
5403 * and calls gtk_window_set_default_size() and/or gtk_window_move()
5404 * to resize/move the window.
5406 * If gtk_window_parse_geometry() returns %TRUE, it will also
5407 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
5408 * indicating to the window manager that the size/position of
5409 * the window was user-specified. This causes most window
5410 * managers to honor the geometry.
5412 * Return value: %TRUE if string was parsed successfully
5415 gtk_window_parse_geometry (GtkWindow *window,
5416 const gchar *geometry)
5421 gboolean size_set, pos_set;
5423 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5424 g_return_val_if_fail (geometry != NULL, FALSE);
5426 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
5428 if ((result & WidthValue) == 0 ||
5431 if ((result & HeightValue) == 0 ||
5436 if ((result & WidthValue) || (result & HeightValue))
5438 gtk_window_set_default_size (window, w, h);
5442 gtk_window_get_size (window, &w, &h);
5444 grav = GDK_GRAVITY_NORTH_WEST;
5446 if ((result & XNegative) && (result & YNegative))
5447 grav = GDK_GRAVITY_SOUTH_EAST;
5448 else if (result & XNegative)
5449 grav = GDK_GRAVITY_NORTH_EAST;
5450 else if (result & YNegative)
5451 grav = GDK_GRAVITY_SOUTH_WEST;
5453 if ((result & XValue) == 0)
5456 if ((result & YValue) == 0)
5459 if (grav == GDK_GRAVITY_SOUTH_WEST ||
5460 grav == GDK_GRAVITY_SOUTH_EAST)
5461 y = gdk_screen_height () - h;
5463 if (grav == GDK_GRAVITY_SOUTH_EAST ||
5464 grav == GDK_GRAVITY_NORTH_EAST)
5465 x = gdk_screen_width () - w;
5474 if ((result & XValue) || (result & YValue))
5476 gtk_window_set_gravity (window, grav);
5477 gtk_window_move (window, x, y);
5481 if (size_set || pos_set)
5483 /* Set USSize, USPosition hints */
5484 GtkWindowGeometryInfo *info;
5486 info = gtk_window_get_geometry_info (window, TRUE);
5489 info->mask |= GDK_HINT_USER_POS;
5491 info->mask |= GDK_HINT_USER_SIZE;