1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
30 #include "gdk/gdkkeysyms.h"
32 #include "gtkprivate.h"
34 #include "gtksignal.h"
35 #include "gtkwindow.h"
36 #include "gtkwindow-decorate.h"
37 #include "gtkbindings.h"
39 #include "gtkiconfactory.h"
41 #include "gtkmarshalers.h"
68 PROP_DESTROY_WITH_PARENT,
77 GdkPixmap *icon_pixmap;
80 guint using_default_icon : 1;
81 guint using_parent_icon : 1;
85 GdkGeometry geometry; /* Last set of geometry hints we set */
87 GdkRectangle configure_request;
88 } GtkWindowLastGeometryInfo;
90 struct _GtkWindowGeometryInfo
92 /* Properties that the app has set on the window
94 GdkGeometry geometry; /* Geometry hints */
96 GtkWidget *widget; /* subwidget to which hints apply */
97 /* from last gtk_window_resize () - if > 0, indicates that
98 * we should resize to this size.
103 /* From last gtk_window_move () prior to mapping -
104 * only used if initial_pos_set
109 /* Default size - used only the FIRST time we map a window,
114 /* whether to use initial_x, initial_y */
115 guint initial_pos_set : 1;
116 /* CENTER_ALWAYS or other position constraint changed since
117 * we sent the last configure request.
119 guint position_constraints_changed : 1;
121 GtkWindowLastGeometryInfo last;
132 static void gtk_window_class_init (GtkWindowClass *klass);
133 static void gtk_window_init (GtkWindow *window);
134 static void gtk_window_dispose (GObject *object);
135 static void gtk_window_destroy (GtkObject *object);
136 static void gtk_window_finalize (GObject *object);
137 static void gtk_window_show (GtkWidget *widget);
138 static void gtk_window_hide (GtkWidget *widget);
139 static void gtk_window_map (GtkWidget *widget);
140 static void gtk_window_unmap (GtkWidget *widget);
141 static void gtk_window_realize (GtkWidget *widget);
142 static void gtk_window_unrealize (GtkWidget *widget);
143 static void gtk_window_size_request (GtkWidget *widget,
144 GtkRequisition *requisition);
145 static void gtk_window_size_allocate (GtkWidget *widget,
146 GtkAllocation *allocation);
147 static gint gtk_window_event (GtkWidget *widget,
149 static gboolean gtk_window_frame_event (GtkWindow *window,
151 static gint gtk_window_configure_event (GtkWidget *widget,
152 GdkEventConfigure *event);
153 static gint gtk_window_key_press_event (GtkWidget *widget,
155 static gint gtk_window_key_release_event (GtkWidget *widget,
157 static gint gtk_window_enter_notify_event (GtkWidget *widget,
158 GdkEventCrossing *event);
159 static gint gtk_window_leave_notify_event (GtkWidget *widget,
160 GdkEventCrossing *event);
161 static gint gtk_window_focus_in_event (GtkWidget *widget,
162 GdkEventFocus *event);
163 static gint gtk_window_focus_out_event (GtkWidget *widget,
164 GdkEventFocus *event);
165 static gint gtk_window_client_event (GtkWidget *widget,
166 GdkEventClient *event);
167 static void gtk_window_check_resize (GtkContainer *container);
168 static gint gtk_window_focus (GtkWidget *widget,
169 GtkDirectionType direction);
170 static void gtk_window_real_set_focus (GtkWindow *window,
173 static void gtk_window_real_activate_default (GtkWindow *window);
174 static void gtk_window_real_activate_focus (GtkWindow *window);
175 static void gtk_window_move_focus (GtkWindow *window,
176 GtkDirectionType dir);
177 static void gtk_window_read_rcfiles (GtkWidget *widget,
178 GdkEventClient *event);
179 static void gtk_window_paint (GtkWidget *widget,
181 static gint gtk_window_expose (GtkWidget *widget,
182 GdkEventExpose *event);
183 static void gtk_window_unset_transient_for (GtkWindow *window);
184 static void gtk_window_transient_parent_realized (GtkWidget *parent,
186 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
189 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
192 static void gtk_window_move_resize (GtkWindow *window);
193 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
195 GdkGeometry *geometry_b,
197 static void gtk_window_constrain_size (GtkWindow *window,
198 GdkGeometry *geometry,
204 static void gtk_window_constrain_position (GtkWindow *window,
209 static void gtk_window_compute_hints (GtkWindow *window,
210 GdkGeometry *new_geometry,
212 static void gtk_window_compute_configure_request (GtkWindow *window,
213 GdkRectangle *request,
214 GdkGeometry *geometry,
217 static void gtk_window_set_default_size_internal (GtkWindow *window,
218 gboolean change_width,
220 gboolean change_height,
223 static void gtk_window_realize_icon (GtkWindow *window);
224 static void gtk_window_unrealize_icon (GtkWindow *window);
225 static void gtk_window_notify_accels_changed (GtkWindow *window);
227 static GSList *toplevel_list = NULL;
228 static GHashTable *mnemonic_hash_table = NULL;
229 static GtkBinClass *parent_class = NULL;
230 static guint window_signals[LAST_SIGNAL] = { 0 };
231 static GList *default_icon_list = NULL;
232 /* FIXME need to be per-screen */
233 static GdkPixmap *default_icon_pixmap = NULL;
234 static GdkPixmap *default_icon_mask = NULL;
236 static void gtk_window_set_property (GObject *object,
240 static void gtk_window_get_property (GObject *object,
247 mnemonic_hash (gconstpointer key)
249 const GtkWindowMnemonic *k;
252 k = (GtkWindowMnemonic *)key;
254 h = (gulong) k->window;
255 h ^= k->keyval << 16;
256 h ^= k->keyval >> 16;
262 mnemonic_equal (gconstpointer a, gconstpointer b)
264 const GtkWindowMnemonic *ka;
265 const GtkWindowMnemonic *kb;
267 ka = (GtkWindowMnemonic *)a;
268 kb = (GtkWindowMnemonic *)b;
271 (ka->window == kb->window) &&
272 (ka->keyval == kb->keyval);
276 gtk_window_get_type (void)
278 static GtkType window_type = 0;
282 static const GtkTypeInfo window_info =
286 sizeof (GtkWindowClass),
287 (GtkClassInitFunc) gtk_window_class_init,
288 (GtkObjectInitFunc) gtk_window_init,
289 /* reserved_1 */ NULL,
290 /* reserved_2 */ NULL,
291 (GtkClassInitFunc) NULL,
294 window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
301 gtk_window_class_init (GtkWindowClass *klass)
303 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
304 GtkObjectClass *object_class;
305 GtkWidgetClass *widget_class;
306 GtkContainerClass *container_class;
307 GtkBindingSet *binding_set;
309 object_class = (GtkObjectClass*) klass;
310 widget_class = (GtkWidgetClass*) klass;
311 container_class = (GtkContainerClass*) klass;
313 parent_class = gtk_type_class (gtk_bin_get_type ());
315 mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
317 gobject_class->dispose = gtk_window_dispose;
318 gobject_class->finalize = gtk_window_finalize;
320 gobject_class->set_property = gtk_window_set_property;
321 gobject_class->get_property = gtk_window_get_property;
323 object_class->destroy = gtk_window_destroy;
325 widget_class->show = gtk_window_show;
326 widget_class->hide = gtk_window_hide;
327 widget_class->map = gtk_window_map;
328 widget_class->unmap = gtk_window_unmap;
329 widget_class->realize = gtk_window_realize;
330 widget_class->unrealize = gtk_window_unrealize;
331 widget_class->size_request = gtk_window_size_request;
332 widget_class->size_allocate = gtk_window_size_allocate;
333 widget_class->configure_event = gtk_window_configure_event;
334 widget_class->key_press_event = gtk_window_key_press_event;
335 widget_class->key_release_event = gtk_window_key_release_event;
336 widget_class->enter_notify_event = gtk_window_enter_notify_event;
337 widget_class->leave_notify_event = gtk_window_leave_notify_event;
338 widget_class->focus_in_event = gtk_window_focus_in_event;
339 widget_class->focus_out_event = gtk_window_focus_out_event;
340 widget_class->client_event = gtk_window_client_event;
341 widget_class->focus = gtk_window_focus;
343 widget_class->expose_event = gtk_window_expose;
345 container_class->check_resize = gtk_window_check_resize;
347 klass->set_focus = gtk_window_real_set_focus;
348 klass->frame_event = gtk_window_frame_event;
350 klass->activate_default = gtk_window_real_activate_default;
351 klass->activate_focus = gtk_window_real_activate_focus;
352 klass->move_focus = gtk_window_move_focus;
353 klass->accels_changed = NULL;
356 g_object_class_install_property (gobject_class,
358 g_param_spec_enum ("type",
360 _("The type of the window"),
361 GTK_TYPE_WINDOW_TYPE,
363 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
366 g_object_class_install_property (gobject_class,
368 g_param_spec_string ("title",
370 _("The title of the window"),
374 g_object_class_install_property (gobject_class,
376 g_param_spec_boolean ("allow_shrink",
378 /* xgettext:no-c-format */
379 _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea."),
383 g_object_class_install_property (gobject_class,
385 g_param_spec_boolean ("allow_grow",
387 _("If TRUE, users can expand the window beyond its minimum size."),
391 g_object_class_install_property (gobject_class,
393 g_param_spec_boolean ("resizable",
395 _("If TRUE, users can resize the window."),
399 g_object_class_install_property (gobject_class,
401 g_param_spec_boolean ("modal",
403 _("If TRUE, the window is modal (other windows are not usable while this one is up)."),
407 g_object_class_install_property (gobject_class,
409 g_param_spec_enum ("window_position",
410 _("Window Position"),
411 _("The initial position of the window."),
412 GTK_TYPE_WINDOW_POSITION,
416 g_object_class_install_property (gobject_class,
418 g_param_spec_int ("default_width",
420 _("The default width of the window, used when initially showing the window."),
426 g_object_class_install_property (gobject_class,
428 g_param_spec_int ("default_height",
430 _("The default height of the window, used when initially showing the window."),
436 g_object_class_install_property (gobject_class,
437 PROP_DESTROY_WITH_PARENT,
438 g_param_spec_boolean ("destroy_with_parent",
439 _("Destroy with Parent"),
440 _("If this window should be destroyed when the parent is destroyed"),
444 g_object_class_install_property (gobject_class,
446 g_param_spec_object ("icon",
448 _("Icon for this window"),
452 window_signals[SET_FOCUS] =
453 g_signal_new ("set_focus",
454 G_TYPE_FROM_CLASS (object_class),
456 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
458 _gtk_marshal_VOID__OBJECT,
462 window_signals[FRAME_EVENT] =
463 g_signal_new ("frame_event",
464 G_TYPE_FROM_CLASS(object_class),
466 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
467 _gtk_boolean_handled_accumulator, NULL,
468 _gtk_marshal_BOOLEAN__BOXED,
472 window_signals[ACTIVATE_FOCUS] =
473 g_signal_new ("activate_focus",
474 G_OBJECT_CLASS_TYPE (object_class),
475 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
476 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_focus),
478 _gtk_marshal_VOID__VOID,
482 window_signals[ACTIVATE_DEFAULT] =
483 g_signal_new ("activate_default",
484 G_OBJECT_CLASS_TYPE (object_class),
485 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
486 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_default),
488 _gtk_marshal_VOID__VOID,
492 window_signals[MOVE_FOCUS] =
493 g_signal_new ("move_focus",
494 G_OBJECT_CLASS_TYPE (object_class),
495 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
496 GTK_SIGNAL_OFFSET (GtkWindowClass, move_focus),
498 _gtk_marshal_VOID__ENUM,
501 GTK_TYPE_DIRECTION_TYPE);
503 window_signals[ACCELS_CHANGED] =
504 g_signal_new ("accels_changed",
505 G_OBJECT_CLASS_TYPE (object_class),
507 GTK_SIGNAL_OFFSET (GtkWindowClass, accels_changed),
509 gtk_marshal_VOID__VOID,
517 binding_set = gtk_binding_set_by_class (klass);
519 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
520 "activate_focus", 0);
521 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
522 "activate_focus", 0);
524 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
525 "activate_default", 0);
527 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
528 "activate_default", 0);
530 gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
532 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
533 gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
535 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
537 gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
539 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
540 gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
542 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
544 gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
546 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);
547 gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
549 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);
551 gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
553 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);
554 gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
556 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);
558 gtk_binding_entry_add_signal (binding_set, GDK_Tab, 0,
560 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
561 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, 0,
563 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
564 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, 0,
566 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
568 gtk_binding_entry_add_signal (binding_set, GDK_Tab, GDK_SHIFT_MASK,
570 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
571 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, GDK_SHIFT_MASK,
573 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
574 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, GDK_SHIFT_MASK,
576 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
580 gtk_window_init (GtkWindow *window)
582 GdkColormap *colormap;
584 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
585 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
587 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
589 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
591 window->title = NULL;
592 window->wmclass_name = g_strdup (g_get_prgname ());
593 window->wmclass_class = g_strdup (gdk_get_program_class ());
594 window->wm_role = NULL;
595 window->geometry_info = NULL;
596 window->type = GTK_WINDOW_TOPLEVEL;
597 window->focus_widget = NULL;
598 window->default_widget = NULL;
599 window->configure_request_count = 0;
600 window->allow_shrink = FALSE;
601 window->allow_grow = TRUE;
602 window->configure_notify_received = FALSE;
603 window->position = GTK_WIN_POS_NONE;
604 window->need_default_size = TRUE;
605 window->need_default_position = TRUE;
606 window->modal = FALSE;
607 window->frame = NULL;
608 window->has_frame = FALSE;
609 window->frame_left = 0;
610 window->frame_right = 0;
611 window->frame_top = 0;
612 window->frame_bottom = 0;
613 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
614 window->gravity = GDK_GRAVITY_NORTH_WEST;
615 window->decorated = TRUE;
616 window->mnemonic_modifier = GDK_MOD1_MASK;
618 colormap = _gtk_widget_peek_colormap ();
620 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
622 gtk_widget_ref (GTK_WIDGET (window));
623 gtk_object_sink (GTK_OBJECT (window));
624 window->has_user_ref_count = TRUE;
625 toplevel_list = g_slist_prepend (toplevel_list, window);
627 gtk_decorated_window_init (window);
629 gtk_signal_connect (GTK_OBJECT (window),
631 GTK_SIGNAL_FUNC (gtk_window_event),
636 gtk_window_set_property (GObject *object,
643 window = GTK_WINDOW (object);
648 window->type = g_value_get_enum (value);
651 gtk_window_set_title (window, g_value_get_string (value));
653 case PROP_ALLOW_SHRINK:
654 window->allow_shrink = g_value_get_boolean (value);
655 gtk_widget_queue_resize (GTK_WIDGET (window));
657 case PROP_ALLOW_GROW:
658 window->allow_grow = g_value_get_boolean (value);
659 gtk_widget_queue_resize (GTK_WIDGET (window));
660 g_object_notify (G_OBJECT (window), "resizable");
663 window->allow_grow = g_value_get_boolean (value);
664 gtk_widget_queue_resize (GTK_WIDGET (window));
665 g_object_notify (G_OBJECT (window), "allow_grow");
668 gtk_window_set_modal (window, g_value_get_boolean (value));
671 gtk_window_set_position (window, g_value_get_enum (value));
673 case PROP_DEFAULT_WIDTH:
674 gtk_window_set_default_size_internal (window,
675 TRUE, g_value_get_int (value),
678 case PROP_DEFAULT_HEIGHT:
679 gtk_window_set_default_size_internal (window,
681 TRUE, g_value_get_int (value));
683 case PROP_DESTROY_WITH_PARENT:
684 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
687 gtk_window_set_icon (window,
688 g_value_get_object (value));
697 gtk_window_get_property (GObject *object,
704 window = GTK_WINDOW (object);
708 GtkWindowGeometryInfo *info;
710 g_value_set_enum (value, window->type);
713 g_value_set_string (value, window->title);
715 case PROP_ALLOW_SHRINK:
716 g_value_set_boolean (value, window->allow_shrink);
718 case PROP_ALLOW_GROW:
719 g_value_set_boolean (value, window->allow_grow);
722 g_value_set_boolean (value, window->allow_grow);
725 g_value_set_boolean (value, window->modal);
728 g_value_set_enum (value, window->position);
730 case PROP_DEFAULT_WIDTH:
731 info = gtk_window_get_geometry_info (window, FALSE);
733 g_value_set_int (value, -1);
735 g_value_set_int (value, info->default_width);
737 case PROP_DEFAULT_HEIGHT:
738 info = gtk_window_get_geometry_info (window, FALSE);
740 g_value_set_int (value, -1);
742 g_value_set_int (value, info->default_height);
744 case PROP_DESTROY_WITH_PARENT:
745 g_value_set_boolean (value, window->destroy_with_parent);
748 g_value_set_object (value, gtk_window_get_icon (window));
751 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
758 * @type: type of window
760 * Creates a new #GtkWindow, which is a toplevel window that can
761 * contain other widgets. Nearly always, the type of the window should
762 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
763 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
764 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
765 * dialogs, though in some other toolkits dialogs are called "popups".
766 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
767 * Popup windows are not controlled by the window manager.
769 * If you simply want an undecorated window (no window borders), use
770 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
772 * Return value: a new #GtkWindow.
775 gtk_window_new (GtkWindowType type)
779 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
781 window = gtk_type_new (GTK_TYPE_WINDOW);
785 return GTK_WIDGET (window);
789 * gtk_window_set_title:
790 * @window: a #GtkWindow
791 * @title: title of the window
793 * Sets the title of the #GtkWindow. The title of a window will be displayed in
794 * its title bar; on the X Window System, the title bar is rendered by the
795 * window manager, so exactly how the title appears to users may vary according
796 * to a user's exact configuration. The title should help a user distinguish
797 * this window from other windows they may have open. A good title might
798 * include the application name and current document filename, for example.
802 gtk_window_set_title (GtkWindow *window,
805 g_return_if_fail (GTK_IS_WINDOW (window));
808 g_free (window->title);
809 window->title = g_strdup (title);
811 if (GTK_WIDGET_REALIZED (window))
813 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
815 gtk_decorated_window_set_title (window, title);
818 g_object_notify (G_OBJECT (window), "title");
822 * gtk_window_get_title:
823 * @window: a #GtkWindow
825 * Retrieves the title of the window. See gtk_window_set_title().
827 * Return value: the title of the window, or %NULL if none has
828 * been set explicitely. The returned string is owned by the widget
829 * and must not be modified or freed.
831 G_CONST_RETURN gchar *
832 gtk_window_get_title (GtkWindow *window)
834 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
836 return window->title;
840 * gtk_window_set_wmclass:
841 * @window: a #GtkWindow
842 * @wmclass_name: window name hint
843 * @wmclass_class: window class hint
845 * Don't use this function. It sets the X Window System "class" and
846 * "name" hints for a window. According to the ICCCM, you should
847 * always set these to the same value for all windows in an
848 * application, and GTK sets them to that value by default, so calling
849 * this function is sort of pointless. However, you may want to call
850 * gtk_window_set_role() on each window in your application, for the
851 * benefit of the session manager. Setting the role allows the window
852 * manager to restore window positions when loading a saved session.
856 gtk_window_set_wmclass (GtkWindow *window,
857 const gchar *wmclass_name,
858 const gchar *wmclass_class)
860 g_return_if_fail (GTK_IS_WINDOW (window));
862 g_free (window->wmclass_name);
863 window->wmclass_name = g_strdup (wmclass_name);
865 g_free (window->wmclass_class);
866 window->wmclass_class = g_strdup (wmclass_class);
868 if (GTK_WIDGET_REALIZED (window))
869 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
873 * gtk_window_set_role:
874 * @window: a #GtkWindow
875 * @role: unique identifier for the window to be used when restoring a session
877 * In combination with the window title, the window role allows a
878 * window manager to identify "the same" window when an application is
879 * restarted. So for example you might set the "toolbox" role on your
880 * app's toolbox window, so that when the user restarts their session,
881 * the window manager can put the toolbox back in the same place.
883 * If a window already has a unique title, you don't need to set the
884 * role, since the WM can use the title to identify the window when
885 * restoring the session.
889 gtk_window_set_role (GtkWindow *window,
892 g_return_if_fail (GTK_IS_WINDOW (window));
894 if (role == window->wm_role)
897 g_free (window->wm_role);
898 window->wm_role = g_strdup (role);
900 if (GTK_WIDGET_REALIZED (window))
901 g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
905 * gtk_window_get_role:
906 * @window: a #GtkWindow
908 * Returns the role of the window. See gtk_window_set_role() for
909 * further explanation.
911 * Return value: the role of the window if set, or %NULL. The
912 * returned is owned by the widget and must not be modified
915 G_CONST_RETURN gchar *
916 gtk_window_get_role (GtkWindow *window)
918 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
920 return window->wm_role;
924 * gtk_window_set_focus:
925 * @window: a #GtkWindow
926 * @focus: widget to be the new focus widget, or %NULL to unset
927 * any focus widget for the toplevel window.
929 * If @focus is not the current focus widget, and is focusable, sets
930 * it as the focus widget for the window. If @focus is %NULL, unsets
931 * the focus widget for this window. To set the focus to a particular
932 * widget in the toplevel, it is usually more convenient to use
933 * gtk_widget_grab_focus() instead of this function.
936 gtk_window_set_focus (GtkWindow *window,
939 g_return_if_fail (GTK_IS_WINDOW (window));
942 g_return_if_fail (GTK_IS_WIDGET (focus));
943 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
947 gtk_widget_grab_focus (focus);
949 _gtk_window_internal_set_focus (window, NULL);
953 _gtk_window_internal_set_focus (GtkWindow *window,
956 g_return_if_fail (GTK_IS_WINDOW (window));
958 if ((window->focus_widget != focus) ||
959 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
960 gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
964 * gtk_window_set_default:
965 * @window: a #GtkWindow
966 * @default_widget: widget to be the default, or %NULL to unset the
967 * default widget for the toplevel.
969 * The default widget is the widget that's activated when the user
970 * presses Enter in a dialog (for example). This function sets or
971 * unsets the default widget for a #GtkWindow about. When setting
972 * (rather than unsetting) the default widget it's generally easier to
973 * call gtk_widget_grab_focus() on the widget. Before making a widget
974 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
975 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
978 gtk_window_set_default (GtkWindow *window,
979 GtkWidget *default_widget)
981 GtkWidget *old_default;
983 g_return_if_fail (GTK_IS_WINDOW (window));
986 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
988 if (window->default_widget != default_widget)
990 GtkWidget *old_default_widget = NULL;
993 g_object_ref (default_widget);
995 if (window->default_widget)
997 old_default_widget = window->default_widget;
999 if (window->focus_widget != window->default_widget ||
1000 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1001 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1002 gtk_widget_queue_draw (window->default_widget);
1005 window->default_widget = default_widget;
1007 if (window->default_widget)
1009 if (window->focus_widget == NULL ||
1010 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1011 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1012 gtk_widget_queue_draw (window->default_widget);
1015 if (old_default_widget)
1016 g_object_notify (G_OBJECT (old_default_widget), "has_default");
1020 g_object_notify (G_OBJECT (default_widget), "has_default");
1021 g_object_unref (default_widget);
1027 gtk_window_set_policy (GtkWindow *window,
1028 gboolean allow_shrink,
1029 gboolean allow_grow,
1030 gboolean auto_shrink)
1032 g_return_if_fail (GTK_IS_WINDOW (window));
1034 window->allow_shrink = (allow_shrink != FALSE);
1035 window->allow_grow = (allow_grow != FALSE);
1037 g_object_freeze_notify (G_OBJECT (window));
1038 g_object_notify (G_OBJECT (window), "allow_shrink");
1039 g_object_notify (G_OBJECT (window), "allow_grow");
1040 g_object_notify (G_OBJECT (window), "resizable");
1041 g_object_thaw_notify (G_OBJECT (window));
1043 gtk_widget_queue_resize (GTK_WIDGET (window));
1047 handle_accels_changed (gpointer data)
1051 GDK_THREADS_ENTER ();
1052 window = GTK_WINDOW (data);
1054 if (window->accels_changed_handler)
1056 gtk_idle_remove (window->accels_changed_handler);
1057 window->accels_changed_handler = 0;
1060 g_signal_emit (window, window_signals[ACCELS_CHANGED], 0);
1061 GDK_THREADS_LEAVE ();
1067 gtk_window_notify_accels_changed (GtkWindow *window)
1069 if (!window->accels_changed_handler)
1070 window->accels_changed_handler = gtk_idle_add (handle_accels_changed, window);
1074 * gtk_window_add_accel_group:
1075 * @window: window to attach accelerator group to
1076 * @accel_group: a #GtkAccelGroup
1078 * Associate @accel_group with @window, such that calling
1079 * gtk_accel_groups_activate() on @window will activate accelerators
1083 gtk_window_add_accel_group (GtkWindow *window,
1084 GtkAccelGroup *accel_group)
1086 g_return_if_fail (GTK_IS_WINDOW (window));
1087 g_return_if_fail (accel_group != NULL);
1089 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1090 g_signal_connect_object (accel_group, "accel_changed",
1091 G_CALLBACK (gtk_window_notify_accels_changed),
1092 window, G_CONNECT_SWAPPED);
1096 * gtk_accel_group_detach:
1097 * @accel_group: a #GtkAccelGroup
1098 * @object: a #GObject
1100 * Reverses the effects of gtk_window_add_accel_group().
1103 gtk_window_remove_accel_group (GtkWindow *window,
1104 GtkAccelGroup *accel_group)
1106 g_return_if_fail (GTK_IS_WINDOW (window));
1107 g_return_if_fail (accel_group != NULL);
1109 g_signal_handlers_disconnect_by_func (accel_group,
1110 G_CALLBACK (gtk_window_notify_accels_changed),
1112 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1116 gtk_window_add_mnemonic (GtkWindow *window,
1120 GtkWindowMnemonic key;
1121 GtkWindowMnemonic *mnemonic;
1123 g_return_if_fail (GTK_IS_WINDOW (window));
1124 g_return_if_fail (GTK_IS_WIDGET (target));
1126 key.window = window;
1127 key.keyval = keyval;
1128 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1132 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1133 mnemonic->targets = g_slist_prepend (mnemonic->targets, target);
1137 mnemonic = g_new (GtkWindowMnemonic, 1);
1139 mnemonic->targets = g_slist_prepend (NULL, target);
1140 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1142 gtk_window_notify_accels_changed (window);
1146 gtk_window_remove_mnemonic (GtkWindow *window,
1150 GtkWindowMnemonic key;
1151 GtkWindowMnemonic *mnemonic;
1153 g_return_if_fail (GTK_IS_WINDOW (window));
1154 g_return_if_fail (GTK_IS_WIDGET (target));
1156 key.window = window;
1157 key.keyval = keyval;
1158 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1160 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1162 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1163 if (mnemonic->targets == NULL)
1165 g_hash_table_remove (mnemonic_hash_table, mnemonic);
1168 gtk_window_notify_accels_changed (window);
1172 gtk_window_mnemonic_activate (GtkWindow *window,
1174 GdkModifierType modifier)
1176 GtkWindowMnemonic key;
1177 GtkWindowMnemonic *mnemonic;
1179 GtkWidget *widget, *chosen_widget;
1180 gboolean overloaded;
1182 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1184 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1187 key.window = window;
1188 key.keyval = keyval;
1189 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1195 chosen_widget = NULL;
1196 list = mnemonic->targets;
1199 widget = GTK_WIDGET (list->data);
1201 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1202 GTK_WIDGET_MAPPED (widget))
1210 chosen_widget = widget;
1212 list = g_slist_next (list);
1217 /* For round robin we put the activated entry on
1218 * the end of the list after activation
1220 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1221 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1223 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1229 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1230 GdkModifierType modifier)
1232 g_return_if_fail (GTK_IS_WINDOW (window));
1233 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1235 window->mnemonic_modifier = modifier;
1236 gtk_window_notify_accels_changed (window);
1240 * gtk_window_get_mnemonic_modifier:
1241 * @window: a #GtkWindow
1243 * Returns the mnemonic modifier for this window. See
1244 * gtk_window_set_mnemonic_modifier().
1246 * Return value: the modifier mask used to activate
1247 * mnemonics on this window.
1250 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1252 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1254 return window->mnemonic_modifier;
1258 gtk_window_set_position (GtkWindow *window,
1259 GtkWindowPosition position)
1261 g_return_if_fail (GTK_IS_WINDOW (window));
1263 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1264 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1266 GtkWindowGeometryInfo *info;
1268 info = gtk_window_get_geometry_info (window, TRUE);
1270 /* this flag causes us to re-request the CENTER_ALWAYS
1271 * constraint in gtk_window_move_resize(), see
1272 * comment in that function.
1274 info->position_constraints_changed = TRUE;
1276 gtk_widget_queue_resize (GTK_WIDGET (window));
1279 window->position = position;
1281 g_object_notify (G_OBJECT (window), "window_position");
1285 gtk_window_activate_focus (GtkWindow *window)
1287 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1289 if (window->focus_widget)
1291 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1292 gtk_widget_activate (window->focus_widget);
1300 * gtk_window_get_focus:
1301 * @window: a #GtkWindow
1303 * Retrieves the current focused widget within the window.
1304 * Note that this is the widget that would have the focus
1305 * if the toplevel window focused; if the toplevel window
1306 * is not focused the GTK_WIDGET_HAS_FOCUS(widget) will
1307 * not be %TRUE for the widget.
1309 * Return value: the currently focused widget.
1312 gtk_window_get_focus (GtkWindow *window)
1314 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1316 return window->focus_widget;
1320 gtk_window_activate_default (GtkWindow *window)
1322 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1324 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1325 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1327 gtk_widget_activate (window->default_widget);
1330 else if (window->focus_widget)
1332 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1333 gtk_widget_activate (window->focus_widget);
1341 * gtk_window_set_modal:
1342 * @window: a #GtkWindow
1343 * @modal: whether the window is modal
1345 * Sets a window modal or non-modal. Modal windows prevent interaction
1346 * with other windows in the same application. To keep modal dialogs
1347 * on top of main application windows, use
1348 * gtk_window_set_transient_for() to make the dialog transient for the
1349 * parent; most window managers will then disallow lowering the dialog
1355 gtk_window_set_modal (GtkWindow *window,
1358 g_return_if_fail (GTK_IS_WINDOW (window));
1360 window->modal = modal != FALSE;
1362 /* adjust desired modality state */
1363 if (GTK_WIDGET_VISIBLE (window) && window->modal)
1364 gtk_grab_add (GTK_WIDGET (window));
1366 gtk_grab_remove (GTK_WIDGET (window));
1368 g_object_notify (G_OBJECT (window), "modal");
1372 * gtk_window_get_modal:
1373 * @window: a #GtkWindow
1375 * Returns whether the window is modal. See gtk_window_set_modal().
1377 * Return value: %TRUE if the window is set to be modal and
1378 * establishes a grab when shown
1381 gtk_window_get_modal (GtkWindow *window)
1383 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1385 return window->modal;
1389 * gtk_window_list_toplevels:
1391 * Returns a list of all existing toplevel windows. The widgets
1392 * in the list are not individually referenced. If you want
1393 * to iterate through the list and perform actions involving
1394 * callbacks that might destroy the widgets, you MUST call
1395 * g_list_foreach (result, (GFunc)g_object_ref, NULL) first, and
1396 * then unref all the widgets afterwards.
1398 * Return value: list of toplevel widgets
1401 gtk_window_list_toplevels (void)
1406 for (slist = toplevel_list; slist; slist = slist->next)
1407 list = g_list_prepend (list, slist->data);
1413 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1415 GList *embedded_windows;
1417 g_return_if_fail (GTK_IS_WINDOW (window));
1419 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1420 if (embedded_windows)
1421 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1422 g_quark_from_static_string ("gtk-embedded"));
1423 embedded_windows = g_list_prepend (embedded_windows,
1424 GUINT_TO_POINTER (xid));
1426 gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
1429 (GtkDestroyNotify) g_list_free : NULL);
1433 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1435 GList *embedded_windows;
1438 g_return_if_fail (GTK_IS_WINDOW (window));
1440 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1441 if (embedded_windows)
1442 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1443 g_quark_from_static_string ("gtk-embedded"));
1445 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1448 embedded_windows = g_list_remove_link (embedded_windows, node);
1449 g_list_free_1 (node);
1452 gtk_object_set_data_full (GTK_OBJECT (window),
1453 "gtk-embedded", embedded_windows,
1455 (GtkDestroyNotify) g_list_free : NULL);
1459 _gtk_window_reposition (GtkWindow *window,
1463 g_return_if_fail (GTK_IS_WINDOW (window));
1465 gtk_window_move (window, x, y);
1469 gtk_window_dispose (GObject *object)
1473 g_return_if_fail (GTK_IS_WINDOW (object));
1475 window = GTK_WINDOW (object);
1477 gtk_window_set_focus (window, NULL);
1478 gtk_window_set_default (window, NULL);
1480 G_OBJECT_CLASS (parent_class)->dispose (object);
1484 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1486 gtk_widget_destroy (GTK_WIDGET (child));
1490 connect_parent_destroyed (GtkWindow *window)
1492 if (window->transient_parent)
1494 gtk_signal_connect (GTK_OBJECT (window->transient_parent),
1496 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1502 disconnect_parent_destroyed (GtkWindow *window)
1504 if (window->transient_parent)
1506 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1507 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1513 gtk_window_transient_parent_realized (GtkWidget *parent,
1516 if (GTK_WIDGET_REALIZED (window))
1517 gdk_window_set_transient_for (window->window, parent->window);
1521 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1524 if (GTK_WIDGET_REALIZED (window))
1525 gdk_property_delete (window->window,
1526 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1530 gtk_window_unset_transient_for (GtkWindow *window)
1532 if (window->transient_parent)
1534 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1535 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1537 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1538 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1540 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1541 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1542 &window->transient_parent);
1544 if (window->destroy_with_parent)
1545 disconnect_parent_destroyed (window);
1547 window->transient_parent = NULL;
1552 * gtk_window_set_transient_for:
1553 * @window: a #GtkWindow
1554 * @parent: parent window
1556 * Dialog windows should be set transient for the main application
1557 * window they were spawned from. This allows window managers to
1558 * e.g. keep the dialog on top of the main window, or center the
1559 * dialog over the main window. gtk_dialog_new_with_buttons() and
1560 * other convenience functions in GTK+ will sometimes call
1561 * gtk_window_set_transient_for() on your behalf.
1565 gtk_window_set_transient_for (GtkWindow *window,
1568 g_return_if_fail (GTK_IS_WINDOW (window));
1569 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1570 g_return_if_fail (window != parent);
1573 if (window->transient_parent)
1575 if (GTK_WIDGET_REALIZED (window) &&
1576 GTK_WIDGET_REALIZED (window->transient_parent) &&
1577 (!parent || !GTK_WIDGET_REALIZED (parent)))
1578 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1579 GTK_WIDGET (window));
1581 gtk_window_unset_transient_for (window);
1584 window->transient_parent = parent;
1588 gtk_signal_connect (GTK_OBJECT (parent), "destroy",
1589 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1590 &window->transient_parent);
1591 gtk_signal_connect (GTK_OBJECT (parent), "realize",
1592 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1594 gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
1595 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1598 if (window->destroy_with_parent)
1599 connect_parent_destroyed (window);
1601 if (GTK_WIDGET_REALIZED (window) &&
1602 GTK_WIDGET_REALIZED (parent))
1603 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1604 GTK_WIDGET (window));
1609 * gtk_window_get_transient_for:
1610 * @window: a #GtkWindow
1612 * Fetches the transient parent for this window. See
1613 * gtk_window_set_transient_for().
1615 * Return value: the transient parent for this window, or %NULL
1616 * if no transient parent has been set.
1619 gtk_window_get_transient_for (GtkWindow *window)
1621 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1623 return window->transient_parent;
1627 * gtk_window_set_type_hint:
1628 * @window: a #GtkWindow
1629 * @hint: the window type
1631 * By setting the type hint for the window, you allow the window
1632 * manager to decorate and handle the window in a way which is
1633 * suitable to the function of the window in your application.
1635 * This function should be called before the window becomes visible.
1637 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1638 * will sometimes call gtk_window_set_type_hint() on your behalf.
1642 gtk_window_set_type_hint (GtkWindow *window,
1643 GdkWindowTypeHint hint)
1645 g_return_if_fail (GTK_IS_WINDOW (window));
1646 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1647 window->type_hint = hint;
1651 * gtk_window_get_type_hint:
1652 * @window: a #GtkWindow
1654 * Gets the type hint for this window. See gtk_window_set_type_hint().
1656 * Return value: the type hint for @window.
1659 gtk_window_get_type_hint (GtkWindow *window)
1661 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1663 return window->type_hint;
1667 * gtk_window_set_destroy_with_parent:
1668 * @window: a #GtkWindow
1669 * @setting: whether to destroy @window with its transient parent
1671 * If @setting is TRUE, then destroying the transient parent of @window
1672 * will also destroy @window itself. This is useful for dialogs that
1673 * shouldn't persist beyond the lifetime of the main window they're
1674 * associated with, for example.
1677 gtk_window_set_destroy_with_parent (GtkWindow *window,
1680 g_return_if_fail (GTK_IS_WINDOW (window));
1682 if (window->destroy_with_parent == (setting != FALSE))
1685 if (window->destroy_with_parent)
1687 disconnect_parent_destroyed (window);
1691 connect_parent_destroyed (window);
1694 window->destroy_with_parent = setting;
1696 g_object_notify (G_OBJECT (window), "destroy_with_parent");
1700 * gtk_window_get_destroy_with_parent:
1701 * @window: a #GtkWindow
1703 * Returns whether the window will be destroyed with its transient parent. See
1704 * gtk_window_set_destroy_with_parent ().
1706 * Return value: %TRUE if the window will be destroyed with its transient parent.
1709 gtk_window_get_destroy_with_parent (GtkWindow *window)
1711 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1713 return window->destroy_with_parent;
1716 static GtkWindowGeometryInfo*
1717 gtk_window_get_geometry_info (GtkWindow *window,
1720 GtkWindowGeometryInfo *info;
1722 info = window->geometry_info;
1723 if (!info && create)
1725 info = g_new0 (GtkWindowGeometryInfo, 1);
1727 info->default_width = -1;
1728 info->default_height = -1;
1729 info->resize_width = -1;
1730 info->resize_height = -1;
1731 info->initial_x = 0;
1732 info->initial_y = 0;
1733 info->initial_pos_set = FALSE;
1734 info->position_constraints_changed = FALSE;
1735 info->last.configure_request.x = 0;
1736 info->last.configure_request.y = 0;
1737 info->last.configure_request.width = -1;
1738 info->last.configure_request.height = -1;
1739 info->widget = NULL;
1741 window->geometry_info = info;
1748 * gtk_window_set_geometry_hints:
1749 * @window: a #GtkWindow
1750 * @geometry_widget: widget the geometry hints will be applied to
1751 * @geometry: struct containing geometry information
1752 * @geom_mask: mask indicating which struct fields should be paid attention to
1754 * This function sets up hints about how a window can be resized by
1755 * the user. You can set a minimum and maximum size; allowed resize
1756 * increments (e.g. for xterm, you can only resize by the size of a
1757 * character); aspect ratios; and more. See the #GdkGeometry struct.
1761 gtk_window_set_geometry_hints (GtkWindow *window,
1762 GtkWidget *geometry_widget,
1763 GdkGeometry *geometry,
1764 GdkWindowHints geom_mask)
1766 GtkWindowGeometryInfo *info;
1768 g_return_if_fail (window != NULL);
1770 info = gtk_window_get_geometry_info (window, TRUE);
1773 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1774 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1777 info->widget = geometry_widget;
1779 gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
1780 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1784 info->geometry = *geometry;
1786 /* We store gravity in window->gravity not in the hints. */
1787 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
1789 if (geom_mask & GDK_HINT_WIN_GRAVITY)
1791 gtk_window_set_gravity (window, geometry->win_gravity);
1794 gtk_widget_queue_resize (GTK_WIDGET (window));
1798 * gtk_window_set_decorated:
1799 * @window: a #GtkWindow
1800 * @setting: %TRUE to decorate the window
1802 * By default, windows are decorated with a title bar, resize
1803 * controls, etc. Some window managers allow GTK+ to disable these
1804 * decorations, creating a borderless window. If you set the decorated
1805 * property to %FALSE using this function, GTK+ will do its best to
1806 * convince the window manager not to decorate the window.
1810 gtk_window_set_decorated (GtkWindow *window,
1813 g_return_if_fail (GTK_IS_WINDOW (window));
1815 setting = setting != FALSE;
1817 if (setting == window->decorated)
1820 window->decorated = setting;
1822 if (GTK_WIDGET (window)->window)
1824 if (window->decorated)
1825 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1828 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1834 * gtk_window_get_decorated:
1835 * @window: a #GtkWindow
1837 * Returns whether the window has been set to have decorations
1838 * such as a title bar via gtk_window_set_decorated().
1840 * Return value: %TRUE if the window has been set to have decorations
1843 gtk_window_get_decorated (GtkWindow *window)
1845 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
1847 return window->decorated;
1850 static GtkWindowIconInfo*
1851 get_icon_info (GtkWindow *window)
1853 return g_object_get_data (G_OBJECT (window),
1854 "gtk-window-icon-info");
1857 static GtkWindowIconInfo*
1858 ensure_icon_info (GtkWindow *window)
1860 GtkWindowIconInfo *info;
1862 info = get_icon_info (window);
1866 info = g_new0 (GtkWindowIconInfo, 1);
1867 g_object_set_data_full (G_OBJECT (window),
1868 "gtk-window-icon-info",
1877 get_pixmap_and_mask (GtkWindowIconInfo *parent_info,
1878 gboolean is_default_list,
1880 GdkPixmap **pmap_return,
1881 GdkBitmap **mask_return)
1883 GdkPixbuf *best_icon;
1887 *pmap_return = NULL;
1888 *mask_return = NULL;
1890 if (is_default_list &&
1891 default_icon_pixmap != NULL)
1893 /* Use shared icon pixmap (eventually will be stored on the
1896 if (default_icon_pixmap)
1897 g_object_ref (G_OBJECT (default_icon_pixmap));
1898 if (default_icon_mask)
1899 g_object_ref (G_OBJECT (default_icon_mask));
1901 *pmap_return = default_icon_pixmap;
1902 *mask_return = default_icon_mask;
1904 else if (parent_info && parent_info->icon_pixmap)
1906 if (parent_info->icon_pixmap)
1907 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1908 if (parent_info->icon_mask)
1909 g_object_ref (G_OBJECT (parent_info->icon_mask));
1911 *pmap_return = parent_info->icon_pixmap;
1912 *mask_return = parent_info->icon_mask;
1916 #define IDEAL_SIZE 48
1918 best_size = G_MAXINT;
1920 tmp_list = icon_list;
1921 while (tmp_list != NULL)
1923 GdkPixbuf *pixbuf = tmp_list->data;
1926 /* average width and height - if someone passes in a rectangular
1927 * icon they deserve what they get.
1929 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
1932 if (best_icon == NULL)
1939 /* icon is better if it's 32 pixels or larger, and closer to
1940 * the ideal size than the current best.
1943 (ABS (best_size - IDEAL_SIZE) <
1944 ABS (this - IDEAL_SIZE)))
1951 tmp_list = tmp_list->next;
1955 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
1956 gdk_colormap_get_system (),
1961 /* Save pmap/mask for others to use if appropriate */
1964 parent_info->icon_pixmap = *pmap_return;
1965 parent_info->icon_mask = *mask_return;
1967 if (parent_info->icon_pixmap)
1968 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1969 if (parent_info->icon_mask)
1970 g_object_ref (G_OBJECT (parent_info->icon_mask));
1972 else if (is_default_list)
1974 default_icon_pixmap = *pmap_return;
1975 default_icon_mask = *mask_return;
1977 if (default_icon_pixmap)
1978 g_object_add_weak_pointer (G_OBJECT (default_icon_pixmap),
1979 (gpointer*)&default_icon_pixmap);
1980 if (default_icon_mask)
1981 g_object_add_weak_pointer (G_OBJECT (default_icon_mask),
1982 (gpointer*)&default_icon_mask);
1988 gtk_window_realize_icon (GtkWindow *window)
1991 GtkWindowIconInfo *info;
1994 widget = GTK_WIDGET (window);
1996 g_return_if_fail (widget->window != NULL);
1998 /* no point setting an icon on override-redirect */
1999 if (window->type == GTK_WINDOW_POPUP)
2004 info = ensure_icon_info (window);
2009 g_return_if_fail (info->icon_pixmap == NULL);
2010 g_return_if_fail (info->icon_mask == NULL);
2012 info->using_default_icon = FALSE;
2013 info->using_parent_icon = FALSE;
2015 icon_list = info->icon_list;
2017 /* Inherit from transient parent */
2018 if (icon_list == NULL && window->transient_parent)
2020 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2022 info->using_parent_icon = TRUE;
2025 /* Inherit from default */
2026 if (icon_list == NULL)
2028 icon_list = default_icon_list;
2030 info->using_default_icon = TRUE;
2033 gdk_window_set_icon_list (widget->window, icon_list);
2035 get_pixmap_and_mask (info->using_parent_icon ?
2036 ensure_icon_info (window->transient_parent) : NULL,
2037 info->using_default_icon,
2042 /* This is a slight ICCCM violation since it's a color pixmap not
2043 * a bitmap, but everyone does it.
2045 gdk_window_set_icon (widget->window,
2050 info->realized = TRUE;
2054 gtk_window_unrealize_icon (GtkWindow *window)
2056 GtkWindowIconInfo *info;
2059 widget = GTK_WIDGET (window);
2061 info = get_icon_info (window);
2066 if (info->icon_pixmap)
2067 g_object_unref (G_OBJECT (info->icon_pixmap));
2069 if (info->icon_mask)
2070 g_object_unref (G_OBJECT (info->icon_mask));
2072 info->icon_pixmap = NULL;
2073 info->icon_mask = NULL;
2075 /* We don't clear the properties on the window, just figure the
2076 * window is going away.
2079 info->realized = FALSE;
2083 * gtk_window_set_icon_list:
2084 * @window: a #GtkWindow
2085 * @list: list of #GdkPixbuf
2087 * Sets up the icon representing a #GtkWindow. The icon is used when
2088 * the window is minimized (also known as iconified). Some window
2089 * managers or desktop environments may also place it in the window
2090 * frame, or display it in other contexts.
2092 * gtk_window_set_icon_list() allows you to pass in the same icon in
2093 * several hand-drawn sizes. The list should contain the natural sizes
2094 * your icon is available in; that is, don't scale the image before
2095 * passing it to GTK+. Scaling is postponed until the last minute,
2096 * when the desired final size is known, to allow best quality.
2098 * By passing several sizes, you may improve the final image quality
2099 * of the icon, by reducing or eliminating automatic image scaling.
2101 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2102 * larger images (64x64, 128x128) if you have them.
2104 * See also gtk_window_set_default_icon_list() to set the icon
2105 * for all windows in your application in one go.
2107 * Note that transient windows (those who have been set transient for another
2108 * window using gtk_window_set_transient_for()) will inherit their
2109 * icon from their transient parent. So there's no need to explicitly
2110 * set the icon on transient windows.
2113 gtk_window_set_icon_list (GtkWindow *window,
2116 GtkWindowIconInfo *info;
2118 g_return_if_fail (GTK_IS_WINDOW (window));
2120 info = ensure_icon_info (window);
2122 if (info->icon_list == list) /* check for NULL mostly */
2125 g_list_foreach (info->icon_list,
2126 (GFunc) g_object_unref, NULL);
2128 g_list_free (info->icon_list);
2130 info->icon_list = g_list_copy (list);
2131 g_list_foreach (info->icon_list,
2132 (GFunc) g_object_ref, NULL);
2134 g_object_notify (G_OBJECT (window), "icon");
2136 gtk_window_unrealize_icon (window);
2138 if (GTK_WIDGET_REALIZED (window))
2139 gtk_window_realize_icon (window);
2141 /* We could try to update our transient children, but I don't think
2142 * it's really worth it. If we did it, the best way would probably
2143 * be to have children connect to notify::icon_list
2148 * gtk_window_get_icon_list:
2149 * @window: a #GtkWindow
2151 * Retrieves the list of icons set by gtk_window_set_icon_list().
2152 * The list is copied, but the reference count on each
2153 * member won't be incremented.
2155 * Return value: copy of window's icon list
2158 gtk_window_get_icon_list (GtkWindow *window)
2160 GtkWindowIconInfo *info;
2162 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2164 info = get_icon_info (window);
2167 return g_list_copy (info->icon_list);
2173 * gtk_window_set_icon:
2174 * @window: a #GtkWindow
2175 * @icon: icon image, or %NULL
2177 * Sets up the icon representing a #GtkWindow. This icon is used when
2178 * the window is minimized (also known as iconified). Some window
2179 * managers or desktop environments may also place it in the window
2180 * frame, or display it in other contexts.
2182 * The icon should be provided in whatever size it was naturally
2183 * drawn; that is, don't scale the image before passing it to
2184 * GTK+. Scaling is postponed until the last minute, when the desired
2185 * final size is known, to allow best quality.
2187 * If you have your icon hand-drawn in multiple sizes, use
2188 * gtk_window_set_icon_list(). Then the best size will be used.
2190 * This function is equivalent to calling gtk_window_set_icon_list()
2191 * with a 1-element list.
2193 * See also gtk_window_set_default_icon_list() to set the icon
2194 * for all windows in your application in one go.
2197 gtk_window_set_icon (GtkWindow *window,
2202 g_return_if_fail (GTK_IS_WINDOW (window));
2203 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2206 list = g_list_append (list, icon);
2207 gtk_window_set_icon_list (window, list);
2212 * gtk_window_get_icon:
2213 * @window: a #GtkWindow
2215 * Gets the value set by gtk_window_set_icon() (or if you've
2216 * called gtk_window_set_icon_list(), gets the first icon in
2219 * Return value: icon for window
2222 gtk_window_get_icon (GtkWindow *window)
2224 GtkWindowIconInfo *info;
2226 info = get_icon_info (window);
2227 if (info && info->icon_list)
2228 return GDK_PIXBUF (info->icon_list->data);
2234 * gtk_window_set_default_icon_list:
2235 * @list: a list of #GdkPixbuf
2237 * Sets an icon list to be used as fallback for windows that haven't
2238 * had gtk_window_set_icon_list() called on them to set up a
2239 * window-specific icon list. This function allows you to set up the
2240 * icon for all windows in your app at once.
2242 * See gtk_window_set_icon_list() for more details.
2246 gtk_window_set_default_icon_list (GList *list)
2250 if (list == default_icon_list)
2253 if (default_icon_pixmap)
2254 g_object_unref (G_OBJECT (default_icon_pixmap));
2255 if (default_icon_mask)
2256 g_object_unref (G_OBJECT (default_icon_mask));
2258 default_icon_pixmap = NULL;
2259 default_icon_mask = NULL;
2261 g_list_foreach (default_icon_list,
2262 (GFunc) g_object_unref, NULL);
2264 g_list_free (default_icon_list);
2266 default_icon_list = g_list_copy (list);
2267 g_list_foreach (default_icon_list,
2268 (GFunc) g_object_ref, NULL);
2270 /* Update all toplevels */
2271 toplevels = gtk_window_list_toplevels ();
2272 tmp_list = toplevels;
2273 while (tmp_list != NULL)
2275 GtkWindowIconInfo *info;
2276 GtkWindow *w = tmp_list->data;
2278 info = get_icon_info (w);
2279 if (info && info->using_default_icon)
2281 gtk_window_unrealize_icon (w);
2282 if (GTK_WIDGET_REALIZED (w))
2283 gtk_window_realize_icon (w);
2286 tmp_list = tmp_list->next;
2288 g_list_free (toplevels);
2292 * gtk_window_get_default_icon_list:
2294 * Gets the value set by gtk_window_set_default_icon_list().
2295 * The list is a copy and should be freed with g_list_free(),
2296 * but the pixbufs in the list have not had their reference count
2299 * Return value: copy of default icon list
2302 gtk_window_get_default_icon_list (void)
2304 return g_list_copy (default_icon_list);
2308 gtk_window_set_default_size_internal (GtkWindow *window,
2309 gboolean change_width,
2311 gboolean change_height,
2314 GtkWindowGeometryInfo *info;
2316 g_return_if_fail (GTK_IS_WINDOW (window));
2317 g_return_if_fail (change_width == FALSE || width >= -1);
2318 g_return_if_fail (change_height == FALSE || height >= -1);
2320 info = gtk_window_get_geometry_info (window, TRUE);
2322 g_object_freeze_notify (G_OBJECT (window));
2332 info->default_width = width;
2334 g_object_notify (G_OBJECT (window), "default_width");
2345 info->default_height = height;
2347 g_object_notify (G_OBJECT (window), "default_height");
2350 g_object_thaw_notify (G_OBJECT (window));
2352 gtk_widget_queue_resize (GTK_WIDGET (window));
2356 * gtk_window_set_default_size:
2357 * @window: a #GtkWindow
2358 * @width: width in pixels, or -1 to unset the default width
2359 * @height: height in pixels, or -1 to unset the default height
2361 * Sets the default size of a window. If the window's "natural" size
2362 * (its size request) is larger than the default, the default will be
2363 * ignored. More generally, if the default size does not obey the
2364 * geometry hints for the window (gtk_window_set_geometry_hints() can
2365 * be used to set these explicitly), the default size will be clamped
2366 * to the nearest permitted size.
2368 * Unlike gtk_widget_set_size_request(), which sets a size request for
2369 * a widget and thus would keep users from shrinking the window, this
2370 * function only sets the initial size, just as if the user had
2371 * resized the window themselves. Users can still shrink the window
2372 * again as they normally would. Setting a default size of -1 means to
2373 * use the "natural" default size (the size request of the window).
2375 * For more control over a window's initial size and how resizing works,
2376 * investigate gtk_window_set_geometry_hints().
2378 * A useful feature: if you set the "geometry widget" via
2379 * gtk_window_set_geometry_hints(), the default size specified by
2380 * gtk_window_set_default_size() will be the default size of that
2381 * widget, not of the entire window.
2383 * For some uses, gtk_window_resize() is a more appropriate function.
2384 * gtk_window_resize() changes the current size of the window, rather
2385 * than the size to be used on initial display. gtk_window_resize() always
2386 * affects the window itself, not the geometry widget.
2388 * The default size of a window only affects the first time a window is
2389 * shown; if a window is hidden and re-shown, it will remember the size
2390 * it had prior to hiding, rather than using the default size.
2392 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2393 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2396 gtk_window_set_default_size (GtkWindow *window,
2400 g_return_if_fail (GTK_IS_WINDOW (window));
2401 g_return_if_fail (width >= -1);
2402 g_return_if_fail (height >= -1);
2404 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height);
2408 * gtk_window_get_default_size:
2409 * @window: a #GtkWindow
2410 * @width: location to store the default width, or %NULL
2411 * @height: location to store the default height, or %NULL
2413 * Gets the default size of the window. A value of -1 for the width or
2414 * height indicates that a default size has not been explicitly set
2415 * for that dimension, so the "natural" size of the window will be
2420 gtk_window_get_default_size (GtkWindow *window,
2424 GtkWindowGeometryInfo *info;
2426 g_return_if_fail (GTK_IS_WINDOW (window));
2428 info = gtk_window_get_geometry_info (window, FALSE);
2431 *width = info->default_width;
2434 *height = info->default_height;
2438 * gtk_window_resize:
2439 * @window: a #GtkWindow
2440 * @width: width to resize the window to
2441 * @height: height to resize the window to
2443 * Resizes the window as if the user had done so, obeying geometry
2444 * constraints. The default geometry constraint is that windows may
2445 * not be smaller than their size request; to override this
2446 * constraint, call gtk_widget_set_size_request() to set the window's
2447 * request to a smaller value.
2449 * If gtk_window_resize() is called before showing a window for the
2450 * first time, it overrides any default size set with
2451 * gtk_window_set_default_size().
2453 * Windows may not be resized smaller than 1 by 1 pixels.
2457 gtk_window_resize (GtkWindow *window,
2461 GtkWindowGeometryInfo *info;
2463 g_return_if_fail (GTK_IS_WINDOW (window));
2464 g_return_if_fail (width > 0);
2465 g_return_if_fail (height > 0);
2467 info = gtk_window_get_geometry_info (window, TRUE);
2469 info->resize_width = width;
2470 info->resize_height = height;
2472 gtk_widget_queue_resize (GTK_WIDGET (window));
2476 * gtk_window_get_size:
2477 * @window: a #GtkWindow
2478 * @width: return location for width, or %NULL
2479 * @height: return location for height, or %NULL
2481 * Obtains the current size of @window. If @window is not onscreen,
2482 * it returns the size GTK+ will suggest to the window manager for the
2483 * initial window size (but this is not reliably the same as the size
2484 * the window manager will actually select). The size obtained by
2485 * gtk_window_get_size() is the last size received in a
2486 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2487 * rather than querying the X server for the size. As a result, if you
2488 * call gtk_window_resize() then immediately call
2489 * gtk_window_get_size(), the size won't have taken effect yet. After
2490 * the window manager processes the resize request, GTK+ receives
2491 * notification that the size has changed via a configure event, and
2492 * the size of the window gets updated.
2494 * Note 1: Nearly any use of this function creates a race condition,
2495 * because the size of the window may change between the time that you
2496 * get the size and the time that you perform some action assuming
2497 * that size is the current size. To avoid race conditions, connect to
2498 * "configure_event" on the window and adjust your size-dependent
2499 * state to match the size delivered in the #GdkEventConfigure.
2501 * Note 2: The returned size does NOT include the size of the window
2502 * manager decorations (aka the window frame or border). Those
2503 * are not drawn by GTK+ and GTK+ has no reliable method of
2504 * determining their size.
2506 * Note 3: If you are getting a window size in order to position
2507 * the window onscreen, there may be a better way. The preferred
2508 * way is to simply set the window's semantic type with
2509 * gtk_window_set_type_hint(), which allows the window manager to
2510 * e.g. center dialogs. Also, if you set the transient parent of
2511 * dialogs with gtk_widget_set_transient_for() window managers
2512 * will often center the dialog over its parent window. It's
2513 * much preferred to let the window manager handle these
2514 * things rather than doing it yourself, because all apps will
2515 * behave consistently and according to user prefs if the window
2516 * manager handles it. Also, the window manager can take the size
2517 * of the window decorations/border into account, while your
2518 * application cannot.
2520 * In any case, if you insist on application-specified window
2521 * positioning, there's STILL a better way than doing it yourself -
2522 * gtk_window_set_position() will frequently handle the details
2527 gtk_window_get_size (GtkWindow *window,
2534 g_return_if_fail (GTK_IS_WINDOW (window));
2536 widget = GTK_WIDGET (window);
2538 if (width == NULL && height == NULL)
2541 if (GTK_WIDGET_MAPPED (window))
2543 gdk_drawable_get_size (GTK_WIDGET (window)->window,
2548 GdkRectangle configure_request;
2550 gtk_window_compute_configure_request (window,
2554 w = configure_request.width;
2555 h = configure_request.height;
2566 * @window: a #GtkWindow
2567 * @x: X coordinate to move window to
2568 * @y: Y coordinate to move window to
2570 * Asks the window manager to move @window to the given position.
2571 * Window managers are free to ignore this; most window managers
2572 * ignore requests for initial window positions (instead using a
2573 * user-defined placement algorithm) and honor requests after the
2574 * window has already been shown.
2576 * Note: the position is the position of the gravity-determined
2577 * reference point for the window. The gravity determines two things:
2578 * first, the location of the reference point in root window
2579 * coordinates; and second, which point on the window is positioned at
2580 * the reference point.
2582 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
2583 * point is simply the @x, @y supplied to gtk_window_move(). The
2584 * top-left corner of the window decorations (aka window frame or
2585 * border) will be placed at @x, @y. Therefore, to position a window
2586 * at the top left of the screen, you want to use the default gravity
2587 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
2589 * To position a window at the bottom right corner of the screen, you
2590 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
2591 * point is at @x + the window width and @y + the window height, and
2592 * the bottom-right corner of the window border will be placed at that
2593 * reference point. So, to place a window in the bottom right corner
2594 * you would first set gravity to south east, then write:
2595 * gtk_window_move (window, gdk_screen_width () - window_width,
2596 * gdk_screen_height () - window_height).
2598 * The extended window manager hints specification at
2599 * http://www.freedesktop.org/standards/wm-spec.html has a nice table
2600 * of gravities in the "implementation notes" section.
2602 * The gtk_window_get_position() documentation may also be relevant.
2606 gtk_window_move (GtkWindow *window,
2610 GtkWindowGeometryInfo *info;
2613 g_return_if_fail (GTK_IS_WINDOW (window));
2615 widget = GTK_WIDGET (window);
2617 info = gtk_window_get_geometry_info (window, TRUE);
2619 if (GTK_WIDGET_MAPPED (window))
2621 /* we have now sent a request with this position
2622 * with currently-active constraints, so toggle flag.
2624 info->position_constraints_changed = FALSE;
2626 /* we only constrain if mapped - if not mapped,
2627 * then gtk_window_compute_configure_request()
2628 * will apply the constraints later, and we
2629 * don't want to lose information about
2630 * what position the user set before then.
2631 * i.e. if you do a move() then turn off POS_CENTER
2632 * then show the window, your move() will work.
2634 gtk_window_constrain_position (window,
2635 widget->allocation.width,
2636 widget->allocation.height,
2639 /* Note that this request doesn't go through our standard request
2640 * framework, e.g. doesn't increment configure_request_count,
2641 * doesn't set info->last, etc.; that's because
2642 * we don't save the info needed to arrive at this same request
2645 * To gtk_window_move_resize(), this will end up looking exactly
2646 * the same as the position being changed by the window
2650 /* FIXME are we handling gravity properly for framed windows? */
2652 gdk_window_move (window->frame,
2653 x - window->frame_left,
2654 y - window->frame_top);
2656 gdk_window_move (GTK_WIDGET (window)->window,
2661 /* Save this position to apply on mapping */
2662 info->initial_x = x;
2663 info->initial_y = y;
2664 info->initial_pos_set = TRUE;
2669 * gtk_window_get_position:
2670 * @window: a #GtkWindow
2671 * @root_x: return location for X coordinate of gravity-determined reference p\oint
2672 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
2674 * This function returns the position you need to pass to
2675 * gtk_window_move() to keep @window in its current position. This
2676 * means that the meaning of the returned value varies with window
2677 * gravity. See gtk_window_move() for more details.
2679 * If you haven't changed the window gravity, its gravity will be
2680 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
2681 * gets the position of the top-left corner of the window manager
2682 * frame for the window. gtk_window_move() sets the position of this
2683 * same top-left corner.
2685 * gtk_window_get_position() is not 100% reliable because the X Window System
2686 * does not specify a way to obtain the geometry of the
2687 * decorations placed on a window by the window manager.
2688 * Thus GTK+ is using a "best guess" that works with most
2691 * Moreover, nearly all window managers are broken with respect to
2692 * their handling of window gravity. So moving a window to its current
2693 * position as returned by gtk_window_get_position() tends to
2694 * result in moving the window slightly.
2696 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
2697 * frame is not relevant, and thus gtk_window_get_position() will
2698 * always produce accurate results. However you can't use static
2699 * gravity to do things like place a window in a corner of the screen,
2700 * because static gravity ignores the window manager decorations.
2702 * If you are saving and restoring your application's window
2703 * positions, you should know that it's impossible for applications to
2704 * do this without getting it somewhat wrong because applications do
2705 * not have sufficient knowledge of window manager state. The Correct
2706 * Mechanism is to support the session management protocol (see the
2707 * "GnomeClient" object in the GNOME libraries for example) and allow
2708 * the window manager to save your window sizes and positions.
2713 gtk_window_get_position (GtkWindow *window,
2719 g_return_if_fail (GTK_IS_WINDOW (window));
2721 widget = GTK_WIDGET (window);
2723 if (window->gravity == GDK_GRAVITY_STATIC)
2725 if (GTK_WIDGET_MAPPED (widget))
2727 /* This does a server round-trip, which is sort of wrong;
2728 * but a server round-trip is inevitable for
2729 * gdk_window_get_frame_extents() in the usual
2730 * NorthWestGravity case below, so not sure what else to
2731 * do. We should likely be consistent about whether we get
2732 * the client-side info or the server-side info.
2734 gdk_window_get_origin (widget->window, root_x, root_y);
2738 GdkRectangle configure_request;
2740 gtk_window_compute_configure_request (window,
2744 *root_x = configure_request.x;
2745 *root_y = configure_request.y;
2750 GdkRectangle frame_extents;
2755 if (GTK_WIDGET_MAPPED (widget))
2758 gdk_window_get_frame_extents (window->frame, &frame_extents);
2760 gdk_window_get_frame_extents (widget->window, &frame_extents);
2761 x = frame_extents.x;
2762 y = frame_extents.y;
2763 gtk_window_get_size (window, &w, &h);
2767 /* We just say the frame has 0 size on all sides.
2768 * Not sure what else to do.
2770 gtk_window_compute_configure_request (window,
2773 x = frame_extents.x;
2774 y = frame_extents.y;
2775 w = frame_extents.width;
2776 h = frame_extents.height;
2779 switch (window->gravity)
2781 case GDK_GRAVITY_NORTH:
2782 case GDK_GRAVITY_CENTER:
2783 case GDK_GRAVITY_SOUTH:
2784 /* Find center of frame. */
2785 x += frame_extents.width / 2;
2786 /* Center client window on that point. */
2790 case GDK_GRAVITY_SOUTH_EAST:
2791 case GDK_GRAVITY_EAST:
2792 case GDK_GRAVITY_NORTH_EAST:
2793 /* Find right edge of frame */
2794 x += frame_extents.width;
2795 /* Align left edge of client at that point. */
2802 switch (window->gravity)
2804 case GDK_GRAVITY_WEST:
2805 case GDK_GRAVITY_CENTER:
2806 case GDK_GRAVITY_EAST:
2807 /* Find center of frame. */
2808 y += frame_extents.height / 2;
2809 /* Center client window there. */
2812 case GDK_GRAVITY_SOUTH_WEST:
2813 case GDK_GRAVITY_SOUTH:
2814 case GDK_GRAVITY_SOUTH_EAST:
2815 /* Find south edge of frame */
2816 y += frame_extents.height;
2817 /* Place bottom edge of client there */
2832 * gtk_window_reshow_with_initial_size:
2833 * @window: a #GtkWindow
2835 * Hides @window, then reshows it, resetting the
2836 * default size and position of the window. Used
2837 * by GUI builders only.
2840 gtk_window_reshow_with_initial_size (GtkWindow *window)
2844 g_return_if_fail (GTK_IS_WINDOW (window));
2846 widget = GTK_WIDGET (window);
2848 gtk_widget_hide (widget);
2849 gtk_widget_unrealize (widget);
2850 gtk_widget_show (widget);
2854 gtk_window_destroy (GtkObject *object)
2858 g_return_if_fail (GTK_IS_WINDOW (object));
2860 window = GTK_WINDOW (object);
2862 if (window->transient_parent)
2863 gtk_window_set_transient_for (window, NULL);
2865 /* frees the icons */
2866 gtk_window_set_icon_list (window, NULL);
2868 if (window->has_user_ref_count)
2870 window->has_user_ref_count = FALSE;
2871 gtk_widget_unref (GTK_WIDGET (window));
2875 gtk_window_group_remove_window (window->group, window);
2877 GTK_OBJECT_CLASS (parent_class)->destroy (object);
2881 gtk_window_mnemonic_hash_remove (gpointer key,
2885 GtkWindowMnemonic *mnemonic = key;
2886 GtkWindow *window = user;
2888 if (mnemonic->window == window)
2890 if (mnemonic->targets)
2892 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
2894 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
2895 name, mnemonic->targets->data);
2898 g_slist_free (mnemonic->targets);
2907 gtk_window_finalize (GObject *object)
2911 g_return_if_fail (GTK_IS_WINDOW (object));
2913 window = GTK_WINDOW (object);
2915 toplevel_list = g_slist_remove (toplevel_list, window);
2917 g_free (window->title);
2918 g_free (window->wmclass_name);
2919 g_free (window->wmclass_class);
2920 g_free (window->wm_role);
2922 g_hash_table_foreach_remove (mnemonic_hash_table,
2923 gtk_window_mnemonic_hash_remove,
2925 if (window->geometry_info)
2927 if (window->geometry_info->widget)
2928 gtk_signal_disconnect_by_func (GTK_OBJECT (window->geometry_info->widget),
2929 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
2930 &window->geometry_info->widget);
2931 g_free (window->geometry_info);
2934 if (window->accels_changed_handler)
2936 gtk_idle_remove (window->accels_changed_handler);
2937 window->accels_changed_handler = 0;
2940 G_OBJECT_CLASS (parent_class)->finalize (object);
2944 gtk_window_show (GtkWidget *widget)
2946 GtkWindow *window = GTK_WINDOW (widget);
2947 GtkContainer *container = GTK_CONTAINER (window);
2948 gboolean need_resize;
2950 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
2952 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
2953 container->need_resize = FALSE;
2957 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
2958 GtkAllocation allocation = { 0, 0 };
2959 GdkRectangle configure_request;
2960 GdkGeometry new_geometry;
2962 gboolean was_realized;
2964 /* We are going to go ahead and perform this configure request
2965 * and then emulate a configure notify by going ahead and
2966 * doing a size allocate. Sort of a synchronous
2967 * mini-copy of gtk_window_move_resize() here.
2969 gtk_window_compute_configure_request (window,
2974 /* We update this because we are going to go ahead
2975 * and gdk_window_resize() below, rather than
2978 info->last.configure_request.width = configure_request.width;
2979 info->last.configure_request.height = configure_request.height;
2981 /* and allocate the window - this is normally done
2982 * in move_resize in response to configure notify
2984 allocation.width = configure_request.width;
2985 allocation.height = configure_request.height;
2986 gtk_widget_size_allocate (widget, &allocation);
2988 /* Then we guarantee we have a realize */
2989 was_realized = FALSE;
2990 if (!GTK_WIDGET_REALIZED (widget))
2992 gtk_widget_realize (widget);
2993 was_realized = TRUE;
2996 /* Must be done after the windows are realized,
2997 * so that the decorations can be read
2999 gtk_decorated_window_calculate_frame_size (window);
3001 /* We only send configure request if we didn't just finish
3002 * creating the window; if we just created the window
3003 * then we created it with widget->allocation anyhow.
3006 gdk_window_resize (widget->window,
3007 configure_request.width,
3008 configure_request.height);
3011 gtk_container_check_resize (container);
3013 gtk_widget_map (widget);
3016 gtk_grab_add (widget);
3020 gtk_window_hide (GtkWidget *widget)
3024 g_return_if_fail (GTK_IS_WINDOW (widget));
3026 window = GTK_WINDOW (widget);
3028 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3029 gtk_widget_unmap (widget);
3032 gtk_grab_remove (widget);
3036 gtk_window_map (GtkWidget *widget)
3039 GdkWindow *toplevel;
3041 g_return_if_fail (GTK_IS_WINDOW (widget));
3043 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3045 window = GTK_WINDOW (widget);
3047 if (window->bin.child &&
3048 GTK_WIDGET_VISIBLE (window->bin.child) &&
3049 !GTK_WIDGET_MAPPED (window->bin.child))
3050 gtk_widget_map (window->bin.child);
3053 toplevel = window->frame;
3055 toplevel = widget->window;
3057 if (window->maximize_initially)
3058 gdk_window_maximize (toplevel);
3060 gdk_window_unmaximize (toplevel);
3062 if (window->stick_initially)
3063 gdk_window_stick (toplevel);
3065 gdk_window_unstick (toplevel);
3067 if (window->iconify_initially)
3068 gdk_window_iconify (toplevel);
3070 gdk_window_deiconify (toplevel);
3072 /* No longer use the default settings */
3073 window->need_default_size = FALSE;
3074 window->need_default_position = FALSE;
3076 gdk_window_show (widget->window);
3079 gdk_window_show (window->frame);
3083 gtk_window_unmap (GtkWidget *widget)
3086 GtkWindowGeometryInfo *info;
3088 window = GTK_WINDOW (widget);
3090 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3092 gdk_window_withdraw (window->frame);
3094 gdk_window_withdraw (widget->window);
3096 window->configure_request_count = 0;
3097 window->configure_notify_received = FALSE;
3099 /* on unmap, we reset the default positioning of the window,
3100 * so it's placed again, but we don't reset the default
3101 * size of the window, so it's remembered.
3103 window->need_default_position = TRUE;
3105 info = gtk_window_get_geometry_info (window, FALSE);
3108 info->initial_pos_set = FALSE;
3109 info->position_constraints_changed = FALSE;
3114 gtk_window_realize (GtkWidget *widget)
3117 GdkWindow *parent_window;
3118 GdkWindowAttr attributes;
3119 gint attributes_mask;
3121 g_return_if_fail (GTK_IS_WINDOW (widget));
3123 window = GTK_WINDOW (widget);
3125 /* ensure widget tree is properly size allocated */
3126 if (widget->allocation.x == -1 &&
3127 widget->allocation.y == -1 &&
3128 widget->allocation.width == 1 &&
3129 widget->allocation.height == 1)
3131 GtkRequisition requisition;
3132 GtkAllocation allocation = { 0, 0, 200, 200 };
3134 gtk_widget_size_request (widget, &requisition);
3135 if (requisition.width || requisition.height)
3137 /* non-empty window */
3138 allocation.width = requisition.width;
3139 allocation.height = requisition.height;
3141 gtk_widget_size_allocate (widget, &allocation);
3143 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3145 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3148 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3150 switch (window->type)
3152 case GTK_WINDOW_TOPLEVEL:
3153 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3155 case GTK_WINDOW_POPUP:
3156 attributes.window_type = GDK_WINDOW_TEMP;
3159 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3163 attributes.title = window->title;
3164 attributes.wmclass_name = window->wmclass_name;
3165 attributes.wmclass_class = window->wmclass_class;
3166 attributes.wclass = GDK_INPUT_OUTPUT;
3167 attributes.visual = gtk_widget_get_visual (widget);
3168 attributes.colormap = gtk_widget_get_colormap (widget);
3170 if (window->has_frame)
3172 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3173 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3174 attributes.event_mask = (GDK_EXPOSURE_MASK |
3175 GDK_KEY_PRESS_MASK |
3176 GDK_ENTER_NOTIFY_MASK |
3177 GDK_LEAVE_NOTIFY_MASK |
3178 GDK_FOCUS_CHANGE_MASK |
3179 GDK_STRUCTURE_MASK |
3180 GDK_BUTTON_MOTION_MASK |
3181 GDK_POINTER_MOTION_HINT_MASK |
3182 GDK_BUTTON_PRESS_MASK |
3183 GDK_BUTTON_RELEASE_MASK);
3185 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3187 window->frame = gdk_window_new (NULL, &attributes, attributes_mask);
3188 gdk_window_set_user_data (window->frame, widget);
3190 attributes.window_type = GDK_WINDOW_CHILD;
3191 attributes.x = window->frame_left;
3192 attributes.y = window->frame_right;
3194 attributes_mask = GDK_WA_X | GDK_WA_Y;
3196 parent_window = window->frame;
3200 attributes_mask = 0;
3201 parent_window = NULL;
3204 attributes.width = widget->allocation.width;
3205 attributes.height = widget->allocation.height;
3206 attributes.event_mask = gtk_widget_get_events (widget);
3207 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3208 GDK_KEY_PRESS_MASK |
3209 GDK_ENTER_NOTIFY_MASK |
3210 GDK_LEAVE_NOTIFY_MASK |
3211 GDK_FOCUS_CHANGE_MASK |
3212 GDK_STRUCTURE_MASK);
3214 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3215 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3216 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3217 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3218 gdk_window_set_user_data (widget->window, window);
3220 widget->style = gtk_style_attach (widget->style, widget->window);
3221 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3223 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3225 /* This is a bad hack to set the window background. */
3226 gtk_window_paint (widget, NULL);
3228 if (window->transient_parent &&
3229 GTK_WIDGET_REALIZED (window->transient_parent))
3230 gdk_window_set_transient_for (widget->window,
3231 GTK_WIDGET (window->transient_parent)->window);
3233 if (window->wm_role)
3234 gdk_window_set_role (widget->window, window->wm_role);
3236 if (!window->decorated)
3237 gdk_window_set_decorations (widget->window, 0);
3239 gdk_window_set_type_hint (widget->window, window->type_hint);
3241 /* transient_for must be set to allow the modal hint */
3242 if (window->transient_parent && window->modal)
3243 gdk_window_set_modal_hint (widget->window, TRUE);
3245 gdk_window_set_modal_hint (widget->window, FALSE);
3248 gtk_window_realize_icon (window);
3252 gtk_window_unrealize (GtkWidget *widget)
3255 GtkWindowGeometryInfo *info;
3257 window = GTK_WINDOW (widget);
3259 /* On unrealize, we reset the size of the window such
3260 * that we will re-apply the default sizing stuff
3261 * next time we show the window.
3263 * Default positioning is reset on unmap, instead of unrealize.
3265 window->need_default_size = TRUE;
3266 info = gtk_window_get_geometry_info (window, FALSE);
3269 info->resize_width = -1;
3270 info->resize_height = -1;
3271 info->last.configure_request.x = 0;
3272 info->last.configure_request.y = 0;
3273 info->last.configure_request.width = -1;
3274 info->last.configure_request.height = -1;
3275 /* be sure we reset geom hints on re-realize */
3276 info->last.flags = 0;
3281 gdk_window_set_user_data (window->frame, NULL);
3282 gdk_window_destroy (window->frame);
3283 window->frame = NULL;
3287 gtk_window_unrealize_icon (window);
3289 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3293 gtk_window_size_request (GtkWidget *widget,
3294 GtkRequisition *requisition)
3299 g_return_if_fail (GTK_IS_WINDOW (widget));
3300 g_return_if_fail (requisition != NULL);
3302 window = GTK_WINDOW (widget);
3303 bin = GTK_BIN (window);
3305 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3306 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3308 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3310 GtkRequisition child_requisition;
3312 gtk_widget_size_request (bin->child, &child_requisition);
3314 requisition->width += child_requisition.width;
3315 requisition->height += child_requisition.height;
3320 gtk_window_size_allocate (GtkWidget *widget,
3321 GtkAllocation *allocation)
3324 GtkAllocation child_allocation;
3326 g_return_if_fail (GTK_IS_WINDOW (widget));
3327 g_return_if_fail (allocation != NULL);
3329 window = GTK_WINDOW (widget);
3330 widget->allocation = *allocation;
3332 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3334 child_allocation.x = GTK_CONTAINER (window)->border_width;
3335 child_allocation.y = GTK_CONTAINER (window)->border_width;
3336 child_allocation.width =
3337 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3338 child_allocation.height =
3339 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3341 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3344 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3346 gdk_window_resize (window->frame,
3347 allocation->width + window->frame_left + window->frame_right,
3348 allocation->height + window->frame_top + window->frame_bottom);
3353 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3356 gboolean return_val;
3359 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3360 g_return_val_if_fail (event != NULL, FALSE);
3362 window = GTK_WINDOW (widget);
3364 if (window->frame && (event->any.window == window->frame))
3366 if ((event->type != GDK_KEY_PRESS) &&
3367 (event->type != GDK_KEY_RELEASE) &&
3368 (event->type != GDK_FOCUS_CHANGE))
3370 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
3372 gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
3377 g_object_unref (event->any.window);
3378 event->any.window = g_object_ref (widget->window);
3386 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3388 GdkEventConfigure *configure_event;
3391 switch (event->type)
3394 configure_event = (GdkEventConfigure *)event;
3396 /* Invalidate the decorations */
3399 rect.width = configure_event->width;
3400 rect.height = configure_event->height;
3402 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3404 /* Pass on the (modified) configure event */
3405 configure_event->width -= window->frame_left + window->frame_right;
3406 configure_event->height -= window->frame_top + window->frame_bottom;
3407 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3416 gtk_window_configure_event (GtkWidget *widget,
3417 GdkEventConfigure *event)
3421 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3422 g_return_val_if_fail (event != NULL, FALSE);
3424 window = GTK_WINDOW (widget);
3426 /* window->configure_request_count incremented for each
3427 * configure request, and decremented to a min of 0 for
3428 * each configure notify.
3430 * All it means is that we know we will get at least
3431 * window->configure_request_count more configure notifies.
3432 * We could get more configure notifies than that; some
3433 * of the configure notifies we get may be unrelated to
3434 * the configure requests. But we will get at least
3435 * window->configure_request_count notifies.
3438 if (window->configure_request_count > 0)
3439 window->configure_request_count -= 1;
3441 /* As an optimization, we avoid a resize when possible.
3443 * The only times we can avoid a resize are:
3444 * - we know only the position changed, not the size
3445 * - we know we have made more requests and so will get more
3446 * notifies and can wait to resize when we get them
3449 if (window->configure_request_count > 0 ||
3450 (widget->allocation.width == event->width &&
3451 widget->allocation.height == event->height))
3455 * If we do need to resize, we do that by:
3456 * - filling in widget->allocation with the new size
3457 * - setting configure_notify_received to TRUE
3458 * for use in gtk_window_move_resize()
3459 * - queueing a resize, leading to invocation of
3460 * gtk_window_move_resize() in an idle handler
3464 window->configure_notify_received = TRUE;
3466 widget->allocation.width = event->width;
3467 widget->allocation.height = event->height;
3469 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3474 /* the accel_key and accel_mods fields of the key have to be setup
3475 * upon calling this function. it'll then return whether that key
3476 * is at all used as accelerator, and if so will OR in the
3477 * accel_flags member of the key.
3480 _gtk_window_query_nonaccels (GtkWindow *window,
3482 GdkModifierType accel_mods)
3484 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3486 /* movement keys are considered locked accels */
3489 static const guint bindings[] = {
3490 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
3491 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
3495 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
3496 if (bindings[i] == accel_key)
3500 /* mnemonics are considered locked accels */
3501 if (accel_mods == window->mnemonic_modifier)
3503 GtkWindowMnemonic mkey;
3505 mkey.window = window;
3506 mkey.keyval = accel_key;
3507 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
3515 gtk_window_key_press_event (GtkWidget *widget,
3522 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3523 g_return_val_if_fail (event != NULL, FALSE);
3525 window = GTK_WINDOW (widget);
3529 focus = window->focus_widget;
3531 g_object_ref (focus);
3534 focus && focus != widget &&
3535 gtk_widget_get_toplevel (focus) == widget)
3539 if (GTK_WIDGET_IS_SENSITIVE (focus))
3540 handled = gtk_widget_event (focus, (GdkEvent*) event);
3542 parent = focus->parent;
3544 g_object_ref (parent);
3546 g_object_unref (focus);
3552 g_object_unref (focus);
3555 handled = gtk_window_mnemonic_activate (window,
3560 handled = gtk_accel_groups_activate (G_OBJECT (window), event->keyval, event->state);
3562 /* Chain up, invokes binding set */
3563 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
3564 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
3570 gtk_window_key_release_event (GtkWidget *widget,
3576 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3577 g_return_val_if_fail (event != NULL, FALSE);
3579 window = GTK_WINDOW (widget);
3581 if (window->focus_widget &&
3582 window->focus_widget != widget &&
3583 GTK_WIDGET_SENSITIVE (window->focus_widget))
3585 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
3588 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
3589 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
3595 gtk_window_real_activate_default (GtkWindow *window)
3597 gtk_window_activate_default (window);
3601 gtk_window_real_activate_focus (GtkWindow *window)
3603 gtk_window_activate_focus (window);
3607 gtk_window_move_focus (GtkWindow *window,
3608 GtkDirectionType dir)
3610 gtk_widget_child_focus (GTK_WIDGET (window), dir);
3612 if (!GTK_CONTAINER (window)->focus_child)
3613 gtk_window_set_focus (window, NULL);
3617 gtk_window_enter_notify_event (GtkWidget *widget,
3618 GdkEventCrossing *event)
3620 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3621 g_return_val_if_fail (event != NULL, FALSE);
3627 gtk_window_leave_notify_event (GtkWidget *widget,
3628 GdkEventCrossing *event)
3630 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3631 g_return_val_if_fail (event != NULL, FALSE);
3637 gtk_window_focus_in_event (GtkWidget *widget,
3638 GdkEventFocus *event)
3640 GtkWindow *window = GTK_WINDOW (widget);
3641 GdkEventFocus fevent;
3643 /* It appears spurious focus in events can occur when
3644 * the window is hidden. So we'll just check to see if
3645 * the window is visible before actually handling the
3648 if (GTK_WIDGET_VISIBLE (widget))
3650 window->has_focus = TRUE;
3652 if (window->focus_widget &&
3653 window->focus_widget != widget &&
3654 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3656 fevent.type = GDK_FOCUS_CHANGE;
3657 fevent.window = window->focus_widget->window;
3660 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
3668 gtk_window_focus_out_event (GtkWidget *widget,
3669 GdkEventFocus *event)
3671 GtkWindow *window = GTK_WINDOW (widget);
3672 GdkEventFocus fevent;
3674 window->has_focus = FALSE;
3676 if (window->focus_widget &&
3677 window->focus_widget != widget &&
3678 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3680 fevent.type = GDK_FOCUS_CHANGE;
3681 fevent.window = window->focus_widget->window;
3684 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
3690 static GdkAtom atom_rcfiles = GDK_NONE;
3693 gtk_window_read_rcfiles (GtkWidget *widget,
3694 GdkEventClient *event)
3696 GList *embedded_windows;
3698 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
3699 if (embedded_windows)
3704 for (i = 0; i < 5; i++)
3706 sev.data_format = 32;
3707 sev.message_type = atom_rcfiles;
3709 while (embedded_windows)
3711 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
3712 gdk_event_send_client_message ((GdkEvent *) &sev, xid);
3713 embedded_windows = embedded_windows->next;
3717 gtk_rc_reparse_all ();
3721 gtk_window_client_event (GtkWidget *widget,
3722 GdkEventClient *event)
3724 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3725 g_return_val_if_fail (event != NULL, FALSE);
3728 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
3730 if (event->message_type == atom_rcfiles)
3731 gtk_window_read_rcfiles (widget, event);
3737 gtk_window_check_resize (GtkContainer *container)
3741 g_return_if_fail (GTK_IS_WINDOW (container));
3743 window = GTK_WINDOW (container);
3745 if (GTK_WIDGET_VISIBLE (container))
3746 gtk_window_move_resize (window);
3750 gtk_window_focus (GtkWidget *widget,
3751 GtkDirectionType direction)
3755 GtkContainer *container;
3756 GtkWidget *old_focus_child;
3759 container = GTK_CONTAINER (widget);
3760 window = GTK_WINDOW (widget);
3761 bin = GTK_BIN (widget);
3763 old_focus_child = container->focus_child;
3765 /* We need a special implementation here to deal properly with wrapping
3766 * around in the tab chain without the danger of going into an
3769 if (old_focus_child)
3771 if (gtk_widget_child_focus (old_focus_child, direction))
3775 if (window->focus_widget)
3777 /* Wrapped off the end, clear the focus setting for the toplpevel */
3778 parent = window->focus_widget->parent;
3781 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
3782 parent = GTK_WIDGET (parent)->parent;
3785 gtk_window_set_focus (GTK_WINDOW (container), NULL);
3788 /* Now try to focus the first widget in the window */
3791 if (gtk_widget_child_focus (bin->child, direction))
3799 gtk_window_real_set_focus (GtkWindow *window,
3802 GdkEventFocus event;
3803 gboolean def_flags = 0;
3805 g_return_if_fail (GTK_IS_WINDOW (window));
3807 if (window->default_widget)
3808 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
3810 if (window->focus_widget)
3812 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3813 (window->focus_widget != window->default_widget))
3815 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3817 if (window->default_widget)
3818 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3821 if (window->has_focus)
3823 event.type = GDK_FOCUS_CHANGE;
3824 event.window = window->focus_widget->window;
3827 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
3831 window->focus_widget = focus;
3833 if (window->focus_widget)
3835 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3836 (window->focus_widget != window->default_widget))
3838 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
3839 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3841 if (window->default_widget)
3842 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3845 if (window->has_focus)
3847 event.type = GDK_FOCUS_CHANGE;
3848 event.window = window->focus_widget->window;
3851 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
3855 if (window->default_widget &&
3856 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
3857 gtk_widget_queue_draw (window->default_widget);
3860 /*********************************
3861 * Functions related to resizing *
3862 *********************************/
3864 /* This function doesn't constrain to geometry hints */
3866 gtk_window_compute_configure_request_size (GtkWindow *window,
3870 GtkRequisition requisition;
3871 GtkWindowGeometryInfo *info;
3875 * - we've done a size request
3878 widget = GTK_WIDGET (window);
3880 info = gtk_window_get_geometry_info (window, FALSE);
3882 if (window->need_default_size)
3884 gtk_widget_get_child_requisition (widget, &requisition);
3886 /* Default to requisition */
3887 *width = requisition.width;
3888 *height = requisition.height;
3890 /* If window is empty so requests 0, default to random nonzero size */
3891 if (*width == 0 && *height == 0)
3897 /* Override requisition with default size */
3901 if (info->default_width > 0)
3902 *width = info->default_width;
3904 if (info->default_height > 0)
3905 *height = info->default_height;
3910 /* Default to keeping current size */
3911 *width = widget->allocation.width;
3912 *height = widget->allocation.height;
3915 /* Override any size with gtk_window_resize() values */
3918 if (info->resize_width > 0)
3919 *width = info->resize_width;
3921 if (info->resize_height > 0)
3922 *height = info->resize_height;
3927 gtk_window_compute_configure_request (GtkWindow *window,
3928 GdkRectangle *request,
3929 GdkGeometry *geometry,
3932 GdkGeometry new_geometry;
3936 GtkWindowPosition pos;
3937 GtkWidget *parent_widget;
3938 GtkWindowGeometryInfo *info;
3941 widget = GTK_WIDGET (window);
3943 gtk_widget_size_request (widget, NULL);
3944 gtk_window_compute_configure_request_size (window, &w, &h);
3946 gtk_window_compute_hints (window, &new_geometry, &new_flags);
3947 gtk_window_constrain_size (window,
3948 &new_geometry, new_flags,
3952 parent_widget = (GtkWidget*) window->transient_parent;
3954 pos = window->position;
3955 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
3956 (parent_widget == NULL ||
3957 !GTK_WIDGET_MAPPED (parent_widget)))
3958 pos = GTK_WIN_POS_NONE;
3960 info = gtk_window_get_geometry_info (window, TRUE);
3962 /* by default, don't change position requested */
3963 x = info->last.configure_request.x;
3964 y = info->last.configure_request.y;
3966 if (window->need_default_position)
3969 /* FIXME this all interrelates with window gravity.
3970 * For most of them I think we want to set GRAVITY_CENTER.
3972 * Not sure how to go about that.
3977 /* here we are only handling CENTER_ALWAYS
3978 * as it relates to default positioning,
3979 * where it's equivalent to simply CENTER
3981 case GTK_WIN_POS_CENTER_ALWAYS:
3982 case GTK_WIN_POS_CENTER:
3984 gint screen_width = gdk_screen_width ();
3985 gint screen_height = gdk_screen_height ();
3987 x = (screen_width - w) / 2;
3988 y = (screen_height - h) / 2;
3992 case GTK_WIN_POS_CENTER_ON_PARENT:
3996 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
3998 gdk_window_get_origin (parent_widget->window,
4001 x = ox + (parent_widget->allocation.width - w) / 2;
4002 y = oy + (parent_widget->allocation.height - h) / 2;
4006 case GTK_WIN_POS_MOUSE:
4008 gint screen_width = gdk_screen_width ();
4009 gint screen_height = gdk_screen_height ();
4012 gdk_window_get_pointer (NULL, &px, &py, NULL);
4015 x = CLAMP (x, 0, screen_width - w);
4016 y = CLAMP (y, 0, screen_height - h);
4023 } /* if (window->need_default_position) */
4025 if (window->need_default_position &&
4026 info->initial_pos_set)
4028 x = info->initial_x;
4029 y = info->initial_y;
4030 gtk_window_constrain_position (window, w, h, &x, &y);
4036 request->height = h;
4039 *geometry = new_geometry;
4045 gtk_window_constrain_position (GtkWindow *window,
4051 /* See long comments in gtk_window_move_resize()
4052 * on when it's safe to call this function.
4054 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4056 gint center_x, center_y;
4057 gint screen_width = gdk_screen_width ();
4058 gint screen_height = gdk_screen_height ();
4060 center_x = (screen_width - new_width) / 2;
4061 center_y = (screen_height - new_height) / 2;
4069 gtk_window_move_resize (GtkWindow *window)
4073 * First we determine whether any information has changed that would
4074 * cause us to revise our last configure request. If we would send
4075 * a different configure request from last time, then
4076 * configure_request_size_changed = TRUE or
4077 * configure_request_pos_changed = TRUE. configure_request_size_changed
4078 * may be true due to new hints, a gtk_window_resize(), or whatever.
4079 * configure_request_pos_changed may be true due to gtk_window_set_position()
4080 * or gtk_window_move().
4082 * If the configure request has changed, we send off a new one. To
4083 * ensure GTK invariants are maintained (resize queue does what it
4084 * should), we go ahead and size_allocate the requested size in this
4087 * If the configure request has not changed, we don't ever resend
4088 * it, because it could mean fighting the user or window manager.
4091 * To prepare the configure request, we come up with a base size/pos:
4092 * - the one from gtk_window_move()/gtk_window_resize()
4093 * - else default_width, default_height if we haven't ever
4095 * - else the size request if we haven't ever been mapped,
4096 * as a substitute default size
4097 * - else the current size of the window, as received from
4098 * configure notifies (i.e. the current allocation)
4100 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4101 * the position request to be centered.
4104 GtkContainer *container;
4105 GtkWindowGeometryInfo *info;
4106 GdkGeometry new_geometry;
4108 GdkRectangle new_request;
4109 gboolean configure_request_size_changed;
4110 gboolean configure_request_pos_changed;
4111 gboolean hints_changed; /* do we need to send these again */
4112 GtkWindowLastGeometryInfo saved_last_info;
4114 widget = GTK_WIDGET (window);
4115 container = GTK_CONTAINER (widget);
4116 info = gtk_window_get_geometry_info (window, TRUE);
4118 configure_request_size_changed = FALSE;
4119 configure_request_pos_changed = FALSE;
4121 gtk_window_compute_configure_request (window, &new_request,
4122 &new_geometry, &new_flags);
4124 /* This check implies the invariant that we never set info->last
4125 * without setting the hints and sending off a configure request.
4127 * If we change info->last without sending the request, we may
4130 if (info->last.configure_request.x != new_request.x ||
4131 info->last.configure_request.y != new_request.y)
4132 configure_request_pos_changed = TRUE;
4134 if ((info->last.configure_request.width != new_request.width ||
4135 info->last.configure_request.height != new_request.height))
4136 configure_request_size_changed = TRUE;
4138 hints_changed = FALSE;
4140 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4141 &new_geometry, new_flags))
4143 hints_changed = TRUE;
4146 /* Position Constraints
4147 * ====================
4149 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4150 * a default. The other POS_ values are used only when the
4151 * window is shown, not after that.
4153 * However, we can't implement a position constraint as
4154 * "anytime the window size changes, center the window"
4155 * because this may well end up fighting the WM or user. In
4156 * fact it gets in an infinite loop with at least one WM.
4158 * Basically, applications are in no way in a position to
4159 * constrain the position of a window, with one exception:
4160 * override redirect windows. (Really the intended purpose
4161 * of CENTER_ALWAYS anyhow, I would think.)
4163 * So the way we implement this "constraint" is to say that when WE
4164 * cause a move or resize, i.e. we make a configure request changing
4165 * window size, we recompute the CENTER_ALWAYS position to reflect
4166 * the new window size, and include it in our request. Also, if we
4167 * just turned on CENTER_ALWAYS we snap to center with a new
4168 * request. Otherwise, if we are just NOTIFIED of a move or resize
4169 * done by someone else e.g. the window manager, we do NOT send a
4170 * new configure request.
4172 * For override redirect windows, this works fine; all window
4173 * sizes are from our configure requests. For managed windows,
4174 * it is at least semi-sane, though who knows what the
4175 * app author is thinking.
4178 /* This condition should be kept in sync with the condition later on
4179 * that determines whether we send a configure request. i.e. we
4180 * should do this position constraining anytime we were going to
4181 * send a configure request anyhow, plus when constraints have
4184 if (configure_request_pos_changed ||
4185 configure_request_size_changed ||
4187 info->position_constraints_changed)
4189 /* We request the constrained position if:
4190 * - we were changing position, and need to clamp
4191 * the change to the constraint
4192 * - we're changing the size anyway
4193 * - set_position() was called to toggle CENTER_ALWAYS on
4196 gtk_window_constrain_position (window,
4202 /* Update whether we need to request a move */
4203 if (info->last.configure_request.x != new_request.x ||
4204 info->last.configure_request.y != new_request.y)
4205 configure_request_pos_changed = TRUE;
4207 configure_request_pos_changed = FALSE;
4212 int notify_x, notify_y;
4214 /* this is the position from the last configure notify */
4215 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4217 g_print ("--- %s ---\n"
4218 "last : %d,%d\t%d x %d\n"
4219 "this : %d,%d\t%d x %d\n"
4220 "alloc: %d,%d\t%d x %d\n"
4222 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4223 "configure_notify_received: %d\n"
4224 "configure_request_count: %d\n"
4225 "position_constraints_changed: %d\n",
4226 window->title ? window->title : "(no title)",
4227 info->last.configure_request.x,
4228 info->last.configure_request.y,
4229 info->last.configure_request.width,
4230 info->last.configure_request.height,
4236 widget->allocation.width,
4237 widget->allocation.height,
4238 widget->requisition.width,
4239 widget->requisition.height,
4240 configure_request_pos_changed,
4241 configure_request_size_changed,
4243 window->configure_notify_received,
4244 window->configure_request_count,
4245 info->position_constraints_changed);
4249 saved_last_info = info->last;
4250 info->last.geometry = new_geometry;
4251 info->last.flags = new_flags;
4252 info->last.configure_request = new_request;
4254 /* need to set PPosition so the WM will look at our position,
4255 * but we don't want to count PPosition coming and going as a hints
4256 * change for future iterations. So we saved info->last prior to
4260 /* Also, if the initial position was explicitly set, then we always
4261 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4265 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4266 * this is an initial map
4269 if ((configure_request_pos_changed ||
4270 info->initial_pos_set ||
4271 (window->need_default_position &&
4272 window->position != GTK_WIN_POS_NONE)) &&
4273 (new_flags & GDK_HINT_POS) == 0)
4275 new_flags |= GDK_HINT_POS;
4276 hints_changed = TRUE;
4279 /* Set hints if necessary
4282 gdk_window_set_geometry_hints (widget->window,
4286 /* handle resizing/moving and widget tree allocation
4288 if (window->configure_notify_received)
4290 GtkAllocation allocation;
4292 /* If we have received a configure event since
4293 * the last time in this function, we need to
4294 * accept our new size and size_allocate child widgets.
4295 * (see gtk_window_configure_event() for more details).
4297 * 1 or more configure notifies may have been received.
4298 * Also, configure_notify_received will only be TRUE
4299 * if all expected configure notifies have been received
4300 * (one per configure request), as an optimization.
4303 window->configure_notify_received = FALSE;
4305 /* gtk_window_configure_event() filled in widget->allocation */
4306 allocation = widget->allocation;
4307 gtk_widget_size_allocate (widget, &allocation);
4309 /* If the configure request changed, it means that
4311 * 1) coincidentally changed hints or widget properties
4312 * impacting the configure request before getting
4313 * a configure notify, or
4314 * 2) some broken widget is changing its size request
4315 * during size allocation, resulting in
4316 * a false appearance of changed configure request.
4318 * For 1), we could just go ahead and ask for the
4319 * new size right now, but doing that for 2)
4320 * might well be fighting the user (and can even
4321 * trigger a loop). Since we really don't want to
4322 * do that, we requeue a resize in hopes that
4323 * by the time it gets handled, the child has seen
4324 * the light and is willing to go along with the
4325 * new size. (this happens for the zvt widget, since
4326 * the size_allocate() above will have stored the
4327 * requisition corresponding to the new size in the
4330 * This doesn't buy us anything for 1), but it shouldn't
4331 * hurt us too badly, since it is what would have
4332 * happened if we had gotten the configure event before
4333 * the new size had been set.
4336 if (configure_request_size_changed ||
4337 configure_request_pos_changed)
4339 /* Don't change the recorded last info after all, because we
4340 * haven't actually updated to the new info yet - we decided
4341 * to postpone our configure request until later.
4343 info->last = saved_last_info;
4345 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
4348 else if ((configure_request_size_changed || hints_changed) &&
4349 (widget->allocation.width != new_request.width ||
4350 widget->allocation.height != new_request.height))
4353 /* We are in one of the following situations:
4354 * A. configure_request_size_changed
4355 * our requisition has changed and we need a different window size,
4356 * so we request it from the window manager.
4357 * B. !configure_request_size_changed && hints_changed
4358 * the window manager rejects our size, but we have just changed the
4359 * window manager hints, so there's a chance our request will
4360 * be honoured this time, so we try again.
4362 * However, if the new requisition is the same as the current allocation,
4363 * we don't request it again, since we won't get a ConfigureNotify back from
4364 * the window manager unless it decides to change our requisition. If
4365 * we don't get the ConfigureNotify back, the resize queue will never be run.
4368 /* Now send the configure request */
4369 if (configure_request_pos_changed)
4373 gdk_window_move_resize (window->frame,
4374 new_request.x - window->frame_left,
4375 new_request.y - window->frame_top,
4376 new_request.width + window->frame_left + window->frame_right,
4377 new_request.height + window->frame_top + window->frame_bottom);
4378 gdk_window_resize (GTK_WIDGET (window)->window,
4379 new_request.width, new_request.height);
4382 gdk_window_move_resize (widget->window,
4383 new_request.x, new_request.y,
4384 new_request.width, new_request.height);
4386 else /* only size changed */
4389 gdk_window_resize (window->frame,
4390 new_request.width + window->frame_left + window->frame_right,
4391 new_request.height + window->frame_top + window->frame_bottom);
4392 gdk_window_resize (widget->window,
4393 new_request.width, new_request.height);
4396 /* Increment the number of have-not-yet-received-notify requests */
4397 window->configure_request_count += 1;
4399 /* We have now sent a request since the last position constraint
4400 * change and definitely don't need a an initial size again (not
4401 * resetting this here can lead to infinite loops for
4402 * GTK_RESIZE_IMMEDIATE containers)
4404 info->position_constraints_changed = FALSE;
4405 window->need_default_position = FALSE;
4407 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
4408 * configure event in response to our resizing request.
4409 * the configure event will cause a new resize with
4410 * ->configure_notify_received=TRUE.
4411 * until then, we want to
4412 * - discard expose events
4413 * - coalesce resizes for our children
4414 * - defer any window resizes until the configure event arrived
4415 * to achieve this, we queue a resize for the window, but remove its
4416 * resizing handler, so resizing will not be handled from the next
4417 * idle handler but when the configure event arrives.
4419 * FIXME: we should also dequeue the pending redraws here, since
4420 * we handle those ourselves upon ->configure_notify_received==TRUE.
4422 if (container->resize_mode == GTK_RESIZE_QUEUE)
4424 gtk_widget_queue_resize (widget);
4425 _gtk_container_dequeue_resize_handler (container);
4430 /* Handle any position changes.
4432 if (configure_request_pos_changed)
4436 gdk_window_move (window->frame,
4437 new_request.x - window->frame_left,
4438 new_request.y - window->frame_top);
4441 gdk_window_move (widget->window,
4442 new_request.x, new_request.y);
4445 /* And run the resize queue.
4447 gtk_container_resize_children (container);
4451 /* Compare two sets of Geometry hints for equality.
4454 gtk_window_compare_hints (GdkGeometry *geometry_a,
4456 GdkGeometry *geometry_b,
4459 if (flags_a != flags_b)
4462 if ((flags_a & GDK_HINT_MIN_SIZE) &&
4463 (geometry_a->min_width != geometry_b->min_width ||
4464 geometry_a->min_height != geometry_b->min_height))
4467 if ((flags_a & GDK_HINT_MAX_SIZE) &&
4468 (geometry_a->max_width != geometry_b->max_width ||
4469 geometry_a->max_height != geometry_b->max_height))
4472 if ((flags_a & GDK_HINT_BASE_SIZE) &&
4473 (geometry_a->base_width != geometry_b->base_width ||
4474 geometry_a->base_height != geometry_b->base_height))
4477 if ((flags_a & GDK_HINT_ASPECT) &&
4478 (geometry_a->min_aspect != geometry_b->min_aspect ||
4479 geometry_a->max_aspect != geometry_b->max_aspect))
4482 if ((flags_a & GDK_HINT_RESIZE_INC) &&
4483 (geometry_a->width_inc != geometry_b->width_inc ||
4484 geometry_a->height_inc != geometry_b->height_inc))
4487 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
4488 geometry_a->win_gravity != geometry_b->win_gravity)
4495 _gtk_window_constrain_size (GtkWindow *window,
4501 GtkWindowGeometryInfo *info;
4503 g_return_if_fail (GTK_IS_WINDOW (window));
4505 info = window->geometry_info;
4508 GdkWindowHints flags = info->last.flags;
4509 GdkGeometry *geometry = &info->last.geometry;
4511 gtk_window_constrain_size (window,
4522 gtk_window_constrain_size (GtkWindow *window,
4523 GdkGeometry *geometry,
4530 gdk_window_constrain_size (geometry, flags, width, height,
4531 new_width, new_height);
4534 /* Compute the set of geometry hints and flags for a window
4535 * based on the application set geometry, and requisiition
4536 * of the window. gtk_widget_size_request() must have been
4540 gtk_window_compute_hints (GtkWindow *window,
4541 GdkGeometry *new_geometry,
4545 gint extra_width = 0;
4546 gint extra_height = 0;
4547 GtkWindowGeometryInfo *geometry_info;
4548 GtkRequisition requisition;
4550 g_return_if_fail (GTK_IS_WINDOW (window));
4552 widget = GTK_WIDGET (window);
4554 gtk_widget_get_child_requisition (widget, &requisition);
4555 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
4559 *new_flags = geometry_info->mask;
4560 *new_geometry = geometry_info->geometry;
4567 if (geometry_info && geometry_info->widget)
4569 extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
4570 extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
4573 /* We don't want to set GDK_HINT_POS in here, we just set it
4574 * in gtk_window_move_resize() when we want the position
4578 if (*new_flags & GDK_HINT_BASE_SIZE)
4580 new_geometry->base_width += extra_width;
4581 new_geometry->base_height += extra_height;
4583 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
4584 (*new_flags & GDK_HINT_RESIZE_INC) &&
4585 ((extra_width != 0) || (extra_height != 0)))
4587 *new_flags |= GDK_HINT_BASE_SIZE;
4589 new_geometry->base_width = extra_width;
4590 new_geometry->base_height = extra_height;
4593 if (*new_flags & GDK_HINT_MIN_SIZE)
4595 if (new_geometry->min_width < 0)
4596 new_geometry->min_width = requisition.width;
4598 new_geometry->min_width += extra_width;
4600 if (new_geometry->min_height < 0)
4601 new_geometry->min_height = requisition.height;
4603 new_geometry->min_height += extra_height;
4605 else if (!window->allow_shrink)
4607 *new_flags |= GDK_HINT_MIN_SIZE;
4609 new_geometry->min_width = requisition.width;
4610 new_geometry->min_height = requisition.height;
4613 if (*new_flags & GDK_HINT_MAX_SIZE)
4615 if (new_geometry->max_width < 0)
4616 new_geometry->max_width = requisition.width;
4618 new_geometry->max_width += extra_width;
4620 if (new_geometry->max_height < 0)
4621 new_geometry->max_width = requisition.height;
4623 new_geometry->max_height += extra_height;
4625 else if (!window->allow_grow)
4627 *new_flags |= GDK_HINT_MAX_SIZE;
4629 new_geometry->max_width = requisition.width;
4630 new_geometry->max_height = requisition.height;
4633 *new_flags |= GDK_HINT_WIN_GRAVITY;
4634 new_geometry->win_gravity = window->gravity;
4637 /***********************
4638 * Redrawing functions *
4639 ***********************/
4642 gtk_window_paint (GtkWidget *widget,
4645 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
4646 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
4650 gtk_window_expose (GtkWidget *widget,
4651 GdkEventExpose *event)
4653 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
4654 g_return_val_if_fail (event != NULL, FALSE);
4656 if (!GTK_WIDGET_APP_PAINTABLE (widget))
4657 gtk_window_paint (widget, &event->area);
4659 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
4660 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
4666 * gtk_window_set_has_frame:
4667 * @window: a #GtkWindow
4668 * @setting: a boolean
4670 * (Note: this is a special-purpose function for the framebuffer port,
4671 * that causes GTK+ to draw its own window border. For most applications,
4672 * you want gtk_window_set_decorated() instead, which tells the window
4673 * manager whether to draw the window border.)
4675 * If this function is called on a window with setting of TRUE, before
4676 * it is realized or showed, it will have a "frame" window around
4677 * widget->window, accessible in window->frame. Using the signal
4678 * frame_event you can recieve all events targeted at the frame.
4680 * This function is used by the linux-fb port to implement managed
4681 * windows, but it could concievably be used by X-programs that
4682 * want to do their own window decorations.
4686 gtk_window_set_has_frame (GtkWindow *window,
4689 g_return_if_fail (GTK_IS_WINDOW (window));
4690 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
4692 window->has_frame = setting != FALSE;
4696 * gtk_window_get_has_frame:
4697 * @window: a #GtkWindow
4699 * Accessor for whether the window has a frame window exterior to
4700 * widget->window. Gets the value set by gtk_window_set_has_frame ().
4702 * Return value: %TRUE if a frame has been added to the window
4703 * via gtk_widow_has_frame
4706 gtk_window_get_has_frame (GtkWindow *window)
4708 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4710 return window->has_frame;
4714 * gtk_window_set_frame_dimensions:
4715 * @window: a #GtkWindow that has a frame
4716 * @left: The width of the left border
4717 * @top: The height of the top border
4718 * @right: The width of the right border
4719 * @bottom: The height of the bottom border
4721 * (Note: this is a special-purpose function intended for the framebuffer
4722 * port; see gtk_window_set_has_frame(). It will have no effect on the
4723 * window border drawn by the window manager, which is the normal
4724 * case when using the X Window system.)
4726 * For windows with frames (see #gtk_window_set_has_frame) this function
4727 * can be used to change the size of the frame border.
4730 gtk_window_set_frame_dimensions (GtkWindow *window,
4736 GtkWidget *widget = GTK_WIDGET (window);
4738 g_return_if_fail (GTK_IS_WINDOW (window));
4740 if (window->frame_left == left &&
4741 window->frame_top == top &&
4742 window->frame_right == right &&
4743 window->frame_bottom == bottom)
4746 window->frame_left = left;
4747 window->frame_top = top;
4748 window->frame_right = right;
4749 window->frame_bottom = bottom;
4751 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4753 gint width = widget->allocation.width + left + right;
4754 gint height = widget->allocation.height + top + bottom;
4755 gdk_window_resize (window->frame, width, height);
4756 gtk_decorated_window_move_resize_window (window,
4758 widget->allocation.width,
4759 widget->allocation.height);
4764 * gtk_window_present:
4765 * @window: a #GtkWindow
4767 * Presents a window to the user. This may mean raising the window
4768 * in the stacking order, deiconifying it, moving it to the current
4769 * desktop, and/or giving it the keyboard focus, possibly dependent
4770 * on the user's platform, window manager, and preferences.
4772 * If @window is hidden, this function calls gtk_widget_show()
4775 * This function should be used when the user tries to open a window
4776 * that's already open. Say for example the preferences dialog is
4777 * currently open, and the user chooses Preferences from the menu
4778 * a second time; use gtk_window_present() to move the already-open dialog
4779 * where the user can see it.
4783 gtk_window_present (GtkWindow *window)
4787 g_return_if_fail (GTK_IS_WINDOW (window));
4789 widget = GTK_WIDGET (window);
4791 if (GTK_WIDGET_VISIBLE (window))
4793 g_assert (widget->window != NULL);
4795 gdk_window_show (widget->window);
4797 /* note that gdk_window_focus() will also move the window to
4798 * the current desktop, for WM spec compliant window managers.
4800 gdk_window_focus (widget->window,
4801 gtk_get_current_event_time ());
4805 gtk_widget_show (widget);
4810 * gtk_window_iconify:
4811 * @window: a #GtkWindow
4813 * Asks to iconify (i.e. minimize) the specified @window. Note that you
4814 * shouldn't assume the window is definitely iconified afterward,
4815 * because other entities (e.g. the user or window manager) could
4816 * deiconify it again, or there may not be a window manager in which
4817 * case iconification isn't possible, etc. But normally the window
4818 * will end up iconified. Just don't write code that crashes if not.
4820 * It's permitted to call this function before showing a window,
4821 * in which case the window will be iconified before it ever appears
4824 * You can track iconification via the "window_state_event" signal
4829 gtk_window_iconify (GtkWindow *window)
4832 GdkWindow *toplevel;
4834 g_return_if_fail (GTK_IS_WINDOW (window));
4836 widget = GTK_WIDGET (window);
4838 window->iconify_initially = TRUE;
4841 toplevel = window->frame;
4843 toplevel = widget->window;
4845 if (toplevel != NULL)
4846 gdk_window_iconify (toplevel);
4850 * gtk_window_deiconify:
4851 * @window: a #GtkWindow
4853 * Asks to deiconify (i.e. unminimize) the specified @window. Note
4854 * that you shouldn't assume the window is definitely deiconified
4855 * afterward, because other entities (e.g. the user or window manager)
4856 * could iconify it again before your code which assumes
4857 * deiconification gets to run.
4859 * You can track iconification via the "window_state_event" signal
4863 gtk_window_deiconify (GtkWindow *window)
4866 GdkWindow *toplevel;
4868 g_return_if_fail (GTK_IS_WINDOW (window));
4870 widget = GTK_WIDGET (window);
4872 window->iconify_initially = FALSE;
4875 toplevel = window->frame;
4877 toplevel = widget->window;
4879 if (toplevel != NULL)
4880 gdk_window_deiconify (toplevel);
4885 * @window: a #GtkWindow
4887 * Asks to stick @window, which means that it will appear on all user
4888 * desktops. Note that you shouldn't assume the window is definitely
4889 * stuck afterward, because other entities (e.g. the user or window
4890 * manager) could unstick it again, and some window managers do not
4891 * support sticking windows. But normally the window will end up
4892 * stuck. Just don't write code that crashes if not.
4894 * It's permitted to call this function before showing a window.
4896 * You can track stickiness via the "window_state_event" signal
4901 gtk_window_stick (GtkWindow *window)
4904 GdkWindow *toplevel;
4906 g_return_if_fail (GTK_IS_WINDOW (window));
4908 widget = GTK_WIDGET (window);
4910 window->stick_initially = TRUE;
4913 toplevel = window->frame;
4915 toplevel = widget->window;
4917 if (toplevel != NULL)
4918 gdk_window_stick (toplevel);
4922 * gtk_window_unstick:
4923 * @window: a #GtkWindow
4925 * Asks to unstick @window, which means that it will appear on only
4926 * one of the user's desktops. Note that you shouldn't assume the
4927 * window is definitely unstuck afterward, because other entities
4928 * (e.g. the user or window manager) could stick it again. But
4929 * normally the window will end up stuck. Just don't write code that
4932 * You can track stickiness via the "window_state_event" signal
4937 gtk_window_unstick (GtkWindow *window)
4940 GdkWindow *toplevel;
4942 g_return_if_fail (GTK_IS_WINDOW (window));
4944 widget = GTK_WIDGET (window);
4946 window->stick_initially = FALSE;
4949 toplevel = window->frame;
4951 toplevel = widget->window;
4953 if (toplevel != NULL)
4954 gdk_window_unstick (toplevel);
4958 * gtk_window_maximize:
4959 * @window: a #GtkWindow
4961 * Asks to maximize @window, so that it becomes full-screen. Note that
4962 * you shouldn't assume the window is definitely maximized afterward,
4963 * because other entities (e.g. the user or window manager) could
4964 * unmaximize it again, and not all window managers support
4965 * maximization. But normally the window will end up maximized. Just
4966 * don't write code that crashes if not.
4968 * It's permitted to call this function before showing a window,
4969 * in which case the window will be maximized when it appears onscreen
4972 * You can track maximization via the "window_state_event" signal
4977 gtk_window_maximize (GtkWindow *window)
4980 GdkWindow *toplevel;
4982 g_return_if_fail (GTK_IS_WINDOW (window));
4984 widget = GTK_WIDGET (window);
4986 window->maximize_initially = TRUE;
4989 toplevel = window->frame;
4991 toplevel = widget->window;
4993 if (toplevel != NULL)
4994 gdk_window_maximize (toplevel);
4998 * gtk_window_unmaximize:
4999 * @window: a #GtkWindow
5001 * Asks to unmaximize @window. Note that you shouldn't assume the
5002 * window is definitely unmaximized afterward, because other entities
5003 * (e.g. the user or window manager) could maximize it again, and not
5004 * all window managers honor requests to unmaximize. But normally the
5005 * window will end up unmaximized. Just don't write code that crashes
5008 * You can track maximization via the "window_state_event" signal
5013 gtk_window_unmaximize (GtkWindow *window)
5016 GdkWindow *toplevel;
5018 g_return_if_fail (GTK_IS_WINDOW (window));
5020 widget = GTK_WIDGET (window);
5022 window->maximize_initially = FALSE;
5025 toplevel = window->frame;
5027 toplevel = widget->window;
5029 if (toplevel != NULL)
5030 gdk_window_unmaximize (toplevel);
5034 * gtk_window_set_resizable:
5035 * @window: a #GtkWindow
5036 * @resizable: %TRUE if the user can resize this window
5038 * Sets whether the user can resize a window. Windows are user resizable
5042 gtk_window_set_resizable (GtkWindow *window,
5045 g_return_if_fail (GTK_IS_WINDOW (window));
5047 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5051 * gtk_window_get_resizable:
5052 * @window: a #GtkWindow
5054 * Gets the value set by gtk_window_set_resizable().
5056 * Return value: %TRUE if the user can resize the window
5059 gtk_window_get_resizable (GtkWindow *window)
5061 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5063 /* allow_grow is most likely to indicate the semantic concept we
5064 * mean by "resizable" (and will be a reliable indicator if
5065 * set_policy() hasn't been called)
5067 return window->allow_grow;
5071 * gtk_window_set_gravity:
5072 * @window: a #GtkWindow
5073 * @gravity: window gravity
5075 * Window gravity defines the meaning of coordinates passed to
5076 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5079 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5080 * typically "do what you mean."
5084 gtk_window_set_gravity (GtkWindow *window,
5087 g_return_if_fail (GTK_IS_WINDOW (window));
5089 if (gravity != window->gravity)
5091 window->gravity = gravity;
5093 /* gtk_window_move_resize() will adapt gravity
5095 gtk_widget_queue_resize (GTK_WIDGET (window));
5100 * gtk_window_get_gravity:
5101 * @window: a #GtkWindow
5103 * Gets the value set by gtk_window_set_gravity().
5105 * Return value: window gravity
5108 gtk_window_get_gravity (GtkWindow *window)
5110 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5112 return window->gravity;
5116 * gtk_window_begin_resize_drag:
5117 * @window: a #GtkWindow
5118 * @button: mouse button that initiated the drag
5119 * @edge: position of the resize control
5120 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5121 * @root_y: Y position where the user clicked to initiate the drag
5122 * @timestamp: timestamp from the click event that initiated the drag
5124 * Starts resizing a window. This function is used if an application
5125 * has window resizing controls. When GDK can support it, the resize
5126 * will be done using the standard mechanism for the window manager or
5127 * windowing system. Otherwise, GDK will try to emulate window
5128 * resizing, potentially not all that well, depending on the windowing system.
5132 gtk_window_begin_resize_drag (GtkWindow *window,
5140 GdkWindow *toplevel;
5142 g_return_if_fail (GTK_IS_WINDOW (window));
5143 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5145 widget = GTK_WIDGET (window);
5148 toplevel = window->frame;
5150 toplevel = widget->window;
5152 gdk_window_begin_resize_drag (toplevel,
5159 * gtk_window_get_frame_dimensions:
5160 * @window: a #GtkWindow
5161 * @left: location to store the width of the frame at the left, or %NULL
5162 * @top: location to store the height of the frame at the top, or %NULL
5163 * @right: location to store the width of the frame at the returns, or %NULL
5164 * @bottom: location to store the height of the frame at the bottom, or %NULL
5166 * (Note: this is a special-purpose function intended for the
5167 * framebuffer port; see gtk_window_set_has_frame(). It will not
5168 * return the size of the window border drawn by the window manager,
5169 * which is the normal case when using a windowing system.
5170 * See gdk_window_get_frame_extents() to get the standard
5171 * window border extents.)
5173 * Retrieves the dimensions of the frame window for this toplevel.
5174 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5177 gtk_window_get_frame_dimensions (GtkWindow *window,
5183 g_return_if_fail (GTK_IS_WINDOW (window));
5186 *left = window->frame_left;
5188 *top = window->frame_top;
5190 *right = window->frame_right;
5192 *bottom = window->frame_bottom;
5196 * gtk_window_begin_move_drag:
5197 * @window: a #GtkWindow
5198 * @button: mouse button that initiated the drag
5199 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5200 * @root_y: Y position where the user clicked to initiate the drag
5201 * @timestamp: timestamp from the click event that initiated the drag
5203 * Starts moving a window. This function is used if an application
5204 * has window movement grips. When GDK can support it, the window movement
5205 * will be done using the standard mechanism for the window manager or
5206 * windowing system. Otherwise, GDK will try to emulate window
5207 * movement, potentially not all that well, depending on the windowing system.
5211 gtk_window_begin_move_drag (GtkWindow *window,
5218 GdkWindow *toplevel;
5220 g_return_if_fail (GTK_IS_WINDOW (window));
5221 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5223 widget = GTK_WIDGET (window);
5226 toplevel = window->frame;
5228 toplevel = widget->window;
5230 gdk_window_begin_move_drag (toplevel,
5238 gtk_window_group_class_init (GtkWindowGroupClass *klass)
5243 gtk_window_group_get_type (void)
5245 static GtkType window_group_type = 0;
5247 if (!window_group_type)
5249 static const GTypeInfo window_group_info =
5251 sizeof (GtkWindowGroupClass),
5252 NULL, /* base_init */
5253 NULL, /* base_finalize */
5254 (GClassInitFunc) gtk_window_group_class_init,
5255 NULL, /* class_finalize */
5256 NULL, /* class_data */
5257 sizeof (GtkWindowGroup),
5258 16, /* n_preallocs */
5259 (GInstanceInitFunc) NULL,
5262 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
5265 return window_group_type;
5269 * gtk_window_group_new:
5271 * Creates a new #GtkWindowGroup object. Grabs added with
5272 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
5274 * Return value: a new #GtkWindowGroup.
5277 gtk_window_group_new (void)
5279 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
5283 window_group_cleanup_grabs (GtkWindowGroup *group,
5287 GSList *to_remove = NULL;
5289 tmp_list = group->grabs;
5292 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
5293 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
5294 tmp_list = tmp_list->next;
5299 gtk_grab_remove (to_remove->data);
5300 g_object_unref (to_remove->data);
5301 to_remove = g_slist_delete_link (to_remove, to_remove);
5306 * gtk_window_group_add_window:
5307 * @window_group: a #GtkWindowGroup
5308 * @window: the #GtkWindow to add
5310 * Adds a window to a #GtkWindowGroup.
5313 gtk_window_group_add_window (GtkWindowGroup *window_group,
5316 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5317 g_return_if_fail (GTK_IS_WINDOW (window));
5319 if (window->group != window_group)
5321 g_object_ref (window);
5322 g_object_ref (window_group);
5325 gtk_window_group_remove_window (window->group, window);
5327 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
5329 window->group = window_group;
5331 g_object_unref (window);
5336 * gtk_window_group_remove_window:
5337 * @window_group: a #GtkWindowGroup
5338 * @window: the #GtkWindow to remove
5340 * Removes a window from a #GtkWindowGroup.
5343 gtk_window_group_remove_window (GtkWindowGroup *window_group,
5346 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5347 g_return_if_fail (GTK_IS_WIDGET (window));
5348 g_return_if_fail (window->group == window_group);
5350 g_object_ref (window);
5352 window_group_cleanup_grabs (window_group, window);
5353 window->group = NULL;
5355 g_object_unref (G_OBJECT (window_group));
5356 g_object_unref (window);
5359 /* Return the group for the window or the default group
5362 _gtk_window_get_group (GtkWindow *window)
5364 if (window && window->group)
5365 return window->group;
5368 static GtkWindowGroup *default_group = NULL;
5371 default_group = gtk_window_group_new ();
5373 return default_group;
5379 Derived from XParseGeometry() in XFree86
5381 Copyright 1985, 1986, 1987,1998 The Open Group
5383 All Rights Reserved.
5385 The above copyright notice and this permission notice shall be included
5386 in all copies or substantial portions of the Software.
5388 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5389 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5390 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
5391 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
5392 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
5393 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
5394 OTHER DEALINGS IN THE SOFTWARE.
5396 Except as contained in this notice, the name of The Open Group shall
5397 not be used in advertising or otherwise to promote the sale, use or
5398 other dealings in this Software without prior written authorization
5399 from The Open Group.
5404 * XParseGeometry parses strings of the form
5405 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5406 * width, height, xoffset, and yoffset are unsigned integers.
5407 * Example: "=80x24+300-49"
5408 * The equal sign is optional.
5409 * It returns a bitmask that indicates which of the four values
5410 * were actually found in the string. For each value found,
5411 * the corresponding argument is updated; for each value
5412 * not found, the corresponding argument is left unchanged.
5415 /* The following code is from Xlib, and is minimally modified, so we
5416 * can track any upstream changes if required. Don't change this
5417 * code. Or if you do, put in a huge comment marking which thing
5422 read_int (gchar *string,
5430 else if (*string == '-')
5436 for (; (*string >= '0') && (*string <= '9'); string++)
5438 result = (result * 10) + (*string - '0');
5450 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
5451 * value (x, y, width, height) was found in the parsed string.
5453 #define NoValue 0x0000
5454 #define XValue 0x0001
5455 #define YValue 0x0002
5456 #define WidthValue 0x0004
5457 #define HeightValue 0x0008
5458 #define AllValues 0x000F
5459 #define XNegative 0x0010
5460 #define YNegative 0x0020
5462 /* Try not to reformat/modify, so we can compare/sync with X sources */
5464 gtk_XParseGeometry (const char *string,
5467 unsigned int *width,
5468 unsigned int *height)
5472 unsigned int tempWidth, tempHeight;
5474 char *nextCharacter;
5476 /* These initializations are just to silence gcc */
5482 if ( (string == NULL) || (*string == '\0')) return(mask);
5484 string++; /* ignore possible '=' at beg of geometry spec */
5486 strind = (char *)string;
5487 if (*strind != '+' && *strind != '-' && *strind != 'x') {
5488 tempWidth = read_int(strind, &nextCharacter);
5489 if (strind == nextCharacter)
5491 strind = nextCharacter;
5495 if (*strind == 'x' || *strind == 'X') {
5497 tempHeight = read_int(strind, &nextCharacter);
5498 if (strind == nextCharacter)
5500 strind = nextCharacter;
5501 mask |= HeightValue;
5504 if ((*strind == '+') || (*strind == '-')) {
5505 if (*strind == '-') {
5507 tempX = -read_int(strind, &nextCharacter);
5508 if (strind == nextCharacter)
5510 strind = nextCharacter;
5516 tempX = read_int(strind, &nextCharacter);
5517 if (strind == nextCharacter)
5519 strind = nextCharacter;
5522 if ((*strind == '+') || (*strind == '-')) {
5523 if (*strind == '-') {
5525 tempY = -read_int(strind, &nextCharacter);
5526 if (strind == nextCharacter)
5528 strind = nextCharacter;
5535 tempY = read_int(strind, &nextCharacter);
5536 if (strind == nextCharacter)
5538 strind = nextCharacter;
5544 /* If strind isn't at the end of the string the it's an invalid
5545 geometry specification. */
5547 if (*strind != '\0') return (0);
5553 if (mask & WidthValue)
5555 if (mask & HeightValue)
5556 *height = tempHeight;
5561 * gtk_window_parse_geometry:
5562 * @window: a #GtkWindow
5563 * @geometry: geometry string
5565 * Parses a standard X Window System geometry string - see the
5566 * manual page for X (type 'man X') for details on this.
5567 * gtk_window_parse_geometry() does work on all GTK+ ports
5568 * including Win32 but is primarily intended for an X environment.
5570 * If either a size or a position can be extracted from the
5571 * geometry string, gtk_window_parse_geometry() returns %TRUE
5572 * and calls gtk_window_set_default_size() and/or gtk_window_move()
5573 * to resize/move the window.
5575 * If gtk_window_parse_geometry() returns %TRUE, it will also
5576 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
5577 * indicating to the window manager that the size/position of
5578 * the window was user-specified. This causes most window
5579 * managers to honor the geometry.
5581 * Return value: %TRUE if string was parsed successfully
5584 gtk_window_parse_geometry (GtkWindow *window,
5585 const gchar *geometry)
5590 gboolean size_set, pos_set;
5592 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5593 g_return_val_if_fail (geometry != NULL, FALSE);
5595 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
5597 if ((result & WidthValue) == 0 ||
5600 if ((result & HeightValue) == 0 ||
5605 if ((result & WidthValue) || (result & HeightValue))
5607 gtk_window_set_default_size (window, w, h);
5611 gtk_window_get_size (window, &w, &h);
5613 grav = GDK_GRAVITY_NORTH_WEST;
5615 if ((result & XNegative) && (result & YNegative))
5616 grav = GDK_GRAVITY_SOUTH_EAST;
5617 else if (result & XNegative)
5618 grav = GDK_GRAVITY_NORTH_EAST;
5619 else if (result & YNegative)
5620 grav = GDK_GRAVITY_SOUTH_WEST;
5622 if ((result & XValue) == 0)
5625 if ((result & YValue) == 0)
5628 if (grav == GDK_GRAVITY_SOUTH_WEST ||
5629 grav == GDK_GRAVITY_SOUTH_EAST)
5630 y = gdk_screen_height () - h;
5632 if (grav == GDK_GRAVITY_SOUTH_EAST ||
5633 grav == GDK_GRAVITY_NORTH_EAST)
5634 x = gdk_screen_width () - w;
5643 if ((result & XValue) || (result & YValue))
5645 gtk_window_set_gravity (window, grav);
5646 gtk_window_move (window, x, y);
5650 if (size_set || pos_set)
5652 /* Set USSize, USPosition hints */
5653 GtkWindowGeometryInfo *info;
5655 info = gtk_window_get_geometry_info (window, TRUE);
5658 info->mask |= GDK_HINT_USER_POS;
5660 info->mask |= GDK_HINT_USER_SIZE;