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"
67 PROP_DESTROY_WITH_PARENT,
76 GdkPixmap *icon_pixmap;
79 guint using_default_icon : 1;
80 guint using_parent_icon : 1;
84 GdkGeometry geometry; /* Last set of geometry hints we set */
86 GdkRectangle configure_request;
87 } GtkWindowLastGeometryInfo;
89 struct _GtkWindowGeometryInfo
91 /* Properties that the app has set on the window
93 GdkGeometry geometry; /* Geometry hints */
95 GtkWidget *widget; /* subwidget to which hints apply */
96 /* from last gtk_window_resize () - if > 0, indicates that
97 * we should resize to this size.
102 /* From last gtk_window_move () prior to mapping -
103 * only used if initial_pos_set
108 /* Default size - used only the FIRST time we map a window,
113 /* whether to use initial_x, initial_y */
114 guint initial_pos_set : 1;
115 /* CENTER_ALWAYS or other position constraint changed since
116 * we sent the last configure request.
118 guint position_constraints_changed : 1;
120 GtkWindowLastGeometryInfo last;
131 static void gtk_window_class_init (GtkWindowClass *klass);
132 static void gtk_window_init (GtkWindow *window);
133 static void gtk_window_dispose (GObject *object);
134 static void gtk_window_destroy (GtkObject *object);
135 static void gtk_window_finalize (GObject *object);
136 static void gtk_window_show (GtkWidget *widget);
137 static void gtk_window_hide (GtkWidget *widget);
138 static void gtk_window_map (GtkWidget *widget);
139 static void gtk_window_unmap (GtkWidget *widget);
140 static void gtk_window_realize (GtkWidget *widget);
141 static void gtk_window_unrealize (GtkWidget *widget);
142 static void gtk_window_size_request (GtkWidget *widget,
143 GtkRequisition *requisition);
144 static void gtk_window_size_allocate (GtkWidget *widget,
145 GtkAllocation *allocation);
146 static gint gtk_window_event (GtkWidget *widget,
148 static gboolean gtk_window_frame_event (GtkWindow *window,
150 static gint gtk_window_configure_event (GtkWidget *widget,
151 GdkEventConfigure *event);
152 static gint gtk_window_key_press_event (GtkWidget *widget,
154 static gint gtk_window_key_release_event (GtkWidget *widget,
156 static gint gtk_window_enter_notify_event (GtkWidget *widget,
157 GdkEventCrossing *event);
158 static gint gtk_window_leave_notify_event (GtkWidget *widget,
159 GdkEventCrossing *event);
160 static gint gtk_window_focus_in_event (GtkWidget *widget,
161 GdkEventFocus *event);
162 static gint gtk_window_focus_out_event (GtkWidget *widget,
163 GdkEventFocus *event);
164 static gint gtk_window_client_event (GtkWidget *widget,
165 GdkEventClient *event);
166 static void gtk_window_check_resize (GtkContainer *container);
167 static gint gtk_window_focus (GtkWidget *widget,
168 GtkDirectionType direction);
169 static void gtk_window_real_set_focus (GtkWindow *window,
172 static void gtk_window_real_activate_default (GtkWindow *window);
173 static void gtk_window_real_activate_focus (GtkWindow *window);
174 static void gtk_window_move_focus (GtkWindow *window,
175 GtkDirectionType dir);
176 static void gtk_window_read_rcfiles (GtkWidget *widget,
177 GdkEventClient *event);
178 static void gtk_window_paint (GtkWidget *widget,
180 static gint gtk_window_expose (GtkWidget *widget,
181 GdkEventExpose *event);
182 static void gtk_window_unset_transient_for (GtkWindow *window);
183 static void gtk_window_transient_parent_realized (GtkWidget *parent,
185 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
188 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
191 static void gtk_window_move_resize (GtkWindow *window);
192 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
194 GdkGeometry *geometry_b,
196 static void gtk_window_constrain_size (GtkWindow *window,
197 GdkGeometry *geometry,
203 static void gtk_window_constrain_position (GtkWindow *window,
208 static void gtk_window_compute_hints (GtkWindow *window,
209 GdkGeometry *new_geometry,
211 static void gtk_window_compute_configure_request (GtkWindow *window,
212 GdkRectangle *request,
213 GdkGeometry *geometry,
216 static void gtk_window_set_default_size_internal (GtkWindow *window,
217 gboolean change_width,
219 gboolean change_height,
222 static void gtk_window_realize_icon (GtkWindow *window);
223 static void gtk_window_unrealize_icon (GtkWindow *window);
224 static void gtk_window_notify_accels_changed (GtkWindow *window);
226 static GSList *toplevel_list = NULL;
227 static GHashTable *mnemonic_hash_table = NULL;
228 static GtkBinClass *parent_class = NULL;
229 static guint window_signals[LAST_SIGNAL] = { 0 };
230 static GList *default_icon_list = NULL;
231 /* FIXME need to be per-screen */
232 static GdkPixmap *default_icon_pixmap = NULL;
233 static GdkPixmap *default_icon_mask = NULL;
235 static void gtk_window_set_property (GObject *object,
239 static void gtk_window_get_property (GObject *object,
246 mnemonic_hash (gconstpointer key)
248 const GtkWindowMnemonic *k;
251 k = (GtkWindowMnemonic *)key;
253 h = (gulong) k->window;
254 h ^= k->keyval << 16;
255 h ^= k->keyval >> 16;
261 mnemonic_equal (gconstpointer a, gconstpointer b)
263 const GtkWindowMnemonic *ka;
264 const GtkWindowMnemonic *kb;
266 ka = (GtkWindowMnemonic *)a;
267 kb = (GtkWindowMnemonic *)b;
270 (ka->window == kb->window) &&
271 (ka->keyval == kb->keyval);
275 gtk_window_get_type (void)
277 static GtkType window_type = 0;
281 static const GtkTypeInfo window_info =
285 sizeof (GtkWindowClass),
286 (GtkClassInitFunc) gtk_window_class_init,
287 (GtkObjectInitFunc) gtk_window_init,
288 /* reserved_1 */ NULL,
289 /* reserved_2 */ NULL,
290 (GtkClassInitFunc) NULL,
293 window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
300 gtk_window_class_init (GtkWindowClass *klass)
302 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
303 GtkObjectClass *object_class;
304 GtkWidgetClass *widget_class;
305 GtkContainerClass *container_class;
306 GtkBindingSet *binding_set;
308 object_class = (GtkObjectClass*) klass;
309 widget_class = (GtkWidgetClass*) klass;
310 container_class = (GtkContainerClass*) klass;
312 parent_class = gtk_type_class (gtk_bin_get_type ());
314 mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
316 gobject_class->dispose = gtk_window_dispose;
317 gobject_class->finalize = gtk_window_finalize;
319 gobject_class->set_property = gtk_window_set_property;
320 gobject_class->get_property = gtk_window_get_property;
322 object_class->destroy = gtk_window_destroy;
324 widget_class->show = gtk_window_show;
325 widget_class->hide = gtk_window_hide;
326 widget_class->map = gtk_window_map;
327 widget_class->unmap = gtk_window_unmap;
328 widget_class->realize = gtk_window_realize;
329 widget_class->unrealize = gtk_window_unrealize;
330 widget_class->size_request = gtk_window_size_request;
331 widget_class->size_allocate = gtk_window_size_allocate;
332 widget_class->configure_event = gtk_window_configure_event;
333 widget_class->key_press_event = gtk_window_key_press_event;
334 widget_class->key_release_event = gtk_window_key_release_event;
335 widget_class->enter_notify_event = gtk_window_enter_notify_event;
336 widget_class->leave_notify_event = gtk_window_leave_notify_event;
337 widget_class->focus_in_event = gtk_window_focus_in_event;
338 widget_class->focus_out_event = gtk_window_focus_out_event;
339 widget_class->client_event = gtk_window_client_event;
340 widget_class->focus = gtk_window_focus;
342 widget_class->expose_event = gtk_window_expose;
344 container_class->check_resize = gtk_window_check_resize;
346 klass->set_focus = gtk_window_real_set_focus;
347 klass->frame_event = gtk_window_frame_event;
349 klass->activate_default = gtk_window_real_activate_default;
350 klass->activate_focus = gtk_window_real_activate_focus;
351 klass->move_focus = gtk_window_move_focus;
352 klass->accels_changed = NULL;
355 g_object_class_install_property (gobject_class,
357 g_param_spec_enum ("type",
359 _("The type of the window"),
360 GTK_TYPE_WINDOW_TYPE,
362 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
365 g_object_class_install_property (gobject_class,
367 g_param_spec_string ("title",
369 _("The title of the window"),
373 g_object_class_install_property (gobject_class,
375 g_param_spec_boolean ("allow_shrink",
377 /* xgettext:no-c-format */
378 _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea."),
382 g_object_class_install_property (gobject_class,
384 g_param_spec_boolean ("allow_grow",
386 _("If TRUE, users can expand the window beyond its minimum size."),
390 g_object_class_install_property (gobject_class,
392 g_param_spec_boolean ("resizable",
394 _("If TRUE, users can resize the window."),
398 g_object_class_install_property (gobject_class,
400 g_param_spec_boolean ("modal",
402 _("If TRUE, the window is modal (other windows are not usable while this one is up)."),
406 g_object_class_install_property (gobject_class,
408 g_param_spec_enum ("window_position",
409 _("Window Position"),
410 _("The initial position of the window."),
411 GTK_TYPE_WINDOW_POSITION,
415 g_object_class_install_property (gobject_class,
417 g_param_spec_int ("default_width",
419 _("The default width of the window, used when initially showing the window."),
425 g_object_class_install_property (gobject_class,
427 g_param_spec_int ("default_height",
429 _("The default height of the window, used when initially showing the window."),
435 g_object_class_install_property (gobject_class,
436 PROP_DESTROY_WITH_PARENT,
437 g_param_spec_boolean ("destroy_with_parent",
438 _("Destroy with Parent"),
439 _("If this window should be destroyed when the parent is destroyed"),
443 g_object_class_install_property (gobject_class,
445 g_param_spec_object ("icon",
447 _("Icon for this window"),
451 window_signals[SET_FOCUS] =
452 g_signal_new ("set_focus",
453 G_TYPE_FROM_CLASS (object_class),
455 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
457 gtk_marshal_VOID__OBJECT,
461 window_signals[FRAME_EVENT] =
462 g_signal_new ("frame_event",
463 G_TYPE_FROM_CLASS(object_class),
465 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
466 _gtk_boolean_handled_accumulator, NULL,
467 gtk_marshal_BOOLEAN__BOXED,
471 window_signals[ACTIVATE_FOCUS] =
472 g_signal_new ("activate_focus",
473 G_OBJECT_CLASS_TYPE (object_class),
474 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
475 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_focus),
477 gtk_marshal_VOID__VOID,
481 window_signals[ACTIVATE_DEFAULT] =
482 g_signal_new ("activate_default",
483 G_OBJECT_CLASS_TYPE (object_class),
484 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
485 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_default),
487 gtk_marshal_VOID__VOID,
491 window_signals[MOVE_FOCUS] =
492 g_signal_new ("move_focus",
493 G_OBJECT_CLASS_TYPE (object_class),
494 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
495 GTK_SIGNAL_OFFSET (GtkWindowClass, move_focus),
497 gtk_marshal_VOID__ENUM,
500 GTK_TYPE_DIRECTION_TYPE);
502 window_signals[ACCELS_CHANGED] =
503 g_signal_new ("accels_changed",
504 G_OBJECT_CLASS_TYPE (object_class),
506 GTK_SIGNAL_OFFSET (GtkWindowClass, accels_changed),
508 gtk_marshal_VOID__VOID,
516 binding_set = gtk_binding_set_by_class (klass);
518 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
519 "activate_focus", 0);
520 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
521 "activate_focus", 0);
523 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
524 "activate_default", 0);
526 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
527 "activate_default", 0);
529 gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
531 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
532 gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
534 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
536 gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
538 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
539 gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
541 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
543 gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
545 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);
546 gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
548 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);
550 gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
552 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);
553 gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
555 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);
557 gtk_binding_entry_add_signal (binding_set, GDK_Tab, 0,
559 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
560 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, 0,
562 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
563 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, 0,
565 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
567 gtk_binding_entry_add_signal (binding_set, GDK_Tab, GDK_SHIFT_MASK,
569 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
570 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, GDK_SHIFT_MASK,
572 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
573 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, GDK_SHIFT_MASK,
575 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
579 gtk_window_init (GtkWindow *window)
581 GdkColormap *colormap;
583 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
584 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
586 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
588 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
590 window->title = NULL;
591 window->wmclass_name = g_strdup (g_get_prgname ());
592 window->wmclass_class = g_strdup (gdk_get_program_class ());
593 window->wm_role = NULL;
594 window->geometry_info = NULL;
595 window->type = GTK_WINDOW_TOPLEVEL;
596 window->focus_widget = NULL;
597 window->default_widget = NULL;
598 window->configure_request_count = 0;
599 window->allow_shrink = FALSE;
600 window->allow_grow = TRUE;
601 window->configure_notify_received = FALSE;
602 window->position = GTK_WIN_POS_NONE;
603 window->need_default_size = TRUE;
604 window->need_default_position = TRUE;
605 window->modal = FALSE;
606 window->frame = NULL;
607 window->has_frame = FALSE;
608 window->frame_left = 0;
609 window->frame_right = 0;
610 window->frame_top = 0;
611 window->frame_bottom = 0;
612 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
613 window->gravity = GDK_GRAVITY_NORTH_WEST;
614 window->decorated = TRUE;
615 window->mnemonic_modifier = GDK_MOD1_MASK;
617 colormap = _gtk_widget_peek_colormap ();
619 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
621 gtk_widget_ref (GTK_WIDGET (window));
622 gtk_object_sink (GTK_OBJECT (window));
623 window->has_user_ref_count = TRUE;
624 toplevel_list = g_slist_prepend (toplevel_list, window);
626 gtk_decorated_window_init (window);
628 gtk_signal_connect (GTK_OBJECT (window),
630 GTK_SIGNAL_FUNC (gtk_window_event),
635 gtk_window_set_property (GObject *object,
642 window = GTK_WINDOW (object);
647 window->type = g_value_get_enum (value);
650 gtk_window_set_title (window, g_value_get_string (value));
652 case PROP_ALLOW_SHRINK:
653 window->allow_shrink = g_value_get_boolean (value);
654 gtk_widget_queue_resize (GTK_WIDGET (window));
656 case PROP_ALLOW_GROW:
657 window->allow_grow = g_value_get_boolean (value);
658 gtk_widget_queue_resize (GTK_WIDGET (window));
659 g_object_notify (G_OBJECT (window), "resizable");
662 window->allow_grow = g_value_get_boolean (value);
663 gtk_widget_queue_resize (GTK_WIDGET (window));
664 g_object_notify (G_OBJECT (window), "allow_grow");
667 gtk_window_set_modal (window, g_value_get_boolean (value));
670 gtk_window_set_position (window, g_value_get_enum (value));
672 case PROP_DEFAULT_WIDTH:
673 gtk_window_set_default_size_internal (window,
674 TRUE, g_value_get_int (value),
677 case PROP_DEFAULT_HEIGHT:
678 gtk_window_set_default_size_internal (window,
680 TRUE, g_value_get_int (value));
682 case PROP_DESTROY_WITH_PARENT:
683 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
686 gtk_window_set_icon (window,
687 g_value_get_object (value));
696 gtk_window_get_property (GObject *object,
703 window = GTK_WINDOW (object);
707 GtkWindowGeometryInfo *info;
709 g_value_set_enum (value, window->type);
712 g_value_set_string (value, window->title);
714 case PROP_ALLOW_SHRINK:
715 g_value_set_boolean (value, window->allow_shrink);
717 case PROP_ALLOW_GROW:
718 g_value_set_boolean (value, window->allow_grow);
721 g_value_set_boolean (value, window->allow_grow);
724 g_value_set_boolean (value, window->modal);
727 g_value_set_enum (value, window->position);
729 case PROP_DEFAULT_WIDTH:
730 info = gtk_window_get_geometry_info (window, FALSE);
732 g_value_set_int (value, -1);
734 g_value_set_int (value, info->default_width);
736 case PROP_DEFAULT_HEIGHT:
737 info = gtk_window_get_geometry_info (window, FALSE);
739 g_value_set_int (value, -1);
741 g_value_set_int (value, info->default_height);
743 case PROP_DESTROY_WITH_PARENT:
744 g_value_set_boolean (value, window->destroy_with_parent);
747 g_value_set_object (value, gtk_window_get_icon (window));
750 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
757 * @type: type of window
759 * Creates a new #GtkWindow, which is a toplevel window that can
760 * contain other widgets. Nearly always, the type of the window should
761 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
762 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
763 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
764 * dialogs, though in some other toolkits dialogs are called "popups".
765 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
766 * Popup windows are not controlled by the window manager.
768 * If you simply want an undecorated window (no window borders), use
769 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
771 * Return value: a new #GtkWindow.
774 gtk_window_new (GtkWindowType type)
778 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
780 window = gtk_type_new (GTK_TYPE_WINDOW);
784 return GTK_WIDGET (window);
788 * gtk_window_set_title:
789 * @window: a #GtkWindow
790 * @title: title of the window
792 * Sets the title of the #GtkWindow. The title of a window will be displayed in
793 * its title bar; on the X Window System, the title bar is rendered by the
794 * window manager, so exactly how the title appears to users may vary according
795 * to a user's exact configuration. The title should help a user distinguish
796 * this window from other windows they may have open. A good title might
797 * include the application name and current document filename, for example.
801 gtk_window_set_title (GtkWindow *window,
804 g_return_if_fail (GTK_IS_WINDOW (window));
807 g_free (window->title);
808 window->title = g_strdup (title);
810 if (GTK_WIDGET_REALIZED (window))
812 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
814 gtk_decorated_window_set_title (window, title);
817 g_object_notify (G_OBJECT (window), "title");
821 * gtk_window_get_title:
822 * @window: a #GtkWindow
824 * Retrieves the title of the window. See gtk_window_set_title().
826 * Return value: the title of the window, or %NULL if none has
827 * been set explicitely. The returned string is owned by the widget
828 * and must not be modified or freed.
830 G_CONST_RETURN gchar *
831 gtk_window_get_title (GtkWindow *window)
833 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
835 return window->title;
839 * gtk_window_set_wmclass:
840 * @window: a #GtkWindow
841 * @wmclass_name: window name hint
842 * @wmclass_class: window class hint
844 * Don't use this function. It sets the X Window System "class" and
845 * "name" hints for a window. According to the ICCCM, you should
846 * always set these to the same value for all windows in an
847 * application, and GTK sets them to that value by default, so calling
848 * this function is sort of pointless. However, you may want to call
849 * gtk_window_set_role() on each window in your application, for the
850 * benefit of the session manager. Setting the role allows the window
851 * manager to restore window positions when loading a saved session.
855 gtk_window_set_wmclass (GtkWindow *window,
856 const gchar *wmclass_name,
857 const gchar *wmclass_class)
859 g_return_if_fail (GTK_IS_WINDOW (window));
861 g_free (window->wmclass_name);
862 window->wmclass_name = g_strdup (wmclass_name);
864 g_free (window->wmclass_class);
865 window->wmclass_class = g_strdup (wmclass_class);
867 if (GTK_WIDGET_REALIZED (window))
868 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
872 * gtk_window_set_role:
873 * @window: a #GtkWindow
874 * @role: unique identifier for the window to be used when restoring a session
876 * In combination with the window title, the window role allows a
877 * window manager to identify "the same" window when an application is
878 * restarted. So for example you might set the "toolbox" role on your
879 * app's toolbox window, so that when the user restarts their session,
880 * the window manager can put the toolbox back in the same place.
882 * If a window already has a unique title, you don't need to set the
883 * role, since the WM can use the title to identify the window when
884 * restoring the session.
888 gtk_window_set_role (GtkWindow *window,
891 g_return_if_fail (GTK_IS_WINDOW (window));
893 if (role == window->wm_role)
896 g_free (window->wm_role);
897 window->wm_role = g_strdup (role);
899 if (GTK_WIDGET_REALIZED (window))
900 g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
904 * gtk_window_get_role:
905 * @window: a #GtkWindow
907 * Returns the role of the window. See gtk_window_set_role() for
908 * further explanation.
910 * Return value: the role of the window if set, or %NULL. The
911 * returned is owned by the widget and must not be modified
914 G_CONST_RETURN gchar *
915 gtk_window_get_role (GtkWindow *window)
917 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
919 return window->wm_role;
923 * gtk_window_set_focus:
924 * @window: a #GtkWindow
925 * @focus: widget to be the new focus widget, or %NULL to unset
926 * any focus widget for the toplevel window.
928 * If @focus is not the current focus widget, and is focusable, sets
929 * it as the focus widget for the window. If @focus is %NULL, unsets
930 * the focus widget for this window. To set the focus to a particular
931 * widget in the toplevel, it is usually more convenient to use
932 * gtk_widget_grab_focus() instead of this function.
935 gtk_window_set_focus (GtkWindow *window,
938 g_return_if_fail (GTK_IS_WINDOW (window));
941 g_return_if_fail (GTK_IS_WIDGET (focus));
942 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
946 gtk_widget_grab_focus (focus);
948 _gtk_window_internal_set_focus (window, NULL);
952 _gtk_window_internal_set_focus (GtkWindow *window,
955 g_return_if_fail (GTK_IS_WINDOW (window));
957 if ((window->focus_widget != focus) ||
958 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
959 gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
963 * gtk_window_set_default:
964 * @window: a #GtkWindow
965 * @default_widget: widget to be the default, or %NULL to unset the
966 * default widget for the toplevel.
968 * The default widget is the widget that's activated when the user
969 * presses Enter in a dialog (for example). This function sets or
970 * unsets the default widget for a #GtkWindow about. When setting
971 * (rather than unsetting) the default widget it's generally easier to
972 * call gtk_widget_grab_focus() on the widget. Before making a widget
973 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
974 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
977 gtk_window_set_default (GtkWindow *window,
978 GtkWidget *default_widget)
980 GtkWidget *old_default;
982 g_return_if_fail (GTK_IS_WINDOW (window));
985 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
987 if (window->default_widget != default_widget)
989 GtkWidget *old_default_widget = NULL;
992 g_object_ref (default_widget);
994 if (window->default_widget)
996 old_default_widget = window->default_widget;
998 if (window->focus_widget != window->default_widget ||
999 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1000 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1001 gtk_widget_queue_draw (window->default_widget);
1004 window->default_widget = default_widget;
1006 if (window->default_widget)
1008 if (window->focus_widget == NULL ||
1009 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1010 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1011 gtk_widget_queue_draw (window->default_widget);
1014 if (old_default_widget)
1015 g_object_notify (G_OBJECT (old_default_widget), "has_default");
1019 g_object_notify (G_OBJECT (default_widget), "has_default");
1020 g_object_unref (default_widget);
1026 gtk_window_set_policy (GtkWindow *window,
1027 gboolean allow_shrink,
1028 gboolean allow_grow,
1029 gboolean auto_shrink)
1031 g_return_if_fail (GTK_IS_WINDOW (window));
1033 window->allow_shrink = (allow_shrink != FALSE);
1034 window->allow_grow = (allow_grow != FALSE);
1036 g_object_freeze_notify (G_OBJECT (window));
1037 g_object_notify (G_OBJECT (window), "allow_shrink");
1038 g_object_notify (G_OBJECT (window), "allow_grow");
1039 g_object_notify (G_OBJECT (window), "resizable");
1040 g_object_thaw_notify (G_OBJECT (window));
1042 gtk_widget_queue_resize (GTK_WIDGET (window));
1046 handle_accels_changed (gpointer data)
1050 GDK_THREADS_ENTER ();
1051 window = GTK_WINDOW (data);
1053 if (window->accels_changed_handler)
1055 gtk_idle_remove (window->accels_changed_handler);
1056 window->accels_changed_handler = 0;
1059 g_signal_emit (window, window_signals[ACCELS_CHANGED], 0);
1060 GDK_THREADS_LEAVE ();
1066 gtk_window_notify_accels_changed (GtkWindow *window)
1068 if (!window->accels_changed_handler)
1069 window->accels_changed_handler = gtk_idle_add (handle_accels_changed, window);
1073 * gtk_window_add_accel_group:
1074 * @window: window to attach accelerator group to
1075 * @accel_group: a #GtkAccelGroup
1077 * Associate @accel_group with @window, such that calling
1078 * gtk_accel_groups_activate() on @window will activate accelerators
1082 gtk_window_add_accel_group (GtkWindow *window,
1083 GtkAccelGroup *accel_group)
1085 g_return_if_fail (GTK_IS_WINDOW (window));
1086 g_return_if_fail (accel_group != NULL);
1088 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1089 g_signal_connect_object (accel_group, "accel_changed",
1090 G_CALLBACK (gtk_window_notify_accels_changed),
1091 window, G_CONNECT_SWAPPED);
1095 * gtk_accel_group_detach:
1096 * @accel_group: a #GtkAccelGroup
1097 * @object: a #GObject
1099 * Reverses the effects of gtk_window_add_accel_group().
1102 gtk_window_remove_accel_group (GtkWindow *window,
1103 GtkAccelGroup *accel_group)
1105 g_return_if_fail (GTK_IS_WINDOW (window));
1106 g_return_if_fail (accel_group != NULL);
1108 g_signal_handlers_disconnect_by_func (accel_group,
1109 G_CALLBACK (gtk_window_notify_accels_changed),
1111 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1115 gtk_window_add_mnemonic (GtkWindow *window,
1119 GtkWindowMnemonic key;
1120 GtkWindowMnemonic *mnemonic;
1122 g_return_if_fail (GTK_IS_WINDOW (window));
1123 g_return_if_fail (GTK_IS_WIDGET (target));
1125 key.window = window;
1126 key.keyval = keyval;
1127 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1131 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1132 mnemonic->targets = g_slist_prepend (mnemonic->targets, target);
1136 mnemonic = g_new (GtkWindowMnemonic, 1);
1138 mnemonic->targets = g_slist_prepend (NULL, target);
1139 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1141 gtk_window_notify_accels_changed (window);
1145 gtk_window_remove_mnemonic (GtkWindow *window,
1149 GtkWindowMnemonic key;
1150 GtkWindowMnemonic *mnemonic;
1152 g_return_if_fail (GTK_IS_WINDOW (window));
1153 g_return_if_fail (GTK_IS_WIDGET (target));
1155 key.window = window;
1156 key.keyval = keyval;
1157 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1159 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1161 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1162 if (mnemonic->targets == NULL)
1164 g_hash_table_remove (mnemonic_hash_table, mnemonic);
1167 gtk_window_notify_accels_changed (window);
1171 gtk_window_mnemonic_activate (GtkWindow *window,
1173 GdkModifierType modifier)
1175 GtkWindowMnemonic key;
1176 GtkWindowMnemonic *mnemonic;
1178 GtkWidget *widget, *chosen_widget;
1179 gboolean overloaded;
1181 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1183 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1186 key.window = window;
1187 key.keyval = keyval;
1188 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1194 chosen_widget = NULL;
1195 list = mnemonic->targets;
1198 widget = GTK_WIDGET (list->data);
1200 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1201 GTK_WIDGET_MAPPED (widget))
1209 chosen_widget = widget;
1211 list = g_slist_next (list);
1216 /* For round robin we put the activated entry on
1217 * the end of the list after activation
1219 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1220 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1222 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1228 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1229 GdkModifierType modifier)
1231 g_return_if_fail (GTK_IS_WINDOW (window));
1232 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1234 window->mnemonic_modifier = modifier;
1235 gtk_window_notify_accels_changed (window);
1239 * gtk_window_get_mnemonic_modifier:
1240 * @window: a #GtkWindow
1242 * Returns the mnemonic modifier for this window. See
1243 * gtk_window_set_mnemonic_modifier().
1245 * Return value: the modifier mask used to activate
1246 * mnemonics on this window.
1249 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1251 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1253 return window->mnemonic_modifier;
1257 gtk_window_set_position (GtkWindow *window,
1258 GtkWindowPosition position)
1260 g_return_if_fail (GTK_IS_WINDOW (window));
1262 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1263 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1265 GtkWindowGeometryInfo *info;
1267 info = gtk_window_get_geometry_info (window, TRUE);
1269 /* this flag causes us to re-request the CENTER_ALWAYS
1270 * constraint in gtk_window_move_resize(), see
1271 * comment in that function.
1273 info->position_constraints_changed = TRUE;
1275 gtk_widget_queue_resize (GTK_WIDGET (window));
1278 window->position = position;
1280 g_object_notify (G_OBJECT (window), "window_position");
1284 gtk_window_activate_focus (GtkWindow *window)
1286 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1288 if (window->focus_widget)
1290 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1291 gtk_widget_activate (window->focus_widget);
1299 * gtk_window_get_focus:
1300 * @window: a #GtkWindow
1302 * Retrieves the current focused widget within the window.
1303 * Note that this is the widget that would have the focus
1304 * if the toplevel window focused; if the toplevel window
1305 * is not focused the GTK_WIDGET_HAS_FOCUS(widget) will
1306 * not be %TRUE for the widget.
1308 * Return value: the currently focused widget.
1311 gtk_window_get_focus (GtkWindow *window)
1313 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1315 return window->focus_widget;
1319 gtk_window_activate_default (GtkWindow *window)
1321 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1323 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1324 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1326 gtk_widget_activate (window->default_widget);
1329 else if (window->focus_widget)
1331 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1332 gtk_widget_activate (window->focus_widget);
1340 * gtk_window_set_modal:
1341 * @window: a #GtkWindow
1342 * @modal: whether the window is modal
1344 * Sets a window modal or non-modal. Modal windows prevent interaction
1345 * with other windows in the same application. To keep modal dialogs
1346 * on top of main application windows, use
1347 * gtk_window_set_transient_for() to make the dialog transient for the
1348 * parent; most window managers will then disallow lowering the dialog
1354 gtk_window_set_modal (GtkWindow *window,
1357 g_return_if_fail (GTK_IS_WINDOW (window));
1359 window->modal = modal != FALSE;
1361 /* adjust desired modality state */
1362 if (GTK_WIDGET_VISIBLE (window) && window->modal)
1363 gtk_grab_add (GTK_WIDGET (window));
1365 gtk_grab_remove (GTK_WIDGET (window));
1367 g_object_notify (G_OBJECT (window), "modal");
1371 * gtk_window_get_modal:
1372 * @window: a #GtkWindow
1374 * Returns whether the window is modal. See gtk_window_set_modal().
1376 * Return value: %TRUE if the window is set to be modal and
1377 * establishes a grab when shown
1380 gtk_window_get_modal (GtkWindow *window)
1382 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1384 return window->modal;
1388 * gtk_window_list_toplevels:
1390 * Returns a list of all existing toplevel windows. The widgets
1391 * in the list are not individually referenced. If you want
1392 * to iterate through the list and perform actions involving
1393 * callbacks that might destroy the widgets, you MUST call
1394 * g_list_foreach (result, (GFunc)g_object_ref, NULL) first, and
1395 * then unref all the widgets afterwards.
1397 * Return value: list of toplevel widgets
1400 gtk_window_list_toplevels (void)
1405 for (slist = toplevel_list; slist; slist = slist->next)
1406 list = g_list_prepend (list, slist->data);
1412 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1414 GList *embedded_windows;
1416 g_return_if_fail (GTK_IS_WINDOW (window));
1418 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1419 if (embedded_windows)
1420 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1421 g_quark_from_static_string ("gtk-embedded"));
1422 embedded_windows = g_list_prepend (embedded_windows,
1423 GUINT_TO_POINTER (xid));
1425 gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
1428 (GtkDestroyNotify) g_list_free : NULL);
1432 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1434 GList *embedded_windows;
1437 g_return_if_fail (GTK_IS_WINDOW (window));
1439 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1440 if (embedded_windows)
1441 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1442 g_quark_from_static_string ("gtk-embedded"));
1444 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1447 embedded_windows = g_list_remove_link (embedded_windows, node);
1448 g_list_free_1 (node);
1451 gtk_object_set_data_full (GTK_OBJECT (window),
1452 "gtk-embedded", embedded_windows,
1454 (GtkDestroyNotify) g_list_free : NULL);
1458 _gtk_window_reposition (GtkWindow *window,
1462 g_return_if_fail (GTK_IS_WINDOW (window));
1464 gtk_window_move (window, x, y);
1468 gtk_window_dispose (GObject *object)
1472 g_return_if_fail (GTK_IS_WINDOW (object));
1474 window = GTK_WINDOW (object);
1476 gtk_window_set_focus (window, NULL);
1477 gtk_window_set_default (window, NULL);
1479 G_OBJECT_CLASS (parent_class)->dispose (object);
1483 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1485 gtk_widget_destroy (GTK_WIDGET (child));
1489 connect_parent_destroyed (GtkWindow *window)
1491 if (window->transient_parent)
1493 gtk_signal_connect (GTK_OBJECT (window->transient_parent),
1495 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1501 disconnect_parent_destroyed (GtkWindow *window)
1503 if (window->transient_parent)
1505 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1506 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1512 gtk_window_transient_parent_realized (GtkWidget *parent,
1515 if (GTK_WIDGET_REALIZED (window))
1516 gdk_window_set_transient_for (window->window, parent->window);
1520 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1523 if (GTK_WIDGET_REALIZED (window))
1524 gdk_property_delete (window->window,
1525 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1529 gtk_window_unset_transient_for (GtkWindow *window)
1531 if (window->transient_parent)
1533 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1534 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1536 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1537 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1539 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1540 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1541 &window->transient_parent);
1543 if (window->destroy_with_parent)
1544 disconnect_parent_destroyed (window);
1546 window->transient_parent = NULL;
1551 * gtk_window_set_transient_for:
1552 * @window: a #GtkWindow
1553 * @parent: parent window
1555 * Dialog windows should be set transient for the main application
1556 * window they were spawned from. This allows window managers to
1557 * e.g. keep the dialog on top of the main window, or center the
1558 * dialog over the main window. gtk_dialog_new_with_buttons() and
1559 * other convenience functions in GTK+ will sometimes call
1560 * gtk_window_set_transient_for() on your behalf.
1564 gtk_window_set_transient_for (GtkWindow *window,
1567 g_return_if_fail (GTK_IS_WINDOW (window));
1568 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1569 g_return_if_fail (window != parent);
1572 if (window->transient_parent)
1574 if (GTK_WIDGET_REALIZED (window) &&
1575 GTK_WIDGET_REALIZED (window->transient_parent) &&
1576 (!parent || !GTK_WIDGET_REALIZED (parent)))
1577 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1578 GTK_WIDGET (window));
1580 gtk_window_unset_transient_for (window);
1583 window->transient_parent = parent;
1587 gtk_signal_connect (GTK_OBJECT (parent), "destroy",
1588 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1589 &window->transient_parent);
1590 gtk_signal_connect (GTK_OBJECT (parent), "realize",
1591 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1593 gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
1594 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1597 if (window->destroy_with_parent)
1598 connect_parent_destroyed (window);
1600 if (GTK_WIDGET_REALIZED (window) &&
1601 GTK_WIDGET_REALIZED (parent))
1602 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1603 GTK_WIDGET (window));
1608 * gtk_window_get_transient_for:
1609 * @window: a #GtkWindow
1611 * Fetches the transient parent for this window. See
1612 * gtk_window_set_transient_for().
1614 * Return value: the transient parent for this window, or %NULL
1615 * if no transient parent has been set.
1618 gtk_window_get_transient_for (GtkWindow *window)
1620 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1622 return window->transient_parent;
1626 * gtk_window_set_type_hint:
1627 * @window: a #GtkWindow
1628 * @hint: the window type
1630 * By setting the type hint for the window, you allow the window
1631 * manager to decorate and handle the window in a way which is
1632 * suitable to the function of the window in your application.
1634 * This function should be called before the window becomes visible.
1636 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1637 * will sometimes call gtk_window_set_type_hint() on your behalf.
1641 gtk_window_set_type_hint (GtkWindow *window,
1642 GdkWindowTypeHint hint)
1644 g_return_if_fail (GTK_IS_WINDOW (window));
1645 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1646 window->type_hint = hint;
1650 * gtk_window_get_type_hint:
1651 * @window: a #GtkWindow
1653 * Gets the type hint for this window. See gtk_window_set_type_hint().
1655 * Return value: the type hint for @window.
1658 gtk_window_get_type_hint (GtkWindow *window)
1660 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1662 return window->type_hint;
1666 * gtk_window_set_destroy_with_parent:
1667 * @window: a #GtkWindow
1668 * @setting: whether to destroy @window with its transient parent
1670 * If @setting is TRUE, then destroying the transient parent of @window
1671 * will also destroy @window itself. This is useful for dialogs that
1672 * shouldn't persist beyond the lifetime of the main window they're
1673 * associated with, for example.
1676 gtk_window_set_destroy_with_parent (GtkWindow *window,
1679 g_return_if_fail (GTK_IS_WINDOW (window));
1681 if (window->destroy_with_parent == (setting != FALSE))
1684 if (window->destroy_with_parent)
1686 disconnect_parent_destroyed (window);
1690 connect_parent_destroyed (window);
1693 window->destroy_with_parent = setting;
1695 g_object_notify (G_OBJECT (window), "destroy_with_parent");
1699 * gtk_window_get_destroy_with_parent:
1700 * @window: a #GtkWindow
1702 * Returns whether the window will be destroyed with its transient parent. See
1703 * gtk_window_set_destroy_with_parent ().
1705 * Return value: %TRUE if the window will be destroyed with its transient parent.
1708 gtk_window_get_destroy_with_parent (GtkWindow *window)
1710 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1712 return window->destroy_with_parent;
1715 static GtkWindowGeometryInfo*
1716 gtk_window_get_geometry_info (GtkWindow *window,
1719 GtkWindowGeometryInfo *info;
1721 info = window->geometry_info;
1722 if (!info && create)
1724 info = g_new0 (GtkWindowGeometryInfo, 1);
1726 info->default_width = -1;
1727 info->default_height = -1;
1728 info->resize_width = -1;
1729 info->resize_height = -1;
1730 info->initial_x = 0;
1731 info->initial_y = 0;
1732 info->initial_pos_set = FALSE;
1733 info->position_constraints_changed = FALSE;
1734 info->last.configure_request.x = 0;
1735 info->last.configure_request.y = 0;
1736 info->last.configure_request.width = -1;
1737 info->last.configure_request.height = -1;
1738 info->widget = NULL;
1740 window->geometry_info = info;
1747 * gtk_window_set_geometry_hints:
1748 * @window: a #GtkWindow
1749 * @geometry_widget: widget the geometry hints will be applied to
1750 * @geometry: struct containing geometry information
1751 * @geom_mask: mask indicating which struct fields should be paid attention to
1753 * This function sets up hints about how a window can be resized by
1754 * the user. You can set a minimum and maximum size; allowed resize
1755 * increments (e.g. for xterm, you can only resize by the size of a
1756 * character); aspect ratios; and more. See the #GdkGeometry struct.
1760 gtk_window_set_geometry_hints (GtkWindow *window,
1761 GtkWidget *geometry_widget,
1762 GdkGeometry *geometry,
1763 GdkWindowHints geom_mask)
1765 GtkWindowGeometryInfo *info;
1767 g_return_if_fail (window != NULL);
1769 info = gtk_window_get_geometry_info (window, TRUE);
1772 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1773 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1776 info->widget = geometry_widget;
1778 gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
1779 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1783 info->geometry = *geometry;
1785 /* We store gravity in window->gravity not in the hints. */
1786 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
1788 if (geom_mask & GDK_HINT_WIN_GRAVITY)
1790 gtk_window_set_gravity (window, geometry->win_gravity);
1793 gtk_widget_queue_resize (GTK_WIDGET (window));
1797 * gtk_window_set_decorated:
1798 * @window: a #GtkWindow
1799 * @setting: %TRUE to decorate the window
1801 * By default, windows are decorated with a title bar, resize
1802 * controls, etc. Some window managers allow GTK+ to disable these
1803 * decorations, creating a borderless window. If you set the decorated
1804 * property to %FALSE using this function, GTK+ will do its best to
1805 * convince the window manager not to decorate the window.
1809 gtk_window_set_decorated (GtkWindow *window,
1812 g_return_if_fail (GTK_IS_WINDOW (window));
1814 setting = setting != FALSE;
1816 if (setting == window->decorated)
1819 window->decorated = setting;
1821 if (GTK_WIDGET (window)->window)
1823 if (window->decorated)
1824 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1827 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1833 * gtk_window_get_decorated:
1834 * @window: a #GtkWindow
1836 * Returns whether the window has been set to have decorations
1837 * such as a title bar via gtk_window_set_decorated().
1839 * Return value: %TRUE if the window has been set to have decorations
1842 gtk_window_get_decorated (GtkWindow *window)
1844 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
1846 return window->decorated;
1849 static GtkWindowIconInfo*
1850 get_icon_info (GtkWindow *window)
1852 return g_object_get_data (G_OBJECT (window),
1853 "gtk-window-icon-info");
1856 static GtkWindowIconInfo*
1857 ensure_icon_info (GtkWindow *window)
1859 GtkWindowIconInfo *info;
1861 info = get_icon_info (window);
1865 info = g_new0 (GtkWindowIconInfo, 1);
1866 g_object_set_data_full (G_OBJECT (window),
1867 "gtk-window-icon-info",
1876 get_pixmap_and_mask (GtkWindowIconInfo *parent_info,
1877 gboolean is_default_list,
1879 GdkPixmap **pmap_return,
1880 GdkBitmap **mask_return)
1882 GdkPixbuf *best_icon;
1886 *pmap_return = NULL;
1887 *mask_return = NULL;
1889 if (is_default_list &&
1890 default_icon_pixmap != NULL)
1892 /* Use shared icon pixmap (eventually will be stored on the
1895 if (default_icon_pixmap)
1896 g_object_ref (G_OBJECT (default_icon_pixmap));
1897 if (default_icon_mask)
1898 g_object_ref (G_OBJECT (default_icon_mask));
1900 *pmap_return = default_icon_pixmap;
1901 *mask_return = default_icon_mask;
1903 else if (parent_info && parent_info->icon_pixmap)
1905 if (parent_info->icon_pixmap)
1906 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1907 if (parent_info->icon_mask)
1908 g_object_ref (G_OBJECT (parent_info->icon_mask));
1910 *pmap_return = parent_info->icon_pixmap;
1911 *mask_return = parent_info->icon_mask;
1915 #define IDEAL_SIZE 48
1917 best_size = G_MAXINT;
1919 tmp_list = icon_list;
1920 while (tmp_list != NULL)
1922 GdkPixbuf *pixbuf = tmp_list->data;
1925 /* average width and height - if someone passes in a rectangular
1926 * icon they deserve what they get.
1928 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
1931 if (best_icon == NULL)
1938 /* icon is better if it's 32 pixels or larger, and closer to
1939 * the ideal size than the current best.
1942 (ABS (best_size - IDEAL_SIZE) <
1943 ABS (this - IDEAL_SIZE)))
1950 tmp_list = tmp_list->next;
1954 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
1955 gdk_colormap_get_system (),
1960 /* Save pmap/mask for others to use if appropriate */
1963 parent_info->icon_pixmap = *pmap_return;
1964 parent_info->icon_mask = *mask_return;
1966 if (parent_info->icon_pixmap)
1967 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1968 if (parent_info->icon_mask)
1969 g_object_ref (G_OBJECT (parent_info->icon_mask));
1971 else if (is_default_list)
1973 default_icon_pixmap = *pmap_return;
1974 default_icon_mask = *mask_return;
1976 if (default_icon_pixmap)
1977 g_object_add_weak_pointer (G_OBJECT (default_icon_pixmap),
1978 (gpointer*)&default_icon_pixmap);
1979 if (default_icon_mask)
1980 g_object_add_weak_pointer (G_OBJECT (default_icon_mask),
1981 (gpointer*)&default_icon_mask);
1987 gtk_window_realize_icon (GtkWindow *window)
1990 GtkWindowIconInfo *info;
1993 widget = GTK_WIDGET (window);
1995 g_return_if_fail (widget->window != NULL);
1997 /* no point setting an icon on override-redirect */
1998 if (window->type == GTK_WINDOW_POPUP)
2003 info = ensure_icon_info (window);
2008 g_return_if_fail (info->icon_pixmap == NULL);
2009 g_return_if_fail (info->icon_mask == NULL);
2011 info->using_default_icon = FALSE;
2012 info->using_parent_icon = FALSE;
2014 icon_list = info->icon_list;
2016 /* Inherit from transient parent */
2017 if (icon_list == NULL && window->transient_parent)
2019 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2021 info->using_parent_icon = TRUE;
2024 /* Inherit from default */
2025 if (icon_list == NULL)
2027 icon_list = default_icon_list;
2029 info->using_default_icon = TRUE;
2032 gdk_window_set_icon_list (widget->window, icon_list);
2034 get_pixmap_and_mask (info->using_parent_icon ?
2035 ensure_icon_info (window->transient_parent) : NULL,
2036 info->using_default_icon,
2041 /* This is a slight ICCCM violation since it's a color pixmap not
2042 * a bitmap, but everyone does it.
2044 gdk_window_set_icon (widget->window,
2049 info->realized = TRUE;
2053 gtk_window_unrealize_icon (GtkWindow *window)
2055 GtkWindowIconInfo *info;
2058 widget = GTK_WIDGET (window);
2060 info = get_icon_info (window);
2065 if (info->icon_pixmap)
2066 g_object_unref (G_OBJECT (info->icon_pixmap));
2068 if (info->icon_mask)
2069 g_object_unref (G_OBJECT (info->icon_mask));
2071 info->icon_pixmap = NULL;
2072 info->icon_mask = NULL;
2074 /* We don't clear the properties on the window, just figure the
2075 * window is going away.
2078 info->realized = FALSE;
2082 * gtk_window_set_icon_list:
2083 * @window: a #GtkWindow
2084 * @list: list of #GdkPixbuf
2086 * Sets up the icon representing a #GtkWindow. The icon is used when
2087 * the window is minimized (also known as iconified). Some window
2088 * managers or desktop environments may also place it in the window
2089 * frame, or display it in other contexts.
2091 * gtk_window_set_icon_list() allows you to pass in the same icon in
2092 * several hand-drawn sizes. The list should contain the natural sizes
2093 * your icon is available in; that is, don't scale the image before
2094 * passing it to GTK+. Scaling is postponed until the last minute,
2095 * when the desired final size is known, to allow best quality.
2097 * By passing several sizes, you may improve the final image quality
2098 * of the icon, by reducing or eliminating automatic image scaling.
2100 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2101 * larger images (64x64, 128x128) if you have them.
2103 * See also gtk_window_set_default_icon_list() to set the icon
2104 * for all windows in your application in one go.
2106 * Note that transient windows (those who have been set transient for another
2107 * window using gtk_window_set_transient_for()) will inherit their
2108 * icon from their transient parent. So there's no need to explicitly
2109 * set the icon on transient windows.
2112 gtk_window_set_icon_list (GtkWindow *window,
2115 GtkWindowIconInfo *info;
2117 g_return_if_fail (GTK_IS_WINDOW (window));
2119 info = ensure_icon_info (window);
2121 if (info->icon_list == list) /* check for NULL mostly */
2124 g_list_foreach (info->icon_list,
2125 (GFunc) g_object_unref, NULL);
2127 g_list_free (info->icon_list);
2129 info->icon_list = g_list_copy (list);
2130 g_list_foreach (info->icon_list,
2131 (GFunc) g_object_ref, NULL);
2133 g_object_notify (G_OBJECT (window), "icon");
2135 gtk_window_unrealize_icon (window);
2137 if (GTK_WIDGET_REALIZED (window))
2138 gtk_window_realize_icon (window);
2140 /* We could try to update our transient children, but I don't think
2141 * it's really worth it. If we did it, the best way would probably
2142 * be to have children connect to notify::icon_list
2147 * gtk_window_get_icon_list:
2148 * @window: a #GtkWindow
2150 * Retrieves the list of icons set by gtk_window_set_icon_list().
2151 * The list is copied, but the reference count on each
2152 * member won't be incremented.
2154 * Return value: copy of window's icon list
2157 gtk_window_get_icon_list (GtkWindow *window)
2159 GtkWindowIconInfo *info;
2161 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2163 info = get_icon_info (window);
2166 return g_list_copy (info->icon_list);
2172 * gtk_window_set_icon:
2173 * @window: a #GtkWindow
2174 * @icon: icon image, or %NULL
2176 * Sets up the icon representing a #GtkWindow. This icon is used when
2177 * the window is minimized (also known as iconified). Some window
2178 * managers or desktop environments may also place it in the window
2179 * frame, or display it in other contexts.
2181 * The icon should be provided in whatever size it was naturally
2182 * drawn; that is, don't scale the image before passing it to
2183 * GTK+. Scaling is postponed until the last minute, when the desired
2184 * final size is known, to allow best quality.
2186 * If you have your icon hand-drawn in multiple sizes, use
2187 * gtk_window_set_icon_list(). Then the best size will be used.
2189 * This function is equivalent to calling gtk_window_set_icon_list()
2190 * with a 1-element list.
2192 * See also gtk_window_set_default_icon_list() to set the icon
2193 * for all windows in your application in one go.
2196 gtk_window_set_icon (GtkWindow *window,
2201 g_return_if_fail (GTK_IS_WINDOW (window));
2202 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2205 list = g_list_append (list, icon);
2206 gtk_window_set_icon_list (window, list);
2211 * gtk_window_get_icon:
2212 * @window: a #GtkWindow
2214 * Gets the value set by gtk_window_set_icon() (or if you've
2215 * called gtk_window_set_icon_list(), gets the first icon in
2218 * Return value: icon for window
2221 gtk_window_get_icon (GtkWindow *window)
2223 GtkWindowIconInfo *info;
2225 info = get_icon_info (window);
2226 if (info && info->icon_list)
2227 return GDK_PIXBUF (info->icon_list->data);
2233 * gtk_window_set_default_icon_list:
2234 * @list: a list of #GdkPixbuf
2236 * Sets an icon list to be used as fallback for windows that haven't
2237 * had gtk_window_set_icon_list() called on them to set up a
2238 * window-specific icon list. This function allows you to set up the
2239 * icon for all windows in your app at once.
2241 * See gtk_window_set_icon_list() for more details.
2245 gtk_window_set_default_icon_list (GList *list)
2249 if (list == default_icon_list)
2252 if (default_icon_pixmap)
2253 g_object_unref (G_OBJECT (default_icon_pixmap));
2254 if (default_icon_mask)
2255 g_object_unref (G_OBJECT (default_icon_mask));
2257 default_icon_pixmap = NULL;
2258 default_icon_mask = NULL;
2260 g_list_foreach (default_icon_list,
2261 (GFunc) g_object_unref, NULL);
2263 g_list_free (default_icon_list);
2265 default_icon_list = g_list_copy (list);
2266 g_list_foreach (default_icon_list,
2267 (GFunc) g_object_ref, NULL);
2269 /* Update all toplevels */
2270 toplevels = gtk_window_list_toplevels ();
2271 tmp_list = toplevels;
2272 while (tmp_list != NULL)
2274 GtkWindowIconInfo *info;
2275 GtkWindow *w = tmp_list->data;
2277 info = get_icon_info (w);
2278 if (info && info->using_default_icon)
2280 gtk_window_unrealize_icon (w);
2281 if (GTK_WIDGET_REALIZED (w))
2282 gtk_window_realize_icon (w);
2285 tmp_list = tmp_list->next;
2287 g_list_free (toplevels);
2291 * gtk_window_get_default_icon_list:
2293 * Gets the value set by gtk_window_set_default_icon_list().
2294 * The list is a copy and should be freed with g_list_free(),
2295 * but the pixbufs in the list have not had their reference count
2298 * Return value: copy of default icon list
2301 gtk_window_get_default_icon_list (void)
2303 return g_list_copy (default_icon_list);
2307 gtk_window_set_default_size_internal (GtkWindow *window,
2308 gboolean change_width,
2310 gboolean change_height,
2313 GtkWindowGeometryInfo *info;
2315 g_return_if_fail (GTK_IS_WINDOW (window));
2316 g_return_if_fail (change_width == FALSE || width >= -1);
2317 g_return_if_fail (change_height == FALSE || height >= -1);
2319 info = gtk_window_get_geometry_info (window, TRUE);
2321 g_object_freeze_notify (G_OBJECT (window));
2331 info->default_width = width;
2333 g_object_notify (G_OBJECT (window), "default_width");
2344 info->default_height = height;
2346 g_object_notify (G_OBJECT (window), "default_height");
2349 g_object_thaw_notify (G_OBJECT (window));
2351 gtk_widget_queue_resize (GTK_WIDGET (window));
2355 * gtk_window_set_default_size:
2356 * @window: a #GtkWindow
2357 * @width: width in pixels, or -1 to unset the default width
2358 * @height: height in pixels, or -1 to unset the default height
2360 * Sets the default size of a window. If the window's "natural" size
2361 * (its size request) is larger than the default, the default will be
2362 * ignored. More generally, if the default size does not obey the
2363 * geometry hints for the window (gtk_window_set_geometry_hints() can
2364 * be used to set these explicitly), the default size will be clamped
2365 * to the nearest permitted size.
2367 * Unlike gtk_widget_set_size_request(), which sets a size request for
2368 * a widget and thus would keep users from shrinking the window, this
2369 * function only sets the initial size, just as if the user had
2370 * resized the window themselves. Users can still shrink the window
2371 * again as they normally would. Setting a default size of -1 means to
2372 * use the "natural" default size (the size request of the window).
2374 * For more control over a window's initial size and how resizing works,
2375 * investigate gtk_window_set_geometry_hints().
2377 * A useful feature: if you set the "geometry widget" via
2378 * gtk_window_set_geometry_hints(), the default size specified by
2379 * gtk_window_set_default_size() will be the default size of that
2380 * widget, not of the entire window.
2382 * For some uses, gtk_window_resize() is a more appropriate function.
2383 * gtk_window_resize() changes the current size of the window, rather
2384 * than the size to be used on initial display. gtk_window_resize() always
2385 * affects the window itself, not the geometry widget.
2387 * The default size of a window only affects the first time a window is
2388 * shown; if a window is hidden and re-shown, it will remember the size
2389 * it had prior to hiding, rather than using the default size.
2391 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2392 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2395 gtk_window_set_default_size (GtkWindow *window,
2399 g_return_if_fail (GTK_IS_WINDOW (window));
2400 g_return_if_fail (width >= -1);
2401 g_return_if_fail (height >= -1);
2403 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height);
2407 * gtk_window_get_default_size:
2408 * @window: a #GtkWindow
2409 * @width: location to store the default width, or %NULL
2410 * @height: location to store the default height, or %NULL
2412 * Gets the default size of the window. A value of -1 for the width or
2413 * height indicates that a default size has not been explicitly set
2414 * for that dimension, so the "natural" size of the window will be
2419 gtk_window_get_default_size (GtkWindow *window,
2423 GtkWindowGeometryInfo *info;
2425 g_return_if_fail (GTK_IS_WINDOW (window));
2427 info = gtk_window_get_geometry_info (window, FALSE);
2430 *width = info->default_width;
2433 *height = info->default_height;
2437 * gtk_window_resize:
2438 * @window: a #GtkWindow
2439 * @width: width to resize the window to
2440 * @height: height to resize the window to
2442 * Resizes the window as if the user had done so, obeying geometry
2443 * constraints. The default geometry constraint is that windows may
2444 * not be smaller than their size request; to override this
2445 * constraint, call gtk_widget_set_size_request() to set the window's
2446 * request to a smaller value.
2448 * If gtk_window_resize() is called before showing a window for the
2449 * first time, it overrides any default size set with
2450 * gtk_window_set_default_size().
2452 * Windows may not be resized smaller than 1 by 1 pixels.
2456 gtk_window_resize (GtkWindow *window,
2460 GtkWindowGeometryInfo *info;
2462 g_return_if_fail (GTK_IS_WINDOW (window));
2463 g_return_if_fail (width > 0);
2464 g_return_if_fail (height > 0);
2466 info = gtk_window_get_geometry_info (window, TRUE);
2468 info->resize_width = width;
2469 info->resize_height = height;
2471 gtk_widget_queue_resize (GTK_WIDGET (window));
2475 * gtk_window_get_size:
2476 * @window: a #GtkWindow
2477 * @width: return location for width, or %NULL
2478 * @height: return location for height, or %NULL
2480 * Obtains the current size of @window. If @window is not onscreen,
2481 * it returns the size GTK+ will suggest to the window manager for the
2482 * initial window size (but this is not reliably the same as the size
2483 * the window manager will actually select). The size obtained by
2484 * gtk_window_get_size() is the last size received in a
2485 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2486 * rather than querying the X server for the size. As a result, if you
2487 * call gtk_window_resize() then immediately call
2488 * gtk_window_get_size(), the size won't have taken effect yet. After
2489 * the window manager processes the resize request, GTK+ receives
2490 * notification that the size has changed via a configure event, and
2491 * the size of the window gets updated.
2493 * Note 1: Nearly any use of this function creates a race condition,
2494 * because the size of the window may change between the time that you
2495 * get the size and the time that you perform some action assuming
2496 * that size is the current size. To avoid race conditions, connect to
2497 * "configure_event" on the window and adjust your size-dependent
2498 * state to match the size delivered in the #GdkEventConfigure.
2500 * Note 2: The returned size does NOT include the size of the window
2501 * manager decorations (aka the window frame or border). Those
2502 * are not drawn by GTK+ and GTK+ has no reliable method of
2503 * determining their size.
2505 * Note 3: If you are getting a window size in order to position
2506 * the window onscreen, there may be a better way. The preferred
2507 * way is to simply set the window's semantic type with
2508 * gtk_window_set_type_hint(), which allows the window manager to
2509 * e.g. center dialogs. Also, if you set the transient parent of
2510 * dialogs with gtk_widget_set_transient_for() window managers
2511 * will often center the dialog over its parent window. It's
2512 * much preferred to let the window manager handle these
2513 * things rather than doing it yourself, because all apps will
2514 * behave consistently and according to user prefs if the window
2515 * manager handles it. Also, the window manager can take the size
2516 * of the window decorations/border into account, while your
2517 * application cannot.
2519 * In any case, if you insist on application-specified window
2520 * positioning, there's STILL a better way than doing it yourself -
2521 * gtk_window_set_position() will frequently handle the details
2526 gtk_window_get_size (GtkWindow *window,
2533 g_return_if_fail (GTK_IS_WINDOW (window));
2535 widget = GTK_WIDGET (window);
2537 if (width == NULL && height == NULL)
2540 if (GTK_WIDGET_MAPPED (window))
2542 gdk_drawable_get_size (GTK_WIDGET (window)->window,
2547 GdkRectangle configure_request;
2549 gtk_window_compute_configure_request (window,
2553 w = configure_request.width;
2554 h = configure_request.height;
2565 * @window: a #GtkWindow
2566 * @x: X coordinate to move window to
2567 * @y: Y coordinate to move window to
2569 * Asks the window manager to move @window to the given position.
2570 * Window managers are free to ignore this; most window managers
2571 * ignore requests for initial window positions (instead using a
2572 * user-defined placement algorithm) and honor requests after the
2573 * window has already been shown.
2575 * Note: the position is the position of the gravity-determined
2576 * reference point for the window. The gravity determines two things:
2577 * first, the location of the reference point in root window
2578 * coordinates; and second, which point on the window is positioned at
2579 * the reference point.
2581 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
2582 * point is simply the @x, @y supplied to gtk_window_move(). The
2583 * top-left corner of the window decorations (aka window frame or
2584 * border) will be placed at @x, @y. Therefore, to position a window
2585 * at the top left of the screen, you want to use the default gravity
2586 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
2588 * To position a window at the bottom right corner of the screen, you
2589 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
2590 * point is at @x + the window width and @y + the window height, and
2591 * the bottom-right corner of the window border will be placed at that
2592 * reference point. So, to place a window in the bottom right corner
2593 * you would first set gravity to south east, then write:
2594 * gtk_window_move (window, gdk_screen_width () - window_width,
2595 * gdk_screen_height () - window_height).
2597 * The extended window manager hints specification at
2598 * http://www.freedesktop.org/standards/wm-spec.html has a nice table
2599 * of gravities in the "implementation notes" section.
2601 * The gtk_window_get_position() documentation may also be relevant.
2605 gtk_window_move (GtkWindow *window,
2609 GtkWindowGeometryInfo *info;
2612 g_return_if_fail (GTK_IS_WINDOW (window));
2614 widget = GTK_WIDGET (window);
2616 info = gtk_window_get_geometry_info (window, TRUE);
2618 if (GTK_WIDGET_MAPPED (window))
2620 /* we have now sent a request with this position
2621 * with currently-active constraints, so toggle flag.
2623 info->position_constraints_changed = FALSE;
2625 /* we only constrain if mapped - if not mapped,
2626 * then gtk_window_compute_configure_request()
2627 * will apply the constraints later, and we
2628 * don't want to lose information about
2629 * what position the user set before then.
2630 * i.e. if you do a move() then turn off POS_CENTER
2631 * then show the window, your move() will work.
2633 gtk_window_constrain_position (window,
2634 widget->allocation.width,
2635 widget->allocation.height,
2638 /* Note that this request doesn't go through our standard request
2639 * framework, e.g. doesn't increment configure_request_count,
2640 * doesn't set info->last, etc.; that's because
2641 * we don't save the info needed to arrive at this same request
2644 * To gtk_window_move_resize(), this will end up looking exactly
2645 * the same as the position being changed by the window
2649 /* FIXME are we handling gravity properly for framed windows? */
2651 gdk_window_move (window->frame,
2652 x - window->frame_left,
2653 y - window->frame_top);
2655 gdk_window_move (GTK_WIDGET (window)->window,
2660 /* Save this position to apply on mapping */
2661 info->initial_x = x;
2662 info->initial_y = y;
2663 info->initial_pos_set = TRUE;
2668 * gtk_window_get_position:
2669 * @window: a #GtkWindow
2670 * @root_x: return location for X coordinate of gravity-determined reference p\oint
2671 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
2673 * This function returns the position you need to pass to
2674 * gtk_window_move() to keep @window in its current position. This
2675 * means that the meaning of the returned value varies with window
2676 * gravity. See gtk_window_move() for more details.
2678 * If you haven't changed the window gravity, its gravity will be
2679 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
2680 * gets the position of the top-left corner of the window manager
2681 * frame for the window. gtk_window_move() sets the position of this
2682 * same top-left corner.
2684 * gtk_window_get_position() is not 100% reliable because the X Window System
2685 * does not specify a way to obtain the geometry of the
2686 * decorations placed on a window by the window manager.
2687 * Thus GTK+ is using a "best guess" that works with most
2690 * Moreover, nearly all window managers are broken with respect to
2691 * their handling of window gravity. So moving a window to its current
2692 * position as returned by gtk_window_get_position() tends to
2693 * result in moving the window slightly.
2695 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
2696 * frame is not relevant, and thus gtk_window_get_position() will
2697 * always produce accurate results. However you can't use static
2698 * gravity to do things like place a window in a corner of the screen,
2699 * because static gravity ignores the window manager decorations.
2701 * If you are saving and restoring your application's window
2702 * positions, you should know that it's impossible for applications to
2703 * do this without getting it somewhat wrong because applications do
2704 * not have sufficient knowledge of window manager state. The Correct
2705 * Mechanism is to support the session management protocol (see the
2706 * "GnomeClient" object in the GNOME libraries for example) and allow
2707 * the window manager to save your window sizes and positions.
2712 gtk_window_get_position (GtkWindow *window,
2718 g_return_if_fail (GTK_IS_WINDOW (window));
2720 widget = GTK_WIDGET (window);
2722 if (window->gravity == GDK_GRAVITY_STATIC)
2724 if (GTK_WIDGET_MAPPED (widget))
2726 /* This does a server round-trip, which is sort of wrong;
2727 * but a server round-trip is inevitable for
2728 * gdk_window_get_frame_extents() in the usual
2729 * NorthWestGravity case below, so not sure what else to
2730 * do. We should likely be consistent about whether we get
2731 * the client-side info or the server-side info.
2733 gdk_window_get_origin (widget->window, root_x, root_y);
2737 GdkRectangle configure_request;
2739 gtk_window_compute_configure_request (window,
2743 *root_x = configure_request.x;
2744 *root_y = configure_request.y;
2749 GdkRectangle frame_extents;
2754 if (GTK_WIDGET_MAPPED (widget))
2757 gdk_window_get_frame_extents (window->frame, &frame_extents);
2759 gdk_window_get_frame_extents (widget->window, &frame_extents);
2760 x = frame_extents.x;
2761 y = frame_extents.y;
2762 gtk_window_get_size (window, &w, &h);
2766 /* We just say the frame has 0 size on all sides.
2767 * Not sure what else to do.
2769 gtk_window_compute_configure_request (window,
2772 x = frame_extents.x;
2773 y = frame_extents.y;
2774 w = frame_extents.width;
2775 h = frame_extents.height;
2778 switch (window->gravity)
2780 case GDK_GRAVITY_NORTH:
2781 case GDK_GRAVITY_CENTER:
2782 case GDK_GRAVITY_SOUTH:
2783 /* Find center of frame. */
2784 x += frame_extents.width / 2;
2785 /* Center client window on that point. */
2789 case GDK_GRAVITY_SOUTH_EAST:
2790 case GDK_GRAVITY_EAST:
2791 case GDK_GRAVITY_NORTH_EAST:
2792 /* Find right edge of frame */
2793 x += frame_extents.width;
2794 /* Align left edge of client at that point. */
2801 switch (window->gravity)
2803 case GDK_GRAVITY_WEST:
2804 case GDK_GRAVITY_CENTER:
2805 case GDK_GRAVITY_EAST:
2806 /* Find center of frame. */
2807 y += frame_extents.height / 2;
2808 /* Center client window there. */
2811 case GDK_GRAVITY_SOUTH_WEST:
2812 case GDK_GRAVITY_SOUTH:
2813 case GDK_GRAVITY_SOUTH_EAST:
2814 /* Find south edge of frame */
2815 y += frame_extents.height;
2816 /* Place bottom edge of client there */
2831 * gtk_window_reshow_with_initial_size:
2832 * @window: a #GtkWindow
2834 * Hides @window, then reshows it, resetting the
2835 * default size and position of the window. Used
2836 * by GUI builders only.
2839 gtk_window_reshow_with_initial_size (GtkWindow *window)
2843 g_return_if_fail (GTK_IS_WINDOW (window));
2845 widget = GTK_WIDGET (window);
2847 gtk_widget_hide (widget);
2848 gtk_widget_unrealize (widget);
2849 gtk_widget_show (widget);
2853 gtk_window_destroy (GtkObject *object)
2857 g_return_if_fail (GTK_IS_WINDOW (object));
2859 window = GTK_WINDOW (object);
2861 if (window->transient_parent)
2862 gtk_window_set_transient_for (window, NULL);
2864 /* frees the icons */
2865 gtk_window_set_icon_list (window, NULL);
2867 if (window->has_user_ref_count)
2869 window->has_user_ref_count = FALSE;
2870 gtk_widget_unref (GTK_WIDGET (window));
2874 gtk_window_group_remove_window (window->group, window);
2876 GTK_OBJECT_CLASS (parent_class)->destroy (object);
2880 gtk_window_mnemonic_hash_remove (gpointer key,
2884 GtkWindowMnemonic *mnemonic = key;
2885 GtkWindow *window = user;
2887 if (mnemonic->window == window)
2889 if (mnemonic->targets)
2891 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
2893 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
2894 name, mnemonic->targets->data);
2897 g_slist_free (mnemonic->targets);
2906 gtk_window_finalize (GObject *object)
2910 g_return_if_fail (GTK_IS_WINDOW (object));
2912 window = GTK_WINDOW (object);
2914 toplevel_list = g_slist_remove (toplevel_list, window);
2916 g_free (window->title);
2917 g_free (window->wmclass_name);
2918 g_free (window->wmclass_class);
2919 g_free (window->wm_role);
2921 g_hash_table_foreach_remove (mnemonic_hash_table,
2922 gtk_window_mnemonic_hash_remove,
2924 if (window->geometry_info)
2926 if (window->geometry_info->widget)
2927 gtk_signal_disconnect_by_func (GTK_OBJECT (window->geometry_info->widget),
2928 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
2929 &window->geometry_info->widget);
2930 g_free (window->geometry_info);
2933 if (window->accels_changed_handler)
2935 gtk_idle_remove (window->accels_changed_handler);
2936 window->accels_changed_handler = 0;
2939 G_OBJECT_CLASS (parent_class)->finalize (object);
2943 gtk_window_show (GtkWidget *widget)
2945 GtkWindow *window = GTK_WINDOW (widget);
2946 GtkContainer *container = GTK_CONTAINER (window);
2947 gboolean need_resize;
2949 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
2951 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
2952 container->need_resize = FALSE;
2956 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
2957 GtkAllocation allocation = { 0, 0 };
2958 GdkRectangle configure_request;
2959 GdkGeometry new_geometry;
2961 gboolean was_realized;
2963 /* We are going to go ahead and perform this configure request
2964 * and then emulate a configure notify by going ahead and
2965 * doing a size allocate. Sort of a synchronous
2966 * mini-copy of gtk_window_move_resize() here.
2968 gtk_window_compute_configure_request (window,
2973 /* We update this because we are going to go ahead
2974 * and gdk_window_resize() below, rather than
2977 info->last.configure_request.width = configure_request.width;
2978 info->last.configure_request.height = configure_request.height;
2980 /* and allocate the window - this is normally done
2981 * in move_resize in response to configure notify
2983 allocation.width = configure_request.width;
2984 allocation.height = configure_request.height;
2985 gtk_widget_size_allocate (widget, &allocation);
2987 /* Then we guarantee we have a realize */
2988 was_realized = FALSE;
2989 if (!GTK_WIDGET_REALIZED (widget))
2991 gtk_widget_realize (widget);
2992 was_realized = TRUE;
2995 /* Must be done after the windows are realized,
2996 * so that the decorations can be read
2998 gtk_decorated_window_calculate_frame_size (window);
3000 /* We only send configure request if we didn't just finish
3001 * creating the window; if we just created the window
3002 * then we created it with widget->allocation anyhow.
3005 gdk_window_resize (widget->window,
3006 configure_request.width,
3007 configure_request.height);
3010 gtk_container_check_resize (container);
3012 gtk_widget_map (widget);
3015 gtk_grab_add (widget);
3019 gtk_window_hide (GtkWidget *widget)
3023 g_return_if_fail (GTK_IS_WINDOW (widget));
3025 window = GTK_WINDOW (widget);
3027 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3028 gtk_widget_unmap (widget);
3031 gtk_grab_remove (widget);
3035 gtk_window_map (GtkWidget *widget)
3038 GdkWindow *toplevel;
3040 g_return_if_fail (GTK_IS_WINDOW (widget));
3042 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3044 window = GTK_WINDOW (widget);
3046 if (window->bin.child &&
3047 GTK_WIDGET_VISIBLE (window->bin.child) &&
3048 !GTK_WIDGET_MAPPED (window->bin.child))
3049 gtk_widget_map (window->bin.child);
3052 toplevel = window->frame;
3054 toplevel = widget->window;
3056 if (window->maximize_initially)
3057 gdk_window_maximize (toplevel);
3059 gdk_window_unmaximize (toplevel);
3061 if (window->stick_initially)
3062 gdk_window_stick (toplevel);
3064 gdk_window_unstick (toplevel);
3066 if (window->iconify_initially)
3067 gdk_window_iconify (toplevel);
3069 gdk_window_deiconify (toplevel);
3071 /* No longer use the default settings */
3072 window->need_default_size = FALSE;
3073 window->need_default_position = FALSE;
3075 gdk_window_show (widget->window);
3078 gdk_window_show (window->frame);
3082 gtk_window_unmap (GtkWidget *widget)
3085 GtkWindowGeometryInfo *info;
3087 window = GTK_WINDOW (widget);
3089 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3091 gdk_window_withdraw (window->frame);
3093 gdk_window_withdraw (widget->window);
3095 window->configure_request_count = 0;
3096 window->configure_notify_received = FALSE;
3098 /* on unmap, we reset the default positioning of the window,
3099 * so it's placed again, but we don't reset the default
3100 * size of the window, so it's remembered.
3102 window->need_default_position = TRUE;
3104 info = gtk_window_get_geometry_info (window, FALSE);
3107 info->initial_pos_set = FALSE;
3108 info->position_constraints_changed = FALSE;
3113 gtk_window_realize (GtkWidget *widget)
3116 GdkWindow *parent_window;
3117 GdkWindowAttr attributes;
3118 gint attributes_mask;
3120 g_return_if_fail (GTK_IS_WINDOW (widget));
3122 window = GTK_WINDOW (widget);
3124 /* ensure widget tree is properly size allocated */
3125 if (widget->allocation.x == -1 &&
3126 widget->allocation.y == -1 &&
3127 widget->allocation.width == 1 &&
3128 widget->allocation.height == 1)
3130 GtkRequisition requisition;
3131 GtkAllocation allocation = { 0, 0, 200, 200 };
3133 gtk_widget_size_request (widget, &requisition);
3134 if (requisition.width || requisition.height)
3136 /* non-empty window */
3137 allocation.width = requisition.width;
3138 allocation.height = requisition.height;
3140 gtk_widget_size_allocate (widget, &allocation);
3142 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3144 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3147 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3149 switch (window->type)
3151 case GTK_WINDOW_TOPLEVEL:
3152 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3154 case GTK_WINDOW_POPUP:
3155 attributes.window_type = GDK_WINDOW_TEMP;
3158 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3162 attributes.title = window->title;
3163 attributes.wmclass_name = window->wmclass_name;
3164 attributes.wmclass_class = window->wmclass_class;
3165 attributes.wclass = GDK_INPUT_OUTPUT;
3166 attributes.visual = gtk_widget_get_visual (widget);
3167 attributes.colormap = gtk_widget_get_colormap (widget);
3169 if (window->has_frame)
3171 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3172 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3173 attributes.event_mask = (GDK_EXPOSURE_MASK |
3174 GDK_KEY_PRESS_MASK |
3175 GDK_ENTER_NOTIFY_MASK |
3176 GDK_LEAVE_NOTIFY_MASK |
3177 GDK_FOCUS_CHANGE_MASK |
3178 GDK_STRUCTURE_MASK |
3179 GDK_BUTTON_MOTION_MASK |
3180 GDK_POINTER_MOTION_HINT_MASK |
3181 GDK_BUTTON_PRESS_MASK |
3182 GDK_BUTTON_RELEASE_MASK);
3184 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3186 window->frame = gdk_window_new (NULL, &attributes, attributes_mask);
3187 gdk_window_set_user_data (window->frame, widget);
3189 attributes.window_type = GDK_WINDOW_CHILD;
3190 attributes.x = window->frame_left;
3191 attributes.y = window->frame_right;
3193 attributes_mask = GDK_WA_X | GDK_WA_Y;
3195 parent_window = window->frame;
3199 attributes_mask = 0;
3200 parent_window = NULL;
3203 attributes.width = widget->allocation.width;
3204 attributes.height = widget->allocation.height;
3205 attributes.event_mask = gtk_widget_get_events (widget);
3206 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3207 GDK_KEY_PRESS_MASK |
3208 GDK_ENTER_NOTIFY_MASK |
3209 GDK_LEAVE_NOTIFY_MASK |
3210 GDK_FOCUS_CHANGE_MASK |
3211 GDK_STRUCTURE_MASK);
3213 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3214 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3215 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3216 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3217 gdk_window_set_user_data (widget->window, window);
3219 widget->style = gtk_style_attach (widget->style, widget->window);
3220 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3222 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3224 /* This is a bad hack to set the window background. */
3225 gtk_window_paint (widget, NULL);
3227 if (window->transient_parent &&
3228 GTK_WIDGET_REALIZED (window->transient_parent))
3229 gdk_window_set_transient_for (widget->window,
3230 GTK_WIDGET (window->transient_parent)->window);
3232 if (window->wm_role)
3233 gdk_window_set_role (widget->window, window->wm_role);
3235 if (!window->decorated)
3236 gdk_window_set_decorations (widget->window, 0);
3238 gdk_window_set_type_hint (widget->window, window->type_hint);
3240 /* transient_for must be set to allow the modal hint */
3241 if (window->transient_parent && window->modal)
3242 gdk_window_set_modal_hint (widget->window, TRUE);
3244 gdk_window_set_modal_hint (widget->window, FALSE);
3247 gtk_window_realize_icon (window);
3251 gtk_window_unrealize (GtkWidget *widget)
3254 GtkWindowGeometryInfo *info;
3256 window = GTK_WINDOW (widget);
3258 /* On unrealize, we reset the size of the window such
3259 * that we will re-apply the default sizing stuff
3260 * next time we show the window.
3262 * Default positioning is reset on unmap, instead of unrealize.
3264 window->need_default_size = TRUE;
3265 info = gtk_window_get_geometry_info (window, FALSE);
3268 info->resize_width = -1;
3269 info->resize_height = -1;
3270 info->last.configure_request.x = 0;
3271 info->last.configure_request.y = 0;
3272 info->last.configure_request.width = -1;
3273 info->last.configure_request.height = -1;
3274 /* be sure we reset geom hints on re-realize */
3275 info->last.flags = 0;
3280 gdk_window_set_user_data (window->frame, NULL);
3281 gdk_window_destroy (window->frame);
3282 window->frame = NULL;
3286 gtk_window_unrealize_icon (window);
3288 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3292 gtk_window_size_request (GtkWidget *widget,
3293 GtkRequisition *requisition)
3298 g_return_if_fail (GTK_IS_WINDOW (widget));
3299 g_return_if_fail (requisition != NULL);
3301 window = GTK_WINDOW (widget);
3302 bin = GTK_BIN (window);
3304 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3305 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3307 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3309 GtkRequisition child_requisition;
3311 gtk_widget_size_request (bin->child, &child_requisition);
3313 requisition->width += child_requisition.width;
3314 requisition->height += child_requisition.height;
3319 gtk_window_size_allocate (GtkWidget *widget,
3320 GtkAllocation *allocation)
3323 GtkAllocation child_allocation;
3325 g_return_if_fail (GTK_IS_WINDOW (widget));
3326 g_return_if_fail (allocation != NULL);
3328 window = GTK_WINDOW (widget);
3329 widget->allocation = *allocation;
3331 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3333 child_allocation.x = GTK_CONTAINER (window)->border_width;
3334 child_allocation.y = GTK_CONTAINER (window)->border_width;
3335 child_allocation.width =
3336 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3337 child_allocation.height =
3338 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3340 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3343 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3345 gdk_window_resize (window->frame,
3346 allocation->width + window->frame_left + window->frame_right,
3347 allocation->height + window->frame_top + window->frame_bottom);
3352 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3355 gboolean return_val;
3358 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3359 g_return_val_if_fail (event != NULL, FALSE);
3361 window = GTK_WINDOW (widget);
3363 if (window->frame && (event->any.window == window->frame))
3365 if ((event->type != GDK_KEY_PRESS) &&
3366 (event->type != GDK_KEY_RELEASE) &&
3367 (event->type != GDK_FOCUS_CHANGE))
3369 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
3371 gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
3376 g_object_unref (event->any.window);
3377 event->any.window = g_object_ref (widget->window);
3385 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3387 GdkEventConfigure *configure_event;
3390 switch (event->type)
3393 configure_event = (GdkEventConfigure *)event;
3395 /* Invalidate the decorations */
3398 rect.width = configure_event->width;
3399 rect.height = configure_event->height;
3401 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3403 /* Pass on the (modified) configure event */
3404 configure_event->width -= window->frame_left + window->frame_right;
3405 configure_event->height -= window->frame_top + window->frame_bottom;
3406 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3415 gtk_window_configure_event (GtkWidget *widget,
3416 GdkEventConfigure *event)
3420 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3421 g_return_val_if_fail (event != NULL, FALSE);
3423 window = GTK_WINDOW (widget);
3425 /* window->configure_request_count incremented for each
3426 * configure request, and decremented to a min of 0 for
3427 * each configure notify.
3429 * All it means is that we know we will get at least
3430 * window->configure_request_count more configure notifies.
3431 * We could get more configure notifies than that; some
3432 * of the configure notifies we get may be unrelated to
3433 * the configure requests. But we will get at least
3434 * window->configure_request_count notifies.
3437 if (window->configure_request_count > 0)
3438 window->configure_request_count -= 1;
3440 /* As an optimization, we avoid a resize when possible.
3442 * The only times we can avoid a resize are:
3443 * - we know only the position changed, not the size
3444 * - we know we have made more requests and so will get more
3445 * notifies and can wait to resize when we get them
3448 if (window->configure_request_count > 0 ||
3449 (widget->allocation.width == event->width &&
3450 widget->allocation.height == event->height))
3454 * If we do need to resize, we do that by:
3455 * - filling in widget->allocation with the new size
3456 * - setting configure_notify_received to TRUE
3457 * for use in gtk_window_move_resize()
3458 * - queueing a resize, leading to invocation of
3459 * gtk_window_move_resize() in an idle handler
3463 window->configure_notify_received = TRUE;
3465 widget->allocation.width = event->width;
3466 widget->allocation.height = event->height;
3468 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3473 /* the accel_key and accel_mods fields of the key have to be setup
3474 * upon calling this function. it'll then return whether that key
3475 * is at all used as accelerator, and if so will OR in the
3476 * accel_flags member of the key.
3479 _gtk_window_query_nonaccels (GtkWindow *window,
3481 GdkModifierType accel_mods)
3483 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3485 /* movement keys are considered locked accels */
3488 static const guint bindings[] = {
3489 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
3490 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
3494 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
3495 if (bindings[i] == accel_key)
3499 /* mnemonics are considered locked accels */
3500 if (accel_mods == window->mnemonic_modifier)
3502 GtkWindowMnemonic mkey;
3504 mkey.window = window;
3505 mkey.keyval = accel_key;
3506 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
3514 gtk_window_key_press_event (GtkWidget *widget,
3521 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3522 g_return_val_if_fail (event != NULL, FALSE);
3524 window = GTK_WINDOW (widget);
3528 focus = window->focus_widget;
3530 g_object_ref (focus);
3533 focus && focus != widget &&
3534 gtk_widget_get_toplevel (focus) == widget)
3538 if (GTK_WIDGET_IS_SENSITIVE (focus))
3539 handled = gtk_widget_event (focus, (GdkEvent*) event);
3541 parent = focus->parent;
3543 g_object_ref (parent);
3545 g_object_unref (focus);
3551 g_object_unref (focus);
3554 handled = gtk_window_mnemonic_activate (window,
3559 handled = gtk_accel_groups_activate (G_OBJECT (window), event->keyval, event->state);
3561 /* Chain up, invokes binding set */
3562 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
3563 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
3569 gtk_window_key_release_event (GtkWidget *widget,
3575 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3576 g_return_val_if_fail (event != NULL, FALSE);
3578 window = GTK_WINDOW (widget);
3580 if (window->focus_widget &&
3581 window->focus_widget != widget &&
3582 GTK_WIDGET_SENSITIVE (window->focus_widget))
3584 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
3587 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
3588 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
3594 gtk_window_real_activate_default (GtkWindow *window)
3596 gtk_window_activate_default (window);
3600 gtk_window_real_activate_focus (GtkWindow *window)
3602 gtk_window_activate_focus (window);
3606 gtk_window_move_focus (GtkWindow *window,
3607 GtkDirectionType dir)
3609 gtk_widget_child_focus (GTK_WIDGET (window), dir);
3611 if (!GTK_CONTAINER (window)->focus_child)
3612 gtk_window_set_focus (window, NULL);
3616 gtk_window_enter_notify_event (GtkWidget *widget,
3617 GdkEventCrossing *event)
3619 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3620 g_return_val_if_fail (event != NULL, FALSE);
3626 gtk_window_leave_notify_event (GtkWidget *widget,
3627 GdkEventCrossing *event)
3629 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3630 g_return_val_if_fail (event != NULL, FALSE);
3636 gtk_window_focus_in_event (GtkWidget *widget,
3637 GdkEventFocus *event)
3639 GtkWindow *window = GTK_WINDOW (widget);
3640 GdkEventFocus fevent;
3642 /* It appears spurious focus in events can occur when
3643 * the window is hidden. So we'll just check to see if
3644 * the window is visible before actually handling the
3647 if (GTK_WIDGET_VISIBLE (widget))
3649 window->has_focus = TRUE;
3651 if (window->focus_widget &&
3652 window->focus_widget != widget &&
3653 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3655 fevent.type = GDK_FOCUS_CHANGE;
3656 fevent.window = window->focus_widget->window;
3659 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
3667 gtk_window_focus_out_event (GtkWidget *widget,
3668 GdkEventFocus *event)
3670 GtkWindow *window = GTK_WINDOW (widget);
3671 GdkEventFocus fevent;
3673 window->has_focus = FALSE;
3675 if (window->focus_widget &&
3676 window->focus_widget != widget &&
3677 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3679 fevent.type = GDK_FOCUS_CHANGE;
3680 fevent.window = window->focus_widget->window;
3683 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
3689 static GdkAtom atom_rcfiles = GDK_NONE;
3692 gtk_window_read_rcfiles (GtkWidget *widget,
3693 GdkEventClient *event)
3695 GList *embedded_windows;
3697 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
3698 if (embedded_windows)
3703 for (i = 0; i < 5; i++)
3705 sev.data_format = 32;
3706 sev.message_type = atom_rcfiles;
3708 while (embedded_windows)
3710 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
3711 gdk_event_send_client_message ((GdkEvent *) &sev, xid);
3712 embedded_windows = embedded_windows->next;
3716 gtk_rc_reparse_all ();
3720 gtk_window_client_event (GtkWidget *widget,
3721 GdkEventClient *event)
3723 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3724 g_return_val_if_fail (event != NULL, FALSE);
3727 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
3729 if (event->message_type == atom_rcfiles)
3730 gtk_window_read_rcfiles (widget, event);
3736 gtk_window_check_resize (GtkContainer *container)
3740 g_return_if_fail (GTK_IS_WINDOW (container));
3742 window = GTK_WINDOW (container);
3744 if (GTK_WIDGET_VISIBLE (container))
3745 gtk_window_move_resize (window);
3749 gtk_window_focus (GtkWidget *widget,
3750 GtkDirectionType direction)
3754 GtkContainer *container;
3755 GtkWidget *old_focus_child;
3758 container = GTK_CONTAINER (widget);
3759 window = GTK_WINDOW (widget);
3760 bin = GTK_BIN (widget);
3762 old_focus_child = container->focus_child;
3764 /* We need a special implementation here to deal properly with wrapping
3765 * around in the tab chain without the danger of going into an
3768 if (old_focus_child)
3770 if (gtk_widget_child_focus (old_focus_child, direction))
3774 if (window->focus_widget)
3776 /* Wrapped off the end, clear the focus setting for the toplpevel */
3777 parent = window->focus_widget->parent;
3780 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
3781 parent = GTK_WIDGET (parent)->parent;
3784 gtk_window_set_focus (GTK_WINDOW (container), NULL);
3787 /* Now try to focus the first widget in the window */
3790 if (gtk_widget_child_focus (bin->child, direction))
3798 gtk_window_real_set_focus (GtkWindow *window,
3801 GdkEventFocus event;
3802 gboolean def_flags = 0;
3804 g_return_if_fail (GTK_IS_WINDOW (window));
3806 if (window->default_widget)
3807 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
3809 if (window->focus_widget)
3811 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3812 (window->focus_widget != window->default_widget))
3814 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3816 if (window->default_widget)
3817 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3820 if (window->has_focus)
3822 event.type = GDK_FOCUS_CHANGE;
3823 event.window = window->focus_widget->window;
3826 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
3830 window->focus_widget = focus;
3832 if (window->focus_widget)
3834 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3835 (window->focus_widget != window->default_widget))
3837 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
3838 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3840 if (window->default_widget)
3841 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3844 if (window->has_focus)
3846 event.type = GDK_FOCUS_CHANGE;
3847 event.window = window->focus_widget->window;
3850 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
3854 if (window->default_widget &&
3855 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
3856 gtk_widget_queue_draw (window->default_widget);
3859 /*********************************
3860 * Functions related to resizing *
3861 *********************************/
3863 /* This function doesn't constrain to geometry hints */
3865 gtk_window_compute_configure_request_size (GtkWindow *window,
3869 GtkRequisition requisition;
3870 GtkWindowGeometryInfo *info;
3874 * - we've done a size request
3877 widget = GTK_WIDGET (window);
3879 info = gtk_window_get_geometry_info (window, FALSE);
3881 if (window->need_default_size)
3883 gtk_widget_get_child_requisition (widget, &requisition);
3885 /* Default to requisition */
3886 *width = requisition.width;
3887 *height = requisition.height;
3889 /* If window is empty so requests 0, default to random nonzero size */
3890 if (*width == 0 && *height == 0)
3896 /* Override requisition with default size */
3900 if (info->default_width > 0)
3901 *width = info->default_width;
3903 if (info->default_height > 0)
3904 *height = info->default_height;
3909 /* Default to keeping current size */
3910 *width = widget->allocation.width;
3911 *height = widget->allocation.height;
3914 /* Override any size with gtk_window_resize() values */
3917 if (info->resize_width > 0)
3918 *width = info->resize_width;
3920 if (info->resize_height > 0)
3921 *height = info->resize_height;
3926 gtk_window_compute_configure_request (GtkWindow *window,
3927 GdkRectangle *request,
3928 GdkGeometry *geometry,
3931 GdkGeometry new_geometry;
3935 GtkWindowPosition pos;
3936 GtkWidget *parent_widget;
3937 GtkWindowGeometryInfo *info;
3940 widget = GTK_WIDGET (window);
3942 gtk_widget_size_request (widget, NULL);
3943 gtk_window_compute_configure_request_size (window, &w, &h);
3945 gtk_window_compute_hints (window, &new_geometry, &new_flags);
3946 gtk_window_constrain_size (window,
3947 &new_geometry, new_flags,
3951 parent_widget = (GtkWidget*) window->transient_parent;
3953 pos = window->position;
3954 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
3955 (parent_widget == NULL ||
3956 !GTK_WIDGET_MAPPED (parent_widget)))
3957 pos = GTK_WIN_POS_NONE;
3959 info = gtk_window_get_geometry_info (window, TRUE);
3961 /* by default, don't change position requested */
3962 x = info->last.configure_request.x;
3963 y = info->last.configure_request.y;
3965 if (window->need_default_position)
3968 /* FIXME this all interrelates with window gravity.
3969 * For most of them I think we want to set GRAVITY_CENTER.
3971 * Not sure how to go about that.
3976 /* here we are only handling CENTER_ALWAYS
3977 * as it relates to default positioning,
3978 * where it's equivalent to simply CENTER
3980 case GTK_WIN_POS_CENTER_ALWAYS:
3981 case GTK_WIN_POS_CENTER:
3983 gint screen_width = gdk_screen_width ();
3984 gint screen_height = gdk_screen_height ();
3986 x = (screen_width - w) / 2;
3987 y = (screen_height - h) / 2;
3991 case GTK_WIN_POS_CENTER_ON_PARENT:
3995 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
3997 gdk_window_get_origin (parent_widget->window,
4000 x = ox + (parent_widget->allocation.width - w) / 2;
4001 y = oy + (parent_widget->allocation.height - h) / 2;
4005 case GTK_WIN_POS_MOUSE:
4007 gint screen_width = gdk_screen_width ();
4008 gint screen_height = gdk_screen_height ();
4011 gdk_window_get_pointer (NULL, &px, &py, NULL);
4014 x = CLAMP (x, 0, screen_width - w);
4015 y = CLAMP (y, 0, screen_height - h);
4022 } /* if (window->need_default_position) */
4024 if (window->need_default_position &&
4025 info->initial_pos_set)
4027 x = info->initial_x;
4028 y = info->initial_y;
4029 gtk_window_constrain_position (window, w, h, &x, &y);
4035 request->height = h;
4038 *geometry = new_geometry;
4044 gtk_window_constrain_position (GtkWindow *window,
4050 /* See long comments in gtk_window_move_resize()
4051 * on when it's safe to call this function.
4053 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4055 gint center_x, center_y;
4056 gint screen_width = gdk_screen_width ();
4057 gint screen_height = gdk_screen_height ();
4059 center_x = (screen_width - new_width) / 2;
4060 center_y = (screen_height - new_height) / 2;
4068 gtk_window_move_resize (GtkWindow *window)
4072 * First we determine whether any information has changed that would
4073 * cause us to revise our last configure request. If we would send
4074 * a different configure request from last time, then
4075 * configure_request_size_changed = TRUE or
4076 * configure_request_pos_changed = TRUE. configure_request_size_changed
4077 * may be true due to new hints, a gtk_window_resize(), or whatever.
4078 * configure_request_pos_changed may be true due to gtk_window_set_position()
4079 * or gtk_window_move().
4081 * If the configure request has changed, we send off a new one. To
4082 * ensure GTK invariants are maintained (resize queue does what it
4083 * should), we go ahead and size_allocate the requested size in this
4086 * If the configure request has not changed, we don't ever resend
4087 * it, because it could mean fighting the user or window manager.
4090 * To prepare the configure request, we come up with a base size/pos:
4091 * - the one from gtk_window_move()/gtk_window_resize()
4092 * - else default_width, default_height if we haven't ever
4094 * - else the size request if we haven't ever been mapped,
4095 * as a substitute default size
4096 * - else the current size of the window, as received from
4097 * configure notifies (i.e. the current allocation)
4099 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4100 * the position request to be centered.
4103 GtkContainer *container;
4104 GtkWindowGeometryInfo *info;
4105 GdkGeometry new_geometry;
4107 GdkRectangle new_request;
4108 gboolean configure_request_size_changed;
4109 gboolean configure_request_pos_changed;
4110 gboolean hints_changed; /* do we need to send these again */
4111 GtkWindowLastGeometryInfo saved_last_info;
4113 widget = GTK_WIDGET (window);
4114 container = GTK_CONTAINER (widget);
4115 info = gtk_window_get_geometry_info (window, TRUE);
4117 configure_request_size_changed = FALSE;
4118 configure_request_pos_changed = FALSE;
4120 gtk_window_compute_configure_request (window, &new_request,
4121 &new_geometry, &new_flags);
4123 /* This check implies the invariant that we never set info->last
4124 * without setting the hints and sending off a configure request.
4126 * If we change info->last without sending the request, we may
4129 if (info->last.configure_request.x != new_request.x ||
4130 info->last.configure_request.y != new_request.y)
4131 configure_request_pos_changed = TRUE;
4133 if ((info->last.configure_request.width != new_request.width ||
4134 info->last.configure_request.height != new_request.height))
4135 configure_request_size_changed = TRUE;
4137 hints_changed = FALSE;
4139 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4140 &new_geometry, new_flags))
4142 hints_changed = TRUE;
4145 /* Position Constraints
4146 * ====================
4148 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4149 * a default. The other POS_ values are used only when the
4150 * window is shown, not after that.
4152 * However, we can't implement a position constraint as
4153 * "anytime the window size changes, center the window"
4154 * because this may well end up fighting the WM or user. In
4155 * fact it gets in an infinite loop with at least one WM.
4157 * Basically, applications are in no way in a position to
4158 * constrain the position of a window, with one exception:
4159 * override redirect windows. (Really the intended purpose
4160 * of CENTER_ALWAYS anyhow, I would think.)
4162 * So the way we implement this "constraint" is to say that when WE
4163 * cause a move or resize, i.e. we make a configure request changing
4164 * window size, we recompute the CENTER_ALWAYS position to reflect
4165 * the new window size, and include it in our request. Also, if we
4166 * just turned on CENTER_ALWAYS we snap to center with a new
4167 * request. Otherwise, if we are just NOTIFIED of a move or resize
4168 * done by someone else e.g. the window manager, we do NOT send a
4169 * new configure request.
4171 * For override redirect windows, this works fine; all window
4172 * sizes are from our configure requests. For managed windows,
4173 * it is at least semi-sane, though who knows what the
4174 * app author is thinking.
4177 /* This condition should be kept in sync with the condition later on
4178 * that determines whether we send a configure request. i.e. we
4179 * should do this position constraining anytime we were going to
4180 * send a configure request anyhow, plus when constraints have
4183 if (configure_request_pos_changed ||
4184 configure_request_size_changed ||
4186 info->position_constraints_changed)
4188 /* We request the constrained position if:
4189 * - we were changing position, and need to clamp
4190 * the change to the constraint
4191 * - we're changing the size anyway
4192 * - set_position() was called to toggle CENTER_ALWAYS on
4195 gtk_window_constrain_position (window,
4201 /* Update whether we need to request a move */
4202 if (info->last.configure_request.x != new_request.x ||
4203 info->last.configure_request.y != new_request.y)
4204 configure_request_pos_changed = TRUE;
4206 configure_request_pos_changed = FALSE;
4211 int notify_x, notify_y;
4213 /* this is the position from the last configure notify */
4214 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4216 g_print ("--- %s ---\n"
4217 "last : %d,%d\t%d x %d\n"
4218 "this : %d,%d\t%d x %d\n"
4219 "alloc: %d,%d\t%d x %d\n"
4221 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4222 "configure_notify_received: %d\n"
4223 "configure_request_count: %d\n"
4224 "position_constraints_changed: %d\n",
4225 window->title ? window->title : "(no title)",
4226 info->last.configure_request.x,
4227 info->last.configure_request.y,
4228 info->last.configure_request.width,
4229 info->last.configure_request.height,
4235 widget->allocation.width,
4236 widget->allocation.height,
4237 widget->requisition.width,
4238 widget->requisition.height,
4239 configure_request_pos_changed,
4240 configure_request_size_changed,
4242 window->configure_notify_received,
4243 window->configure_request_count,
4244 info->position_constraints_changed);
4248 saved_last_info = info->last;
4249 info->last.geometry = new_geometry;
4250 info->last.flags = new_flags;
4251 info->last.configure_request = new_request;
4253 /* need to set PPosition so the WM will look at our position,
4254 * but we don't want to count PPosition coming and going as a hints
4255 * change for future iterations. So we saved info->last prior to
4259 /* Also, if the initial position was explicitly set, then we always
4260 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4264 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4265 * this is an initial map
4268 if ((configure_request_pos_changed ||
4269 info->initial_pos_set ||
4270 (window->need_default_position &&
4271 window->position != GTK_WIN_POS_NONE)) &&
4272 (new_flags & GDK_HINT_POS) == 0)
4274 new_flags |= GDK_HINT_POS;
4275 hints_changed = TRUE;
4278 /* Set hints if necessary
4281 gdk_window_set_geometry_hints (widget->window,
4285 /* handle resizing/moving and widget tree allocation
4287 if (window->configure_notify_received)
4289 GtkAllocation allocation;
4291 /* If we have received a configure event since
4292 * the last time in this function, we need to
4293 * accept our new size and size_allocate child widgets.
4294 * (see gtk_window_configure_event() for more details).
4296 * 1 or more configure notifies may have been received.
4297 * Also, configure_notify_received will only be TRUE
4298 * if all expected configure notifies have been received
4299 * (one per configure request), as an optimization.
4302 window->configure_notify_received = FALSE;
4304 /* gtk_window_configure_event() filled in widget->allocation */
4305 allocation = widget->allocation;
4306 gtk_widget_size_allocate (widget, &allocation);
4308 /* If the configure request changed, it means that
4310 * 1) coincidentally changed hints or widget properties
4311 * impacting the configure request before getting
4312 * a configure notify, or
4313 * 2) some broken widget is changing its size request
4314 * during size allocation, resulting in
4315 * a false appearance of changed configure request.
4317 * For 1), we could just go ahead and ask for the
4318 * new size right now, but doing that for 2)
4319 * might well be fighting the user (and can even
4320 * trigger a loop). Since we really don't want to
4321 * do that, we requeue a resize in hopes that
4322 * by the time it gets handled, the child has seen
4323 * the light and is willing to go along with the
4324 * new size. (this happens for the zvt widget, since
4325 * the size_allocate() above will have stored the
4326 * requisition corresponding to the new size in the
4329 * This doesn't buy us anything for 1), but it shouldn't
4330 * hurt us too badly, since it is what would have
4331 * happened if we had gotten the configure event before
4332 * the new size had been set.
4335 if (configure_request_size_changed ||
4336 configure_request_pos_changed)
4338 /* Don't change the recorded last info after all, because we
4339 * haven't actually updated to the new info yet - we decided
4340 * to postpone our configure request until later.
4342 info->last = saved_last_info;
4344 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
4347 else if ((configure_request_size_changed || hints_changed) &&
4348 (widget->allocation.width != new_request.width ||
4349 widget->allocation.height != new_request.height))
4352 /* We are in one of the following situations:
4353 * A. configure_request_size_changed
4354 * our requisition has changed and we need a different window size,
4355 * so we request it from the window manager.
4356 * B. !configure_request_size_changed && hints_changed
4357 * the window manager rejects our size, but we have just changed the
4358 * window manager hints, so there's a chance our request will
4359 * be honoured this time, so we try again.
4361 * However, if the new requisition is the same as the current allocation,
4362 * we don't request it again, since we won't get a ConfigureNotify back from
4363 * the window manager unless it decides to change our requisition. If
4364 * we don't get the ConfigureNotify back, the resize queue will never be run.
4367 /* Now send the configure request */
4368 if (configure_request_pos_changed)
4372 gdk_window_move_resize (window->frame,
4373 new_request.x - window->frame_left,
4374 new_request.y - window->frame_top,
4375 new_request.width + window->frame_left + window->frame_right,
4376 new_request.height + window->frame_top + window->frame_bottom);
4377 gdk_window_resize (GTK_WIDGET (window)->window,
4378 new_request.width, new_request.height);
4381 gdk_window_move_resize (widget->window,
4382 new_request.x, new_request.y,
4383 new_request.width, new_request.height);
4385 else /* only size changed */
4388 gdk_window_resize (window->frame,
4389 new_request.width + window->frame_left + window->frame_right,
4390 new_request.height + window->frame_top + window->frame_bottom);
4391 gdk_window_resize (widget->window,
4392 new_request.width, new_request.height);
4395 /* Increment the number of have-not-yet-received-notify requests */
4396 window->configure_request_count += 1;
4398 /* We have now sent a request since the last position constraint
4399 * change and definitely don't need a an initial size again (not
4400 * resetting this here can lead to infinite loops for
4401 * GTK_RESIZE_IMMEDIATE containers)
4403 info->position_constraints_changed = FALSE;
4404 window->need_default_position = FALSE;
4406 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
4407 * configure event in response to our resizing request.
4408 * the configure event will cause a new resize with
4409 * ->configure_notify_received=TRUE.
4410 * until then, we want to
4411 * - discard expose events
4412 * - coalesce resizes for our children
4413 * - defer any window resizes until the configure event arrived
4414 * to achieve this, we queue a resize for the window, but remove its
4415 * resizing handler, so resizing will not be handled from the next
4416 * idle handler but when the configure event arrives.
4418 * FIXME: we should also dequeue the pending redraws here, since
4419 * we handle those ourselves upon ->configure_notify_received==TRUE.
4421 if (container->resize_mode == GTK_RESIZE_QUEUE)
4423 gtk_widget_queue_resize (widget);
4424 _gtk_container_dequeue_resize_handler (container);
4429 /* Handle any position changes.
4431 if (configure_request_pos_changed)
4435 gdk_window_move (window->frame,
4436 new_request.x - window->frame_left,
4437 new_request.y - window->frame_top);
4440 gdk_window_move (widget->window,
4441 new_request.x, new_request.y);
4444 /* And run the resize queue.
4446 gtk_container_resize_children (container);
4450 /* Compare two sets of Geometry hints for equality.
4453 gtk_window_compare_hints (GdkGeometry *geometry_a,
4455 GdkGeometry *geometry_b,
4458 if (flags_a != flags_b)
4461 if ((flags_a & GDK_HINT_MIN_SIZE) &&
4462 (geometry_a->min_width != geometry_b->min_width ||
4463 geometry_a->min_height != geometry_b->min_height))
4466 if ((flags_a & GDK_HINT_MAX_SIZE) &&
4467 (geometry_a->max_width != geometry_b->max_width ||
4468 geometry_a->max_height != geometry_b->max_height))
4471 if ((flags_a & GDK_HINT_BASE_SIZE) &&
4472 (geometry_a->base_width != geometry_b->base_width ||
4473 geometry_a->base_height != geometry_b->base_height))
4476 if ((flags_a & GDK_HINT_ASPECT) &&
4477 (geometry_a->min_aspect != geometry_b->min_aspect ||
4478 geometry_a->max_aspect != geometry_b->max_aspect))
4481 if ((flags_a & GDK_HINT_RESIZE_INC) &&
4482 (geometry_a->width_inc != geometry_b->width_inc ||
4483 geometry_a->height_inc != geometry_b->height_inc))
4486 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
4487 geometry_a->win_gravity != geometry_b->win_gravity)
4494 _gtk_window_constrain_size (GtkWindow *window,
4500 GtkWindowGeometryInfo *info;
4502 g_return_if_fail (GTK_IS_WINDOW (window));
4504 info = window->geometry_info;
4507 GdkWindowHints flags = info->last.flags;
4508 GdkGeometry *geometry = &info->last.geometry;
4510 gtk_window_constrain_size (window,
4521 gtk_window_constrain_size (GtkWindow *window,
4522 GdkGeometry *geometry,
4529 gdk_window_constrain_size (geometry, flags, width, height,
4530 new_width, new_height);
4533 /* Compute the set of geometry hints and flags for a window
4534 * based on the application set geometry, and requisiition
4535 * of the window. gtk_widget_size_request() must have been
4539 gtk_window_compute_hints (GtkWindow *window,
4540 GdkGeometry *new_geometry,
4544 gint extra_width = 0;
4545 gint extra_height = 0;
4546 GtkWindowGeometryInfo *geometry_info;
4547 GtkRequisition requisition;
4549 g_return_if_fail (GTK_IS_WINDOW (window));
4551 widget = GTK_WIDGET (window);
4553 gtk_widget_get_child_requisition (widget, &requisition);
4554 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
4558 *new_flags = geometry_info->mask;
4559 *new_geometry = geometry_info->geometry;
4566 if (geometry_info && geometry_info->widget)
4568 extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
4569 extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
4572 /* We don't want to set GDK_HINT_POS in here, we just set it
4573 * in gtk_window_move_resize() when we want the position
4577 if (*new_flags & GDK_HINT_BASE_SIZE)
4579 new_geometry->base_width += extra_width;
4580 new_geometry->base_height += extra_height;
4582 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
4583 (*new_flags & GDK_HINT_RESIZE_INC) &&
4584 ((extra_width != 0) || (extra_height != 0)))
4586 *new_flags |= GDK_HINT_BASE_SIZE;
4588 new_geometry->base_width = extra_width;
4589 new_geometry->base_height = extra_height;
4592 if (*new_flags & GDK_HINT_MIN_SIZE)
4594 if (new_geometry->min_width < 0)
4595 new_geometry->min_width = requisition.width;
4597 new_geometry->min_width += extra_width;
4599 if (new_geometry->min_height < 0)
4600 new_geometry->min_height = requisition.height;
4602 new_geometry->min_height += extra_height;
4604 else if (!window->allow_shrink)
4606 *new_flags |= GDK_HINT_MIN_SIZE;
4608 new_geometry->min_width = requisition.width;
4609 new_geometry->min_height = requisition.height;
4612 if (*new_flags & GDK_HINT_MAX_SIZE)
4614 if (new_geometry->max_width < 0)
4615 new_geometry->max_width = requisition.width;
4617 new_geometry->max_width += extra_width;
4619 if (new_geometry->max_height < 0)
4620 new_geometry->max_width = requisition.height;
4622 new_geometry->max_height += extra_height;
4624 else if (!window->allow_grow)
4626 *new_flags |= GDK_HINT_MAX_SIZE;
4628 new_geometry->max_width = requisition.width;
4629 new_geometry->max_height = requisition.height;
4632 *new_flags |= GDK_HINT_WIN_GRAVITY;
4633 new_geometry->win_gravity = window->gravity;
4636 /***********************
4637 * Redrawing functions *
4638 ***********************/
4641 gtk_window_paint (GtkWidget *widget,
4644 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
4645 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
4649 gtk_window_expose (GtkWidget *widget,
4650 GdkEventExpose *event)
4652 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
4653 g_return_val_if_fail (event != NULL, FALSE);
4655 if (!GTK_WIDGET_APP_PAINTABLE (widget))
4656 gtk_window_paint (widget, &event->area);
4658 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
4659 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
4665 * gtk_window_set_has_frame:
4666 * @window: a #GtkWindow
4667 * @setting: a boolean
4669 * (Note: this is a special-purpose function for the framebuffer port,
4670 * that causes GTK+ to draw its own window border. For most applications,
4671 * you want gtk_window_set_decorated() instead, which tells the window
4672 * manager whether to draw the window border.)
4674 * If this function is called on a window with setting of TRUE, before
4675 * it is realized or showed, it will have a "frame" window around
4676 * widget->window, accessible in window->frame. Using the signal
4677 * frame_event you can recieve all events targeted at the frame.
4679 * This function is used by the linux-fb port to implement managed
4680 * windows, but it could concievably be used by X-programs that
4681 * want to do their own window decorations.
4685 gtk_window_set_has_frame (GtkWindow *window,
4688 g_return_if_fail (GTK_IS_WINDOW (window));
4689 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
4691 window->has_frame = setting != FALSE;
4695 * gtk_window_get_has_frame:
4696 * @window: a #GtkWindow
4698 * Accessor for whether the window has a frame window exterior to
4699 * widget->window. Gets the value set by gtk_window_set_has_frame ().
4701 * Return value: %TRUE if a frame has been added to the window
4702 * via gtk_widow_has_frame
4705 gtk_window_get_has_frame (GtkWindow *window)
4707 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4709 return window->has_frame;
4713 * gtk_window_set_frame_dimensions:
4714 * @window: a #GtkWindow that has a frame
4715 * @left: The width of the left border
4716 * @top: The height of the top border
4717 * @right: The width of the right border
4718 * @bottom: The height of the bottom border
4720 * (Note: this is a special-purpose function intended for the framebuffer
4721 * port; see gtk_window_set_has_frame(). It will have no effect on the
4722 * window border drawn by the window manager, which is the normal
4723 * case when using the X Window system.)
4725 * For windows with frames (see #gtk_window_set_has_frame) this function
4726 * can be used to change the size of the frame border.
4729 gtk_window_set_frame_dimensions (GtkWindow *window,
4735 GtkWidget *widget = GTK_WIDGET (window);
4737 g_return_if_fail (GTK_IS_WINDOW (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 you
4813 * shouldn't assume the window is definitely iconified afterward,
4814 * because other entities (e.g. the user or window manager) could
4815 * deiconify it again, or there may not be a window manager in which
4816 * case iconification isn't possible, etc. But normally the window
4817 * will end up iconified. Just don't write code that crashes if not.
4819 * It's permitted to call this function before showing a window,
4820 * in which case the window will be iconified before it ever appears
4823 * You can track iconification via the "window_state_event" signal
4828 gtk_window_iconify (GtkWindow *window)
4831 GdkWindow *toplevel;
4833 g_return_if_fail (GTK_IS_WINDOW (window));
4835 widget = GTK_WIDGET (window);
4837 window->iconify_initially = TRUE;
4840 toplevel = window->frame;
4842 toplevel = widget->window;
4844 if (toplevel != NULL)
4845 gdk_window_iconify (toplevel);
4849 * gtk_window_deiconify:
4850 * @window: a #GtkWindow
4852 * Asks to deiconify (i.e. unminimize) the specified @window. Note
4853 * that you shouldn't assume the window is definitely deiconified
4854 * afterward, because other entities (e.g. the user or window manager)
4855 * could iconify it again before your code which assumes
4856 * deiconification gets to run.
4858 * You can track iconification via the "window_state_event" signal
4862 gtk_window_deiconify (GtkWindow *window)
4865 GdkWindow *toplevel;
4867 g_return_if_fail (GTK_IS_WINDOW (window));
4869 widget = GTK_WIDGET (window);
4871 window->iconify_initially = FALSE;
4874 toplevel = window->frame;
4876 toplevel = widget->window;
4878 if (toplevel != NULL)
4879 gdk_window_deiconify (toplevel);
4884 * @window: a #GtkWindow
4886 * Asks to stick @window, which means that it will appear on all user
4887 * desktops. Note that you shouldn't assume the window is definitely
4888 * stuck afterward, because other entities (e.g. the user or window
4889 * manager) could unstick it again, and some window managers do not
4890 * support sticking windows. But normally the window will end up
4891 * stuck. Just don't write code that crashes if not.
4893 * It's permitted to call this function before showing a window.
4895 * You can track stickiness via the "window_state_event" signal
4900 gtk_window_stick (GtkWindow *window)
4903 GdkWindow *toplevel;
4905 g_return_if_fail (GTK_IS_WINDOW (window));
4907 widget = GTK_WIDGET (window);
4909 window->stick_initially = TRUE;
4912 toplevel = window->frame;
4914 toplevel = widget->window;
4916 if (toplevel != NULL)
4917 gdk_window_stick (toplevel);
4921 * gtk_window_unstick:
4922 * @window: a #GtkWindow
4924 * Asks to unstick @window, which means that it will appear on only
4925 * one of the user's desktops. Note that you shouldn't assume the
4926 * window is definitely unstuck afterward, because other entities
4927 * (e.g. the user or window manager) could stick it again. But
4928 * normally the window will end up stuck. Just don't write code that
4931 * You can track stickiness via the "window_state_event" signal
4936 gtk_window_unstick (GtkWindow *window)
4939 GdkWindow *toplevel;
4941 g_return_if_fail (GTK_IS_WINDOW (window));
4943 widget = GTK_WIDGET (window);
4945 window->stick_initially = FALSE;
4948 toplevel = window->frame;
4950 toplevel = widget->window;
4952 if (toplevel != NULL)
4953 gdk_window_unstick (toplevel);
4957 * gtk_window_maximize:
4958 * @window: a #GtkWindow
4960 * Asks to maximize @window, so that it becomes full-screen. Note that
4961 * you shouldn't assume the window is definitely maximized afterward,
4962 * because other entities (e.g. the user or window manager) could
4963 * unmaximize it again, and not all window managers support
4964 * maximization. But normally the window will end up maximized. Just
4965 * don't write code that crashes if not.
4967 * It's permitted to call this function before showing a window,
4968 * in which case the window will be maximized when it appears onscreen
4971 * You can track maximization via the "window_state_event" signal
4976 gtk_window_maximize (GtkWindow *window)
4979 GdkWindow *toplevel;
4981 g_return_if_fail (GTK_IS_WINDOW (window));
4983 widget = GTK_WIDGET (window);
4985 window->maximize_initially = TRUE;
4988 toplevel = window->frame;
4990 toplevel = widget->window;
4992 if (toplevel != NULL)
4993 gdk_window_maximize (toplevel);
4997 * gtk_window_unmaximize:
4998 * @window: a #GtkWindow
5000 * Asks to unmaximize @window. Note that you shouldn't assume the
5001 * window is definitely unmaximized afterward, because other entities
5002 * (e.g. the user or window manager) could maximize it again, and not
5003 * all window managers honor requests to unmaximize. But normally the
5004 * window will end up unmaximized. Just don't write code that crashes
5007 * You can track maximization via the "window_state_event" signal
5012 gtk_window_unmaximize (GtkWindow *window)
5015 GdkWindow *toplevel;
5017 g_return_if_fail (GTK_IS_WINDOW (window));
5019 widget = GTK_WIDGET (window);
5021 window->maximize_initially = FALSE;
5024 toplevel = window->frame;
5026 toplevel = widget->window;
5028 if (toplevel != NULL)
5029 gdk_window_unmaximize (toplevel);
5033 * gtk_window_set_resizable:
5034 * @window: a #GtkWindow
5035 * @resizable: %TRUE if the user can resize this window
5037 * Sets whether the user can resize a window. Windows are user resizable
5041 gtk_window_set_resizable (GtkWindow *window,
5044 g_return_if_fail (GTK_IS_WINDOW (window));
5046 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5050 * gtk_window_get_resizable:
5051 * @window: a #GtkWindow
5053 * Gets the value set by gtk_window_set_resizable().
5055 * Return value: %TRUE if the user can resize the window
5058 gtk_window_get_resizable (GtkWindow *window)
5060 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5062 /* allow_grow is most likely to indicate the semantic concept we
5063 * mean by "resizable" (and will be a reliable indicator if
5064 * set_policy() hasn't been called)
5066 return window->allow_grow;
5070 * gtk_window_set_gravity:
5071 * @window: a #GtkWindow
5072 * @gravity: window gravity
5074 * Window gravity defines the meaning of coordinates passed to
5075 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5078 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5079 * typically "do what you mean."
5083 gtk_window_set_gravity (GtkWindow *window,
5086 g_return_if_fail (GTK_IS_WINDOW (window));
5088 if (gravity != window->gravity)
5090 window->gravity = gravity;
5092 /* gtk_window_move_resize() will adapt gravity
5094 gtk_widget_queue_resize (GTK_WIDGET (window));
5099 * gtk_window_get_gravity:
5100 * @window: a #GtkWindow
5102 * Gets the value set by gtk_window_set_gravity().
5104 * Return value: window gravity
5107 gtk_window_get_gravity (GtkWindow *window)
5109 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5111 return window->gravity;
5115 * gtk_window_begin_resize_drag:
5116 * @window: a #GtkWindow
5117 * @button: mouse button that initiated the drag
5118 * @edge: position of the resize control
5119 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5120 * @root_y: Y position where the user clicked to initiate the drag
5121 * @timestamp: timestamp from the click event that initiated the drag
5123 * Starts resizing a window. This function is used if an application
5124 * has window resizing controls. When GDK can support it, the resize
5125 * will be done using the standard mechanism for the window manager or
5126 * windowing system. Otherwise, GDK will try to emulate window
5127 * resizing, potentially not all that well, depending on the windowing system.
5131 gtk_window_begin_resize_drag (GtkWindow *window,
5139 GdkWindow *toplevel;
5141 g_return_if_fail (GTK_IS_WINDOW (window));
5142 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5144 widget = GTK_WIDGET (window);
5147 toplevel = window->frame;
5149 toplevel = widget->window;
5151 gdk_window_begin_resize_drag (toplevel,
5158 * gtk_window_get_frame_dimensions:
5159 * @window: a #GtkWindow
5160 * @left: location to store the width of the frame at the left, or %NULL
5161 * @top: location to store the height of the frame at the top, or %NULL
5162 * @right: location to store the width of the frame at the returns, or %NULL
5163 * @bottom: location to store the height of the frame at the bottom, or %NULL
5165 * (Note: this is a special-purpose function intended for the
5166 * framebuffer port; see gtk_window_set_has_frame(). It will not
5167 * return the size of the window border drawn by the window manager,
5168 * which is the normal case when using a windowing system.
5169 * See gdk_window_get_frame_extents() to get the standard
5170 * window border extents.)
5172 * Retrieves the dimensions of the frame window for this toplevel.
5173 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5176 gtk_window_get_frame_dimensions (GtkWindow *window,
5182 g_return_if_fail (GTK_IS_WINDOW (window));
5185 *left = window->frame_left;
5187 *top = window->frame_top;
5189 *right = window->frame_right;
5191 *bottom = window->frame_bottom;
5195 * gtk_window_begin_move_drag:
5196 * @window: a #GtkWindow
5197 * @button: mouse button that initiated the drag
5198 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5199 * @root_y: Y position where the user clicked to initiate the drag
5200 * @timestamp: timestamp from the click event that initiated the drag
5202 * Starts moving a window. This function is used if an application
5203 * has window movement grips. When GDK can support it, the window movement
5204 * will be done using the standard mechanism for the window manager or
5205 * windowing system. Otherwise, GDK will try to emulate window
5206 * movement, potentially not all that well, depending on the windowing system.
5210 gtk_window_begin_move_drag (GtkWindow *window,
5217 GdkWindow *toplevel;
5219 g_return_if_fail (GTK_IS_WINDOW (window));
5220 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5222 widget = GTK_WIDGET (window);
5225 toplevel = window->frame;
5227 toplevel = widget->window;
5229 gdk_window_begin_move_drag (toplevel,
5237 gtk_window_group_class_init (GtkWindowGroupClass *klass)
5242 gtk_window_group_get_type (void)
5244 static GtkType window_group_type = 0;
5246 if (!window_group_type)
5248 static const GTypeInfo window_group_info =
5250 sizeof (GtkWindowGroupClass),
5251 NULL, /* base_init */
5252 NULL, /* base_finalize */
5253 (GClassInitFunc) gtk_window_group_class_init,
5254 NULL, /* class_finalize */
5255 NULL, /* class_data */
5256 sizeof (GtkWindowGroup),
5257 16, /* n_preallocs */
5258 (GInstanceInitFunc) NULL,
5261 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
5264 return window_group_type;
5268 * gtk_window_group_new:
5270 * Creates a new #GtkWindowGroup object. Grabs added with
5271 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
5273 * Return value: a new #GtkWindowGroup.
5276 gtk_window_group_new (void)
5278 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
5282 window_group_cleanup_grabs (GtkWindowGroup *group,
5286 GSList *to_remove = NULL;
5288 tmp_list = group->grabs;
5291 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
5292 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
5293 tmp_list = tmp_list->next;
5298 gtk_grab_remove (to_remove->data);
5299 g_object_unref (to_remove->data);
5300 to_remove = g_slist_delete_link (to_remove, to_remove);
5305 * gtk_window_group_add_window:
5306 * @window_group: a #GtkWindowGroup
5307 * @window: the #GtkWindow to add
5309 * Adds a window to a #GtkWindowGroup.
5312 gtk_window_group_add_window (GtkWindowGroup *window_group,
5315 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5316 g_return_if_fail (GTK_IS_WINDOW (window));
5318 if (window->group != window_group)
5320 g_object_ref (window);
5321 g_object_ref (window_group);
5324 gtk_window_group_remove_window (window->group, window);
5326 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
5328 window->group = window_group;
5330 g_object_unref (window);
5335 * gtk_window_group_remove_window:
5336 * @window_group: a #GtkWindowGroup
5337 * @window: the #GtkWindow to remove
5339 * Removes a window from a #GtkWindowGroup.
5342 gtk_window_group_remove_window (GtkWindowGroup *window_group,
5345 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5346 g_return_if_fail (GTK_IS_WIDGET (window));
5347 g_return_if_fail (window->group == window_group);
5349 g_object_ref (window);
5351 window_group_cleanup_grabs (window_group, window);
5352 window->group = NULL;
5354 g_object_unref (G_OBJECT (window_group));
5355 g_object_unref (window);
5358 /* Return the group for the window or the default group
5361 _gtk_window_get_group (GtkWindow *window)
5363 if (window && window->group)
5364 return window->group;
5367 static GtkWindowGroup *default_group = NULL;
5370 default_group = gtk_window_group_new ();
5372 return default_group;
5378 Derived from XParseGeometry() in XFree86
5380 Copyright 1985, 1986, 1987,1998 The Open Group
5382 All Rights Reserved.
5384 The above copyright notice and this permission notice shall be included
5385 in all copies or substantial portions of the Software.
5387 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5388 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5389 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
5390 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
5391 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
5392 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
5393 OTHER DEALINGS IN THE SOFTWARE.
5395 Except as contained in this notice, the name of The Open Group shall
5396 not be used in advertising or otherwise to promote the sale, use or
5397 other dealings in this Software without prior written authorization
5398 from The Open Group.
5403 * XParseGeometry parses strings of the form
5404 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5405 * width, height, xoffset, and yoffset are unsigned integers.
5406 * Example: "=80x24+300-49"
5407 * The equal sign is optional.
5408 * It returns a bitmask that indicates which of the four values
5409 * were actually found in the string. For each value found,
5410 * the corresponding argument is updated; for each value
5411 * not found, the corresponding argument is left unchanged.
5414 /* The following code is from Xlib, and is minimally modified, so we
5415 * can track any upstream changes if required. Don't change this
5416 * code. Or if you do, put in a huge comment marking which thing
5421 read_int (gchar *string,
5429 else if (*string == '-')
5435 for (; (*string >= '0') && (*string <= '9'); string++)
5437 result = (result * 10) + (*string - '0');
5449 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
5450 * value (x, y, width, height) was found in the parsed string.
5452 #define NoValue 0x0000
5453 #define XValue 0x0001
5454 #define YValue 0x0002
5455 #define WidthValue 0x0004
5456 #define HeightValue 0x0008
5457 #define AllValues 0x000F
5458 #define XNegative 0x0010
5459 #define YNegative 0x0020
5461 /* Try not to reformat/modify, so we can compare/sync with X sources */
5463 gtk_XParseGeometry (const char *string,
5466 unsigned int *width,
5467 unsigned int *height)
5471 unsigned int tempWidth, tempHeight;
5473 char *nextCharacter;
5475 /* These initializations are just to silence gcc */
5481 if ( (string == NULL) || (*string == '\0')) return(mask);
5483 string++; /* ignore possible '=' at beg of geometry spec */
5485 strind = (char *)string;
5486 if (*strind != '+' && *strind != '-' && *strind != 'x') {
5487 tempWidth = read_int(strind, &nextCharacter);
5488 if (strind == nextCharacter)
5490 strind = nextCharacter;
5494 if (*strind == 'x' || *strind == 'X') {
5496 tempHeight = read_int(strind, &nextCharacter);
5497 if (strind == nextCharacter)
5499 strind = nextCharacter;
5500 mask |= HeightValue;
5503 if ((*strind == '+') || (*strind == '-')) {
5504 if (*strind == '-') {
5506 tempX = -read_int(strind, &nextCharacter);
5507 if (strind == nextCharacter)
5509 strind = nextCharacter;
5515 tempX = read_int(strind, &nextCharacter);
5516 if (strind == nextCharacter)
5518 strind = nextCharacter;
5521 if ((*strind == '+') || (*strind == '-')) {
5522 if (*strind == '-') {
5524 tempY = -read_int(strind, &nextCharacter);
5525 if (strind == nextCharacter)
5527 strind = nextCharacter;
5534 tempY = read_int(strind, &nextCharacter);
5535 if (strind == nextCharacter)
5537 strind = nextCharacter;
5543 /* If strind isn't at the end of the string the it's an invalid
5544 geometry specification. */
5546 if (*strind != '\0') return (0);
5552 if (mask & WidthValue)
5554 if (mask & HeightValue)
5555 *height = tempHeight;
5560 * gtk_window_parse_geometry:
5561 * @window: a #GtkWindow
5562 * @geometry: geometry string
5564 * Parses a standard X Window System geometry string - see the
5565 * manual page for X (type 'man X') for details on this.
5566 * gtk_window_parse_geometry() does work on all GTK+ ports
5567 * including Win32 but is primarily intended for an X environment.
5569 * If either a size or a position can be extracted from the
5570 * geometry string, gtk_window_parse_geometry() returns %TRUE
5571 * and calls gtk_window_set_default_size() and/or gtk_window_move()
5572 * to resize/move the window.
5574 * If gtk_window_parse_geometry() returns %TRUE, it will also
5575 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
5576 * indicating to the window manager that the size/position of
5577 * the window was user-specified. This causes most window
5578 * managers to honor the geometry.
5580 * Return value: %TRUE if string was parsed successfully
5583 gtk_window_parse_geometry (GtkWindow *window,
5584 const gchar *geometry)
5589 gboolean size_set, pos_set;
5591 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5592 g_return_val_if_fail (geometry != NULL, FALSE);
5594 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
5596 if ((result & WidthValue) == 0 ||
5599 if ((result & HeightValue) == 0 ||
5604 if ((result & WidthValue) || (result & HeightValue))
5606 gtk_window_set_default_size (window, w, h);
5610 gtk_window_get_size (window, &w, &h);
5612 grav = GDK_GRAVITY_NORTH_WEST;
5614 if ((result & XNegative) && (result & YNegative))
5615 grav = GDK_GRAVITY_SOUTH_EAST;
5616 else if (result & XNegative)
5617 grav = GDK_GRAVITY_NORTH_EAST;
5618 else if (result & YNegative)
5619 grav = GDK_GRAVITY_SOUTH_WEST;
5621 if ((result & XValue) == 0)
5624 if ((result & YValue) == 0)
5627 if (grav == GDK_GRAVITY_SOUTH_WEST ||
5628 grav == GDK_GRAVITY_SOUTH_EAST)
5629 y = gdk_screen_height () - h;
5631 if (grav == GDK_GRAVITY_SOUTH_EAST ||
5632 grav == GDK_GRAVITY_NORTH_EAST)
5633 x = gdk_screen_width () - w;
5642 if ((result & XValue) || (result & YValue))
5644 gtk_window_set_gravity (window, grav);
5645 gtk_window_move (window, x, y);
5649 if (size_set || pos_set)
5651 /* Set USSize, USPosition hints */
5652 GtkWindowGeometryInfo *info;
5654 info = gtk_window_get_geometry_info (window, TRUE);
5657 info->mask |= GDK_HINT_USER_POS;
5659 info->mask |= GDK_HINT_USER_SIZE;