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 #include "gtkprivate.h"
34 #include "gtksignal.h"
35 #include "gtkwindow.h"
36 #include "gtkwindow-decorate.h"
37 #include "gtkbindings.h"
39 #include "gtkiconfactory.h"
41 #include "gtkmarshalers.h"
68 PROP_DESTROY_WITH_PARENT,
77 GdkPixmap *icon_pixmap;
80 guint using_default_icon : 1;
81 guint using_parent_icon : 1;
85 GdkGeometry geometry; /* Last set of geometry hints we set */
87 GdkRectangle configure_request;
88 } GtkWindowLastGeometryInfo;
90 struct _GtkWindowGeometryInfo
92 /* Properties that the app has set on the window
94 GdkGeometry geometry; /* Geometry hints */
96 GtkWidget *widget; /* subwidget to which hints apply */
97 /* from last gtk_window_resize () - if > 0, indicates that
98 * we should resize to this size.
103 /* From last gtk_window_move () prior to mapping -
104 * only used if initial_pos_set
109 /* Default size - used only the FIRST time we map a window,
114 /* whether to use initial_x, initial_y */
115 guint initial_pos_set : 1;
116 /* CENTER_ALWAYS or other position constraint changed since
117 * we sent the last configure request.
119 guint position_constraints_changed : 1;
121 GtkWindowLastGeometryInfo last;
132 static void gtk_window_class_init (GtkWindowClass *klass);
133 static void gtk_window_init (GtkWindow *window);
134 static void gtk_window_dispose (GObject *object);
135 static void gtk_window_destroy (GtkObject *object);
136 static void gtk_window_finalize (GObject *object);
137 static void gtk_window_show (GtkWidget *widget);
138 static void gtk_window_hide (GtkWidget *widget);
139 static void gtk_window_map (GtkWidget *widget);
140 static void gtk_window_unmap (GtkWidget *widget);
141 static void gtk_window_realize (GtkWidget *widget);
142 static void gtk_window_unrealize (GtkWidget *widget);
143 static void gtk_window_size_request (GtkWidget *widget,
144 GtkRequisition *requisition);
145 static void gtk_window_size_allocate (GtkWidget *widget,
146 GtkAllocation *allocation);
147 static gint gtk_window_event (GtkWidget *widget,
149 static gboolean gtk_window_frame_event (GtkWindow *window,
151 static gint gtk_window_configure_event (GtkWidget *widget,
152 GdkEventConfigure *event);
153 static gint gtk_window_key_press_event (GtkWidget *widget,
155 static gint gtk_window_key_release_event (GtkWidget *widget,
157 static gint gtk_window_enter_notify_event (GtkWidget *widget,
158 GdkEventCrossing *event);
159 static gint gtk_window_leave_notify_event (GtkWidget *widget,
160 GdkEventCrossing *event);
161 static gint gtk_window_focus_in_event (GtkWidget *widget,
162 GdkEventFocus *event);
163 static gint gtk_window_focus_out_event (GtkWidget *widget,
164 GdkEventFocus *event);
165 static gint gtk_window_client_event (GtkWidget *widget,
166 GdkEventClient *event);
167 static void gtk_window_check_resize (GtkContainer *container);
168 static gint gtk_window_focus (GtkWidget *widget,
169 GtkDirectionType direction);
170 static void gtk_window_real_set_focus (GtkWindow *window,
173 static void gtk_window_real_activate_default (GtkWindow *window);
174 static void gtk_window_real_activate_focus (GtkWindow *window);
175 static void gtk_window_move_focus (GtkWindow *window,
176 GtkDirectionType dir);
177 static void gtk_window_read_rcfiles (GtkWidget *widget,
178 GdkEventClient *event);
179 static void gtk_window_paint (GtkWidget *widget,
181 static gint gtk_window_expose (GtkWidget *widget,
182 GdkEventExpose *event);
183 static void gtk_window_unset_transient_for (GtkWindow *window);
184 static void gtk_window_transient_parent_realized (GtkWidget *parent,
186 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
189 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
192 static void gtk_window_move_resize (GtkWindow *window);
193 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
195 GdkGeometry *geometry_b,
197 static void gtk_window_constrain_size (GtkWindow *window,
198 GdkGeometry *geometry,
204 static void gtk_window_constrain_position (GtkWindow *window,
209 static void gtk_window_compute_hints (GtkWindow *window,
210 GdkGeometry *new_geometry,
212 static void gtk_window_compute_configure_request (GtkWindow *window,
213 GdkRectangle *request,
214 GdkGeometry *geometry,
217 static void gtk_window_set_default_size_internal (GtkWindow *window,
218 gboolean change_width,
220 gboolean change_height,
223 static void gtk_window_realize_icon (GtkWindow *window);
224 static void gtk_window_unrealize_icon (GtkWindow *window);
225 static void gtk_window_notify_keys_changed (GtkWindow *window);
227 static GSList *toplevel_list = NULL;
228 static GHashTable *mnemonic_hash_table = NULL;
229 static GtkBinClass *parent_class = NULL;
230 static guint window_signals[LAST_SIGNAL] = { 0 };
231 static GList *default_icon_list = NULL;
232 /* FIXME need to be per-screen */
233 static GdkPixmap *default_icon_pixmap = NULL;
234 static GdkPixmap *default_icon_mask = NULL;
236 static void gtk_window_set_property (GObject *object,
240 static void gtk_window_get_property (GObject *object,
247 mnemonic_hash (gconstpointer key)
249 const GtkWindowMnemonic *k;
252 k = (GtkWindowMnemonic *)key;
254 h = (gulong) k->window;
255 h ^= k->keyval << 16;
256 h ^= k->keyval >> 16;
262 mnemonic_equal (gconstpointer a, gconstpointer b)
264 const GtkWindowMnemonic *ka;
265 const GtkWindowMnemonic *kb;
267 ka = (GtkWindowMnemonic *)a;
268 kb = (GtkWindowMnemonic *)b;
271 (ka->window == kb->window) &&
272 (ka->keyval == kb->keyval);
276 gtk_window_get_type (void)
278 static GtkType window_type = 0;
282 static const GtkTypeInfo window_info =
286 sizeof (GtkWindowClass),
287 (GtkClassInitFunc) gtk_window_class_init,
288 (GtkObjectInitFunc) gtk_window_init,
289 /* reserved_1 */ NULL,
290 /* reserved_2 */ NULL,
291 (GtkClassInitFunc) NULL,
294 window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
301 add_tab_bindings (GtkBindingSet *binding_set,
302 GdkModifierType modifiers,
303 GtkDirectionType direction)
305 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
307 GTK_TYPE_DIRECTION_TYPE, direction);
308 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
310 GTK_TYPE_DIRECTION_TYPE, direction);
311 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, modifiers,
313 GTK_TYPE_DIRECTION_TYPE, direction);
317 gtk_window_class_init (GtkWindowClass *klass)
319 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
320 GtkObjectClass *object_class;
321 GtkWidgetClass *widget_class;
322 GtkContainerClass *container_class;
323 GtkBindingSet *binding_set;
325 object_class = (GtkObjectClass*) klass;
326 widget_class = (GtkWidgetClass*) klass;
327 container_class = (GtkContainerClass*) klass;
329 parent_class = gtk_type_class (gtk_bin_get_type ());
331 mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
333 gobject_class->dispose = gtk_window_dispose;
334 gobject_class->finalize = gtk_window_finalize;
336 gobject_class->set_property = gtk_window_set_property;
337 gobject_class->get_property = gtk_window_get_property;
339 object_class->destroy = gtk_window_destroy;
341 widget_class->show = gtk_window_show;
342 widget_class->hide = gtk_window_hide;
343 widget_class->map = gtk_window_map;
344 widget_class->unmap = gtk_window_unmap;
345 widget_class->realize = gtk_window_realize;
346 widget_class->unrealize = gtk_window_unrealize;
347 widget_class->size_request = gtk_window_size_request;
348 widget_class->size_allocate = gtk_window_size_allocate;
349 widget_class->configure_event = gtk_window_configure_event;
350 widget_class->key_press_event = gtk_window_key_press_event;
351 widget_class->key_release_event = gtk_window_key_release_event;
352 widget_class->enter_notify_event = gtk_window_enter_notify_event;
353 widget_class->leave_notify_event = gtk_window_leave_notify_event;
354 widget_class->focus_in_event = gtk_window_focus_in_event;
355 widget_class->focus_out_event = gtk_window_focus_out_event;
356 widget_class->client_event = gtk_window_client_event;
357 widget_class->focus = gtk_window_focus;
359 widget_class->expose_event = gtk_window_expose;
361 container_class->check_resize = gtk_window_check_resize;
363 klass->set_focus = gtk_window_real_set_focus;
364 klass->frame_event = gtk_window_frame_event;
366 klass->activate_default = gtk_window_real_activate_default;
367 klass->activate_focus = gtk_window_real_activate_focus;
368 klass->move_focus = gtk_window_move_focus;
369 klass->keys_changed = NULL;
372 g_object_class_install_property (gobject_class,
374 g_param_spec_enum ("type",
376 _("The type of the window"),
377 GTK_TYPE_WINDOW_TYPE,
379 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
382 g_object_class_install_property (gobject_class,
384 g_param_spec_string ("title",
386 _("The title of the window"),
390 g_object_class_install_property (gobject_class,
392 g_param_spec_boolean ("allow_shrink",
394 /* xgettext:no-c-format */
395 _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea."),
399 g_object_class_install_property (gobject_class,
401 g_param_spec_boolean ("allow_grow",
403 _("If TRUE, users can expand the window beyond its minimum size."),
407 g_object_class_install_property (gobject_class,
409 g_param_spec_boolean ("resizable",
411 _("If TRUE, users can resize the window."),
415 g_object_class_install_property (gobject_class,
417 g_param_spec_boolean ("modal",
419 _("If TRUE, the window is modal (other windows are not usable while this one is up)."),
423 g_object_class_install_property (gobject_class,
425 g_param_spec_enum ("window_position",
426 _("Window Position"),
427 _("The initial position of the window."),
428 GTK_TYPE_WINDOW_POSITION,
432 g_object_class_install_property (gobject_class,
434 g_param_spec_int ("default_width",
436 _("The default width of the window, used when initially showing the window."),
442 g_object_class_install_property (gobject_class,
444 g_param_spec_int ("default_height",
446 _("The default height of the window, used when initially showing the window."),
452 g_object_class_install_property (gobject_class,
453 PROP_DESTROY_WITH_PARENT,
454 g_param_spec_boolean ("destroy_with_parent",
455 _("Destroy with Parent"),
456 _("If this window should be destroyed when the parent is destroyed"),
460 g_object_class_install_property (gobject_class,
462 g_param_spec_object ("icon",
464 _("Icon for this window"),
468 window_signals[SET_FOCUS] =
469 g_signal_new ("set_focus",
470 G_TYPE_FROM_CLASS (object_class),
472 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
474 _gtk_marshal_VOID__OBJECT,
478 window_signals[FRAME_EVENT] =
479 g_signal_new ("frame_event",
480 G_TYPE_FROM_CLASS(object_class),
482 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
483 _gtk_boolean_handled_accumulator, NULL,
484 _gtk_marshal_BOOLEAN__BOXED,
488 window_signals[ACTIVATE_FOCUS] =
489 g_signal_new ("activate_focus",
490 G_OBJECT_CLASS_TYPE (object_class),
491 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
492 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_focus),
494 _gtk_marshal_VOID__VOID,
498 window_signals[ACTIVATE_DEFAULT] =
499 g_signal_new ("activate_default",
500 G_OBJECT_CLASS_TYPE (object_class),
501 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
502 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_default),
504 _gtk_marshal_VOID__VOID,
508 window_signals[MOVE_FOCUS] =
509 g_signal_new ("move_focus",
510 G_OBJECT_CLASS_TYPE (object_class),
511 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
512 GTK_SIGNAL_OFFSET (GtkWindowClass, move_focus),
514 _gtk_marshal_VOID__ENUM,
517 GTK_TYPE_DIRECTION_TYPE);
519 window_signals[KEYS_CHANGED] =
520 g_signal_new ("keys_changed",
521 G_OBJECT_CLASS_TYPE (object_class),
523 GTK_SIGNAL_OFFSET (GtkWindowClass, keys_changed),
525 gtk_marshal_VOID__VOID,
533 binding_set = gtk_binding_set_by_class (klass);
535 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
536 "activate_focus", 0);
537 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
538 "activate_focus", 0);
540 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
541 "activate_default", 0);
543 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
544 "activate_default", 0);
546 gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
548 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
549 gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
551 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
553 gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
555 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
556 gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
558 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
560 gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
562 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);
563 gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
565 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);
567 gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
569 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);
570 gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
572 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);
574 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
575 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
576 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
577 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
581 gtk_window_init (GtkWindow *window)
583 GdkColormap *colormap;
585 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
586 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
588 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
590 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
592 window->title = NULL;
593 window->wmclass_name = g_strdup (g_get_prgname ());
594 window->wmclass_class = g_strdup (gdk_get_program_class ());
595 window->wm_role = NULL;
596 window->geometry_info = NULL;
597 window->type = GTK_WINDOW_TOPLEVEL;
598 window->focus_widget = NULL;
599 window->default_widget = NULL;
600 window->configure_request_count = 0;
601 window->allow_shrink = FALSE;
602 window->allow_grow = TRUE;
603 window->configure_notify_received = FALSE;
604 window->position = GTK_WIN_POS_NONE;
605 window->need_default_size = TRUE;
606 window->need_default_position = TRUE;
607 window->modal = FALSE;
608 window->frame = NULL;
609 window->has_frame = FALSE;
610 window->frame_left = 0;
611 window->frame_right = 0;
612 window->frame_top = 0;
613 window->frame_bottom = 0;
614 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
615 window->gravity = GDK_GRAVITY_NORTH_WEST;
616 window->decorated = TRUE;
617 window->mnemonic_modifier = GDK_MOD1_MASK;
619 colormap = _gtk_widget_peek_colormap ();
621 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
623 gtk_widget_ref (GTK_WIDGET (window));
624 gtk_object_sink (GTK_OBJECT (window));
625 window->has_user_ref_count = TRUE;
626 toplevel_list = g_slist_prepend (toplevel_list, window);
628 gtk_decorated_window_init (window);
630 gtk_signal_connect (GTK_OBJECT (window),
632 GTK_SIGNAL_FUNC (gtk_window_event),
637 gtk_window_set_property (GObject *object,
644 window = GTK_WINDOW (object);
649 window->type = g_value_get_enum (value);
652 gtk_window_set_title (window, g_value_get_string (value));
654 case PROP_ALLOW_SHRINK:
655 window->allow_shrink = g_value_get_boolean (value);
656 gtk_widget_queue_resize (GTK_WIDGET (window));
658 case PROP_ALLOW_GROW:
659 window->allow_grow = g_value_get_boolean (value);
660 gtk_widget_queue_resize (GTK_WIDGET (window));
661 g_object_notify (G_OBJECT (window), "resizable");
664 window->allow_grow = g_value_get_boolean (value);
665 gtk_widget_queue_resize (GTK_WIDGET (window));
666 g_object_notify (G_OBJECT (window), "allow_grow");
669 gtk_window_set_modal (window, g_value_get_boolean (value));
672 gtk_window_set_position (window, g_value_get_enum (value));
674 case PROP_DEFAULT_WIDTH:
675 gtk_window_set_default_size_internal (window,
676 TRUE, g_value_get_int (value),
679 case PROP_DEFAULT_HEIGHT:
680 gtk_window_set_default_size_internal (window,
682 TRUE, g_value_get_int (value));
684 case PROP_DESTROY_WITH_PARENT:
685 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
688 gtk_window_set_icon (window,
689 g_value_get_object (value));
698 gtk_window_get_property (GObject *object,
705 window = GTK_WINDOW (object);
709 GtkWindowGeometryInfo *info;
711 g_value_set_enum (value, window->type);
714 g_value_set_string (value, window->title);
716 case PROP_ALLOW_SHRINK:
717 g_value_set_boolean (value, window->allow_shrink);
719 case PROP_ALLOW_GROW:
720 g_value_set_boolean (value, window->allow_grow);
723 g_value_set_boolean (value, window->allow_grow);
726 g_value_set_boolean (value, window->modal);
729 g_value_set_enum (value, window->position);
731 case PROP_DEFAULT_WIDTH:
732 info = gtk_window_get_geometry_info (window, FALSE);
734 g_value_set_int (value, -1);
736 g_value_set_int (value, info->default_width);
738 case PROP_DEFAULT_HEIGHT:
739 info = gtk_window_get_geometry_info (window, FALSE);
741 g_value_set_int (value, -1);
743 g_value_set_int (value, info->default_height);
745 case PROP_DESTROY_WITH_PARENT:
746 g_value_set_boolean (value, window->destroy_with_parent);
749 g_value_set_object (value, gtk_window_get_icon (window));
752 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
759 * @type: type of window
761 * Creates a new #GtkWindow, which is a toplevel window that can
762 * contain other widgets. Nearly always, the type of the window should
763 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
764 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
765 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
766 * dialogs, though in some other toolkits dialogs are called "popups".
767 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
768 * On X11, popup windows are not controlled by the <link
769 * linkend="gtk-X11-arch">window manager</link>.
771 * If you simply want an undecorated window (no window borders), use
772 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
774 * Return value: a new #GtkWindow.
777 gtk_window_new (GtkWindowType type)
781 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
783 window = gtk_type_new (GTK_TYPE_WINDOW);
787 return GTK_WIDGET (window);
791 * gtk_window_set_title:
792 * @window: a #GtkWindow
793 * @title: title of the window
795 * Sets the title of the #GtkWindow. The title of a window will be
796 * displayed in its title bar; on the X Window System, the title bar
797 * is rendered by the <link linkend="gtk-X11-arch">window
798 * manager</link>, so exactly how the title appears to users may vary
799 * according to a user's exact configuration. The title should help a
800 * user distinguish this window from other windows they may have
801 * open. A good title might include the application name and current
802 * document filename, for example.
806 gtk_window_set_title (GtkWindow *window,
809 g_return_if_fail (GTK_IS_WINDOW (window));
812 g_free (window->title);
813 window->title = g_strdup (title);
815 if (GTK_WIDGET_REALIZED (window))
817 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
819 gtk_decorated_window_set_title (window, title);
822 g_object_notify (G_OBJECT (window), "title");
826 * gtk_window_get_title:
827 * @window: a #GtkWindow
829 * Retrieves the title of the window. See gtk_window_set_title().
831 * Return value: the title of the window, or %NULL if none has
832 * been set explicitely. The returned string is owned by the widget
833 * and must not be modified or freed.
835 G_CONST_RETURN gchar *
836 gtk_window_get_title (GtkWindow *window)
838 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
840 return window->title;
844 * gtk_window_set_wmclass:
845 * @window: a #GtkWindow
846 * @wmclass_name: window name hint
847 * @wmclass_class: window class hint
849 * Don't use this function. It sets the X Window System "class" and
850 * "name" hints for a window. According to the ICCCM, you should
851 * always set these to the same value for all windows in an
852 * application, and GTK+ sets them to that value by default, so calling
853 * this function is sort of pointless. However, you may want to call
854 * gtk_window_set_role() on each window in your application, for the
855 * benefit of the session manager. Setting the role allows the window
856 * manager to restore window positions when loading a saved session.
860 gtk_window_set_wmclass (GtkWindow *window,
861 const gchar *wmclass_name,
862 const gchar *wmclass_class)
864 g_return_if_fail (GTK_IS_WINDOW (window));
866 g_free (window->wmclass_name);
867 window->wmclass_name = g_strdup (wmclass_name);
869 g_free (window->wmclass_class);
870 window->wmclass_class = g_strdup (wmclass_class);
872 if (GTK_WIDGET_REALIZED (window))
873 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
877 * gtk_window_set_role:
878 * @window: a #GtkWindow
879 * @role: unique identifier for the window to be used when restoring a session
881 * This function is only useful on X11, not with other GTK+ targets.
883 * In combination with the window title, the window role allows a
884 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
885 * same" window when an application is restarted. So for example you
886 * might set the "toolbox" role on your app's toolbox window, so that
887 * when the user restarts their session, the window manager can put
888 * the toolbox back in the same place.
890 * If a window already has a unique title, you don't need to set the
891 * role, since the WM can use the title to identify the window when
892 * restoring the session.
896 gtk_window_set_role (GtkWindow *window,
899 g_return_if_fail (GTK_IS_WINDOW (window));
901 if (role == window->wm_role)
904 g_free (window->wm_role);
905 window->wm_role = g_strdup (role);
907 if (GTK_WIDGET_REALIZED (window))
908 g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
912 * gtk_window_get_role:
913 * @window: a #GtkWindow
915 * Returns the role of the window. See gtk_window_set_role() for
916 * further explanation.
918 * Return value: the role of the window if set, or %NULL. The
919 * returned is owned by the widget and must not be modified
922 G_CONST_RETURN gchar *
923 gtk_window_get_role (GtkWindow *window)
925 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
927 return window->wm_role;
931 * gtk_window_set_focus:
932 * @window: a #GtkWindow
933 * @focus: widget to be the new focus widget, or %NULL to unset
934 * any focus widget for the toplevel window.
936 * If @focus is not the current focus widget, and is focusable, sets
937 * it as the focus widget for the window. If @focus is %NULL, unsets
938 * the focus widget for this window. To set the focus to a particular
939 * widget in the toplevel, it is usually more convenient to use
940 * gtk_widget_grab_focus() instead of this function.
943 gtk_window_set_focus (GtkWindow *window,
946 g_return_if_fail (GTK_IS_WINDOW (window));
949 g_return_if_fail (GTK_IS_WIDGET (focus));
950 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
954 gtk_widget_grab_focus (focus);
956 _gtk_window_internal_set_focus (window, NULL);
960 _gtk_window_internal_set_focus (GtkWindow *window,
963 g_return_if_fail (GTK_IS_WINDOW (window));
965 if ((window->focus_widget != focus) ||
966 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
967 gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
971 * gtk_window_set_default:
972 * @window: a #GtkWindow
973 * @default_widget: widget to be the default, or %NULL to unset the
974 * default widget for the toplevel.
976 * The default widget is the widget that's activated when the user
977 * presses Enter in a dialog (for example). This function sets or
978 * unsets the default widget for a #GtkWindow about. When setting
979 * (rather than unsetting) the default widget it's generally easier to
980 * call gtk_widget_grab_focus() on the widget. Before making a widget
981 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
982 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
985 gtk_window_set_default (GtkWindow *window,
986 GtkWidget *default_widget)
988 g_return_if_fail (GTK_IS_WINDOW (window));
991 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
993 if (window->default_widget != default_widget)
995 GtkWidget *old_default_widget = NULL;
998 g_object_ref (default_widget);
1000 if (window->default_widget)
1002 old_default_widget = window->default_widget;
1004 if (window->focus_widget != window->default_widget ||
1005 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1006 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1007 gtk_widget_queue_draw (window->default_widget);
1010 window->default_widget = default_widget;
1012 if (window->default_widget)
1014 if (window->focus_widget == NULL ||
1015 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1016 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1017 gtk_widget_queue_draw (window->default_widget);
1020 if (old_default_widget)
1021 g_object_notify (G_OBJECT (old_default_widget), "has_default");
1025 g_object_notify (G_OBJECT (default_widget), "has_default");
1026 g_object_unref (default_widget);
1032 gtk_window_set_policy (GtkWindow *window,
1033 gboolean allow_shrink,
1034 gboolean allow_grow,
1035 gboolean auto_shrink)
1037 g_return_if_fail (GTK_IS_WINDOW (window));
1039 window->allow_shrink = (allow_shrink != FALSE);
1040 window->allow_grow = (allow_grow != FALSE);
1042 g_object_freeze_notify (G_OBJECT (window));
1043 g_object_notify (G_OBJECT (window), "allow_shrink");
1044 g_object_notify (G_OBJECT (window), "allow_grow");
1045 g_object_notify (G_OBJECT (window), "resizable");
1046 g_object_thaw_notify (G_OBJECT (window));
1048 gtk_widget_queue_resize (GTK_WIDGET (window));
1052 handle_keys_changed (gpointer data)
1056 GDK_THREADS_ENTER ();
1057 window = GTK_WINDOW (data);
1059 if (window->keys_changed_handler)
1061 gtk_idle_remove (window->keys_changed_handler);
1062 window->keys_changed_handler = 0;
1065 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1066 GDK_THREADS_LEAVE ();
1072 gtk_window_notify_keys_changed (GtkWindow *window)
1074 if (!window->keys_changed_handler)
1075 window->keys_changed_handler = gtk_idle_add (handle_keys_changed, window);
1079 * gtk_window_add_accel_group:
1080 * @window: window to attach accelerator group to
1081 * @accel_group: a #GtkAccelGroup
1083 * Associate @accel_group with @window, such that calling
1084 * gtk_accel_groups_activate() on @window will activate accelerators
1088 gtk_window_add_accel_group (GtkWindow *window,
1089 GtkAccelGroup *accel_group)
1091 g_return_if_fail (GTK_IS_WINDOW (window));
1092 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1094 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1095 g_signal_connect_object (accel_group, "accel_changed",
1096 G_CALLBACK (gtk_window_notify_keys_changed),
1097 window, G_CONNECT_SWAPPED);
1101 * gtk_window_remove_accel_group:
1102 * @window: a #GtkWindow
1103 * @accel_group: a #GtkAccelGroup
1105 * Reverses the effects of gtk_window_add_accel_group().
1108 gtk_window_remove_accel_group (GtkWindow *window,
1109 GtkAccelGroup *accel_group)
1111 g_return_if_fail (GTK_IS_WINDOW (window));
1112 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1114 g_signal_handlers_disconnect_by_func (accel_group,
1115 G_CALLBACK (gtk_window_notify_keys_changed),
1117 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1121 gtk_window_add_mnemonic (GtkWindow *window,
1125 GtkWindowMnemonic key;
1126 GtkWindowMnemonic *mnemonic;
1128 g_return_if_fail (GTK_IS_WINDOW (window));
1129 g_return_if_fail (GTK_IS_WIDGET (target));
1131 key.window = window;
1132 key.keyval = keyval;
1133 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1137 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1138 mnemonic->targets = g_slist_prepend (mnemonic->targets, target);
1142 mnemonic = g_new (GtkWindowMnemonic, 1);
1144 mnemonic->targets = g_slist_prepend (NULL, target);
1145 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1147 gtk_window_notify_keys_changed (window);
1151 gtk_window_remove_mnemonic (GtkWindow *window,
1155 GtkWindowMnemonic key;
1156 GtkWindowMnemonic *mnemonic;
1158 g_return_if_fail (GTK_IS_WINDOW (window));
1159 g_return_if_fail (GTK_IS_WIDGET (target));
1161 key.window = window;
1162 key.keyval = keyval;
1163 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1165 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1167 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1168 if (mnemonic->targets == NULL)
1170 g_hash_table_remove (mnemonic_hash_table, mnemonic);
1173 gtk_window_notify_keys_changed (window);
1177 gtk_window_mnemonic_activate (GtkWindow *window,
1179 GdkModifierType modifier)
1181 GtkWindowMnemonic key;
1182 GtkWindowMnemonic *mnemonic;
1184 GtkWidget *widget, *chosen_widget;
1185 gboolean overloaded;
1187 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1189 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1192 key.window = window;
1193 key.keyval = keyval;
1194 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1200 chosen_widget = NULL;
1201 list = mnemonic->targets;
1204 widget = GTK_WIDGET (list->data);
1206 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1207 GTK_WIDGET_MAPPED (widget))
1215 chosen_widget = widget;
1217 list = g_slist_next (list);
1222 /* For round robin we put the activated entry on
1223 * the end of the list after activation
1225 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1226 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1228 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1234 * gtk_window_set_mnemonic_modifier:
1235 * @window: a #GtkWindow
1236 * @modifier: the modifier mask used to activate
1237 * mnemonics on this window.
1239 * Sets the mnemonic modifier for this window.
1242 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1243 GdkModifierType modifier)
1245 g_return_if_fail (GTK_IS_WINDOW (window));
1246 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1248 window->mnemonic_modifier = modifier;
1249 gtk_window_notify_keys_changed (window);
1253 * gtk_window_get_mnemonic_modifier:
1254 * @window: a #GtkWindow
1256 * Returns the mnemonic modifier for this window. See
1257 * gtk_window_set_mnemonic_modifier().
1259 * Return value: the modifier mask used to activate
1260 * mnemonics on this window.
1263 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1265 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1267 return window->mnemonic_modifier;
1271 * gtk_window_set_position:
1272 * @window: a #GtkWindow.
1273 * @position: a position constraint.
1275 * Sets a position constraint for this window. If the old or new
1276 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1277 * the window to be repositioned to satisfy the new constraint.
1280 gtk_window_set_position (GtkWindow *window,
1281 GtkWindowPosition position)
1283 g_return_if_fail (GTK_IS_WINDOW (window));
1285 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1286 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1288 GtkWindowGeometryInfo *info;
1290 info = gtk_window_get_geometry_info (window, TRUE);
1292 /* this flag causes us to re-request the CENTER_ALWAYS
1293 * constraint in gtk_window_move_resize(), see
1294 * comment in that function.
1296 info->position_constraints_changed = TRUE;
1298 gtk_widget_queue_resize (GTK_WIDGET (window));
1301 window->position = position;
1303 g_object_notify (G_OBJECT (window), "window_position");
1307 gtk_window_activate_focus (GtkWindow *window)
1309 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1311 if (window->focus_widget)
1313 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1314 gtk_widget_activate (window->focus_widget);
1322 * gtk_window_get_focus:
1323 * @window: a #GtkWindow
1325 * Retrieves the current focused widget within the window.
1326 * Note that this is the widget that would have the focus
1327 * if the toplevel window focused; if the toplevel window
1328 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1329 * not be %TRUE for the widget.
1331 * Return value: the currently focused widget.
1334 gtk_window_get_focus (GtkWindow *window)
1336 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1338 return window->focus_widget;
1342 gtk_window_activate_default (GtkWindow *window)
1344 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1346 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1347 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1349 gtk_widget_activate (window->default_widget);
1352 else if (window->focus_widget)
1354 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1355 gtk_widget_activate (window->focus_widget);
1363 * gtk_window_set_modal:
1364 * @window: a #GtkWindow
1365 * @modal: whether the window is modal
1367 * Sets a window modal or non-modal. Modal windows prevent interaction
1368 * with other windows in the same application. To keep modal dialogs
1369 * on top of main application windows, use
1370 * gtk_window_set_transient_for() to make the dialog transient for the
1371 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1372 * will then disallow lowering the dialog below the parent.
1377 gtk_window_set_modal (GtkWindow *window,
1380 g_return_if_fail (GTK_IS_WINDOW (window));
1382 window->modal = modal != FALSE;
1384 /* adjust desired modality state */
1385 if (GTK_WIDGET_VISIBLE (window) && window->modal)
1386 gtk_grab_add (GTK_WIDGET (window));
1388 gtk_grab_remove (GTK_WIDGET (window));
1390 g_object_notify (G_OBJECT (window), "modal");
1394 * gtk_window_get_modal:
1395 * @window: a #GtkWindow
1397 * Returns whether the window is modal. See gtk_window_set_modal().
1399 * Return value: %TRUE if the window is set to be modal and
1400 * establishes a grab when shown
1403 gtk_window_get_modal (GtkWindow *window)
1405 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1407 return window->modal;
1411 * gtk_window_list_toplevels:
1413 * Returns a list of all existing toplevel windows. The widgets
1414 * in the list are not individually referenced. If you want
1415 * to iterate through the list and perform actions involving
1416 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1417 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1418 * then unref all the widgets afterwards.
1420 * Return value: list of toplevel widgets
1423 gtk_window_list_toplevels (void)
1428 for (slist = toplevel_list; slist; slist = slist->next)
1429 list = g_list_prepend (list, slist->data);
1435 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1437 GList *embedded_windows;
1439 g_return_if_fail (GTK_IS_WINDOW (window));
1441 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1442 if (embedded_windows)
1443 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1444 g_quark_from_static_string ("gtk-embedded"));
1445 embedded_windows = g_list_prepend (embedded_windows,
1446 GUINT_TO_POINTER (xid));
1448 gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
1451 (GtkDestroyNotify) g_list_free : NULL);
1455 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1457 GList *embedded_windows;
1460 g_return_if_fail (GTK_IS_WINDOW (window));
1462 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1463 if (embedded_windows)
1464 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1465 g_quark_from_static_string ("gtk-embedded"));
1467 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1470 embedded_windows = g_list_remove_link (embedded_windows, node);
1471 g_list_free_1 (node);
1474 gtk_object_set_data_full (GTK_OBJECT (window),
1475 "gtk-embedded", embedded_windows,
1477 (GtkDestroyNotify) g_list_free : NULL);
1481 _gtk_window_reposition (GtkWindow *window,
1485 g_return_if_fail (GTK_IS_WINDOW (window));
1487 gtk_window_move (window, x, y);
1491 gtk_window_dispose (GObject *object)
1493 GtkWindow *window = GTK_WINDOW (object);
1495 gtk_window_set_focus (window, NULL);
1496 gtk_window_set_default (window, NULL);
1498 G_OBJECT_CLASS (parent_class)->dispose (object);
1502 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1504 gtk_widget_destroy (GTK_WIDGET (child));
1508 connect_parent_destroyed (GtkWindow *window)
1510 if (window->transient_parent)
1512 gtk_signal_connect (GTK_OBJECT (window->transient_parent),
1514 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1520 disconnect_parent_destroyed (GtkWindow *window)
1522 if (window->transient_parent)
1524 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1525 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1531 gtk_window_transient_parent_realized (GtkWidget *parent,
1534 if (GTK_WIDGET_REALIZED (window))
1535 gdk_window_set_transient_for (window->window, parent->window);
1539 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1542 if (GTK_WIDGET_REALIZED (window))
1543 gdk_property_delete (window->window,
1544 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1548 gtk_window_unset_transient_for (GtkWindow *window)
1550 if (window->transient_parent)
1552 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1553 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1555 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1556 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1558 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1559 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1560 &window->transient_parent);
1562 if (window->destroy_with_parent)
1563 disconnect_parent_destroyed (window);
1565 window->transient_parent = NULL;
1570 * gtk_window_set_transient_for:
1571 * @window: a #GtkWindow
1572 * @parent: parent window
1574 * Dialog windows should be set transient for the main application
1575 * window they were spawned from. This allows <link
1576 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1577 * dialog on top of the main window, or center the dialog over the
1578 * main window. gtk_dialog_new_with_buttons() and other convenience
1579 * functions in GTK+ will sometimes call
1580 * gtk_window_set_transient_for() on your behalf.
1582 * On Windows, this function will and put the child window
1583 * on top of the parent, much as the window manager would have
1588 gtk_window_set_transient_for (GtkWindow *window,
1591 g_return_if_fail (GTK_IS_WINDOW (window));
1592 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1593 g_return_if_fail (window != parent);
1596 if (window->transient_parent)
1598 if (GTK_WIDGET_REALIZED (window) &&
1599 GTK_WIDGET_REALIZED (window->transient_parent) &&
1600 (!parent || !GTK_WIDGET_REALIZED (parent)))
1601 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1602 GTK_WIDGET (window));
1604 gtk_window_unset_transient_for (window);
1607 window->transient_parent = parent;
1611 gtk_signal_connect (GTK_OBJECT (parent), "destroy",
1612 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1613 &window->transient_parent);
1614 gtk_signal_connect (GTK_OBJECT (parent), "realize",
1615 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1617 gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
1618 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1621 if (window->destroy_with_parent)
1622 connect_parent_destroyed (window);
1624 if (GTK_WIDGET_REALIZED (window) &&
1625 GTK_WIDGET_REALIZED (parent))
1626 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1627 GTK_WIDGET (window));
1632 * gtk_window_get_transient_for:
1633 * @window: a #GtkWindow
1635 * Fetches the transient parent for this window. See
1636 * gtk_window_set_transient_for().
1638 * Return value: the transient parent for this window, or %NULL
1639 * if no transient parent has been set.
1642 gtk_window_get_transient_for (GtkWindow *window)
1644 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1646 return window->transient_parent;
1650 * gtk_window_set_type_hint:
1651 * @window: a #GtkWindow
1652 * @hint: the window type
1654 * By setting the type hint for the window, you allow the window
1655 * manager to decorate and handle the window in a way which is
1656 * suitable to the function of the window in your application.
1658 * This function should be called before the window becomes visible.
1660 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1661 * will sometimes call gtk_window_set_type_hint() on your behalf.
1665 gtk_window_set_type_hint (GtkWindow *window,
1666 GdkWindowTypeHint hint)
1668 g_return_if_fail (GTK_IS_WINDOW (window));
1669 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1670 window->type_hint = hint;
1674 * gtk_window_get_type_hint:
1675 * @window: a #GtkWindow
1677 * Gets the type hint for this window. See gtk_window_set_type_hint().
1679 * Return value: the type hint for @window.
1682 gtk_window_get_type_hint (GtkWindow *window)
1684 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1686 return window->type_hint;
1690 * gtk_window_set_destroy_with_parent:
1691 * @window: a #GtkWindow
1692 * @setting: whether to destroy @window with its transient parent
1694 * If @setting is %TRUE, then destroying the transient parent of @window
1695 * will also destroy @window itself. This is useful for dialogs that
1696 * shouldn't persist beyond the lifetime of the main window they're
1697 * associated with, for example.
1700 gtk_window_set_destroy_with_parent (GtkWindow *window,
1703 g_return_if_fail (GTK_IS_WINDOW (window));
1705 if (window->destroy_with_parent == (setting != FALSE))
1708 if (window->destroy_with_parent)
1710 disconnect_parent_destroyed (window);
1714 connect_parent_destroyed (window);
1717 window->destroy_with_parent = setting;
1719 g_object_notify (G_OBJECT (window), "destroy_with_parent");
1723 * gtk_window_get_destroy_with_parent:
1724 * @window: a #GtkWindow
1726 * Returns whether the window will be destroyed with its transient parent. See
1727 * gtk_window_set_destroy_with_parent ().
1729 * Return value: %TRUE if the window will be destroyed with its transient parent.
1732 gtk_window_get_destroy_with_parent (GtkWindow *window)
1734 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1736 return window->destroy_with_parent;
1739 static GtkWindowGeometryInfo*
1740 gtk_window_get_geometry_info (GtkWindow *window,
1743 GtkWindowGeometryInfo *info;
1745 info = window->geometry_info;
1746 if (!info && create)
1748 info = g_new0 (GtkWindowGeometryInfo, 1);
1750 info->default_width = -1;
1751 info->default_height = -1;
1752 info->resize_width = -1;
1753 info->resize_height = -1;
1754 info->initial_x = 0;
1755 info->initial_y = 0;
1756 info->initial_pos_set = FALSE;
1757 info->position_constraints_changed = FALSE;
1758 info->last.configure_request.x = 0;
1759 info->last.configure_request.y = 0;
1760 info->last.configure_request.width = -1;
1761 info->last.configure_request.height = -1;
1762 info->widget = NULL;
1764 window->geometry_info = info;
1771 * gtk_window_set_geometry_hints:
1772 * @window: a #GtkWindow
1773 * @geometry_widget: widget the geometry hints will be applied to
1774 * @geometry: struct containing geometry information
1775 * @geom_mask: mask indicating which struct fields should be paid attention to
1777 * This function sets up hints about how a window can be resized by
1778 * the user. You can set a minimum and maximum size; allowed resize
1779 * increments (e.g. for xterm, you can only resize by the size of a
1780 * character); aspect ratios; and more. See the #GdkGeometry struct.
1784 gtk_window_set_geometry_hints (GtkWindow *window,
1785 GtkWidget *geometry_widget,
1786 GdkGeometry *geometry,
1787 GdkWindowHints geom_mask)
1789 GtkWindowGeometryInfo *info;
1791 g_return_if_fail (GTK_IS_WINDOW (window));
1792 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
1794 info = gtk_window_get_geometry_info (window, TRUE);
1797 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1798 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1801 info->widget = geometry_widget;
1803 gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
1804 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1808 info->geometry = *geometry;
1810 /* We store gravity in window->gravity not in the hints. */
1811 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
1813 if (geom_mask & GDK_HINT_WIN_GRAVITY)
1815 gtk_window_set_gravity (window, geometry->win_gravity);
1818 gtk_widget_queue_resize (GTK_WIDGET (window));
1822 * gtk_window_set_decorated:
1823 * @window: a #GtkWindow
1824 * @setting: %TRUE to decorate the window
1826 * By default, windows are decorated with a title bar, resize
1827 * controls, etc. Some <link linkend="gtk-X11-arch">window
1828 * managers</link> allow GTK+ to disable these decorations, creating a
1829 * borderless window. If you set the decorated property to %FALSE
1830 * using this function, GTK+ will do its best to convince the window
1831 * manager not to decorate the window.
1833 * On Windows, this function always works, since there's no window manager
1838 gtk_window_set_decorated (GtkWindow *window,
1841 g_return_if_fail (GTK_IS_WINDOW (window));
1843 setting = setting != FALSE;
1845 if (setting == window->decorated)
1848 window->decorated = setting;
1850 if (GTK_WIDGET (window)->window)
1852 if (window->decorated)
1853 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1856 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1862 * gtk_window_get_decorated:
1863 * @window: a #GtkWindow
1865 * Returns whether the window has been set to have decorations
1866 * such as a title bar via gtk_window_set_decorated().
1868 * Return value: %TRUE if the window has been set to have decorations
1871 gtk_window_get_decorated (GtkWindow *window)
1873 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
1875 return window->decorated;
1878 static GtkWindowIconInfo*
1879 get_icon_info (GtkWindow *window)
1881 return g_object_get_data (G_OBJECT (window),
1882 "gtk-window-icon-info");
1885 static GtkWindowIconInfo*
1886 ensure_icon_info (GtkWindow *window)
1888 GtkWindowIconInfo *info;
1890 info = get_icon_info (window);
1894 info = g_new0 (GtkWindowIconInfo, 1);
1895 g_object_set_data_full (G_OBJECT (window),
1896 "gtk-window-icon-info",
1905 get_pixmap_and_mask (GtkWindowIconInfo *parent_info,
1906 gboolean is_default_list,
1908 GdkPixmap **pmap_return,
1909 GdkBitmap **mask_return)
1911 GdkPixbuf *best_icon;
1915 *pmap_return = NULL;
1916 *mask_return = NULL;
1918 if (is_default_list &&
1919 default_icon_pixmap != NULL)
1921 /* Use shared icon pixmap (eventually will be stored on the
1924 if (default_icon_pixmap)
1925 g_object_ref (G_OBJECT (default_icon_pixmap));
1926 if (default_icon_mask)
1927 g_object_ref (G_OBJECT (default_icon_mask));
1929 *pmap_return = default_icon_pixmap;
1930 *mask_return = default_icon_mask;
1932 else if (parent_info && parent_info->icon_pixmap)
1934 if (parent_info->icon_pixmap)
1935 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1936 if (parent_info->icon_mask)
1937 g_object_ref (G_OBJECT (parent_info->icon_mask));
1939 *pmap_return = parent_info->icon_pixmap;
1940 *mask_return = parent_info->icon_mask;
1944 #define IDEAL_SIZE 48
1946 best_size = G_MAXINT;
1948 tmp_list = icon_list;
1949 while (tmp_list != NULL)
1951 GdkPixbuf *pixbuf = tmp_list->data;
1954 /* average width and height - if someone passes in a rectangular
1955 * icon they deserve what they get.
1957 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
1960 if (best_icon == NULL)
1967 /* icon is better if it's 32 pixels or larger, and closer to
1968 * the ideal size than the current best.
1971 (ABS (best_size - IDEAL_SIZE) <
1972 ABS (this - IDEAL_SIZE)))
1979 tmp_list = tmp_list->next;
1983 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
1984 gdk_colormap_get_system (),
1989 /* Save pmap/mask for others to use if appropriate */
1992 parent_info->icon_pixmap = *pmap_return;
1993 parent_info->icon_mask = *mask_return;
1995 if (parent_info->icon_pixmap)
1996 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1997 if (parent_info->icon_mask)
1998 g_object_ref (G_OBJECT (parent_info->icon_mask));
2000 else if (is_default_list)
2002 default_icon_pixmap = *pmap_return;
2003 default_icon_mask = *mask_return;
2005 if (default_icon_pixmap)
2006 g_object_add_weak_pointer (G_OBJECT (default_icon_pixmap),
2007 (gpointer*)&default_icon_pixmap);
2008 if (default_icon_mask)
2009 g_object_add_weak_pointer (G_OBJECT (default_icon_mask),
2010 (gpointer*)&default_icon_mask);
2016 gtk_window_realize_icon (GtkWindow *window)
2019 GtkWindowIconInfo *info;
2022 widget = GTK_WIDGET (window);
2024 g_return_if_fail (widget->window != NULL);
2026 /* no point setting an icon on override-redirect */
2027 if (window->type == GTK_WINDOW_POPUP)
2032 info = ensure_icon_info (window);
2037 g_return_if_fail (info->icon_pixmap == NULL);
2038 g_return_if_fail (info->icon_mask == NULL);
2040 info->using_default_icon = FALSE;
2041 info->using_parent_icon = FALSE;
2043 icon_list = info->icon_list;
2045 /* Inherit from transient parent */
2046 if (icon_list == NULL && window->transient_parent)
2048 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2050 info->using_parent_icon = TRUE;
2053 /* Inherit from default */
2054 if (icon_list == NULL)
2056 icon_list = default_icon_list;
2058 info->using_default_icon = TRUE;
2061 gdk_window_set_icon_list (widget->window, icon_list);
2063 get_pixmap_and_mask (info->using_parent_icon ?
2064 ensure_icon_info (window->transient_parent) : NULL,
2065 info->using_default_icon,
2070 /* This is a slight ICCCM violation since it's a color pixmap not
2071 * a bitmap, but everyone does it.
2073 gdk_window_set_icon (widget->window,
2078 info->realized = TRUE;
2082 gtk_window_unrealize_icon (GtkWindow *window)
2084 GtkWindowIconInfo *info;
2087 widget = GTK_WIDGET (window);
2089 info = get_icon_info (window);
2094 if (info->icon_pixmap)
2095 g_object_unref (G_OBJECT (info->icon_pixmap));
2097 if (info->icon_mask)
2098 g_object_unref (G_OBJECT (info->icon_mask));
2100 info->icon_pixmap = NULL;
2101 info->icon_mask = NULL;
2103 /* We don't clear the properties on the window, just figure the
2104 * window is going away.
2107 info->realized = FALSE;
2111 * gtk_window_set_icon_list:
2112 * @window: a #GtkWindow
2113 * @list: list of #GdkPixbuf
2115 * Sets up the icon representing a #GtkWindow. The icon is used when
2116 * the window is minimized (also known as iconified). Some window
2117 * managers or desktop environments may also place it in the window
2118 * frame, or display it in other contexts.
2120 * gtk_window_set_icon_list() allows you to pass in the same icon in
2121 * several hand-drawn sizes. The list should contain the natural sizes
2122 * your icon is available in; that is, don't scale the image before
2123 * passing it to GTK+. Scaling is postponed until the last minute,
2124 * when the desired final size is known, to allow best quality.
2126 * By passing several sizes, you may improve the final image quality
2127 * of the icon, by reducing or eliminating automatic image scaling.
2129 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2130 * larger images (64x64, 128x128) if you have them.
2132 * See also gtk_window_set_default_icon_list() to set the icon
2133 * for all windows in your application in one go.
2135 * Note that transient windows (those who have been set transient for another
2136 * window using gtk_window_set_transient_for()) will inherit their
2137 * icon from their transient parent. So there's no need to explicitly
2138 * set the icon on transient windows.
2141 gtk_window_set_icon_list (GtkWindow *window,
2144 GtkWindowIconInfo *info;
2146 g_return_if_fail (GTK_IS_WINDOW (window));
2148 info = ensure_icon_info (window);
2150 if (info->icon_list == list) /* check for NULL mostly */
2153 g_list_foreach (info->icon_list,
2154 (GFunc) g_object_unref, NULL);
2156 g_list_free (info->icon_list);
2158 info->icon_list = g_list_copy (list);
2159 g_list_foreach (info->icon_list,
2160 (GFunc) g_object_ref, NULL);
2162 g_object_notify (G_OBJECT (window), "icon");
2164 gtk_window_unrealize_icon (window);
2166 if (GTK_WIDGET_REALIZED (window))
2167 gtk_window_realize_icon (window);
2169 /* We could try to update our transient children, but I don't think
2170 * it's really worth it. If we did it, the best way would probably
2171 * be to have children connect to notify::icon_list
2176 * gtk_window_get_icon_list:
2177 * @window: a #GtkWindow
2179 * Retrieves the list of icons set by gtk_window_set_icon_list().
2180 * The list is copied, but the reference count on each
2181 * member won't be incremented.
2183 * Return value: copy of window's icon list
2186 gtk_window_get_icon_list (GtkWindow *window)
2188 GtkWindowIconInfo *info;
2190 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2192 info = get_icon_info (window);
2195 return g_list_copy (info->icon_list);
2201 * gtk_window_set_icon:
2202 * @window: a #GtkWindow
2203 * @icon: icon image, or %NULL
2205 * Sets up the icon representing a #GtkWindow. This icon is used when
2206 * the window is minimized (also known as iconified). Some window
2207 * managers or desktop environments may also place it in the window
2208 * frame, or display it in other contexts.
2210 * The icon should be provided in whatever size it was naturally
2211 * drawn; that is, don't scale the image before passing it to
2212 * GTK+. Scaling is postponed until the last minute, when the desired
2213 * final size is known, to allow best quality.
2215 * If you have your icon hand-drawn in multiple sizes, use
2216 * gtk_window_set_icon_list(). Then the best size will be used.
2218 * This function is equivalent to calling gtk_window_set_icon_list()
2219 * with a 1-element list.
2221 * See also gtk_window_set_default_icon_list() to set the icon
2222 * for all windows in your application in one go.
2225 gtk_window_set_icon (GtkWindow *window,
2230 g_return_if_fail (GTK_IS_WINDOW (window));
2231 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2234 list = g_list_append (list, icon);
2235 gtk_window_set_icon_list (window, list);
2240 * gtk_window_get_icon:
2241 * @window: a #GtkWindow
2243 * Gets the value set by gtk_window_set_icon() (or if you've
2244 * called gtk_window_set_icon_list(), gets the first icon in
2247 * Return value: icon for window
2250 gtk_window_get_icon (GtkWindow *window)
2252 GtkWindowIconInfo *info;
2254 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2256 info = get_icon_info (window);
2257 if (info && info->icon_list)
2258 return GDK_PIXBUF (info->icon_list->data);
2264 * gtk_window_set_default_icon_list:
2265 * @list: a list of #GdkPixbuf
2267 * Sets an icon list to be used as fallback for windows that haven't
2268 * had gtk_window_set_icon_list() called on them to set up a
2269 * window-specific icon list. This function allows you to set up the
2270 * icon for all windows in your app at once.
2272 * See gtk_window_set_icon_list() for more details.
2276 gtk_window_set_default_icon_list (GList *list)
2280 if (list == default_icon_list)
2283 if (default_icon_pixmap)
2284 g_object_unref (G_OBJECT (default_icon_pixmap));
2285 if (default_icon_mask)
2286 g_object_unref (G_OBJECT (default_icon_mask));
2288 default_icon_pixmap = NULL;
2289 default_icon_mask = NULL;
2291 g_list_foreach (default_icon_list,
2292 (GFunc) g_object_unref, NULL);
2294 g_list_free (default_icon_list);
2296 default_icon_list = g_list_copy (list);
2297 g_list_foreach (default_icon_list,
2298 (GFunc) g_object_ref, NULL);
2300 /* Update all toplevels */
2301 toplevels = gtk_window_list_toplevels ();
2302 tmp_list = toplevels;
2303 while (tmp_list != NULL)
2305 GtkWindowIconInfo *info;
2306 GtkWindow *w = tmp_list->data;
2308 info = get_icon_info (w);
2309 if (info && info->using_default_icon)
2311 gtk_window_unrealize_icon (w);
2312 if (GTK_WIDGET_REALIZED (w))
2313 gtk_window_realize_icon (w);
2316 tmp_list = tmp_list->next;
2318 g_list_free (toplevels);
2322 * gtk_window_get_default_icon_list:
2324 * Gets the value set by gtk_window_set_default_icon_list().
2325 * The list is a copy and should be freed with g_list_free(),
2326 * but the pixbufs in the list have not had their reference count
2329 * Return value: copy of default icon list
2332 gtk_window_get_default_icon_list (void)
2334 return g_list_copy (default_icon_list);
2338 gtk_window_set_default_size_internal (GtkWindow *window,
2339 gboolean change_width,
2341 gboolean change_height,
2344 GtkWindowGeometryInfo *info;
2346 g_return_if_fail (change_width == FALSE || width >= -1);
2347 g_return_if_fail (change_height == FALSE || height >= -1);
2349 info = gtk_window_get_geometry_info (window, TRUE);
2351 g_object_freeze_notify (G_OBJECT (window));
2361 info->default_width = width;
2363 g_object_notify (G_OBJECT (window), "default_width");
2374 info->default_height = height;
2376 g_object_notify (G_OBJECT (window), "default_height");
2379 g_object_thaw_notify (G_OBJECT (window));
2381 gtk_widget_queue_resize (GTK_WIDGET (window));
2385 * gtk_window_set_default_size:
2386 * @window: a #GtkWindow
2387 * @width: width in pixels, or -1 to unset the default width
2388 * @height: height in pixels, or -1 to unset the default height
2390 * Sets the default size of a window. If the window's "natural" size
2391 * (its size request) is larger than the default, the default will be
2392 * ignored. More generally, if the default size does not obey the
2393 * geometry hints for the window (gtk_window_set_geometry_hints() can
2394 * be used to set these explicitly), the default size will be clamped
2395 * to the nearest permitted size.
2397 * Unlike gtk_widget_set_size_request(), which sets a size request for
2398 * a widget and thus would keep users from shrinking the window, this
2399 * function only sets the initial size, just as if the user had
2400 * resized the window themselves. Users can still shrink the window
2401 * again as they normally would. Setting a default size of -1 means to
2402 * use the "natural" default size (the size request of the window).
2404 * For more control over a window's initial size and how resizing works,
2405 * investigate gtk_window_set_geometry_hints().
2407 * A useful feature: if you set the "geometry widget" via
2408 * gtk_window_set_geometry_hints(), the default size specified by
2409 * gtk_window_set_default_size() will be the default size of that
2410 * widget, not of the entire window.
2412 * For some uses, gtk_window_resize() is a more appropriate function.
2413 * gtk_window_resize() changes the current size of the window, rather
2414 * than the size to be used on initial display. gtk_window_resize() always
2415 * affects the window itself, not the geometry widget.
2417 * The default size of a window only affects the first time a window is
2418 * shown; if a window is hidden and re-shown, it will remember the size
2419 * it had prior to hiding, rather than using the default size.
2421 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2422 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2425 gtk_window_set_default_size (GtkWindow *window,
2429 g_return_if_fail (GTK_IS_WINDOW (window));
2430 g_return_if_fail (width >= -1);
2431 g_return_if_fail (height >= -1);
2433 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height);
2437 * gtk_window_get_default_size:
2438 * @window: a #GtkWindow
2439 * @width: location to store the default width, or %NULL
2440 * @height: location to store the default height, or %NULL
2442 * Gets the default size of the window. A value of -1 for the width or
2443 * height indicates that a default size has not been explicitly set
2444 * for that dimension, so the "natural" size of the window will be
2449 gtk_window_get_default_size (GtkWindow *window,
2453 GtkWindowGeometryInfo *info;
2455 g_return_if_fail (GTK_IS_WINDOW (window));
2457 info = gtk_window_get_geometry_info (window, FALSE);
2460 *width = info->default_width;
2463 *height = info->default_height;
2467 * gtk_window_resize:
2468 * @window: a #GtkWindow
2469 * @width: width to resize the window to
2470 * @height: height to resize the window to
2472 * Resizes the window as if the user had done so, obeying geometry
2473 * constraints. The default geometry constraint is that windows may
2474 * not be smaller than their size request; to override this
2475 * constraint, call gtk_widget_set_size_request() to set the window's
2476 * request to a smaller value.
2478 * If gtk_window_resize() is called before showing a window for the
2479 * first time, it overrides any default size set with
2480 * gtk_window_set_default_size().
2482 * Windows may not be resized smaller than 1 by 1 pixels.
2486 gtk_window_resize (GtkWindow *window,
2490 GtkWindowGeometryInfo *info;
2492 g_return_if_fail (GTK_IS_WINDOW (window));
2493 g_return_if_fail (width > 0);
2494 g_return_if_fail (height > 0);
2496 info = gtk_window_get_geometry_info (window, TRUE);
2498 info->resize_width = width;
2499 info->resize_height = height;
2501 gtk_widget_queue_resize (GTK_WIDGET (window));
2505 * gtk_window_get_size:
2506 * @window: a #GtkWindow
2507 * @width: return location for width, or %NULL
2508 * @height: return location for height, or %NULL
2510 * Obtains the current size of @window. If @window is not onscreen,
2511 * it returns the size GTK+ will suggest to the <link
2512 * linkend="gtk-X11-arch">window manager</link> for the initial window
2513 * size (but this is not reliably the same as the size the window
2514 * manager will actually select). The size obtained by
2515 * gtk_window_get_size() is the last size received in a
2516 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2517 * rather than querying the X server for the size. As a result, if you
2518 * call gtk_window_resize() then immediately call
2519 * gtk_window_get_size(), the size won't have taken effect yet. After
2520 * the window manager processes the resize request, GTK+ receives
2521 * notification that the size has changed via a configure event, and
2522 * the size of the window gets updated.
2524 * Note 1: Nearly any use of this function creates a race condition,
2525 * because the size of the window may change between the time that you
2526 * get the size and the time that you perform some action assuming
2527 * that size is the current size. To avoid race conditions, connect to
2528 * "configure_event" on the window and adjust your size-dependent
2529 * state to match the size delivered in the #GdkEventConfigure.
2531 * Note 2: The returned size does <emphasis>not</emphasis> include the
2532 * size of the window manager decorations (aka the window frame or
2533 * border). Those are not drawn by GTK+ and GTK+ has no reliable
2534 * method of determining their size.
2536 * Note 3: If you are getting a window size in order to position
2537 * the window onscreen, there may be a better way. The preferred
2538 * way is to simply set the window's semantic type with
2539 * gtk_window_set_type_hint(), which allows the window manager to
2540 * e.g. center dialogs. Also, if you set the transient parent of
2541 * dialogs with gtk_window_set_transient_for() window managers
2542 * will often center the dialog over its parent window. It's
2543 * much preferred to let the window manager handle these
2544 * things rather than doing it yourself, because all apps will
2545 * behave consistently and according to user prefs if the window
2546 * manager handles it. Also, the window manager can take the size
2547 * of the window decorations/border into account, while your
2548 * application cannot.
2550 * In any case, if you insist on application-specified window
2551 * positioning, there's <emphasis>still</emphasis> a better way than
2552 * doing it yourself - gtk_window_set_position() will frequently
2553 * handle the details for you.
2557 gtk_window_get_size (GtkWindow *window,
2564 g_return_if_fail (GTK_IS_WINDOW (window));
2566 widget = GTK_WIDGET (window);
2568 if (width == NULL && height == NULL)
2571 if (GTK_WIDGET_MAPPED (window))
2573 gdk_drawable_get_size (GTK_WIDGET (window)->window,
2578 GdkRectangle configure_request;
2580 gtk_window_compute_configure_request (window,
2584 w = configure_request.width;
2585 h = configure_request.height;
2596 * @window: a #GtkWindow
2597 * @x: X coordinate to move window to
2598 * @y: Y coordinate to move window to
2600 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
2601 * @window to the given position. Window managers are free to ignore
2602 * this; most window managers ignore requests for initial window
2603 * positions (instead using a user-defined placement algorithm) and
2604 * honor requests after the window has already been shown.
2606 * Note: the position is the position of the gravity-determined
2607 * reference point for the window. The gravity determines two things:
2608 * first, the location of the reference point in root window
2609 * coordinates; and second, which point on the window is positioned at
2610 * the reference point.
2612 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
2613 * point is simply the @x, @y supplied to gtk_window_move(). The
2614 * top-left corner of the window decorations (aka window frame or
2615 * border) will be placed at @x, @y. Therefore, to position a window
2616 * at the top left of the screen, you want to use the default gravity
2617 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
2619 * To position a window at the bottom right corner of the screen, you
2620 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
2621 * point is at @x + the window width and @y + the window height, and
2622 * the bottom-right corner of the window border will be placed at that
2623 * reference point. So, to place a window in the bottom right corner
2624 * you would first set gravity to south east, then write:
2625 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
2626 * gdk_screen_height () - window_height)</literal>.
2628 * The extended window manager hints specification at <ulink
2629 * url="http://www.freedesktop.org/standards/wm-spec.html"
2630 * >http://www.freedesktop.org/standards/wm-spec.html</ulink> has a
2631 * nice table of gravities in the "implementation notes" section.
2633 * The gtk_window_get_position() documentation may also be relevant.
2637 gtk_window_move (GtkWindow *window,
2641 GtkWindowGeometryInfo *info;
2644 g_return_if_fail (GTK_IS_WINDOW (window));
2646 widget = GTK_WIDGET (window);
2648 info = gtk_window_get_geometry_info (window, TRUE);
2650 if (GTK_WIDGET_MAPPED (window))
2652 /* we have now sent a request with this position
2653 * with currently-active constraints, so toggle flag.
2655 info->position_constraints_changed = FALSE;
2657 /* we only constrain if mapped - if not mapped,
2658 * then gtk_window_compute_configure_request()
2659 * will apply the constraints later, and we
2660 * don't want to lose information about
2661 * what position the user set before then.
2662 * i.e. if you do a move() then turn off POS_CENTER
2663 * then show the window, your move() will work.
2665 gtk_window_constrain_position (window,
2666 widget->allocation.width,
2667 widget->allocation.height,
2670 /* Note that this request doesn't go through our standard request
2671 * framework, e.g. doesn't increment configure_request_count,
2672 * doesn't set info->last, etc.; that's because
2673 * we don't save the info needed to arrive at this same request
2676 * To gtk_window_move_resize(), this will end up looking exactly
2677 * the same as the position being changed by the window
2681 /* FIXME are we handling gravity properly for framed windows? */
2683 gdk_window_move (window->frame,
2684 x - window->frame_left,
2685 y - window->frame_top);
2687 gdk_window_move (GTK_WIDGET (window)->window,
2692 /* Save this position to apply on mapping */
2693 info->initial_x = x;
2694 info->initial_y = y;
2695 info->initial_pos_set = TRUE;
2700 * gtk_window_get_position:
2701 * @window: a #GtkWindow
2702 * @root_x: return location for X coordinate of gravity-determined reference p\oint
2703 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
2705 * This function returns the position you need to pass to
2706 * gtk_window_move() to keep @window in its current position. This
2707 * means that the meaning of the returned value varies with window
2708 * gravity. See gtk_window_move() for more details.
2710 * If you haven't changed the window gravity, its gravity will be
2711 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
2712 * gets the position of the top-left corner of the window manager
2713 * frame for the window. gtk_window_move() sets the position of this
2714 * same top-left corner.
2716 * gtk_window_get_position() is not 100% reliable because the X Window System
2717 * does not specify a way to obtain the geometry of the
2718 * decorations placed on a window by the window manager.
2719 * Thus GTK+ is using a "best guess" that works with most
2722 * Moreover, nearly all window managers are historically broken with
2723 * respect to their handling of window gravity. So moving a window to
2724 * its current position as returned by gtk_window_get_position() tends
2725 * to result in moving the window slightly. Window managers are
2726 * slowly getting better over time.
2728 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
2729 * frame is not relevant, and thus gtk_window_get_position() will
2730 * always produce accurate results. However you can't use static
2731 * gravity to do things like place a window in a corner of the screen,
2732 * because static gravity ignores the window manager decorations.
2734 * If you are saving and restoring your application's window
2735 * positions, you should know that it's impossible for applications to
2736 * do this without getting it somewhat wrong because applications do
2737 * not have sufficient knowledge of window manager state. The Correct
2738 * Mechanism is to support the session management protocol (see the
2739 * "GnomeClient" object in the GNOME libraries for example) and allow
2740 * the window manager to save your window sizes and positions.
2745 gtk_window_get_position (GtkWindow *window,
2751 g_return_if_fail (GTK_IS_WINDOW (window));
2753 widget = GTK_WIDGET (window);
2755 if (window->gravity == GDK_GRAVITY_STATIC)
2757 if (GTK_WIDGET_MAPPED (widget))
2759 /* This does a server round-trip, which is sort of wrong;
2760 * but a server round-trip is inevitable for
2761 * gdk_window_get_frame_extents() in the usual
2762 * NorthWestGravity case below, so not sure what else to
2763 * do. We should likely be consistent about whether we get
2764 * the client-side info or the server-side info.
2766 gdk_window_get_origin (widget->window, root_x, root_y);
2770 GdkRectangle configure_request;
2772 gtk_window_compute_configure_request (window,
2776 *root_x = configure_request.x;
2777 *root_y = configure_request.y;
2782 GdkRectangle frame_extents;
2787 if (GTK_WIDGET_MAPPED (widget))
2790 gdk_window_get_frame_extents (window->frame, &frame_extents);
2792 gdk_window_get_frame_extents (widget->window, &frame_extents);
2793 x = frame_extents.x;
2794 y = frame_extents.y;
2795 gtk_window_get_size (window, &w, &h);
2799 /* We just say the frame has 0 size on all sides.
2800 * Not sure what else to do.
2802 gtk_window_compute_configure_request (window,
2805 x = frame_extents.x;
2806 y = frame_extents.y;
2807 w = frame_extents.width;
2808 h = frame_extents.height;
2811 switch (window->gravity)
2813 case GDK_GRAVITY_NORTH:
2814 case GDK_GRAVITY_CENTER:
2815 case GDK_GRAVITY_SOUTH:
2816 /* Find center of frame. */
2817 x += frame_extents.width / 2;
2818 /* Center client window on that point. */
2822 case GDK_GRAVITY_SOUTH_EAST:
2823 case GDK_GRAVITY_EAST:
2824 case GDK_GRAVITY_NORTH_EAST:
2825 /* Find right edge of frame */
2826 x += frame_extents.width;
2827 /* Align left edge of client at that point. */
2834 switch (window->gravity)
2836 case GDK_GRAVITY_WEST:
2837 case GDK_GRAVITY_CENTER:
2838 case GDK_GRAVITY_EAST:
2839 /* Find center of frame. */
2840 y += frame_extents.height / 2;
2841 /* Center client window there. */
2844 case GDK_GRAVITY_SOUTH_WEST:
2845 case GDK_GRAVITY_SOUTH:
2846 case GDK_GRAVITY_SOUTH_EAST:
2847 /* Find south edge of frame */
2848 y += frame_extents.height;
2849 /* Place bottom edge of client there */
2864 * gtk_window_reshow_with_initial_size:
2865 * @window: a #GtkWindow
2867 * Hides @window, then reshows it, resetting the
2868 * default size and position of the window. Used
2869 * by GUI builders only.
2872 gtk_window_reshow_with_initial_size (GtkWindow *window)
2876 g_return_if_fail (GTK_IS_WINDOW (window));
2878 widget = GTK_WIDGET (window);
2880 gtk_widget_hide (widget);
2881 gtk_widget_unrealize (widget);
2882 gtk_widget_show (widget);
2886 gtk_window_destroy (GtkObject *object)
2888 GtkWindow *window = GTK_WINDOW (object);
2890 if (window->transient_parent)
2891 gtk_window_set_transient_for (window, NULL);
2893 /* frees the icons */
2894 gtk_window_set_icon_list (window, NULL);
2896 if (window->has_user_ref_count)
2898 window->has_user_ref_count = FALSE;
2899 gtk_widget_unref (GTK_WIDGET (window));
2903 gtk_window_group_remove_window (window->group, window);
2905 GTK_OBJECT_CLASS (parent_class)->destroy (object);
2909 gtk_window_mnemonic_hash_remove (gpointer key,
2913 GtkWindowMnemonic *mnemonic = key;
2914 GtkWindow *window = user;
2916 if (mnemonic->window == window)
2918 if (mnemonic->targets)
2920 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
2922 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
2923 name, mnemonic->targets->data);
2926 g_slist_free (mnemonic->targets);
2935 gtk_window_finalize (GObject *object)
2937 GtkWindow *window = GTK_WINDOW (object);
2939 toplevel_list = g_slist_remove (toplevel_list, window);
2941 g_free (window->title);
2942 g_free (window->wmclass_name);
2943 g_free (window->wmclass_class);
2944 g_free (window->wm_role);
2946 g_hash_table_foreach_remove (mnemonic_hash_table,
2947 gtk_window_mnemonic_hash_remove,
2949 if (window->geometry_info)
2951 if (window->geometry_info->widget)
2952 gtk_signal_disconnect_by_func (GTK_OBJECT (window->geometry_info->widget),
2953 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
2954 &window->geometry_info->widget);
2955 g_free (window->geometry_info);
2958 if (window->keys_changed_handler)
2960 gtk_idle_remove (window->keys_changed_handler);
2961 window->keys_changed_handler = 0;
2964 G_OBJECT_CLASS (parent_class)->finalize (object);
2968 gtk_window_show (GtkWidget *widget)
2970 GtkWindow *window = GTK_WINDOW (widget);
2971 GtkContainer *container = GTK_CONTAINER (window);
2972 gboolean need_resize;
2974 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
2976 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
2977 container->need_resize = FALSE;
2981 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
2982 GtkAllocation allocation = { 0, 0 };
2983 GdkRectangle configure_request;
2984 GdkGeometry new_geometry;
2986 gboolean was_realized;
2988 /* We are going to go ahead and perform this configure request
2989 * and then emulate a configure notify by going ahead and
2990 * doing a size allocate. Sort of a synchronous
2991 * mini-copy of gtk_window_move_resize() here.
2993 gtk_window_compute_configure_request (window,
2998 /* We update this because we are going to go ahead
2999 * and gdk_window_resize() below, rather than
3002 info->last.configure_request.width = configure_request.width;
3003 info->last.configure_request.height = configure_request.height;
3005 /* and allocate the window - this is normally done
3006 * in move_resize in response to configure notify
3008 allocation.width = configure_request.width;
3009 allocation.height = configure_request.height;
3010 gtk_widget_size_allocate (widget, &allocation);
3012 /* Then we guarantee we have a realize */
3013 was_realized = FALSE;
3014 if (!GTK_WIDGET_REALIZED (widget))
3016 gtk_widget_realize (widget);
3017 was_realized = TRUE;
3020 /* Must be done after the windows are realized,
3021 * so that the decorations can be read
3023 gtk_decorated_window_calculate_frame_size (window);
3025 /* We only send configure request if we didn't just finish
3026 * creating the window; if we just created the window
3027 * then we created it with widget->allocation anyhow.
3030 gdk_window_resize (widget->window,
3031 configure_request.width,
3032 configure_request.height);
3035 gtk_container_check_resize (container);
3037 gtk_widget_map (widget);
3039 /* Try to make sure that we have some focused widget
3041 if (!window->focus_widget)
3042 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
3045 gtk_grab_add (widget);
3049 gtk_window_hide (GtkWidget *widget)
3051 GtkWindow *window = GTK_WINDOW (widget);
3053 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3054 gtk_widget_unmap (widget);
3057 gtk_grab_remove (widget);
3061 gtk_window_map (GtkWidget *widget)
3063 GtkWindow *window = GTK_WINDOW (widget);
3064 GdkWindow *toplevel;
3066 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3068 if (window->bin.child &&
3069 GTK_WIDGET_VISIBLE (window->bin.child) &&
3070 !GTK_WIDGET_MAPPED (window->bin.child))
3071 gtk_widget_map (window->bin.child);
3074 toplevel = window->frame;
3076 toplevel = widget->window;
3078 if (window->maximize_initially)
3079 gdk_window_maximize (toplevel);
3081 gdk_window_unmaximize (toplevel);
3083 if (window->stick_initially)
3084 gdk_window_stick (toplevel);
3086 gdk_window_unstick (toplevel);
3088 if (window->iconify_initially)
3089 gdk_window_iconify (toplevel);
3091 gdk_window_deiconify (toplevel);
3093 /* No longer use the default settings */
3094 window->need_default_size = FALSE;
3095 window->need_default_position = FALSE;
3097 gdk_window_show (widget->window);
3100 gdk_window_show (window->frame);
3104 gtk_window_unmap (GtkWidget *widget)
3106 GtkWindow *window = GTK_WINDOW (widget);
3107 GtkWindowGeometryInfo *info;
3109 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3111 gdk_window_withdraw (window->frame);
3113 gdk_window_withdraw (widget->window);
3115 window->configure_request_count = 0;
3116 window->configure_notify_received = FALSE;
3118 /* on unmap, we reset the default positioning of the window,
3119 * so it's placed again, but we don't reset the default
3120 * size of the window, so it's remembered.
3122 window->need_default_position = TRUE;
3124 info = gtk_window_get_geometry_info (window, FALSE);
3127 info->initial_pos_set = FALSE;
3128 info->position_constraints_changed = FALSE;
3133 gtk_window_realize (GtkWidget *widget)
3136 GdkWindow *parent_window;
3137 GdkWindowAttr attributes;
3138 gint attributes_mask;
3140 window = GTK_WINDOW (widget);
3142 /* ensure widget tree is properly size allocated */
3143 if (widget->allocation.x == -1 &&
3144 widget->allocation.y == -1 &&
3145 widget->allocation.width == 1 &&
3146 widget->allocation.height == 1)
3148 GtkRequisition requisition;
3149 GtkAllocation allocation = { 0, 0, 200, 200 };
3151 gtk_widget_size_request (widget, &requisition);
3152 if (requisition.width || requisition.height)
3154 /* non-empty window */
3155 allocation.width = requisition.width;
3156 allocation.height = requisition.height;
3158 gtk_widget_size_allocate (widget, &allocation);
3160 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3162 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3165 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3167 switch (window->type)
3169 case GTK_WINDOW_TOPLEVEL:
3170 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3172 case GTK_WINDOW_POPUP:
3173 attributes.window_type = GDK_WINDOW_TEMP;
3176 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3180 attributes.title = window->title;
3181 attributes.wmclass_name = window->wmclass_name;
3182 attributes.wmclass_class = window->wmclass_class;
3183 attributes.wclass = GDK_INPUT_OUTPUT;
3184 attributes.visual = gtk_widget_get_visual (widget);
3185 attributes.colormap = gtk_widget_get_colormap (widget);
3187 if (window->has_frame)
3189 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3190 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3191 attributes.event_mask = (GDK_EXPOSURE_MASK |
3192 GDK_KEY_PRESS_MASK |
3193 GDK_ENTER_NOTIFY_MASK |
3194 GDK_LEAVE_NOTIFY_MASK |
3195 GDK_FOCUS_CHANGE_MASK |
3196 GDK_STRUCTURE_MASK |
3197 GDK_BUTTON_MOTION_MASK |
3198 GDK_POINTER_MOTION_HINT_MASK |
3199 GDK_BUTTON_PRESS_MASK |
3200 GDK_BUTTON_RELEASE_MASK);
3202 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3204 window->frame = gdk_window_new (NULL, &attributes, attributes_mask);
3205 gdk_window_set_user_data (window->frame, widget);
3207 attributes.window_type = GDK_WINDOW_CHILD;
3208 attributes.x = window->frame_left;
3209 attributes.y = window->frame_right;
3211 attributes_mask = GDK_WA_X | GDK_WA_Y;
3213 parent_window = window->frame;
3217 attributes_mask = 0;
3218 parent_window = NULL;
3221 attributes.width = widget->allocation.width;
3222 attributes.height = widget->allocation.height;
3223 attributes.event_mask = gtk_widget_get_events (widget);
3224 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3225 GDK_KEY_PRESS_MASK |
3226 GDK_KEY_RELEASE_MASK |
3227 GDK_ENTER_NOTIFY_MASK |
3228 GDK_LEAVE_NOTIFY_MASK |
3229 GDK_FOCUS_CHANGE_MASK |
3230 GDK_STRUCTURE_MASK);
3232 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3233 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3234 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3235 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3236 gdk_window_set_user_data (widget->window, window);
3238 widget->style = gtk_style_attach (widget->style, widget->window);
3239 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3241 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3243 /* This is a bad hack to set the window background. */
3244 gtk_window_paint (widget, NULL);
3246 if (window->transient_parent &&
3247 GTK_WIDGET_REALIZED (window->transient_parent))
3248 gdk_window_set_transient_for (widget->window,
3249 GTK_WIDGET (window->transient_parent)->window);
3251 if (window->wm_role)
3252 gdk_window_set_role (widget->window, window->wm_role);
3254 if (!window->decorated)
3255 gdk_window_set_decorations (widget->window, 0);
3257 gdk_window_set_type_hint (widget->window, window->type_hint);
3259 /* transient_for must be set to allow the modal hint */
3260 if (window->transient_parent && window->modal)
3261 gdk_window_set_modal_hint (widget->window, TRUE);
3263 gdk_window_set_modal_hint (widget->window, FALSE);
3266 gtk_window_realize_icon (window);
3270 gtk_window_unrealize (GtkWidget *widget)
3273 GtkWindowGeometryInfo *info;
3275 window = GTK_WINDOW (widget);
3277 /* On unrealize, we reset the size of the window such
3278 * that we will re-apply the default sizing stuff
3279 * next time we show the window.
3281 * Default positioning is reset on unmap, instead of unrealize.
3283 window->need_default_size = TRUE;
3284 info = gtk_window_get_geometry_info (window, FALSE);
3287 info->resize_width = -1;
3288 info->resize_height = -1;
3289 info->last.configure_request.x = 0;
3290 info->last.configure_request.y = 0;
3291 info->last.configure_request.width = -1;
3292 info->last.configure_request.height = -1;
3293 /* be sure we reset geom hints on re-realize */
3294 info->last.flags = 0;
3299 gdk_window_set_user_data (window->frame, NULL);
3300 gdk_window_destroy (window->frame);
3301 window->frame = NULL;
3305 gtk_window_unrealize_icon (window);
3307 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3311 gtk_window_size_request (GtkWidget *widget,
3312 GtkRequisition *requisition)
3317 window = GTK_WINDOW (widget);
3318 bin = GTK_BIN (window);
3320 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3321 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3323 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3325 GtkRequisition child_requisition;
3327 gtk_widget_size_request (bin->child, &child_requisition);
3329 requisition->width += child_requisition.width;
3330 requisition->height += child_requisition.height;
3335 gtk_window_size_allocate (GtkWidget *widget,
3336 GtkAllocation *allocation)
3339 GtkAllocation child_allocation;
3341 window = GTK_WINDOW (widget);
3342 widget->allocation = *allocation;
3344 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3346 child_allocation.x = GTK_CONTAINER (window)->border_width;
3347 child_allocation.y = GTK_CONTAINER (window)->border_width;
3348 child_allocation.width =
3349 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3350 child_allocation.height =
3351 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3353 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3356 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3358 gdk_window_resize (window->frame,
3359 allocation->width + window->frame_left + window->frame_right,
3360 allocation->height + window->frame_top + window->frame_bottom);
3365 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3368 gboolean return_val;
3370 window = GTK_WINDOW (widget);
3372 if (window->frame && (event->any.window == window->frame))
3374 if ((event->type != GDK_KEY_PRESS) &&
3375 (event->type != GDK_KEY_RELEASE) &&
3376 (event->type != GDK_FOCUS_CHANGE))
3378 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
3380 gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
3385 g_object_unref (event->any.window);
3386 event->any.window = g_object_ref (widget->window);
3394 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3396 GdkEventConfigure *configure_event;
3399 switch (event->type)
3402 configure_event = (GdkEventConfigure *)event;
3404 /* Invalidate the decorations */
3407 rect.width = configure_event->width;
3408 rect.height = configure_event->height;
3410 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3412 /* Pass on the (modified) configure event */
3413 configure_event->width -= window->frame_left + window->frame_right;
3414 configure_event->height -= window->frame_top + window->frame_bottom;
3415 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3424 gtk_window_configure_event (GtkWidget *widget,
3425 GdkEventConfigure *event)
3427 GtkWindow *window = GTK_WINDOW (widget);
3429 /* window->configure_request_count incremented for each
3430 * configure request, and decremented to a min of 0 for
3431 * each configure notify.
3433 * All it means is that we know we will get at least
3434 * window->configure_request_count more configure notifies.
3435 * We could get more configure notifies than that; some
3436 * of the configure notifies we get may be unrelated to
3437 * the configure requests. But we will get at least
3438 * window->configure_request_count notifies.
3441 if (window->configure_request_count > 0)
3442 window->configure_request_count -= 1;
3444 /* As an optimization, we avoid a resize when possible.
3446 * The only times we can avoid a resize are:
3447 * - we know only the position changed, not the size
3448 * - we know we have made more requests and so will get more
3449 * notifies and can wait to resize when we get them
3452 if (window->configure_request_count > 0 ||
3453 (widget->allocation.width == event->width &&
3454 widget->allocation.height == event->height))
3458 * If we do need to resize, we do that by:
3459 * - filling in widget->allocation with the new size
3460 * - setting configure_notify_received to TRUE
3461 * for use in gtk_window_move_resize()
3462 * - queueing a resize, leading to invocation of
3463 * gtk_window_move_resize() in an idle handler
3467 window->configure_notify_received = TRUE;
3469 widget->allocation.width = event->width;
3470 widget->allocation.height = event->height;
3472 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3477 /* the accel_key and accel_mods fields of the key have to be setup
3478 * upon calling this function. it'll then return whether that key
3479 * is at all used as accelerator, and if so will OR in the
3480 * accel_flags member of the key.
3483 _gtk_window_query_nonaccels (GtkWindow *window,
3485 GdkModifierType accel_mods)
3487 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3489 /* movement keys are considered locked accels */
3492 static const guint bindings[] = {
3493 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
3494 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
3498 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
3499 if (bindings[i] == accel_key)
3503 /* mnemonics are considered locked accels */
3504 if (accel_mods == window->mnemonic_modifier)
3506 GtkWindowMnemonic mkey;
3508 mkey.window = window;
3509 mkey.keyval = accel_key;
3510 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
3518 gtk_window_key_press_event (GtkWidget *widget,
3525 window = GTK_WINDOW (widget);
3530 handled = gtk_window_mnemonic_activate (window,
3535 handled = gtk_accel_groups_activate (G_OBJECT (window), event->keyval, event->state);
3539 focus = window->focus_widget;
3541 g_object_ref (focus);
3544 focus && focus != widget &&
3545 gtk_widget_get_toplevel (focus) == widget)
3549 if (GTK_WIDGET_IS_SENSITIVE (focus))
3550 handled = gtk_widget_event (focus, (GdkEvent*) event);
3552 parent = focus->parent;
3554 g_object_ref (parent);
3556 g_object_unref (focus);
3562 g_object_unref (focus);
3565 /* Chain up, invokes binding set */
3566 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
3567 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
3573 gtk_window_key_release_event (GtkWidget *widget,
3579 window = GTK_WINDOW (widget);
3581 if (window->focus_widget &&
3582 window->focus_widget != widget &&
3583 GTK_WIDGET_SENSITIVE (window->focus_widget))
3585 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
3588 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
3589 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
3595 gtk_window_real_activate_default (GtkWindow *window)
3597 gtk_window_activate_default (window);
3601 gtk_window_real_activate_focus (GtkWindow *window)
3603 gtk_window_activate_focus (window);
3607 gtk_window_move_focus (GtkWindow *window,
3608 GtkDirectionType dir)
3610 gtk_widget_child_focus (GTK_WIDGET (window), dir);
3612 if (!GTK_CONTAINER (window)->focus_child)
3613 gtk_window_set_focus (window, NULL);
3617 gtk_window_enter_notify_event (GtkWidget *widget,
3618 GdkEventCrossing *event)
3624 gtk_window_leave_notify_event (GtkWidget *widget,
3625 GdkEventCrossing *event)
3631 gtk_window_focus_in_event (GtkWidget *widget,
3632 GdkEventFocus *event)
3634 GtkWindow *window = GTK_WINDOW (widget);
3635 GdkEventFocus fevent;
3637 /* It appears spurious focus in events can occur when
3638 * the window is hidden. So we'll just check to see if
3639 * the window is visible before actually handling the
3642 if (GTK_WIDGET_VISIBLE (widget))
3644 window->has_focus = TRUE;
3646 if (window->focus_widget &&
3647 window->focus_widget != widget &&
3648 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3650 fevent.type = GDK_FOCUS_CHANGE;
3651 fevent.window = window->focus_widget->window;
3654 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
3662 gtk_window_focus_out_event (GtkWidget *widget,
3663 GdkEventFocus *event)
3665 GtkWindow *window = GTK_WINDOW (widget);
3666 GdkEventFocus fevent;
3668 window->has_focus = FALSE;
3670 if (window->focus_widget &&
3671 window->focus_widget != widget &&
3672 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3674 fevent.type = GDK_FOCUS_CHANGE;
3675 fevent.window = window->focus_widget->window;
3678 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
3684 static GdkAtom atom_rcfiles = GDK_NONE;
3687 gtk_window_read_rcfiles (GtkWidget *widget,
3688 GdkEventClient *event)
3690 GList *embedded_windows;
3692 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
3693 if (embedded_windows)
3698 for (i = 0; i < 5; i++)
3700 sev.data_format = 32;
3701 sev.message_type = atom_rcfiles;
3703 while (embedded_windows)
3705 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
3706 gdk_event_send_client_message ((GdkEvent *) &sev, xid);
3707 embedded_windows = embedded_windows->next;
3711 gtk_rc_reparse_all ();
3715 gtk_window_client_event (GtkWidget *widget,
3716 GdkEventClient *event)
3719 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
3721 if (event->message_type == atom_rcfiles)
3722 gtk_window_read_rcfiles (widget, event);
3728 gtk_window_check_resize (GtkContainer *container)
3730 GtkWindow *window = GTK_WINDOW (container);
3732 if (GTK_WIDGET_VISIBLE (container))
3733 gtk_window_move_resize (window);
3737 gtk_window_focus (GtkWidget *widget,
3738 GtkDirectionType direction)
3742 GtkContainer *container;
3743 GtkWidget *old_focus_child;
3746 container = GTK_CONTAINER (widget);
3747 window = GTK_WINDOW (widget);
3748 bin = GTK_BIN (widget);
3750 old_focus_child = container->focus_child;
3752 /* We need a special implementation here to deal properly with wrapping
3753 * around in the tab chain without the danger of going into an
3756 if (old_focus_child)
3758 if (gtk_widget_child_focus (old_focus_child, direction))
3762 if (window->focus_widget)
3764 /* Wrapped off the end, clear the focus setting for the toplpevel */
3765 parent = window->focus_widget->parent;
3768 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
3769 parent = GTK_WIDGET (parent)->parent;
3772 gtk_window_set_focus (GTK_WINDOW (container), NULL);
3775 /* Now try to focus the first widget in the window */
3778 if (gtk_widget_child_focus (bin->child, direction))
3786 gtk_window_real_set_focus (GtkWindow *window,
3789 GdkEventFocus event;
3790 gboolean def_flags = 0;
3792 if (window->default_widget)
3793 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
3795 if (window->focus_widget)
3797 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3798 (window->focus_widget != window->default_widget))
3800 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3802 if (window->default_widget)
3803 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3806 if (window->has_focus)
3808 event.type = GDK_FOCUS_CHANGE;
3809 event.window = window->focus_widget->window;
3812 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
3816 window->focus_widget = focus;
3818 if (window->focus_widget)
3820 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3821 (window->focus_widget != window->default_widget))
3823 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
3824 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3826 if (window->default_widget)
3827 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3830 if (window->has_focus)
3832 event.type = GDK_FOCUS_CHANGE;
3833 event.window = window->focus_widget->window;
3836 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
3840 if (window->default_widget &&
3841 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
3842 gtk_widget_queue_draw (window->default_widget);
3845 /*********************************
3846 * Functions related to resizing *
3847 *********************************/
3849 /* This function doesn't constrain to geometry hints */
3851 gtk_window_compute_configure_request_size (GtkWindow *window,
3855 GtkRequisition requisition;
3856 GtkWindowGeometryInfo *info;
3860 * - we've done a size request
3863 widget = GTK_WIDGET (window);
3865 info = gtk_window_get_geometry_info (window, FALSE);
3867 if (window->need_default_size)
3869 gtk_widget_get_child_requisition (widget, &requisition);
3871 /* Default to requisition */
3872 *width = requisition.width;
3873 *height = requisition.height;
3875 /* If window is empty so requests 0, default to random nonzero size */
3876 if (*width == 0 && *height == 0)
3882 /* Override requisition with default size */
3886 if (info->default_width > 0)
3887 *width = info->default_width;
3889 if (info->default_height > 0)
3890 *height = info->default_height;
3895 /* Default to keeping current size */
3896 *width = widget->allocation.width;
3897 *height = widget->allocation.height;
3900 /* Override any size with gtk_window_resize() values */
3903 if (info->resize_width > 0)
3904 *width = info->resize_width;
3906 if (info->resize_height > 0)
3907 *height = info->resize_height;
3912 gtk_window_compute_configure_request (GtkWindow *window,
3913 GdkRectangle *request,
3914 GdkGeometry *geometry,
3917 GdkGeometry new_geometry;
3921 GtkWindowPosition pos;
3922 GtkWidget *parent_widget;
3923 GtkWindowGeometryInfo *info;
3926 widget = GTK_WIDGET (window);
3928 gtk_widget_size_request (widget, NULL);
3929 gtk_window_compute_configure_request_size (window, &w, &h);
3931 gtk_window_compute_hints (window, &new_geometry, &new_flags);
3932 gtk_window_constrain_size (window,
3933 &new_geometry, new_flags,
3937 parent_widget = (GtkWidget*) window->transient_parent;
3939 pos = window->position;
3940 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
3941 (parent_widget == NULL ||
3942 !GTK_WIDGET_MAPPED (parent_widget)))
3943 pos = GTK_WIN_POS_NONE;
3945 info = gtk_window_get_geometry_info (window, TRUE);
3947 /* by default, don't change position requested */
3948 x = info->last.configure_request.x;
3949 y = info->last.configure_request.y;
3951 if (window->need_default_position)
3954 /* FIXME this all interrelates with window gravity.
3955 * For most of them I think we want to set GRAVITY_CENTER.
3957 * Not sure how to go about that.
3962 /* here we are only handling CENTER_ALWAYS
3963 * as it relates to default positioning,
3964 * where it's equivalent to simply CENTER
3966 case GTK_WIN_POS_CENTER_ALWAYS:
3967 case GTK_WIN_POS_CENTER:
3969 gint screen_width = gdk_screen_width ();
3970 gint screen_height = gdk_screen_height ();
3972 x = (screen_width - w) / 2;
3973 y = (screen_height - h) / 2;
3977 case GTK_WIN_POS_CENTER_ON_PARENT:
3981 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
3983 gdk_window_get_origin (parent_widget->window,
3986 x = ox + (parent_widget->allocation.width - w) / 2;
3987 y = oy + (parent_widget->allocation.height - h) / 2;
3991 case GTK_WIN_POS_MOUSE:
3993 gint screen_width = gdk_screen_width ();
3994 gint screen_height = gdk_screen_height ();
3997 gdk_window_get_pointer (NULL, &px, &py, NULL);
4000 x = CLAMP (x, 0, screen_width - w);
4001 y = CLAMP (y, 0, screen_height - h);
4008 } /* if (window->need_default_position) */
4010 if (window->need_default_position &&
4011 info->initial_pos_set)
4013 x = info->initial_x;
4014 y = info->initial_y;
4015 gtk_window_constrain_position (window, w, h, &x, &y);
4021 request->height = h;
4024 *geometry = new_geometry;
4030 gtk_window_constrain_position (GtkWindow *window,
4036 /* See long comments in gtk_window_move_resize()
4037 * on when it's safe to call this function.
4039 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4041 gint center_x, center_y;
4042 gint screen_width = gdk_screen_width ();
4043 gint screen_height = gdk_screen_height ();
4045 center_x = (screen_width - new_width) / 2;
4046 center_y = (screen_height - new_height) / 2;
4054 gtk_window_move_resize (GtkWindow *window)
4058 * First we determine whether any information has changed that would
4059 * cause us to revise our last configure request. If we would send
4060 * a different configure request from last time, then
4061 * configure_request_size_changed = TRUE or
4062 * configure_request_pos_changed = TRUE. configure_request_size_changed
4063 * may be true due to new hints, a gtk_window_resize(), or whatever.
4064 * configure_request_pos_changed may be true due to gtk_window_set_position()
4065 * or gtk_window_move().
4067 * If the configure request has changed, we send off a new one. To
4068 * ensure GTK+ invariants are maintained (resize queue does what it
4069 * should), we go ahead and size_allocate the requested size in this
4072 * If the configure request has not changed, we don't ever resend
4073 * it, because it could mean fighting the user or window manager.
4076 * To prepare the configure request, we come up with a base size/pos:
4077 * - the one from gtk_window_move()/gtk_window_resize()
4078 * - else default_width, default_height if we haven't ever
4080 * - else the size request if we haven't ever been mapped,
4081 * as a substitute default size
4082 * - else the current size of the window, as received from
4083 * configure notifies (i.e. the current allocation)
4085 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4086 * the position request to be centered.
4089 GtkContainer *container;
4090 GtkWindowGeometryInfo *info;
4091 GdkGeometry new_geometry;
4093 GdkRectangle new_request;
4094 gboolean configure_request_size_changed;
4095 gboolean configure_request_pos_changed;
4096 gboolean hints_changed; /* do we need to send these again */
4097 GtkWindowLastGeometryInfo saved_last_info;
4099 widget = GTK_WIDGET (window);
4100 container = GTK_CONTAINER (widget);
4101 info = gtk_window_get_geometry_info (window, TRUE);
4103 configure_request_size_changed = FALSE;
4104 configure_request_pos_changed = FALSE;
4106 gtk_window_compute_configure_request (window, &new_request,
4107 &new_geometry, &new_flags);
4109 /* This check implies the invariant that we never set info->last
4110 * without setting the hints and sending off a configure request.
4112 * If we change info->last without sending the request, we may
4115 if (info->last.configure_request.x != new_request.x ||
4116 info->last.configure_request.y != new_request.y)
4117 configure_request_pos_changed = TRUE;
4119 if ((info->last.configure_request.width != new_request.width ||
4120 info->last.configure_request.height != new_request.height))
4121 configure_request_size_changed = TRUE;
4123 hints_changed = FALSE;
4125 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4126 &new_geometry, new_flags))
4128 hints_changed = TRUE;
4131 /* Position Constraints
4132 * ====================
4134 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4135 * a default. The other POS_ values are used only when the
4136 * window is shown, not after that.
4138 * However, we can't implement a position constraint as
4139 * "anytime the window size changes, center the window"
4140 * because this may well end up fighting the WM or user. In
4141 * fact it gets in an infinite loop with at least one WM.
4143 * Basically, applications are in no way in a position to
4144 * constrain the position of a window, with one exception:
4145 * override redirect windows. (Really the intended purpose
4146 * of CENTER_ALWAYS anyhow, I would think.)
4148 * So the way we implement this "constraint" is to say that when WE
4149 * cause a move or resize, i.e. we make a configure request changing
4150 * window size, we recompute the CENTER_ALWAYS position to reflect
4151 * the new window size, and include it in our request. Also, if we
4152 * just turned on CENTER_ALWAYS we snap to center with a new
4153 * request. Otherwise, if we are just NOTIFIED of a move or resize
4154 * done by someone else e.g. the window manager, we do NOT send a
4155 * new configure request.
4157 * For override redirect windows, this works fine; all window
4158 * sizes are from our configure requests. For managed windows,
4159 * it is at least semi-sane, though who knows what the
4160 * app author is thinking.
4163 /* This condition should be kept in sync with the condition later on
4164 * that determines whether we send a configure request. i.e. we
4165 * should do this position constraining anytime we were going to
4166 * send a configure request anyhow, plus when constraints have
4169 if (configure_request_pos_changed ||
4170 configure_request_size_changed ||
4172 info->position_constraints_changed)
4174 /* We request the constrained position if:
4175 * - we were changing position, and need to clamp
4176 * the change to the constraint
4177 * - we're changing the size anyway
4178 * - set_position() was called to toggle CENTER_ALWAYS on
4181 gtk_window_constrain_position (window,
4187 /* Update whether we need to request a move */
4188 if (info->last.configure_request.x != new_request.x ||
4189 info->last.configure_request.y != new_request.y)
4190 configure_request_pos_changed = TRUE;
4192 configure_request_pos_changed = FALSE;
4197 int notify_x, notify_y;
4199 /* this is the position from the last configure notify */
4200 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4202 g_print ("--- %s ---\n"
4203 "last : %d,%d\t%d x %d\n"
4204 "this : %d,%d\t%d x %d\n"
4205 "alloc: %d,%d\t%d x %d\n"
4207 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4208 "configure_notify_received: %d\n"
4209 "configure_request_count: %d\n"
4210 "position_constraints_changed: %d\n",
4211 window->title ? window->title : "(no title)",
4212 info->last.configure_request.x,
4213 info->last.configure_request.y,
4214 info->last.configure_request.width,
4215 info->last.configure_request.height,
4221 widget->allocation.width,
4222 widget->allocation.height,
4223 widget->requisition.width,
4224 widget->requisition.height,
4225 configure_request_pos_changed,
4226 configure_request_size_changed,
4228 window->configure_notify_received,
4229 window->configure_request_count,
4230 info->position_constraints_changed);
4234 saved_last_info = info->last;
4235 info->last.geometry = new_geometry;
4236 info->last.flags = new_flags;
4237 info->last.configure_request = new_request;
4239 /* need to set PPosition so the WM will look at our position,
4240 * but we don't want to count PPosition coming and going as a hints
4241 * change for future iterations. So we saved info->last prior to
4245 /* Also, if the initial position was explicitly set, then we always
4246 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4250 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4251 * this is an initial map
4254 if ((configure_request_pos_changed ||
4255 info->initial_pos_set ||
4256 (window->need_default_position &&
4257 window->position != GTK_WIN_POS_NONE)) &&
4258 (new_flags & GDK_HINT_POS) == 0)
4260 new_flags |= GDK_HINT_POS;
4261 hints_changed = TRUE;
4264 /* Set hints if necessary
4267 gdk_window_set_geometry_hints (widget->window,
4271 /* handle resizing/moving and widget tree allocation
4273 if (window->configure_notify_received)
4275 GtkAllocation allocation;
4277 /* If we have received a configure event since
4278 * the last time in this function, we need to
4279 * accept our new size and size_allocate child widgets.
4280 * (see gtk_window_configure_event() for more details).
4282 * 1 or more configure notifies may have been received.
4283 * Also, configure_notify_received will only be TRUE
4284 * if all expected configure notifies have been received
4285 * (one per configure request), as an optimization.
4288 window->configure_notify_received = FALSE;
4290 /* gtk_window_configure_event() filled in widget->allocation */
4291 allocation = widget->allocation;
4292 gtk_widget_size_allocate (widget, &allocation);
4294 /* If the configure request changed, it means that
4296 * 1) coincidentally changed hints or widget properties
4297 * impacting the configure request before getting
4298 * a configure notify, or
4299 * 2) some broken widget is changing its size request
4300 * during size allocation, resulting in
4301 * a false appearance of changed configure request.
4303 * For 1), we could just go ahead and ask for the
4304 * new size right now, but doing that for 2)
4305 * might well be fighting the user (and can even
4306 * trigger a loop). Since we really don't want to
4307 * do that, we requeue a resize in hopes that
4308 * by the time it gets handled, the child has seen
4309 * the light and is willing to go along with the
4310 * new size. (this happens for the zvt widget, since
4311 * the size_allocate() above will have stored the
4312 * requisition corresponding to the new size in the
4315 * This doesn't buy us anything for 1), but it shouldn't
4316 * hurt us too badly, since it is what would have
4317 * happened if we had gotten the configure event before
4318 * the new size had been set.
4321 if (configure_request_size_changed ||
4322 configure_request_pos_changed)
4324 /* Don't change the recorded last info after all, because we
4325 * haven't actually updated to the new info yet - we decided
4326 * to postpone our configure request until later.
4328 info->last = saved_last_info;
4330 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
4333 else if ((configure_request_size_changed || hints_changed) &&
4334 (widget->allocation.width != new_request.width ||
4335 widget->allocation.height != new_request.height))
4338 /* We are in one of the following situations:
4339 * A. configure_request_size_changed
4340 * our requisition has changed and we need a different window size,
4341 * so we request it from the window manager.
4342 * B. !configure_request_size_changed && hints_changed
4343 * the window manager rejects our size, but we have just changed the
4344 * window manager hints, so there's a chance our request will
4345 * be honoured this time, so we try again.
4347 * However, if the new requisition is the same as the current allocation,
4348 * we don't request it again, since we won't get a ConfigureNotify back from
4349 * the window manager unless it decides to change our requisition. If
4350 * we don't get the ConfigureNotify back, the resize queue will never be run.
4353 /* Now send the configure request */
4354 if (configure_request_pos_changed)
4358 gdk_window_move_resize (window->frame,
4359 new_request.x - window->frame_left,
4360 new_request.y - window->frame_top,
4361 new_request.width + window->frame_left + window->frame_right,
4362 new_request.height + window->frame_top + window->frame_bottom);
4363 gdk_window_resize (GTK_WIDGET (window)->window,
4364 new_request.width, new_request.height);
4367 gdk_window_move_resize (widget->window,
4368 new_request.x, new_request.y,
4369 new_request.width, new_request.height);
4371 else /* only size changed */
4374 gdk_window_resize (window->frame,
4375 new_request.width + window->frame_left + window->frame_right,
4376 new_request.height + window->frame_top + window->frame_bottom);
4377 gdk_window_resize (widget->window,
4378 new_request.width, new_request.height);
4381 /* Increment the number of have-not-yet-received-notify requests */
4382 window->configure_request_count += 1;
4384 /* We have now sent a request since the last position constraint
4385 * change and definitely don't need a an initial size again (not
4386 * resetting this here can lead to infinite loops for
4387 * GTK_RESIZE_IMMEDIATE containers)
4389 info->position_constraints_changed = FALSE;
4390 window->need_default_position = FALSE;
4391 info->initial_pos_set = FALSE;
4393 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
4394 * configure event in response to our resizing request.
4395 * the configure event will cause a new resize with
4396 * ->configure_notify_received=TRUE.
4397 * until then, we want to
4398 * - discard expose events
4399 * - coalesce resizes for our children
4400 * - defer any window resizes until the configure event arrived
4401 * to achieve this, we queue a resize for the window, but remove its
4402 * resizing handler, so resizing will not be handled from the next
4403 * idle handler but when the configure event arrives.
4405 * FIXME: we should also dequeue the pending redraws here, since
4406 * we handle those ourselves upon ->configure_notify_received==TRUE.
4408 if (container->resize_mode == GTK_RESIZE_QUEUE)
4410 gtk_widget_queue_resize (widget);
4411 _gtk_container_dequeue_resize_handler (container);
4416 /* Handle any position changes.
4418 if (configure_request_pos_changed)
4422 gdk_window_move (window->frame,
4423 new_request.x - window->frame_left,
4424 new_request.y - window->frame_top);
4427 gdk_window_move (widget->window,
4428 new_request.x, new_request.y);
4431 /* And run the resize queue.
4433 gtk_container_resize_children (container);
4437 /* Compare two sets of Geometry hints for equality.
4440 gtk_window_compare_hints (GdkGeometry *geometry_a,
4442 GdkGeometry *geometry_b,
4445 if (flags_a != flags_b)
4448 if ((flags_a & GDK_HINT_MIN_SIZE) &&
4449 (geometry_a->min_width != geometry_b->min_width ||
4450 geometry_a->min_height != geometry_b->min_height))
4453 if ((flags_a & GDK_HINT_MAX_SIZE) &&
4454 (geometry_a->max_width != geometry_b->max_width ||
4455 geometry_a->max_height != geometry_b->max_height))
4458 if ((flags_a & GDK_HINT_BASE_SIZE) &&
4459 (geometry_a->base_width != geometry_b->base_width ||
4460 geometry_a->base_height != geometry_b->base_height))
4463 if ((flags_a & GDK_HINT_ASPECT) &&
4464 (geometry_a->min_aspect != geometry_b->min_aspect ||
4465 geometry_a->max_aspect != geometry_b->max_aspect))
4468 if ((flags_a & GDK_HINT_RESIZE_INC) &&
4469 (geometry_a->width_inc != geometry_b->width_inc ||
4470 geometry_a->height_inc != geometry_b->height_inc))
4473 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
4474 geometry_a->win_gravity != geometry_b->win_gravity)
4481 _gtk_window_constrain_size (GtkWindow *window,
4487 GtkWindowGeometryInfo *info;
4489 g_return_if_fail (GTK_IS_WINDOW (window));
4491 info = window->geometry_info;
4494 GdkWindowHints flags = info->last.flags;
4495 GdkGeometry *geometry = &info->last.geometry;
4497 gtk_window_constrain_size (window,
4508 gtk_window_constrain_size (GtkWindow *window,
4509 GdkGeometry *geometry,
4516 gdk_window_constrain_size (geometry, flags, width, height,
4517 new_width, new_height);
4520 /* Compute the set of geometry hints and flags for a window
4521 * based on the application set geometry, and requisiition
4522 * of the window. gtk_widget_size_request() must have been
4526 gtk_window_compute_hints (GtkWindow *window,
4527 GdkGeometry *new_geometry,
4531 gint extra_width = 0;
4532 gint extra_height = 0;
4533 GtkWindowGeometryInfo *geometry_info;
4534 GtkRequisition requisition;
4536 widget = GTK_WIDGET (window);
4538 gtk_widget_get_child_requisition (widget, &requisition);
4539 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
4543 *new_flags = geometry_info->mask;
4544 *new_geometry = geometry_info->geometry;
4551 if (geometry_info && geometry_info->widget)
4553 GtkRequisition child_requisition;
4555 /* FIXME: This really isn't right. It gets the min size wrong and forces
4556 * callers to do horrible hacks like set a huge usize on the child requisition
4557 * to get the base size right. We really want to find the answers to:
4559 * - If the geometry widget was infinitely big, how much extra space
4560 * would be needed for the stuff around it.
4562 * - If the geometry widget was infinitely small, how big would the
4563 * window still have to be.
4565 * Finding these answers would be a bit of a mess here. (Bug #68668)
4567 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
4569 extra_width = widget->requisition.width - child_requisition.width;
4570 extra_height = widget->requisition.height - child_requisition.height;
4573 /* We don't want to set GDK_HINT_POS in here, we just set it
4574 * in gtk_window_move_resize() when we want the position
4578 if (*new_flags & GDK_HINT_BASE_SIZE)
4580 new_geometry->base_width += extra_width;
4581 new_geometry->base_height += extra_height;
4583 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
4584 (*new_flags & GDK_HINT_RESIZE_INC) &&
4585 ((extra_width != 0) || (extra_height != 0)))
4587 *new_flags |= GDK_HINT_BASE_SIZE;
4589 new_geometry->base_width = extra_width;
4590 new_geometry->base_height = extra_height;
4593 if (*new_flags & GDK_HINT_MIN_SIZE)
4595 if (new_geometry->min_width < 0)
4596 new_geometry->min_width = requisition.width;
4598 new_geometry->min_width += extra_width;
4600 if (new_geometry->min_height < 0)
4601 new_geometry->min_height = requisition.height;
4603 new_geometry->min_height += extra_height;
4605 else if (!window->allow_shrink)
4607 *new_flags |= GDK_HINT_MIN_SIZE;
4609 new_geometry->min_width = requisition.width;
4610 new_geometry->min_height = requisition.height;
4613 if (*new_flags & GDK_HINT_MAX_SIZE)
4615 if (new_geometry->max_width < 0)
4616 new_geometry->max_width = requisition.width;
4618 new_geometry->max_width += extra_width;
4620 if (new_geometry->max_height < 0)
4621 new_geometry->max_width = requisition.height;
4623 new_geometry->max_height += extra_height;
4625 else if (!window->allow_grow)
4627 *new_flags |= GDK_HINT_MAX_SIZE;
4629 new_geometry->max_width = requisition.width;
4630 new_geometry->max_height = requisition.height;
4633 *new_flags |= GDK_HINT_WIN_GRAVITY;
4634 new_geometry->win_gravity = window->gravity;
4637 /***********************
4638 * Redrawing functions *
4639 ***********************/
4642 gtk_window_paint (GtkWidget *widget,
4645 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
4646 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
4650 gtk_window_expose (GtkWidget *widget,
4651 GdkEventExpose *event)
4653 if (!GTK_WIDGET_APP_PAINTABLE (widget))
4654 gtk_window_paint (widget, &event->area);
4656 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
4657 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
4663 * gtk_window_set_has_frame:
4664 * @window: a #GtkWindow
4665 * @setting: a boolean
4667 * (Note: this is a special-purpose function for the framebuffer port,
4668 * that causes GTK+ to draw its own window border. For most applications,
4669 * you want gtk_window_set_decorated() instead, which tells the window
4670 * manager whether to draw the window border.)
4672 * If this function is called on a window with setting of %TRUE, before
4673 * it is realized or showed, it will have a "frame" window around
4674 * @window->window, accessible in @window->frame. Using the signal
4675 * frame_event you can recieve all events targeted at the frame.
4677 * This function is used by the linux-fb port to implement managed
4678 * windows, but it could concievably be used by X-programs that
4679 * want to do their own window decorations.
4683 gtk_window_set_has_frame (GtkWindow *window,
4686 g_return_if_fail (GTK_IS_WINDOW (window));
4687 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
4689 window->has_frame = setting != FALSE;
4693 * gtk_window_get_has_frame:
4694 * @window: a #GtkWindow
4696 * Accessor for whether the window has a frame window exterior to
4697 * @window->window. Gets the value set by gtk_window_set_has_frame ().
4699 * Return value: %TRUE if a frame has been added to the window
4700 * via gtk_window_set_has_frame().
4703 gtk_window_get_has_frame (GtkWindow *window)
4705 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4707 return window->has_frame;
4711 * gtk_window_set_frame_dimensions:
4712 * @window: a #GtkWindow that has a frame
4713 * @left: The width of the left border
4714 * @top: The height of the top border
4715 * @right: The width of the right border
4716 * @bottom: The height of the bottom border
4718 * (Note: this is a special-purpose function intended for the framebuffer
4719 * port; see gtk_window_set_has_frame(). It will have no effect on the
4720 * window border drawn by the window manager, which is the normal
4721 * case when using the X Window system.)
4723 * For windows with frames (see gtk_window_set_has_frame()) this function
4724 * can be used to change the size of the frame border.
4727 gtk_window_set_frame_dimensions (GtkWindow *window,
4735 g_return_if_fail (GTK_IS_WINDOW (window));
4737 widget = GTK_WIDGET (window);
4739 if (window->frame_left == left &&
4740 window->frame_top == top &&
4741 window->frame_right == right &&
4742 window->frame_bottom == bottom)
4745 window->frame_left = left;
4746 window->frame_top = top;
4747 window->frame_right = right;
4748 window->frame_bottom = bottom;
4750 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4752 gint width = widget->allocation.width + left + right;
4753 gint height = widget->allocation.height + top + bottom;
4754 gdk_window_resize (window->frame, width, height);
4755 gtk_decorated_window_move_resize_window (window,
4757 widget->allocation.width,
4758 widget->allocation.height);
4763 * gtk_window_present:
4764 * @window: a #GtkWindow
4766 * Presents a window to the user. This may mean raising the window
4767 * in the stacking order, deiconifying it, moving it to the current
4768 * desktop, and/or giving it the keyboard focus, possibly dependent
4769 * on the user's platform, window manager, and preferences.
4771 * If @window is hidden, this function calls gtk_widget_show()
4774 * This function should be used when the user tries to open a window
4775 * that's already open. Say for example the preferences dialog is
4776 * currently open, and the user chooses Preferences from the menu
4777 * a second time; use gtk_window_present() to move the already-open dialog
4778 * where the user can see it.
4782 gtk_window_present (GtkWindow *window)
4786 g_return_if_fail (GTK_IS_WINDOW (window));
4788 widget = GTK_WIDGET (window);
4790 if (GTK_WIDGET_VISIBLE (window))
4792 g_assert (widget->window != NULL);
4794 gdk_window_show (widget->window);
4796 /* note that gdk_window_focus() will also move the window to
4797 * the current desktop, for WM spec compliant window managers.
4799 gdk_window_focus (widget->window,
4800 gtk_get_current_event_time ());
4804 gtk_widget_show (widget);
4809 * gtk_window_iconify:
4810 * @window: a #GtkWindow
4812 * Asks to iconify (i.e. minimize) the specified @window. Note that
4813 * you shouldn't assume the window is definitely iconified afterward,
4814 * because other entities (e.g. the user or <link
4815 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
4816 * again, or there may not be a window manager in which case
4817 * iconification isn't possible, etc. But normally the window will end
4818 * up iconified. Just don't write code that crashes if not.
4820 * It's permitted to call this function before showing a window,
4821 * in which case the window will be iconified before it ever appears
4824 * You can track iconification via the "window_state_event" signal
4829 gtk_window_iconify (GtkWindow *window)
4832 GdkWindow *toplevel;
4834 g_return_if_fail (GTK_IS_WINDOW (window));
4836 widget = GTK_WIDGET (window);
4838 window->iconify_initially = TRUE;
4841 toplevel = window->frame;
4843 toplevel = widget->window;
4845 if (toplevel != NULL)
4846 gdk_window_iconify (toplevel);
4850 * gtk_window_deiconify:
4851 * @window: a #GtkWindow
4853 * Asks to deiconify (i.e. unminimize) the specified @window. Note
4854 * that you shouldn't assume the window is definitely deiconified
4855 * afterward, because other entities (e.g. the user or <link
4856 * linkend="gtk-X11-arch">window manager</link>) could iconify it
4857 * again before your code which assumes deiconification gets to run.
4859 * You can track iconification via the "window_state_event" signal
4863 gtk_window_deiconify (GtkWindow *window)
4866 GdkWindow *toplevel;
4868 g_return_if_fail (GTK_IS_WINDOW (window));
4870 widget = GTK_WIDGET (window);
4872 window->iconify_initially = FALSE;
4875 toplevel = window->frame;
4877 toplevel = widget->window;
4879 if (toplevel != NULL)
4880 gdk_window_deiconify (toplevel);
4885 * @window: a #GtkWindow
4887 * Asks to stick @window, which means that it will appear on all user
4888 * desktops. Note that you shouldn't assume the window is definitely
4889 * stuck afterward, because other entities (e.g. the user or <link
4890 * linkend="gtk-X11-arch">window manager</link>) could unstick it
4891 * again, and some window managers do not support sticking
4892 * windows. But normally the window will end up stuck. Just don't
4893 * write code that crashes if not.
4895 * It's permitted to call this function before showing a window.
4897 * You can track stickiness via the "window_state_event" signal
4902 gtk_window_stick (GtkWindow *window)
4905 GdkWindow *toplevel;
4907 g_return_if_fail (GTK_IS_WINDOW (window));
4909 widget = GTK_WIDGET (window);
4911 window->stick_initially = TRUE;
4914 toplevel = window->frame;
4916 toplevel = widget->window;
4918 if (toplevel != NULL)
4919 gdk_window_stick (toplevel);
4923 * gtk_window_unstick:
4924 * @window: a #GtkWindow
4926 * Asks to unstick @window, which means that it will appear on only
4927 * one of the user's desktops. Note that you shouldn't assume the
4928 * window is definitely unstuck afterward, because other entities
4929 * (e.g. the user or <link linkend="gtk-X11-arch">window
4930 * manager</link>) could stick it again. But normally the window will
4931 * end up stuck. Just don't write code that crashes if not.
4933 * You can track stickiness via the "window_state_event" signal
4938 gtk_window_unstick (GtkWindow *window)
4941 GdkWindow *toplevel;
4943 g_return_if_fail (GTK_IS_WINDOW (window));
4945 widget = GTK_WIDGET (window);
4947 window->stick_initially = FALSE;
4950 toplevel = window->frame;
4952 toplevel = widget->window;
4954 if (toplevel != NULL)
4955 gdk_window_unstick (toplevel);
4959 * gtk_window_maximize:
4960 * @window: a #GtkWindow
4962 * Asks to maximize @window, so that it becomes full-screen. Note that
4963 * you shouldn't assume the window is definitely maximized afterward,
4964 * because other entities (e.g. the user or <link
4965 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
4966 * again, and not all window managers support maximization. But
4967 * normally the window will end up maximized. Just don't write code
4968 * that crashes if not.
4970 * It's permitted to call this function before showing a window,
4971 * in which case the window will be maximized when it appears onscreen
4974 * You can track maximization via the "window_state_event" signal
4979 gtk_window_maximize (GtkWindow *window)
4982 GdkWindow *toplevel;
4984 g_return_if_fail (GTK_IS_WINDOW (window));
4986 widget = GTK_WIDGET (window);
4988 window->maximize_initially = TRUE;
4991 toplevel = window->frame;
4993 toplevel = widget->window;
4995 if (toplevel != NULL)
4996 gdk_window_maximize (toplevel);
5000 * gtk_window_unmaximize:
5001 * @window: a #GtkWindow
5003 * Asks to unmaximize @window. Note that you shouldn't assume the
5004 * window is definitely unmaximized afterward, because other entities
5005 * (e.g. the user or <link linkend="gtk-X11-arch">window
5006 * manager</link>) could maximize it again, and not all window
5007 * managers honor requests to unmaximize. But normally the window will
5008 * end up unmaximized. Just don't write code that crashes if not.
5010 * You can track maximization via the "window_state_event" signal
5015 gtk_window_unmaximize (GtkWindow *window)
5018 GdkWindow *toplevel;
5020 g_return_if_fail (GTK_IS_WINDOW (window));
5022 widget = GTK_WIDGET (window);
5024 window->maximize_initially = FALSE;
5027 toplevel = window->frame;
5029 toplevel = widget->window;
5031 if (toplevel != NULL)
5032 gdk_window_unmaximize (toplevel);
5036 * gtk_window_set_resizable:
5037 * @window: a #GtkWindow
5038 * @resizable: %TRUE if the user can resize this window
5040 * Sets whether the user can resize a window. Windows are user resizable
5044 gtk_window_set_resizable (GtkWindow *window,
5047 g_return_if_fail (GTK_IS_WINDOW (window));
5049 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5053 * gtk_window_get_resizable:
5054 * @window: a #GtkWindow
5056 * Gets the value set by gtk_window_set_resizable().
5058 * Return value: %TRUE if the user can resize the window
5061 gtk_window_get_resizable (GtkWindow *window)
5063 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5065 /* allow_grow is most likely to indicate the semantic concept we
5066 * mean by "resizable" (and will be a reliable indicator if
5067 * set_policy() hasn't been called)
5069 return window->allow_grow;
5073 * gtk_window_set_gravity:
5074 * @window: a #GtkWindow
5075 * @gravity: window gravity
5077 * Window gravity defines the meaning of coordinates passed to
5078 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5081 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5082 * typically "do what you mean."
5086 gtk_window_set_gravity (GtkWindow *window,
5089 g_return_if_fail (GTK_IS_WINDOW (window));
5091 if (gravity != window->gravity)
5093 window->gravity = gravity;
5095 /* gtk_window_move_resize() will adapt gravity
5097 gtk_widget_queue_resize (GTK_WIDGET (window));
5102 * gtk_window_get_gravity:
5103 * @window: a #GtkWindow
5105 * Gets the value set by gtk_window_set_gravity().
5107 * Return value: window gravity
5110 gtk_window_get_gravity (GtkWindow *window)
5112 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5114 return window->gravity;
5118 * gtk_window_begin_resize_drag:
5119 * @window: a #GtkWindow
5120 * @button: mouse button that initiated the drag
5121 * @edge: position of the resize control
5122 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5123 * @root_y: Y position where the user clicked to initiate the drag
5124 * @timestamp: timestamp from the click event that initiated the drag
5126 * Starts resizing a window. This function is used if an application
5127 * has window resizing controls. When GDK can support it, the resize
5128 * will be done using the standard mechanism for the <link
5129 * linkend="gtk-X11-arch">window manager</link> or windowing
5130 * system. Otherwise, GDK will try to emulate window resizing,
5131 * potentially not all that well, depending on the windowing system.
5135 gtk_window_begin_resize_drag (GtkWindow *window,
5143 GdkWindow *toplevel;
5145 g_return_if_fail (GTK_IS_WINDOW (window));
5146 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5148 widget = GTK_WIDGET (window);
5151 toplevel = window->frame;
5153 toplevel = widget->window;
5155 gdk_window_begin_resize_drag (toplevel,
5162 * gtk_window_get_frame_dimensions:
5163 * @window: a #GtkWindow
5164 * @left: location to store the width of the frame at the left, or %NULL
5165 * @top: location to store the height of the frame at the top, or %NULL
5166 * @right: location to store the width of the frame at the returns, or %NULL
5167 * @bottom: location to store the height of the frame at the bottom, or %NULL
5169 * (Note: this is a special-purpose function intended for the
5170 * framebuffer port; see gtk_window_set_has_frame(). It will not
5171 * return the size of the window border drawn by the <link
5172 * linkend="gtk-X11-arch">window manager</link>, which is the normal
5173 * case when using a windowing system. See
5174 * gdk_window_get_frame_extents() to get the standard window border
5177 * Retrieves the dimensions of the frame window for this toplevel.
5178 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5181 gtk_window_get_frame_dimensions (GtkWindow *window,
5187 g_return_if_fail (GTK_IS_WINDOW (window));
5190 *left = window->frame_left;
5192 *top = window->frame_top;
5194 *right = window->frame_right;
5196 *bottom = window->frame_bottom;
5200 * gtk_window_begin_move_drag:
5201 * @window: a #GtkWindow
5202 * @button: mouse button that initiated the drag
5203 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5204 * @root_y: Y position where the user clicked to initiate the drag
5205 * @timestamp: timestamp from the click event that initiated the drag
5207 * Starts moving a window. This function is used if an application has
5208 * window movement grips. When GDK can support it, the window movement
5209 * will be done using the standard mechanism for the <link
5210 * linkend="gtk-X11-arch">window manager</link> or windowing
5211 * system. Otherwise, GDK will try to emulate window movement,
5212 * potentially not all that well, depending on the windowing system.
5216 gtk_window_begin_move_drag (GtkWindow *window,
5223 GdkWindow *toplevel;
5225 g_return_if_fail (GTK_IS_WINDOW (window));
5226 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5228 widget = GTK_WIDGET (window);
5231 toplevel = window->frame;
5233 toplevel = widget->window;
5235 gdk_window_begin_move_drag (toplevel,
5243 gtk_window_group_class_init (GtkWindowGroupClass *klass)
5248 gtk_window_group_get_type (void)
5250 static GtkType window_group_type = 0;
5252 if (!window_group_type)
5254 static const GTypeInfo window_group_info =
5256 sizeof (GtkWindowGroupClass),
5257 NULL, /* base_init */
5258 NULL, /* base_finalize */
5259 (GClassInitFunc) gtk_window_group_class_init,
5260 NULL, /* class_finalize */
5261 NULL, /* class_data */
5262 sizeof (GtkWindowGroup),
5263 16, /* n_preallocs */
5264 (GInstanceInitFunc) NULL,
5267 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
5270 return window_group_type;
5274 * gtk_window_group_new:
5276 * Creates a new #GtkWindowGroup object. Grabs added with
5277 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
5279 * Return value: a new #GtkWindowGroup.
5282 gtk_window_group_new (void)
5284 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
5288 window_group_cleanup_grabs (GtkWindowGroup *group,
5292 GSList *to_remove = NULL;
5294 tmp_list = group->grabs;
5297 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
5298 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
5299 tmp_list = tmp_list->next;
5304 gtk_grab_remove (to_remove->data);
5305 g_object_unref (to_remove->data);
5306 to_remove = g_slist_delete_link (to_remove, to_remove);
5311 * gtk_window_group_add_window:
5312 * @window_group: a #GtkWindowGroup
5313 * @window: the #GtkWindow to add
5315 * Adds a window to a #GtkWindowGroup.
5318 gtk_window_group_add_window (GtkWindowGroup *window_group,
5321 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5322 g_return_if_fail (GTK_IS_WINDOW (window));
5324 if (window->group != window_group)
5326 g_object_ref (window);
5327 g_object_ref (window_group);
5330 gtk_window_group_remove_window (window->group, window);
5332 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
5334 window->group = window_group;
5336 g_object_unref (window);
5341 * gtk_window_group_remove_window:
5342 * @window_group: a #GtkWindowGroup
5343 * @window: the #GtkWindow to remove
5345 * Removes a window from a #GtkWindowGroup.
5348 gtk_window_group_remove_window (GtkWindowGroup *window_group,
5351 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5352 g_return_if_fail (GTK_IS_WIDGET (window));
5353 g_return_if_fail (window->group == window_group);
5355 g_object_ref (window);
5357 window_group_cleanup_grabs (window_group, window);
5358 window->group = NULL;
5360 g_object_unref (G_OBJECT (window_group));
5361 g_object_unref (window);
5364 /* Return the group for the window or the default group
5367 _gtk_window_get_group (GtkWindow *window)
5369 if (window && window->group)
5370 return window->group;
5373 static GtkWindowGroup *default_group = NULL;
5376 default_group = gtk_window_group_new ();
5378 return default_group;
5384 Derived from XParseGeometry() in XFree86
5386 Copyright 1985, 1986, 1987,1998 The Open Group
5388 All Rights Reserved.
5390 The above copyright notice and this permission notice shall be included
5391 in all copies or substantial portions of the Software.
5393 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5394 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5395 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
5396 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
5397 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
5398 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
5399 OTHER DEALINGS IN THE SOFTWARE.
5401 Except as contained in this notice, the name of The Open Group shall
5402 not be used in advertising or otherwise to promote the sale, use or
5403 other dealings in this Software without prior written authorization
5404 from The Open Group.
5409 * XParseGeometry parses strings of the form
5410 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5411 * width, height, xoffset, and yoffset are unsigned integers.
5412 * Example: "=80x24+300-49"
5413 * The equal sign is optional.
5414 * It returns a bitmask that indicates which of the four values
5415 * were actually found in the string. For each value found,
5416 * the corresponding argument is updated; for each value
5417 * not found, the corresponding argument is left unchanged.
5420 /* The following code is from Xlib, and is minimally modified, so we
5421 * can track any upstream changes if required. Don't change this
5422 * code. Or if you do, put in a huge comment marking which thing
5427 read_int (gchar *string,
5435 else if (*string == '-')
5441 for (; (*string >= '0') && (*string <= '9'); string++)
5443 result = (result * 10) + (*string - '0');
5455 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
5456 * value (x, y, width, height) was found in the parsed string.
5458 #define NoValue 0x0000
5459 #define XValue 0x0001
5460 #define YValue 0x0002
5461 #define WidthValue 0x0004
5462 #define HeightValue 0x0008
5463 #define AllValues 0x000F
5464 #define XNegative 0x0010
5465 #define YNegative 0x0020
5467 /* Try not to reformat/modify, so we can compare/sync with X sources */
5469 gtk_XParseGeometry (const char *string,
5472 unsigned int *width,
5473 unsigned int *height)
5477 unsigned int tempWidth, tempHeight;
5479 char *nextCharacter;
5481 /* These initializations are just to silence gcc */
5487 if ( (string == NULL) || (*string == '\0')) return(mask);
5489 string++; /* ignore possible '=' at beg of geometry spec */
5491 strind = (char *)string;
5492 if (*strind != '+' && *strind != '-' && *strind != 'x') {
5493 tempWidth = read_int(strind, &nextCharacter);
5494 if (strind == nextCharacter)
5496 strind = nextCharacter;
5500 if (*strind == 'x' || *strind == 'X') {
5502 tempHeight = read_int(strind, &nextCharacter);
5503 if (strind == nextCharacter)
5505 strind = nextCharacter;
5506 mask |= HeightValue;
5509 if ((*strind == '+') || (*strind == '-')) {
5510 if (*strind == '-') {
5512 tempX = -read_int(strind, &nextCharacter);
5513 if (strind == nextCharacter)
5515 strind = nextCharacter;
5521 tempX = read_int(strind, &nextCharacter);
5522 if (strind == nextCharacter)
5524 strind = nextCharacter;
5527 if ((*strind == '+') || (*strind == '-')) {
5528 if (*strind == '-') {
5530 tempY = -read_int(strind, &nextCharacter);
5531 if (strind == nextCharacter)
5533 strind = nextCharacter;
5540 tempY = read_int(strind, &nextCharacter);
5541 if (strind == nextCharacter)
5543 strind = nextCharacter;
5549 /* If strind isn't at the end of the string the it's an invalid
5550 geometry specification. */
5552 if (*strind != '\0') return (0);
5558 if (mask & WidthValue)
5560 if (mask & HeightValue)
5561 *height = tempHeight;
5566 * gtk_window_parse_geometry:
5567 * @window: a #GtkWindow
5568 * @geometry: geometry string
5570 * Parses a standard X Window System geometry string - see the
5571 * manual page for X (type 'man X') for details on this.
5572 * gtk_window_parse_geometry() does work on all GTK+ ports
5573 * including Win32 but is primarily intended for an X environment.
5575 * If either a size or a position can be extracted from the
5576 * geometry string, gtk_window_parse_geometry() returns %TRUE
5577 * and calls gtk_window_set_default_size() and/or gtk_window_move()
5578 * to resize/move the window.
5580 * If gtk_window_parse_geometry() returns %TRUE, it will also
5581 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
5582 * indicating to the window manager that the size/position of
5583 * the window was user-specified. This causes most window
5584 * managers to honor the geometry.
5586 * Return value: %TRUE if string was parsed successfully
5589 gtk_window_parse_geometry (GtkWindow *window,
5590 const gchar *geometry)
5595 gboolean size_set, pos_set;
5597 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5598 g_return_val_if_fail (geometry != NULL, FALSE);
5600 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
5602 if ((result & WidthValue) == 0 ||
5605 if ((result & HeightValue) == 0 ||
5610 if ((result & WidthValue) || (result & HeightValue))
5612 gtk_window_set_default_size (window, w, h);
5616 gtk_window_get_size (window, &w, &h);
5618 grav = GDK_GRAVITY_NORTH_WEST;
5620 if ((result & XNegative) && (result & YNegative))
5621 grav = GDK_GRAVITY_SOUTH_EAST;
5622 else if (result & XNegative)
5623 grav = GDK_GRAVITY_NORTH_EAST;
5624 else if (result & YNegative)
5625 grav = GDK_GRAVITY_SOUTH_WEST;
5627 if ((result & XValue) == 0)
5630 if ((result & YValue) == 0)
5633 if (grav == GDK_GRAVITY_SOUTH_WEST ||
5634 grav == GDK_GRAVITY_SOUTH_EAST)
5635 y = gdk_screen_height () - h;
5637 if (grav == GDK_GRAVITY_SOUTH_EAST ||
5638 grav == GDK_GRAVITY_NORTH_EAST)
5639 x = gdk_screen_width () - w;
5648 if ((result & XValue) || (result & YValue))
5650 gtk_window_set_gravity (window, grav);
5651 gtk_window_move (window, x, y);
5655 if (size_set || pos_set)
5657 /* Set USSize, USPosition hints */
5658 GtkWindowGeometryInfo *info;
5660 info = gtk_window_get_geometry_info (window, TRUE);
5663 info->mask |= GDK_HINT_USER_POS;
5665 info->mask |= GDK_HINT_USER_SIZE;