1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
30 #include "gdk/gdkkeysyms.h"
32 #include "gtkprivate.h"
34 #include "gtksignal.h"
35 #include "gtkwindow.h"
36 #include "gtkwindow-decorate.h"
37 #include "gtkbindings.h"
39 #include "gtkiconfactory.h"
41 #include "gtkmarshalers.h"
68 PROP_DESTROY_WITH_PARENT,
77 GdkPixmap *icon_pixmap;
80 guint using_default_icon : 1;
81 guint using_parent_icon : 1;
85 GdkGeometry geometry; /* Last set of geometry hints we set */
87 GdkRectangle configure_request;
88 } GtkWindowLastGeometryInfo;
90 struct _GtkWindowGeometryInfo
92 /* Properties that the app has set on the window
94 GdkGeometry geometry; /* Geometry hints */
96 GtkWidget *widget; /* subwidget to which hints apply */
97 /* from last gtk_window_resize () - if > 0, indicates that
98 * we should resize to this size.
103 /* From last gtk_window_move () prior to mapping -
104 * only used if initial_pos_set
109 /* Default size - used only the FIRST time we map a window,
114 /* whether to use initial_x, initial_y */
115 guint initial_pos_set : 1;
116 /* CENTER_ALWAYS or other position constraint changed since
117 * we sent the last configure request.
119 guint position_constraints_changed : 1;
121 GtkWindowLastGeometryInfo last;
132 static void gtk_window_class_init (GtkWindowClass *klass);
133 static void gtk_window_init (GtkWindow *window);
134 static void gtk_window_dispose (GObject *object);
135 static void gtk_window_destroy (GtkObject *object);
136 static void gtk_window_finalize (GObject *object);
137 static void gtk_window_show (GtkWidget *widget);
138 static void gtk_window_hide (GtkWidget *widget);
139 static void gtk_window_map (GtkWidget *widget);
140 static void gtk_window_unmap (GtkWidget *widget);
141 static void gtk_window_realize (GtkWidget *widget);
142 static void gtk_window_unrealize (GtkWidget *widget);
143 static void gtk_window_size_request (GtkWidget *widget,
144 GtkRequisition *requisition);
145 static void gtk_window_size_allocate (GtkWidget *widget,
146 GtkAllocation *allocation);
147 static gint gtk_window_event (GtkWidget *widget,
149 static gboolean gtk_window_frame_event (GtkWindow *window,
151 static gint gtk_window_configure_event (GtkWidget *widget,
152 GdkEventConfigure *event);
153 static gint gtk_window_key_press_event (GtkWidget *widget,
155 static gint gtk_window_key_release_event (GtkWidget *widget,
157 static gint gtk_window_enter_notify_event (GtkWidget *widget,
158 GdkEventCrossing *event);
159 static gint gtk_window_leave_notify_event (GtkWidget *widget,
160 GdkEventCrossing *event);
161 static gint gtk_window_focus_in_event (GtkWidget *widget,
162 GdkEventFocus *event);
163 static gint gtk_window_focus_out_event (GtkWidget *widget,
164 GdkEventFocus *event);
165 static gint gtk_window_client_event (GtkWidget *widget,
166 GdkEventClient *event);
167 static void gtk_window_check_resize (GtkContainer *container);
168 static gint gtk_window_focus (GtkWidget *widget,
169 GtkDirectionType direction);
170 static void gtk_window_real_set_focus (GtkWindow *window,
173 static void gtk_window_real_activate_default (GtkWindow *window);
174 static void gtk_window_real_activate_focus (GtkWindow *window);
175 static void gtk_window_move_focus (GtkWindow *window,
176 GtkDirectionType dir);
177 static void gtk_window_read_rcfiles (GtkWidget *widget,
178 GdkEventClient *event);
179 static void gtk_window_paint (GtkWidget *widget,
181 static gint gtk_window_expose (GtkWidget *widget,
182 GdkEventExpose *event);
183 static void gtk_window_unset_transient_for (GtkWindow *window);
184 static void gtk_window_transient_parent_realized (GtkWidget *parent,
186 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
189 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
192 static void gtk_window_move_resize (GtkWindow *window);
193 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
195 GdkGeometry *geometry_b,
197 static void gtk_window_constrain_size (GtkWindow *window,
198 GdkGeometry *geometry,
204 static void gtk_window_constrain_position (GtkWindow *window,
209 static void gtk_window_compute_hints (GtkWindow *window,
210 GdkGeometry *new_geometry,
212 static void gtk_window_compute_configure_request (GtkWindow *window,
213 GdkRectangle *request,
214 GdkGeometry *geometry,
217 static void gtk_window_set_default_size_internal (GtkWindow *window,
218 gboolean change_width,
220 gboolean change_height,
223 static void gtk_window_realize_icon (GtkWindow *window);
224 static void gtk_window_unrealize_icon (GtkWindow *window);
225 static void gtk_window_notify_keys_changed (GtkWindow *window);
227 static GSList *toplevel_list = NULL;
228 static GHashTable *mnemonic_hash_table = NULL;
229 static GtkBinClass *parent_class = NULL;
230 static guint window_signals[LAST_SIGNAL] = { 0 };
231 static GList *default_icon_list = NULL;
232 /* FIXME need to be per-screen */
233 static GdkPixmap *default_icon_pixmap = NULL;
234 static GdkPixmap *default_icon_mask = NULL;
236 static void gtk_window_set_property (GObject *object,
240 static void gtk_window_get_property (GObject *object,
247 mnemonic_hash (gconstpointer key)
249 const GtkWindowMnemonic *k;
252 k = (GtkWindowMnemonic *)key;
254 h = (gulong) k->window;
255 h ^= k->keyval << 16;
256 h ^= k->keyval >> 16;
262 mnemonic_equal (gconstpointer a, gconstpointer b)
264 const GtkWindowMnemonic *ka;
265 const GtkWindowMnemonic *kb;
267 ka = (GtkWindowMnemonic *)a;
268 kb = (GtkWindowMnemonic *)b;
271 (ka->window == kb->window) &&
272 (ka->keyval == kb->keyval);
276 gtk_window_get_type (void)
278 static GtkType window_type = 0;
282 static const GtkTypeInfo window_info =
286 sizeof (GtkWindowClass),
287 (GtkClassInitFunc) gtk_window_class_init,
288 (GtkObjectInitFunc) gtk_window_init,
289 /* reserved_1 */ NULL,
290 /* reserved_2 */ NULL,
291 (GtkClassInitFunc) NULL,
294 window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
301 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->keys_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[KEYS_CHANGED] =
504 g_signal_new ("keys_changed",
505 G_OBJECT_CLASS_TYPE (object_class),
507 GTK_SIGNAL_OFFSET (GtkWindowClass, keys_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 g_return_if_fail (GTK_IS_WINDOW (window));
984 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
986 if (window->default_widget != default_widget)
988 GtkWidget *old_default_widget = NULL;
991 g_object_ref (default_widget);
993 if (window->default_widget)
995 old_default_widget = window->default_widget;
997 if (window->focus_widget != window->default_widget ||
998 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
999 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1000 gtk_widget_queue_draw (window->default_widget);
1003 window->default_widget = default_widget;
1005 if (window->default_widget)
1007 if (window->focus_widget == NULL ||
1008 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1009 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1010 gtk_widget_queue_draw (window->default_widget);
1013 if (old_default_widget)
1014 g_object_notify (G_OBJECT (old_default_widget), "has_default");
1018 g_object_notify (G_OBJECT (default_widget), "has_default");
1019 g_object_unref (default_widget);
1025 gtk_window_set_policy (GtkWindow *window,
1026 gboolean allow_shrink,
1027 gboolean allow_grow,
1028 gboolean auto_shrink)
1030 g_return_if_fail (GTK_IS_WINDOW (window));
1032 window->allow_shrink = (allow_shrink != FALSE);
1033 window->allow_grow = (allow_grow != FALSE);
1035 g_object_freeze_notify (G_OBJECT (window));
1036 g_object_notify (G_OBJECT (window), "allow_shrink");
1037 g_object_notify (G_OBJECT (window), "allow_grow");
1038 g_object_notify (G_OBJECT (window), "resizable");
1039 g_object_thaw_notify (G_OBJECT (window));
1041 gtk_widget_queue_resize (GTK_WIDGET (window));
1045 handle_keys_changed (gpointer data)
1049 GDK_THREADS_ENTER ();
1050 window = GTK_WINDOW (data);
1052 if (window->keys_changed_handler)
1054 gtk_idle_remove (window->keys_changed_handler);
1055 window->keys_changed_handler = 0;
1058 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1059 GDK_THREADS_LEAVE ();
1065 gtk_window_notify_keys_changed (GtkWindow *window)
1067 if (!window->keys_changed_handler)
1068 window->keys_changed_handler = gtk_idle_add (handle_keys_changed, window);
1072 * gtk_window_add_accel_group:
1073 * @window: window to attach accelerator group to
1074 * @accel_group: a #GtkAccelGroup
1076 * Associate @accel_group with @window, such that calling
1077 * gtk_accel_groups_activate() on @window will activate accelerators
1081 gtk_window_add_accel_group (GtkWindow *window,
1082 GtkAccelGroup *accel_group)
1084 g_return_if_fail (GTK_IS_WINDOW (window));
1085 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1087 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1088 g_signal_connect_object (accel_group, "accel_changed",
1089 G_CALLBACK (gtk_window_notify_keys_changed),
1090 window, G_CONNECT_SWAPPED);
1094 * gtk_accel_group_detach:
1095 * @accel_group: a #GtkAccelGroup
1096 * @object: a #GObject
1098 * Reverses the effects of gtk_window_add_accel_group().
1101 gtk_window_remove_accel_group (GtkWindow *window,
1102 GtkAccelGroup *accel_group)
1104 g_return_if_fail (GTK_IS_WINDOW (window));
1105 g_return_if_fail (accel_group != NULL);
1107 g_signal_handlers_disconnect_by_func (accel_group,
1108 G_CALLBACK (gtk_window_notify_keys_changed),
1110 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1114 gtk_window_add_mnemonic (GtkWindow *window,
1118 GtkWindowMnemonic key;
1119 GtkWindowMnemonic *mnemonic;
1121 g_return_if_fail (GTK_IS_WINDOW (window));
1122 g_return_if_fail (GTK_IS_WIDGET (target));
1124 key.window = window;
1125 key.keyval = keyval;
1126 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1130 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1131 mnemonic->targets = g_slist_prepend (mnemonic->targets, target);
1135 mnemonic = g_new (GtkWindowMnemonic, 1);
1137 mnemonic->targets = g_slist_prepend (NULL, target);
1138 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1140 gtk_window_notify_keys_changed (window);
1144 gtk_window_remove_mnemonic (GtkWindow *window,
1148 GtkWindowMnemonic key;
1149 GtkWindowMnemonic *mnemonic;
1151 g_return_if_fail (GTK_IS_WINDOW (window));
1152 g_return_if_fail (GTK_IS_WIDGET (target));
1154 key.window = window;
1155 key.keyval = keyval;
1156 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1158 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1160 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1161 if (mnemonic->targets == NULL)
1163 g_hash_table_remove (mnemonic_hash_table, mnemonic);
1166 gtk_window_notify_keys_changed (window);
1170 gtk_window_mnemonic_activate (GtkWindow *window,
1172 GdkModifierType modifier)
1174 GtkWindowMnemonic key;
1175 GtkWindowMnemonic *mnemonic;
1177 GtkWidget *widget, *chosen_widget;
1178 gboolean overloaded;
1180 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1182 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1185 key.window = window;
1186 key.keyval = keyval;
1187 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1193 chosen_widget = NULL;
1194 list = mnemonic->targets;
1197 widget = GTK_WIDGET (list->data);
1199 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1200 GTK_WIDGET_MAPPED (widget))
1208 chosen_widget = widget;
1210 list = g_slist_next (list);
1215 /* For round robin we put the activated entry on
1216 * the end of the list after activation
1218 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1219 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1221 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1227 * gtk_window_set_mnemonic_modifier:
1228 * @window: a #GtkWindow
1229 * @modifier: the modifier mask used to activate
1230 * mnemonics on this window.
1232 * Sets the mnemonic modifier for this window.
1235 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1236 GdkModifierType modifier)
1238 g_return_if_fail (GTK_IS_WINDOW (window));
1239 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1241 window->mnemonic_modifier = modifier;
1242 gtk_window_notify_keys_changed (window);
1246 * gtk_window_get_mnemonic_modifier:
1247 * @window: a #GtkWindow
1249 * Returns the mnemonic modifier for this window. See
1250 * gtk_window_set_mnemonic_modifier().
1252 * Return value: the modifier mask used to activate
1253 * mnemonics on this window.
1256 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1258 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1260 return window->mnemonic_modifier;
1264 gtk_window_set_position (GtkWindow *window,
1265 GtkWindowPosition position)
1267 g_return_if_fail (GTK_IS_WINDOW (window));
1269 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1270 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1272 GtkWindowGeometryInfo *info;
1274 info = gtk_window_get_geometry_info (window, TRUE);
1276 /* this flag causes us to re-request the CENTER_ALWAYS
1277 * constraint in gtk_window_move_resize(), see
1278 * comment in that function.
1280 info->position_constraints_changed = TRUE;
1282 gtk_widget_queue_resize (GTK_WIDGET (window));
1285 window->position = position;
1287 g_object_notify (G_OBJECT (window), "window_position");
1291 gtk_window_activate_focus (GtkWindow *window)
1293 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1295 if (window->focus_widget)
1297 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1298 gtk_widget_activate (window->focus_widget);
1306 * gtk_window_get_focus:
1307 * @window: a #GtkWindow
1309 * Retrieves the current focused widget within the window.
1310 * Note that this is the widget that would have the focus
1311 * if the toplevel window focused; if the toplevel window
1312 * is not focused the GTK_WIDGET_HAS_FOCUS(widget) will
1313 * not be %TRUE for the widget.
1315 * Return value: the currently focused widget.
1318 gtk_window_get_focus (GtkWindow *window)
1320 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1322 return window->focus_widget;
1326 gtk_window_activate_default (GtkWindow *window)
1328 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1330 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1331 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1333 gtk_widget_activate (window->default_widget);
1336 else if (window->focus_widget)
1338 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1339 gtk_widget_activate (window->focus_widget);
1347 * gtk_window_set_modal:
1348 * @window: a #GtkWindow
1349 * @modal: whether the window is modal
1351 * Sets a window modal or non-modal. Modal windows prevent interaction
1352 * with other windows in the same application. To keep modal dialogs
1353 * on top of main application windows, use
1354 * gtk_window_set_transient_for() to make the dialog transient for the
1355 * parent; most window managers will then disallow lowering the dialog
1361 gtk_window_set_modal (GtkWindow *window,
1364 g_return_if_fail (GTK_IS_WINDOW (window));
1366 window->modal = modal != FALSE;
1368 /* adjust desired modality state */
1369 if (GTK_WIDGET_VISIBLE (window) && window->modal)
1370 gtk_grab_add (GTK_WIDGET (window));
1372 gtk_grab_remove (GTK_WIDGET (window));
1374 g_object_notify (G_OBJECT (window), "modal");
1378 * gtk_window_get_modal:
1379 * @window: a #GtkWindow
1381 * Returns whether the window is modal. See gtk_window_set_modal().
1383 * Return value: %TRUE if the window is set to be modal and
1384 * establishes a grab when shown
1387 gtk_window_get_modal (GtkWindow *window)
1389 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1391 return window->modal;
1395 * gtk_window_list_toplevels:
1397 * Returns a list of all existing toplevel windows. The widgets
1398 * in the list are not individually referenced. If you want
1399 * to iterate through the list and perform actions involving
1400 * callbacks that might destroy the widgets, you MUST call
1401 * g_list_foreach (result, (GFunc)g_object_ref, NULL) first, and
1402 * then unref all the widgets afterwards.
1404 * Return value: list of toplevel widgets
1407 gtk_window_list_toplevels (void)
1412 for (slist = toplevel_list; slist; slist = slist->next)
1413 list = g_list_prepend (list, slist->data);
1419 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1421 GList *embedded_windows;
1423 g_return_if_fail (GTK_IS_WINDOW (window));
1425 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1426 if (embedded_windows)
1427 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1428 g_quark_from_static_string ("gtk-embedded"));
1429 embedded_windows = g_list_prepend (embedded_windows,
1430 GUINT_TO_POINTER (xid));
1432 gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
1435 (GtkDestroyNotify) g_list_free : NULL);
1439 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1441 GList *embedded_windows;
1444 g_return_if_fail (GTK_IS_WINDOW (window));
1446 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1447 if (embedded_windows)
1448 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1449 g_quark_from_static_string ("gtk-embedded"));
1451 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1454 embedded_windows = g_list_remove_link (embedded_windows, node);
1455 g_list_free_1 (node);
1458 gtk_object_set_data_full (GTK_OBJECT (window),
1459 "gtk-embedded", embedded_windows,
1461 (GtkDestroyNotify) g_list_free : NULL);
1465 _gtk_window_reposition (GtkWindow *window,
1469 g_return_if_fail (GTK_IS_WINDOW (window));
1471 gtk_window_move (window, x, y);
1475 gtk_window_dispose (GObject *object)
1479 g_return_if_fail (GTK_IS_WINDOW (object));
1481 window = GTK_WINDOW (object);
1483 gtk_window_set_focus (window, NULL);
1484 gtk_window_set_default (window, NULL);
1486 G_OBJECT_CLASS (parent_class)->dispose (object);
1490 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1492 gtk_widget_destroy (GTK_WIDGET (child));
1496 connect_parent_destroyed (GtkWindow *window)
1498 if (window->transient_parent)
1500 gtk_signal_connect (GTK_OBJECT (window->transient_parent),
1502 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1508 disconnect_parent_destroyed (GtkWindow *window)
1510 if (window->transient_parent)
1512 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1513 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1519 gtk_window_transient_parent_realized (GtkWidget *parent,
1522 if (GTK_WIDGET_REALIZED (window))
1523 gdk_window_set_transient_for (window->window, parent->window);
1527 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1530 if (GTK_WIDGET_REALIZED (window))
1531 gdk_property_delete (window->window,
1532 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1536 gtk_window_unset_transient_for (GtkWindow *window)
1538 if (window->transient_parent)
1540 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1541 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1543 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1544 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1546 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1547 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1548 &window->transient_parent);
1550 if (window->destroy_with_parent)
1551 disconnect_parent_destroyed (window);
1553 window->transient_parent = NULL;
1558 * gtk_window_set_transient_for:
1559 * @window: a #GtkWindow
1560 * @parent: parent window
1562 * Dialog windows should be set transient for the main application
1563 * window they were spawned from. This allows window managers to
1564 * e.g. keep the dialog on top of the main window, or center the
1565 * dialog over the main window. gtk_dialog_new_with_buttons() and
1566 * other convenience functions in GTK+ will sometimes call
1567 * gtk_window_set_transient_for() on your behalf.
1571 gtk_window_set_transient_for (GtkWindow *window,
1574 g_return_if_fail (GTK_IS_WINDOW (window));
1575 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1576 g_return_if_fail (window != parent);
1579 if (window->transient_parent)
1581 if (GTK_WIDGET_REALIZED (window) &&
1582 GTK_WIDGET_REALIZED (window->transient_parent) &&
1583 (!parent || !GTK_WIDGET_REALIZED (parent)))
1584 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1585 GTK_WIDGET (window));
1587 gtk_window_unset_transient_for (window);
1590 window->transient_parent = parent;
1594 gtk_signal_connect (GTK_OBJECT (parent), "destroy",
1595 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1596 &window->transient_parent);
1597 gtk_signal_connect (GTK_OBJECT (parent), "realize",
1598 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1600 gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
1601 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1604 if (window->destroy_with_parent)
1605 connect_parent_destroyed (window);
1607 if (GTK_WIDGET_REALIZED (window) &&
1608 GTK_WIDGET_REALIZED (parent))
1609 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1610 GTK_WIDGET (window));
1615 * gtk_window_get_transient_for:
1616 * @window: a #GtkWindow
1618 * Fetches the transient parent for this window. See
1619 * gtk_window_set_transient_for().
1621 * Return value: the transient parent for this window, or %NULL
1622 * if no transient parent has been set.
1625 gtk_window_get_transient_for (GtkWindow *window)
1627 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1629 return window->transient_parent;
1633 * gtk_window_set_type_hint:
1634 * @window: a #GtkWindow
1635 * @hint: the window type
1637 * By setting the type hint for the window, you allow the window
1638 * manager to decorate and handle the window in a way which is
1639 * suitable to the function of the window in your application.
1641 * This function should be called before the window becomes visible.
1643 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1644 * will sometimes call gtk_window_set_type_hint() on your behalf.
1648 gtk_window_set_type_hint (GtkWindow *window,
1649 GdkWindowTypeHint hint)
1651 g_return_if_fail (GTK_IS_WINDOW (window));
1652 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1653 window->type_hint = hint;
1657 * gtk_window_get_type_hint:
1658 * @window: a #GtkWindow
1660 * Gets the type hint for this window. See gtk_window_set_type_hint().
1662 * Return value: the type hint for @window.
1665 gtk_window_get_type_hint (GtkWindow *window)
1667 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1669 return window->type_hint;
1673 * gtk_window_set_destroy_with_parent:
1674 * @window: a #GtkWindow
1675 * @setting: whether to destroy @window with its transient parent
1677 * If @setting is TRUE, then destroying the transient parent of @window
1678 * will also destroy @window itself. This is useful for dialogs that
1679 * shouldn't persist beyond the lifetime of the main window they're
1680 * associated with, for example.
1683 gtk_window_set_destroy_with_parent (GtkWindow *window,
1686 g_return_if_fail (GTK_IS_WINDOW (window));
1688 if (window->destroy_with_parent == (setting != FALSE))
1691 if (window->destroy_with_parent)
1693 disconnect_parent_destroyed (window);
1697 connect_parent_destroyed (window);
1700 window->destroy_with_parent = setting;
1702 g_object_notify (G_OBJECT (window), "destroy_with_parent");
1706 * gtk_window_get_destroy_with_parent:
1707 * @window: a #GtkWindow
1709 * Returns whether the window will be destroyed with its transient parent. See
1710 * gtk_window_set_destroy_with_parent ().
1712 * Return value: %TRUE if the window will be destroyed with its transient parent.
1715 gtk_window_get_destroy_with_parent (GtkWindow *window)
1717 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1719 return window->destroy_with_parent;
1722 static GtkWindowGeometryInfo*
1723 gtk_window_get_geometry_info (GtkWindow *window,
1726 GtkWindowGeometryInfo *info;
1728 info = window->geometry_info;
1729 if (!info && create)
1731 info = g_new0 (GtkWindowGeometryInfo, 1);
1733 info->default_width = -1;
1734 info->default_height = -1;
1735 info->resize_width = -1;
1736 info->resize_height = -1;
1737 info->initial_x = 0;
1738 info->initial_y = 0;
1739 info->initial_pos_set = FALSE;
1740 info->position_constraints_changed = FALSE;
1741 info->last.configure_request.x = 0;
1742 info->last.configure_request.y = 0;
1743 info->last.configure_request.width = -1;
1744 info->last.configure_request.height = -1;
1745 info->widget = NULL;
1747 window->geometry_info = info;
1754 * gtk_window_set_geometry_hints:
1755 * @window: a #GtkWindow
1756 * @geometry_widget: widget the geometry hints will be applied to
1757 * @geometry: struct containing geometry information
1758 * @geom_mask: mask indicating which struct fields should be paid attention to
1760 * This function sets up hints about how a window can be resized by
1761 * the user. You can set a minimum and maximum size; allowed resize
1762 * increments (e.g. for xterm, you can only resize by the size of a
1763 * character); aspect ratios; and more. See the #GdkGeometry struct.
1767 gtk_window_set_geometry_hints (GtkWindow *window,
1768 GtkWidget *geometry_widget,
1769 GdkGeometry *geometry,
1770 GdkWindowHints geom_mask)
1772 GtkWindowGeometryInfo *info;
1774 g_return_if_fail (window != NULL);
1776 info = gtk_window_get_geometry_info (window, TRUE);
1779 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1780 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1783 info->widget = geometry_widget;
1785 gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
1786 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1790 info->geometry = *geometry;
1792 /* We store gravity in window->gravity not in the hints. */
1793 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
1795 if (geom_mask & GDK_HINT_WIN_GRAVITY)
1797 gtk_window_set_gravity (window, geometry->win_gravity);
1800 gtk_widget_queue_resize (GTK_WIDGET (window));
1804 * gtk_window_set_decorated:
1805 * @window: a #GtkWindow
1806 * @setting: %TRUE to decorate the window
1808 * By default, windows are decorated with a title bar, resize
1809 * controls, etc. Some window managers allow GTK+ to disable these
1810 * decorations, creating a borderless window. If you set the decorated
1811 * property to %FALSE using this function, GTK+ will do its best to
1812 * convince the window manager not to decorate the window.
1816 gtk_window_set_decorated (GtkWindow *window,
1819 g_return_if_fail (GTK_IS_WINDOW (window));
1821 setting = setting != FALSE;
1823 if (setting == window->decorated)
1826 window->decorated = setting;
1828 if (GTK_WIDGET (window)->window)
1830 if (window->decorated)
1831 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1834 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1840 * gtk_window_get_decorated:
1841 * @window: a #GtkWindow
1843 * Returns whether the window has been set to have decorations
1844 * such as a title bar via gtk_window_set_decorated().
1846 * Return value: %TRUE if the window has been set to have decorations
1849 gtk_window_get_decorated (GtkWindow *window)
1851 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
1853 return window->decorated;
1856 static GtkWindowIconInfo*
1857 get_icon_info (GtkWindow *window)
1859 return g_object_get_data (G_OBJECT (window),
1860 "gtk-window-icon-info");
1863 static GtkWindowIconInfo*
1864 ensure_icon_info (GtkWindow *window)
1866 GtkWindowIconInfo *info;
1868 info = get_icon_info (window);
1872 info = g_new0 (GtkWindowIconInfo, 1);
1873 g_object_set_data_full (G_OBJECT (window),
1874 "gtk-window-icon-info",
1883 get_pixmap_and_mask (GtkWindowIconInfo *parent_info,
1884 gboolean is_default_list,
1886 GdkPixmap **pmap_return,
1887 GdkBitmap **mask_return)
1889 GdkPixbuf *best_icon;
1893 *pmap_return = NULL;
1894 *mask_return = NULL;
1896 if (is_default_list &&
1897 default_icon_pixmap != NULL)
1899 /* Use shared icon pixmap (eventually will be stored on the
1902 if (default_icon_pixmap)
1903 g_object_ref (G_OBJECT (default_icon_pixmap));
1904 if (default_icon_mask)
1905 g_object_ref (G_OBJECT (default_icon_mask));
1907 *pmap_return = default_icon_pixmap;
1908 *mask_return = default_icon_mask;
1910 else if (parent_info && parent_info->icon_pixmap)
1912 if (parent_info->icon_pixmap)
1913 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1914 if (parent_info->icon_mask)
1915 g_object_ref (G_OBJECT (parent_info->icon_mask));
1917 *pmap_return = parent_info->icon_pixmap;
1918 *mask_return = parent_info->icon_mask;
1922 #define IDEAL_SIZE 48
1924 best_size = G_MAXINT;
1926 tmp_list = icon_list;
1927 while (tmp_list != NULL)
1929 GdkPixbuf *pixbuf = tmp_list->data;
1932 /* average width and height - if someone passes in a rectangular
1933 * icon they deserve what they get.
1935 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
1938 if (best_icon == NULL)
1945 /* icon is better if it's 32 pixels or larger, and closer to
1946 * the ideal size than the current best.
1949 (ABS (best_size - IDEAL_SIZE) <
1950 ABS (this - IDEAL_SIZE)))
1957 tmp_list = tmp_list->next;
1961 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
1962 gdk_colormap_get_system (),
1967 /* Save pmap/mask for others to use if appropriate */
1970 parent_info->icon_pixmap = *pmap_return;
1971 parent_info->icon_mask = *mask_return;
1973 if (parent_info->icon_pixmap)
1974 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1975 if (parent_info->icon_mask)
1976 g_object_ref (G_OBJECT (parent_info->icon_mask));
1978 else if (is_default_list)
1980 default_icon_pixmap = *pmap_return;
1981 default_icon_mask = *mask_return;
1983 if (default_icon_pixmap)
1984 g_object_add_weak_pointer (G_OBJECT (default_icon_pixmap),
1985 (gpointer*)&default_icon_pixmap);
1986 if (default_icon_mask)
1987 g_object_add_weak_pointer (G_OBJECT (default_icon_mask),
1988 (gpointer*)&default_icon_mask);
1994 gtk_window_realize_icon (GtkWindow *window)
1997 GtkWindowIconInfo *info;
2000 widget = GTK_WIDGET (window);
2002 g_return_if_fail (widget->window != NULL);
2004 /* no point setting an icon on override-redirect */
2005 if (window->type == GTK_WINDOW_POPUP)
2010 info = ensure_icon_info (window);
2015 g_return_if_fail (info->icon_pixmap == NULL);
2016 g_return_if_fail (info->icon_mask == NULL);
2018 info->using_default_icon = FALSE;
2019 info->using_parent_icon = FALSE;
2021 icon_list = info->icon_list;
2023 /* Inherit from transient parent */
2024 if (icon_list == NULL && window->transient_parent)
2026 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2028 info->using_parent_icon = TRUE;
2031 /* Inherit from default */
2032 if (icon_list == NULL)
2034 icon_list = default_icon_list;
2036 info->using_default_icon = TRUE;
2039 gdk_window_set_icon_list (widget->window, icon_list);
2041 get_pixmap_and_mask (info->using_parent_icon ?
2042 ensure_icon_info (window->transient_parent) : NULL,
2043 info->using_default_icon,
2048 /* This is a slight ICCCM violation since it's a color pixmap not
2049 * a bitmap, but everyone does it.
2051 gdk_window_set_icon (widget->window,
2056 info->realized = TRUE;
2060 gtk_window_unrealize_icon (GtkWindow *window)
2062 GtkWindowIconInfo *info;
2065 widget = GTK_WIDGET (window);
2067 info = get_icon_info (window);
2072 if (info->icon_pixmap)
2073 g_object_unref (G_OBJECT (info->icon_pixmap));
2075 if (info->icon_mask)
2076 g_object_unref (G_OBJECT (info->icon_mask));
2078 info->icon_pixmap = NULL;
2079 info->icon_mask = NULL;
2081 /* We don't clear the properties on the window, just figure the
2082 * window is going away.
2085 info->realized = FALSE;
2089 * gtk_window_set_icon_list:
2090 * @window: a #GtkWindow
2091 * @list: list of #GdkPixbuf
2093 * Sets up the icon representing a #GtkWindow. The icon is used when
2094 * the window is minimized (also known as iconified). Some window
2095 * managers or desktop environments may also place it in the window
2096 * frame, or display it in other contexts.
2098 * gtk_window_set_icon_list() allows you to pass in the same icon in
2099 * several hand-drawn sizes. The list should contain the natural sizes
2100 * your icon is available in; that is, don't scale the image before
2101 * passing it to GTK+. Scaling is postponed until the last minute,
2102 * when the desired final size is known, to allow best quality.
2104 * By passing several sizes, you may improve the final image quality
2105 * of the icon, by reducing or eliminating automatic image scaling.
2107 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2108 * larger images (64x64, 128x128) if you have them.
2110 * See also gtk_window_set_default_icon_list() to set the icon
2111 * for all windows in your application in one go.
2113 * Note that transient windows (those who have been set transient for another
2114 * window using gtk_window_set_transient_for()) will inherit their
2115 * icon from their transient parent. So there's no need to explicitly
2116 * set the icon on transient windows.
2119 gtk_window_set_icon_list (GtkWindow *window,
2122 GtkWindowIconInfo *info;
2124 g_return_if_fail (GTK_IS_WINDOW (window));
2126 info = ensure_icon_info (window);
2128 if (info->icon_list == list) /* check for NULL mostly */
2131 g_list_foreach (info->icon_list,
2132 (GFunc) g_object_unref, NULL);
2134 g_list_free (info->icon_list);
2136 info->icon_list = g_list_copy (list);
2137 g_list_foreach (info->icon_list,
2138 (GFunc) g_object_ref, NULL);
2140 g_object_notify (G_OBJECT (window), "icon");
2142 gtk_window_unrealize_icon (window);
2144 if (GTK_WIDGET_REALIZED (window))
2145 gtk_window_realize_icon (window);
2147 /* We could try to update our transient children, but I don't think
2148 * it's really worth it. If we did it, the best way would probably
2149 * be to have children connect to notify::icon_list
2154 * gtk_window_get_icon_list:
2155 * @window: a #GtkWindow
2157 * Retrieves the list of icons set by gtk_window_set_icon_list().
2158 * The list is copied, but the reference count on each
2159 * member won't be incremented.
2161 * Return value: copy of window's icon list
2164 gtk_window_get_icon_list (GtkWindow *window)
2166 GtkWindowIconInfo *info;
2168 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2170 info = get_icon_info (window);
2173 return g_list_copy (info->icon_list);
2179 * gtk_window_set_icon:
2180 * @window: a #GtkWindow
2181 * @icon: icon image, or %NULL
2183 * Sets up the icon representing a #GtkWindow. This icon is used when
2184 * the window is minimized (also known as iconified). Some window
2185 * managers or desktop environments may also place it in the window
2186 * frame, or display it in other contexts.
2188 * The icon should be provided in whatever size it was naturally
2189 * drawn; that is, don't scale the image before passing it to
2190 * GTK+. Scaling is postponed until the last minute, when the desired
2191 * final size is known, to allow best quality.
2193 * If you have your icon hand-drawn in multiple sizes, use
2194 * gtk_window_set_icon_list(). Then the best size will be used.
2196 * This function is equivalent to calling gtk_window_set_icon_list()
2197 * with a 1-element list.
2199 * See also gtk_window_set_default_icon_list() to set the icon
2200 * for all windows in your application in one go.
2203 gtk_window_set_icon (GtkWindow *window,
2208 g_return_if_fail (GTK_IS_WINDOW (window));
2209 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2212 list = g_list_append (list, icon);
2213 gtk_window_set_icon_list (window, list);
2218 * gtk_window_get_icon:
2219 * @window: a #GtkWindow
2221 * Gets the value set by gtk_window_set_icon() (or if you've
2222 * called gtk_window_set_icon_list(), gets the first icon in
2225 * Return value: icon for window
2228 gtk_window_get_icon (GtkWindow *window)
2230 GtkWindowIconInfo *info;
2232 info = get_icon_info (window);
2233 if (info && info->icon_list)
2234 return GDK_PIXBUF (info->icon_list->data);
2240 * gtk_window_set_default_icon_list:
2241 * @list: a list of #GdkPixbuf
2243 * Sets an icon list to be used as fallback for windows that haven't
2244 * had gtk_window_set_icon_list() called on them to set up a
2245 * window-specific icon list. This function allows you to set up the
2246 * icon for all windows in your app at once.
2248 * See gtk_window_set_icon_list() for more details.
2252 gtk_window_set_default_icon_list (GList *list)
2256 if (list == default_icon_list)
2259 if (default_icon_pixmap)
2260 g_object_unref (G_OBJECT (default_icon_pixmap));
2261 if (default_icon_mask)
2262 g_object_unref (G_OBJECT (default_icon_mask));
2264 default_icon_pixmap = NULL;
2265 default_icon_mask = NULL;
2267 g_list_foreach (default_icon_list,
2268 (GFunc) g_object_unref, NULL);
2270 g_list_free (default_icon_list);
2272 default_icon_list = g_list_copy (list);
2273 g_list_foreach (default_icon_list,
2274 (GFunc) g_object_ref, NULL);
2276 /* Update all toplevels */
2277 toplevels = gtk_window_list_toplevels ();
2278 tmp_list = toplevels;
2279 while (tmp_list != NULL)
2281 GtkWindowIconInfo *info;
2282 GtkWindow *w = tmp_list->data;
2284 info = get_icon_info (w);
2285 if (info && info->using_default_icon)
2287 gtk_window_unrealize_icon (w);
2288 if (GTK_WIDGET_REALIZED (w))
2289 gtk_window_realize_icon (w);
2292 tmp_list = tmp_list->next;
2294 g_list_free (toplevels);
2298 * gtk_window_get_default_icon_list:
2300 * Gets the value set by gtk_window_set_default_icon_list().
2301 * The list is a copy and should be freed with g_list_free(),
2302 * but the pixbufs in the list have not had their reference count
2305 * Return value: copy of default icon list
2308 gtk_window_get_default_icon_list (void)
2310 return g_list_copy (default_icon_list);
2314 gtk_window_set_default_size_internal (GtkWindow *window,
2315 gboolean change_width,
2317 gboolean change_height,
2320 GtkWindowGeometryInfo *info;
2322 g_return_if_fail (GTK_IS_WINDOW (window));
2323 g_return_if_fail (change_width == FALSE || width >= -1);
2324 g_return_if_fail (change_height == FALSE || height >= -1);
2326 info = gtk_window_get_geometry_info (window, TRUE);
2328 g_object_freeze_notify (G_OBJECT (window));
2338 info->default_width = width;
2340 g_object_notify (G_OBJECT (window), "default_width");
2351 info->default_height = height;
2353 g_object_notify (G_OBJECT (window), "default_height");
2356 g_object_thaw_notify (G_OBJECT (window));
2358 gtk_widget_queue_resize (GTK_WIDGET (window));
2362 * gtk_window_set_default_size:
2363 * @window: a #GtkWindow
2364 * @width: width in pixels, or -1 to unset the default width
2365 * @height: height in pixels, or -1 to unset the default height
2367 * Sets the default size of a window. If the window's "natural" size
2368 * (its size request) is larger than the default, the default will be
2369 * ignored. More generally, if the default size does not obey the
2370 * geometry hints for the window (gtk_window_set_geometry_hints() can
2371 * be used to set these explicitly), the default size will be clamped
2372 * to the nearest permitted size.
2374 * Unlike gtk_widget_set_size_request(), which sets a size request for
2375 * a widget and thus would keep users from shrinking the window, this
2376 * function only sets the initial size, just as if the user had
2377 * resized the window themselves. Users can still shrink the window
2378 * again as they normally would. Setting a default size of -1 means to
2379 * use the "natural" default size (the size request of the window).
2381 * For more control over a window's initial size and how resizing works,
2382 * investigate gtk_window_set_geometry_hints().
2384 * A useful feature: if you set the "geometry widget" via
2385 * gtk_window_set_geometry_hints(), the default size specified by
2386 * gtk_window_set_default_size() will be the default size of that
2387 * widget, not of the entire window.
2389 * For some uses, gtk_window_resize() is a more appropriate function.
2390 * gtk_window_resize() changes the current size of the window, rather
2391 * than the size to be used on initial display. gtk_window_resize() always
2392 * affects the window itself, not the geometry widget.
2394 * The default size of a window only affects the first time a window is
2395 * shown; if a window is hidden and re-shown, it will remember the size
2396 * it had prior to hiding, rather than using the default size.
2398 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2399 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2402 gtk_window_set_default_size (GtkWindow *window,
2406 g_return_if_fail (GTK_IS_WINDOW (window));
2407 g_return_if_fail (width >= -1);
2408 g_return_if_fail (height >= -1);
2410 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height);
2414 * gtk_window_get_default_size:
2415 * @window: a #GtkWindow
2416 * @width: location to store the default width, or %NULL
2417 * @height: location to store the default height, or %NULL
2419 * Gets the default size of the window. A value of -1 for the width or
2420 * height indicates that a default size has not been explicitly set
2421 * for that dimension, so the "natural" size of the window will be
2426 gtk_window_get_default_size (GtkWindow *window,
2430 GtkWindowGeometryInfo *info;
2432 g_return_if_fail (GTK_IS_WINDOW (window));
2434 info = gtk_window_get_geometry_info (window, FALSE);
2437 *width = info->default_width;
2440 *height = info->default_height;
2444 * gtk_window_resize:
2445 * @window: a #GtkWindow
2446 * @width: width to resize the window to
2447 * @height: height to resize the window to
2449 * Resizes the window as if the user had done so, obeying geometry
2450 * constraints. The default geometry constraint is that windows may
2451 * not be smaller than their size request; to override this
2452 * constraint, call gtk_widget_set_size_request() to set the window's
2453 * request to a smaller value.
2455 * If gtk_window_resize() is called before showing a window for the
2456 * first time, it overrides any default size set with
2457 * gtk_window_set_default_size().
2459 * Windows may not be resized smaller than 1 by 1 pixels.
2463 gtk_window_resize (GtkWindow *window,
2467 GtkWindowGeometryInfo *info;
2469 g_return_if_fail (GTK_IS_WINDOW (window));
2470 g_return_if_fail (width > 0);
2471 g_return_if_fail (height > 0);
2473 info = gtk_window_get_geometry_info (window, TRUE);
2475 info->resize_width = width;
2476 info->resize_height = height;
2478 gtk_widget_queue_resize (GTK_WIDGET (window));
2482 * gtk_window_get_size:
2483 * @window: a #GtkWindow
2484 * @width: return location for width, or %NULL
2485 * @height: return location for height, or %NULL
2487 * Obtains the current size of @window. If @window is not onscreen,
2488 * it returns the size GTK+ will suggest to the window manager for the
2489 * initial window size (but this is not reliably the same as the size
2490 * the window manager will actually select). The size obtained by
2491 * gtk_window_get_size() is the last size received in a
2492 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2493 * rather than querying the X server for the size. As a result, if you
2494 * call gtk_window_resize() then immediately call
2495 * gtk_window_get_size(), the size won't have taken effect yet. After
2496 * the window manager processes the resize request, GTK+ receives
2497 * notification that the size has changed via a configure event, and
2498 * the size of the window gets updated.
2500 * Note 1: Nearly any use of this function creates a race condition,
2501 * because the size of the window may change between the time that you
2502 * get the size and the time that you perform some action assuming
2503 * that size is the current size. To avoid race conditions, connect to
2504 * "configure_event" on the window and adjust your size-dependent
2505 * state to match the size delivered in the #GdkEventConfigure.
2507 * Note 2: The returned size does NOT include the size of the window
2508 * manager decorations (aka the window frame or border). Those
2509 * are not drawn by GTK+ and GTK+ has no reliable method of
2510 * determining their size.
2512 * Note 3: If you are getting a window size in order to position
2513 * the window onscreen, there may be a better way. The preferred
2514 * way is to simply set the window's semantic type with
2515 * gtk_window_set_type_hint(), which allows the window manager to
2516 * e.g. center dialogs. Also, if you set the transient parent of
2517 * dialogs with gtk_widget_set_transient_for() window managers
2518 * will often center the dialog over its parent window. It's
2519 * much preferred to let the window manager handle these
2520 * things rather than doing it yourself, because all apps will
2521 * behave consistently and according to user prefs if the window
2522 * manager handles it. Also, the window manager can take the size
2523 * of the window decorations/border into account, while your
2524 * application cannot.
2526 * In any case, if you insist on application-specified window
2527 * positioning, there's STILL a better way than doing it yourself -
2528 * gtk_window_set_position() will frequently handle the details
2533 gtk_window_get_size (GtkWindow *window,
2540 g_return_if_fail (GTK_IS_WINDOW (window));
2542 widget = GTK_WIDGET (window);
2544 if (width == NULL && height == NULL)
2547 if (GTK_WIDGET_MAPPED (window))
2549 gdk_drawable_get_size (GTK_WIDGET (window)->window,
2554 GdkRectangle configure_request;
2556 gtk_window_compute_configure_request (window,
2560 w = configure_request.width;
2561 h = configure_request.height;
2572 * @window: a #GtkWindow
2573 * @x: X coordinate to move window to
2574 * @y: Y coordinate to move window to
2576 * Asks the window manager to move @window to the given position.
2577 * Window managers are free to ignore this; most window managers
2578 * ignore requests for initial window positions (instead using a
2579 * user-defined placement algorithm) and honor requests after the
2580 * window has already been shown.
2582 * Note: the position is the position of the gravity-determined
2583 * reference point for the window. The gravity determines two things:
2584 * first, the location of the reference point in root window
2585 * coordinates; and second, which point on the window is positioned at
2586 * the reference point.
2588 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
2589 * point is simply the @x, @y supplied to gtk_window_move(). The
2590 * top-left corner of the window decorations (aka window frame or
2591 * border) will be placed at @x, @y. Therefore, to position a window
2592 * at the top left of the screen, you want to use the default gravity
2593 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
2595 * To position a window at the bottom right corner of the screen, you
2596 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
2597 * point is at @x + the window width and @y + the window height, and
2598 * the bottom-right corner of the window border will be placed at that
2599 * reference point. So, to place a window in the bottom right corner
2600 * you would first set gravity to south east, then write:
2601 * gtk_window_move (window, gdk_screen_width () - window_width,
2602 * gdk_screen_height () - window_height).
2604 * The extended window manager hints specification at <ulink
2605 * url="http://www.freedesktop.org/standards/wm-spec.html"
2606 * >http://www.freedesktop.org/standards/wm-spec.html</ulink> has a
2607 * nice table of gravities in the "implementation notes" section.
2609 * The gtk_window_get_position() documentation may also be relevant.
2613 gtk_window_move (GtkWindow *window,
2617 GtkWindowGeometryInfo *info;
2620 g_return_if_fail (GTK_IS_WINDOW (window));
2622 widget = GTK_WIDGET (window);
2624 info = gtk_window_get_geometry_info (window, TRUE);
2626 if (GTK_WIDGET_MAPPED (window))
2628 /* we have now sent a request with this position
2629 * with currently-active constraints, so toggle flag.
2631 info->position_constraints_changed = FALSE;
2633 /* we only constrain if mapped - if not mapped,
2634 * then gtk_window_compute_configure_request()
2635 * will apply the constraints later, and we
2636 * don't want to lose information about
2637 * what position the user set before then.
2638 * i.e. if you do a move() then turn off POS_CENTER
2639 * then show the window, your move() will work.
2641 gtk_window_constrain_position (window,
2642 widget->allocation.width,
2643 widget->allocation.height,
2646 /* Note that this request doesn't go through our standard request
2647 * framework, e.g. doesn't increment configure_request_count,
2648 * doesn't set info->last, etc.; that's because
2649 * we don't save the info needed to arrive at this same request
2652 * To gtk_window_move_resize(), this will end up looking exactly
2653 * the same as the position being changed by the window
2657 /* FIXME are we handling gravity properly for framed windows? */
2659 gdk_window_move (window->frame,
2660 x - window->frame_left,
2661 y - window->frame_top);
2663 gdk_window_move (GTK_WIDGET (window)->window,
2668 /* Save this position to apply on mapping */
2669 info->initial_x = x;
2670 info->initial_y = y;
2671 info->initial_pos_set = TRUE;
2676 * gtk_window_get_position:
2677 * @window: a #GtkWindow
2678 * @root_x: return location for X coordinate of gravity-determined reference p\oint
2679 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
2681 * This function returns the position you need to pass to
2682 * gtk_window_move() to keep @window in its current position. This
2683 * means that the meaning of the returned value varies with window
2684 * gravity. See gtk_window_move() for more details.
2686 * If you haven't changed the window gravity, its gravity will be
2687 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
2688 * gets the position of the top-left corner of the window manager
2689 * frame for the window. gtk_window_move() sets the position of this
2690 * same top-left corner.
2692 * gtk_window_get_position() is not 100% reliable because the X Window System
2693 * does not specify a way to obtain the geometry of the
2694 * decorations placed on a window by the window manager.
2695 * Thus GTK+ is using a "best guess" that works with most
2698 * Moreover, nearly all window managers are broken with respect to
2699 * their handling of window gravity. So moving a window to its current
2700 * position as returned by gtk_window_get_position() tends to
2701 * result in moving the window slightly.
2703 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
2704 * frame is not relevant, and thus gtk_window_get_position() will
2705 * always produce accurate results. However you can't use static
2706 * gravity to do things like place a window in a corner of the screen,
2707 * because static gravity ignores the window manager decorations.
2709 * If you are saving and restoring your application's window
2710 * positions, you should know that it's impossible for applications to
2711 * do this without getting it somewhat wrong because applications do
2712 * not have sufficient knowledge of window manager state. The Correct
2713 * Mechanism is to support the session management protocol (see the
2714 * "GnomeClient" object in the GNOME libraries for example) and allow
2715 * the window manager to save your window sizes and positions.
2720 gtk_window_get_position (GtkWindow *window,
2726 g_return_if_fail (GTK_IS_WINDOW (window));
2728 widget = GTK_WIDGET (window);
2730 if (window->gravity == GDK_GRAVITY_STATIC)
2732 if (GTK_WIDGET_MAPPED (widget))
2734 /* This does a server round-trip, which is sort of wrong;
2735 * but a server round-trip is inevitable for
2736 * gdk_window_get_frame_extents() in the usual
2737 * NorthWestGravity case below, so not sure what else to
2738 * do. We should likely be consistent about whether we get
2739 * the client-side info or the server-side info.
2741 gdk_window_get_origin (widget->window, root_x, root_y);
2745 GdkRectangle configure_request;
2747 gtk_window_compute_configure_request (window,
2751 *root_x = configure_request.x;
2752 *root_y = configure_request.y;
2757 GdkRectangle frame_extents;
2762 if (GTK_WIDGET_MAPPED (widget))
2765 gdk_window_get_frame_extents (window->frame, &frame_extents);
2767 gdk_window_get_frame_extents (widget->window, &frame_extents);
2768 x = frame_extents.x;
2769 y = frame_extents.y;
2770 gtk_window_get_size (window, &w, &h);
2774 /* We just say the frame has 0 size on all sides.
2775 * Not sure what else to do.
2777 gtk_window_compute_configure_request (window,
2780 x = frame_extents.x;
2781 y = frame_extents.y;
2782 w = frame_extents.width;
2783 h = frame_extents.height;
2786 switch (window->gravity)
2788 case GDK_GRAVITY_NORTH:
2789 case GDK_GRAVITY_CENTER:
2790 case GDK_GRAVITY_SOUTH:
2791 /* Find center of frame. */
2792 x += frame_extents.width / 2;
2793 /* Center client window on that point. */
2797 case GDK_GRAVITY_SOUTH_EAST:
2798 case GDK_GRAVITY_EAST:
2799 case GDK_GRAVITY_NORTH_EAST:
2800 /* Find right edge of frame */
2801 x += frame_extents.width;
2802 /* Align left edge of client at that point. */
2809 switch (window->gravity)
2811 case GDK_GRAVITY_WEST:
2812 case GDK_GRAVITY_CENTER:
2813 case GDK_GRAVITY_EAST:
2814 /* Find center of frame. */
2815 y += frame_extents.height / 2;
2816 /* Center client window there. */
2819 case GDK_GRAVITY_SOUTH_WEST:
2820 case GDK_GRAVITY_SOUTH:
2821 case GDK_GRAVITY_SOUTH_EAST:
2822 /* Find south edge of frame */
2823 y += frame_extents.height;
2824 /* Place bottom edge of client there */
2839 * gtk_window_reshow_with_initial_size:
2840 * @window: a #GtkWindow
2842 * Hides @window, then reshows it, resetting the
2843 * default size and position of the window. Used
2844 * by GUI builders only.
2847 gtk_window_reshow_with_initial_size (GtkWindow *window)
2851 g_return_if_fail (GTK_IS_WINDOW (window));
2853 widget = GTK_WIDGET (window);
2855 gtk_widget_hide (widget);
2856 gtk_widget_unrealize (widget);
2857 gtk_widget_show (widget);
2861 gtk_window_destroy (GtkObject *object)
2865 g_return_if_fail (GTK_IS_WINDOW (object));
2867 window = GTK_WINDOW (object);
2869 if (window->transient_parent)
2870 gtk_window_set_transient_for (window, NULL);
2872 /* frees the icons */
2873 gtk_window_set_icon_list (window, NULL);
2875 if (window->has_user_ref_count)
2877 window->has_user_ref_count = FALSE;
2878 gtk_widget_unref (GTK_WIDGET (window));
2882 gtk_window_group_remove_window (window->group, window);
2884 GTK_OBJECT_CLASS (parent_class)->destroy (object);
2888 gtk_window_mnemonic_hash_remove (gpointer key,
2892 GtkWindowMnemonic *mnemonic = key;
2893 GtkWindow *window = user;
2895 if (mnemonic->window == window)
2897 if (mnemonic->targets)
2899 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
2901 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
2902 name, mnemonic->targets->data);
2905 g_slist_free (mnemonic->targets);
2914 gtk_window_finalize (GObject *object)
2918 g_return_if_fail (GTK_IS_WINDOW (object));
2920 window = GTK_WINDOW (object);
2922 toplevel_list = g_slist_remove (toplevel_list, window);
2924 g_free (window->title);
2925 g_free (window->wmclass_name);
2926 g_free (window->wmclass_class);
2927 g_free (window->wm_role);
2929 g_hash_table_foreach_remove (mnemonic_hash_table,
2930 gtk_window_mnemonic_hash_remove,
2932 if (window->geometry_info)
2934 if (window->geometry_info->widget)
2935 gtk_signal_disconnect_by_func (GTK_OBJECT (window->geometry_info->widget),
2936 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
2937 &window->geometry_info->widget);
2938 g_free (window->geometry_info);
2941 if (window->keys_changed_handler)
2943 gtk_idle_remove (window->keys_changed_handler);
2944 window->keys_changed_handler = 0;
2947 G_OBJECT_CLASS (parent_class)->finalize (object);
2951 gtk_window_show (GtkWidget *widget)
2953 GtkWindow *window = GTK_WINDOW (widget);
2954 GtkContainer *container = GTK_CONTAINER (window);
2955 gboolean need_resize;
2957 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
2959 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
2960 container->need_resize = FALSE;
2964 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
2965 GtkAllocation allocation = { 0, 0 };
2966 GdkRectangle configure_request;
2967 GdkGeometry new_geometry;
2969 gboolean was_realized;
2971 /* We are going to go ahead and perform this configure request
2972 * and then emulate a configure notify by going ahead and
2973 * doing a size allocate. Sort of a synchronous
2974 * mini-copy of gtk_window_move_resize() here.
2976 gtk_window_compute_configure_request (window,
2981 /* We update this because we are going to go ahead
2982 * and gdk_window_resize() below, rather than
2985 info->last.configure_request.width = configure_request.width;
2986 info->last.configure_request.height = configure_request.height;
2988 /* and allocate the window - this is normally done
2989 * in move_resize in response to configure notify
2991 allocation.width = configure_request.width;
2992 allocation.height = configure_request.height;
2993 gtk_widget_size_allocate (widget, &allocation);
2995 /* Then we guarantee we have a realize */
2996 was_realized = FALSE;
2997 if (!GTK_WIDGET_REALIZED (widget))
2999 gtk_widget_realize (widget);
3000 was_realized = TRUE;
3003 /* Must be done after the windows are realized,
3004 * so that the decorations can be read
3006 gtk_decorated_window_calculate_frame_size (window);
3008 /* We only send configure request if we didn't just finish
3009 * creating the window; if we just created the window
3010 * then we created it with widget->allocation anyhow.
3013 gdk_window_resize (widget->window,
3014 configure_request.width,
3015 configure_request.height);
3018 gtk_container_check_resize (container);
3020 gtk_widget_map (widget);
3023 gtk_grab_add (widget);
3027 gtk_window_hide (GtkWidget *widget)
3031 g_return_if_fail (GTK_IS_WINDOW (widget));
3033 window = GTK_WINDOW (widget);
3035 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3036 gtk_widget_unmap (widget);
3039 gtk_grab_remove (widget);
3043 gtk_window_map (GtkWidget *widget)
3046 GdkWindow *toplevel;
3048 g_return_if_fail (GTK_IS_WINDOW (widget));
3050 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3052 window = GTK_WINDOW (widget);
3054 if (window->bin.child &&
3055 GTK_WIDGET_VISIBLE (window->bin.child) &&
3056 !GTK_WIDGET_MAPPED (window->bin.child))
3057 gtk_widget_map (window->bin.child);
3060 toplevel = window->frame;
3062 toplevel = widget->window;
3064 if (window->maximize_initially)
3065 gdk_window_maximize (toplevel);
3067 gdk_window_unmaximize (toplevel);
3069 if (window->stick_initially)
3070 gdk_window_stick (toplevel);
3072 gdk_window_unstick (toplevel);
3074 if (window->iconify_initially)
3075 gdk_window_iconify (toplevel);
3077 gdk_window_deiconify (toplevel);
3079 /* No longer use the default settings */
3080 window->need_default_size = FALSE;
3081 window->need_default_position = FALSE;
3083 gdk_window_show (widget->window);
3086 gdk_window_show (window->frame);
3090 gtk_window_unmap (GtkWidget *widget)
3093 GtkWindowGeometryInfo *info;
3095 window = GTK_WINDOW (widget);
3097 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3099 gdk_window_withdraw (window->frame);
3101 gdk_window_withdraw (widget->window);
3103 window->configure_request_count = 0;
3104 window->configure_notify_received = FALSE;
3106 /* on unmap, we reset the default positioning of the window,
3107 * so it's placed again, but we don't reset the default
3108 * size of the window, so it's remembered.
3110 window->need_default_position = TRUE;
3112 info = gtk_window_get_geometry_info (window, FALSE);
3115 info->initial_pos_set = FALSE;
3116 info->position_constraints_changed = FALSE;
3121 gtk_window_realize (GtkWidget *widget)
3124 GdkWindow *parent_window;
3125 GdkWindowAttr attributes;
3126 gint attributes_mask;
3128 g_return_if_fail (GTK_IS_WINDOW (widget));
3130 window = GTK_WINDOW (widget);
3132 /* ensure widget tree is properly size allocated */
3133 if (widget->allocation.x == -1 &&
3134 widget->allocation.y == -1 &&
3135 widget->allocation.width == 1 &&
3136 widget->allocation.height == 1)
3138 GtkRequisition requisition;
3139 GtkAllocation allocation = { 0, 0, 200, 200 };
3141 gtk_widget_size_request (widget, &requisition);
3142 if (requisition.width || requisition.height)
3144 /* non-empty window */
3145 allocation.width = requisition.width;
3146 allocation.height = requisition.height;
3148 gtk_widget_size_allocate (widget, &allocation);
3150 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3152 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3155 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3157 switch (window->type)
3159 case GTK_WINDOW_TOPLEVEL:
3160 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3162 case GTK_WINDOW_POPUP:
3163 attributes.window_type = GDK_WINDOW_TEMP;
3166 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3170 attributes.title = window->title;
3171 attributes.wmclass_name = window->wmclass_name;
3172 attributes.wmclass_class = window->wmclass_class;
3173 attributes.wclass = GDK_INPUT_OUTPUT;
3174 attributes.visual = gtk_widget_get_visual (widget);
3175 attributes.colormap = gtk_widget_get_colormap (widget);
3177 if (window->has_frame)
3179 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3180 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3181 attributes.event_mask = (GDK_EXPOSURE_MASK |
3182 GDK_KEY_PRESS_MASK |
3183 GDK_ENTER_NOTIFY_MASK |
3184 GDK_LEAVE_NOTIFY_MASK |
3185 GDK_FOCUS_CHANGE_MASK |
3186 GDK_STRUCTURE_MASK |
3187 GDK_BUTTON_MOTION_MASK |
3188 GDK_POINTER_MOTION_HINT_MASK |
3189 GDK_BUTTON_PRESS_MASK |
3190 GDK_BUTTON_RELEASE_MASK);
3192 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3194 window->frame = gdk_window_new (NULL, &attributes, attributes_mask);
3195 gdk_window_set_user_data (window->frame, widget);
3197 attributes.window_type = GDK_WINDOW_CHILD;
3198 attributes.x = window->frame_left;
3199 attributes.y = window->frame_right;
3201 attributes_mask = GDK_WA_X | GDK_WA_Y;
3203 parent_window = window->frame;
3207 attributes_mask = 0;
3208 parent_window = NULL;
3211 attributes.width = widget->allocation.width;
3212 attributes.height = widget->allocation.height;
3213 attributes.event_mask = gtk_widget_get_events (widget);
3214 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3215 GDK_KEY_PRESS_MASK |
3216 GDK_ENTER_NOTIFY_MASK |
3217 GDK_LEAVE_NOTIFY_MASK |
3218 GDK_FOCUS_CHANGE_MASK |
3219 GDK_STRUCTURE_MASK);
3221 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3222 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3223 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3224 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3225 gdk_window_set_user_data (widget->window, window);
3227 widget->style = gtk_style_attach (widget->style, widget->window);
3228 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3230 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3232 /* This is a bad hack to set the window background. */
3233 gtk_window_paint (widget, NULL);
3235 if (window->transient_parent &&
3236 GTK_WIDGET_REALIZED (window->transient_parent))
3237 gdk_window_set_transient_for (widget->window,
3238 GTK_WIDGET (window->transient_parent)->window);
3240 if (window->wm_role)
3241 gdk_window_set_role (widget->window, window->wm_role);
3243 if (!window->decorated)
3244 gdk_window_set_decorations (widget->window, 0);
3246 gdk_window_set_type_hint (widget->window, window->type_hint);
3248 /* transient_for must be set to allow the modal hint */
3249 if (window->transient_parent && window->modal)
3250 gdk_window_set_modal_hint (widget->window, TRUE);
3252 gdk_window_set_modal_hint (widget->window, FALSE);
3255 gtk_window_realize_icon (window);
3259 gtk_window_unrealize (GtkWidget *widget)
3262 GtkWindowGeometryInfo *info;
3264 window = GTK_WINDOW (widget);
3266 /* On unrealize, we reset the size of the window such
3267 * that we will re-apply the default sizing stuff
3268 * next time we show the window.
3270 * Default positioning is reset on unmap, instead of unrealize.
3272 window->need_default_size = TRUE;
3273 info = gtk_window_get_geometry_info (window, FALSE);
3276 info->resize_width = -1;
3277 info->resize_height = -1;
3278 info->last.configure_request.x = 0;
3279 info->last.configure_request.y = 0;
3280 info->last.configure_request.width = -1;
3281 info->last.configure_request.height = -1;
3282 /* be sure we reset geom hints on re-realize */
3283 info->last.flags = 0;
3288 gdk_window_set_user_data (window->frame, NULL);
3289 gdk_window_destroy (window->frame);
3290 window->frame = NULL;
3294 gtk_window_unrealize_icon (window);
3296 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3300 gtk_window_size_request (GtkWidget *widget,
3301 GtkRequisition *requisition)
3306 g_return_if_fail (GTK_IS_WINDOW (widget));
3307 g_return_if_fail (requisition != NULL);
3309 window = GTK_WINDOW (widget);
3310 bin = GTK_BIN (window);
3312 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3313 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3315 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3317 GtkRequisition child_requisition;
3319 gtk_widget_size_request (bin->child, &child_requisition);
3321 requisition->width += child_requisition.width;
3322 requisition->height += child_requisition.height;
3327 gtk_window_size_allocate (GtkWidget *widget,
3328 GtkAllocation *allocation)
3331 GtkAllocation child_allocation;
3333 g_return_if_fail (GTK_IS_WINDOW (widget));
3334 g_return_if_fail (allocation != NULL);
3336 window = GTK_WINDOW (widget);
3337 widget->allocation = *allocation;
3339 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3341 child_allocation.x = GTK_CONTAINER (window)->border_width;
3342 child_allocation.y = GTK_CONTAINER (window)->border_width;
3343 child_allocation.width =
3344 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3345 child_allocation.height =
3346 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3348 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3351 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3353 gdk_window_resize (window->frame,
3354 allocation->width + window->frame_left + window->frame_right,
3355 allocation->height + window->frame_top + window->frame_bottom);
3360 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3363 gboolean return_val;
3366 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3367 g_return_val_if_fail (event != NULL, FALSE);
3369 window = GTK_WINDOW (widget);
3371 if (window->frame && (event->any.window == window->frame))
3373 if ((event->type != GDK_KEY_PRESS) &&
3374 (event->type != GDK_KEY_RELEASE) &&
3375 (event->type != GDK_FOCUS_CHANGE))
3377 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
3379 gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
3384 g_object_unref (event->any.window);
3385 event->any.window = g_object_ref (widget->window);
3393 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3395 GdkEventConfigure *configure_event;
3398 switch (event->type)
3401 configure_event = (GdkEventConfigure *)event;
3403 /* Invalidate the decorations */
3406 rect.width = configure_event->width;
3407 rect.height = configure_event->height;
3409 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3411 /* Pass on the (modified) configure event */
3412 configure_event->width -= window->frame_left + window->frame_right;
3413 configure_event->height -= window->frame_top + window->frame_bottom;
3414 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3423 gtk_window_configure_event (GtkWidget *widget,
3424 GdkEventConfigure *event)
3428 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3429 g_return_val_if_fail (event != NULL, FALSE);
3431 window = GTK_WINDOW (widget);
3433 /* window->configure_request_count incremented for each
3434 * configure request, and decremented to a min of 0 for
3435 * each configure notify.
3437 * All it means is that we know we will get at least
3438 * window->configure_request_count more configure notifies.
3439 * We could get more configure notifies than that; some
3440 * of the configure notifies we get may be unrelated to
3441 * the configure requests. But we will get at least
3442 * window->configure_request_count notifies.
3445 if (window->configure_request_count > 0)
3446 window->configure_request_count -= 1;
3448 /* As an optimization, we avoid a resize when possible.
3450 * The only times we can avoid a resize are:
3451 * - we know only the position changed, not the size
3452 * - we know we have made more requests and so will get more
3453 * notifies and can wait to resize when we get them
3456 if (window->configure_request_count > 0 ||
3457 (widget->allocation.width == event->width &&
3458 widget->allocation.height == event->height))
3462 * If we do need to resize, we do that by:
3463 * - filling in widget->allocation with the new size
3464 * - setting configure_notify_received to TRUE
3465 * for use in gtk_window_move_resize()
3466 * - queueing a resize, leading to invocation of
3467 * gtk_window_move_resize() in an idle handler
3471 window->configure_notify_received = TRUE;
3473 widget->allocation.width = event->width;
3474 widget->allocation.height = event->height;
3476 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3481 /* the accel_key and accel_mods fields of the key have to be setup
3482 * upon calling this function. it'll then return whether that key
3483 * is at all used as accelerator, and if so will OR in the
3484 * accel_flags member of the key.
3487 _gtk_window_query_nonaccels (GtkWindow *window,
3489 GdkModifierType accel_mods)
3491 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3493 /* movement keys are considered locked accels */
3496 static const guint bindings[] = {
3497 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
3498 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
3502 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
3503 if (bindings[i] == accel_key)
3507 /* mnemonics are considered locked accels */
3508 if (accel_mods == window->mnemonic_modifier)
3510 GtkWindowMnemonic mkey;
3512 mkey.window = window;
3513 mkey.keyval = accel_key;
3514 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
3522 gtk_window_key_press_event (GtkWidget *widget,
3529 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3530 g_return_val_if_fail (event != NULL, FALSE);
3532 window = GTK_WINDOW (widget);
3537 handled = gtk_window_mnemonic_activate (window,
3542 handled = gtk_accel_groups_activate (G_OBJECT (window), event->keyval, event->state);
3546 focus = window->focus_widget;
3548 g_object_ref (focus);
3551 focus && focus != widget &&
3552 gtk_widget_get_toplevel (focus) == widget)
3556 if (GTK_WIDGET_IS_SENSITIVE (focus))
3557 handled = gtk_widget_event (focus, (GdkEvent*) event);
3559 parent = focus->parent;
3561 g_object_ref (parent);
3563 g_object_unref (focus);
3569 g_object_unref (focus);
3572 /* Chain up, invokes binding set */
3573 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
3574 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
3580 gtk_window_key_release_event (GtkWidget *widget,
3586 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3587 g_return_val_if_fail (event != NULL, FALSE);
3589 window = GTK_WINDOW (widget);
3591 if (window->focus_widget &&
3592 window->focus_widget != widget &&
3593 GTK_WIDGET_SENSITIVE (window->focus_widget))
3595 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
3598 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
3599 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
3605 gtk_window_real_activate_default (GtkWindow *window)
3607 gtk_window_activate_default (window);
3611 gtk_window_real_activate_focus (GtkWindow *window)
3613 gtk_window_activate_focus (window);
3617 gtk_window_move_focus (GtkWindow *window,
3618 GtkDirectionType dir)
3620 gtk_widget_child_focus (GTK_WIDGET (window), dir);
3622 if (!GTK_CONTAINER (window)->focus_child)
3623 gtk_window_set_focus (window, NULL);
3627 gtk_window_enter_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_leave_notify_event (GtkWidget *widget,
3638 GdkEventCrossing *event)
3640 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3641 g_return_val_if_fail (event != NULL, FALSE);
3647 gtk_window_focus_in_event (GtkWidget *widget,
3648 GdkEventFocus *event)
3650 GtkWindow *window = GTK_WINDOW (widget);
3651 GdkEventFocus fevent;
3653 /* It appears spurious focus in events can occur when
3654 * the window is hidden. So we'll just check to see if
3655 * the window is visible before actually handling the
3658 if (GTK_WIDGET_VISIBLE (widget))
3660 window->has_focus = TRUE;
3662 if (window->focus_widget &&
3663 window->focus_widget != widget &&
3664 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3666 fevent.type = GDK_FOCUS_CHANGE;
3667 fevent.window = window->focus_widget->window;
3670 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
3678 gtk_window_focus_out_event (GtkWidget *widget,
3679 GdkEventFocus *event)
3681 GtkWindow *window = GTK_WINDOW (widget);
3682 GdkEventFocus fevent;
3684 window->has_focus = FALSE;
3686 if (window->focus_widget &&
3687 window->focus_widget != widget &&
3688 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3690 fevent.type = GDK_FOCUS_CHANGE;
3691 fevent.window = window->focus_widget->window;
3694 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
3700 static GdkAtom atom_rcfiles = GDK_NONE;
3703 gtk_window_read_rcfiles (GtkWidget *widget,
3704 GdkEventClient *event)
3706 GList *embedded_windows;
3708 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
3709 if (embedded_windows)
3714 for (i = 0; i < 5; i++)
3716 sev.data_format = 32;
3717 sev.message_type = atom_rcfiles;
3719 while (embedded_windows)
3721 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
3722 gdk_event_send_client_message ((GdkEvent *) &sev, xid);
3723 embedded_windows = embedded_windows->next;
3727 gtk_rc_reparse_all ();
3731 gtk_window_client_event (GtkWidget *widget,
3732 GdkEventClient *event)
3734 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3735 g_return_val_if_fail (event != NULL, FALSE);
3738 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
3740 if (event->message_type == atom_rcfiles)
3741 gtk_window_read_rcfiles (widget, event);
3747 gtk_window_check_resize (GtkContainer *container)
3751 g_return_if_fail (GTK_IS_WINDOW (container));
3753 window = GTK_WINDOW (container);
3755 if (GTK_WIDGET_VISIBLE (container))
3756 gtk_window_move_resize (window);
3760 gtk_window_focus (GtkWidget *widget,
3761 GtkDirectionType direction)
3765 GtkContainer *container;
3766 GtkWidget *old_focus_child;
3769 container = GTK_CONTAINER (widget);
3770 window = GTK_WINDOW (widget);
3771 bin = GTK_BIN (widget);
3773 old_focus_child = container->focus_child;
3775 /* We need a special implementation here to deal properly with wrapping
3776 * around in the tab chain without the danger of going into an
3779 if (old_focus_child)
3781 if (gtk_widget_child_focus (old_focus_child, direction))
3785 if (window->focus_widget)
3787 /* Wrapped off the end, clear the focus setting for the toplpevel */
3788 parent = window->focus_widget->parent;
3791 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
3792 parent = GTK_WIDGET (parent)->parent;
3795 gtk_window_set_focus (GTK_WINDOW (container), NULL);
3798 /* Now try to focus the first widget in the window */
3801 if (gtk_widget_child_focus (bin->child, direction))
3809 gtk_window_real_set_focus (GtkWindow *window,
3812 GdkEventFocus event;
3813 gboolean def_flags = 0;
3815 g_return_if_fail (GTK_IS_WINDOW (window));
3817 if (window->default_widget)
3818 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
3820 if (window->focus_widget)
3822 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3823 (window->focus_widget != window->default_widget))
3825 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3827 if (window->default_widget)
3828 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3831 if (window->has_focus)
3833 event.type = GDK_FOCUS_CHANGE;
3834 event.window = window->focus_widget->window;
3837 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
3841 window->focus_widget = focus;
3843 if (window->focus_widget)
3845 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3846 (window->focus_widget != window->default_widget))
3848 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
3849 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3851 if (window->default_widget)
3852 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3855 if (window->has_focus)
3857 event.type = GDK_FOCUS_CHANGE;
3858 event.window = window->focus_widget->window;
3861 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
3865 if (window->default_widget &&
3866 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
3867 gtk_widget_queue_draw (window->default_widget);
3870 /*********************************
3871 * Functions related to resizing *
3872 *********************************/
3874 /* This function doesn't constrain to geometry hints */
3876 gtk_window_compute_configure_request_size (GtkWindow *window,
3880 GtkRequisition requisition;
3881 GtkWindowGeometryInfo *info;
3885 * - we've done a size request
3888 widget = GTK_WIDGET (window);
3890 info = gtk_window_get_geometry_info (window, FALSE);
3892 if (window->need_default_size)
3894 gtk_widget_get_child_requisition (widget, &requisition);
3896 /* Default to requisition */
3897 *width = requisition.width;
3898 *height = requisition.height;
3900 /* If window is empty so requests 0, default to random nonzero size */
3901 if (*width == 0 && *height == 0)
3907 /* Override requisition with default size */
3911 if (info->default_width > 0)
3912 *width = info->default_width;
3914 if (info->default_height > 0)
3915 *height = info->default_height;
3920 /* Default to keeping current size */
3921 *width = widget->allocation.width;
3922 *height = widget->allocation.height;
3925 /* Override any size with gtk_window_resize() values */
3928 if (info->resize_width > 0)
3929 *width = info->resize_width;
3931 if (info->resize_height > 0)
3932 *height = info->resize_height;
3937 gtk_window_compute_configure_request (GtkWindow *window,
3938 GdkRectangle *request,
3939 GdkGeometry *geometry,
3942 GdkGeometry new_geometry;
3946 GtkWindowPosition pos;
3947 GtkWidget *parent_widget;
3948 GtkWindowGeometryInfo *info;
3951 widget = GTK_WIDGET (window);
3953 gtk_widget_size_request (widget, NULL);
3954 gtk_window_compute_configure_request_size (window, &w, &h);
3956 gtk_window_compute_hints (window, &new_geometry, &new_flags);
3957 gtk_window_constrain_size (window,
3958 &new_geometry, new_flags,
3962 parent_widget = (GtkWidget*) window->transient_parent;
3964 pos = window->position;
3965 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
3966 (parent_widget == NULL ||
3967 !GTK_WIDGET_MAPPED (parent_widget)))
3968 pos = GTK_WIN_POS_NONE;
3970 info = gtk_window_get_geometry_info (window, TRUE);
3972 /* by default, don't change position requested */
3973 x = info->last.configure_request.x;
3974 y = info->last.configure_request.y;
3976 if (window->need_default_position)
3979 /* FIXME this all interrelates with window gravity.
3980 * For most of them I think we want to set GRAVITY_CENTER.
3982 * Not sure how to go about that.
3987 /* here we are only handling CENTER_ALWAYS
3988 * as it relates to default positioning,
3989 * where it's equivalent to simply CENTER
3991 case GTK_WIN_POS_CENTER_ALWAYS:
3992 case GTK_WIN_POS_CENTER:
3994 gint screen_width = gdk_screen_width ();
3995 gint screen_height = gdk_screen_height ();
3997 x = (screen_width - w) / 2;
3998 y = (screen_height - h) / 2;
4002 case GTK_WIN_POS_CENTER_ON_PARENT:
4006 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
4008 gdk_window_get_origin (parent_widget->window,
4011 x = ox + (parent_widget->allocation.width - w) / 2;
4012 y = oy + (parent_widget->allocation.height - h) / 2;
4016 case GTK_WIN_POS_MOUSE:
4018 gint screen_width = gdk_screen_width ();
4019 gint screen_height = gdk_screen_height ();
4022 gdk_window_get_pointer (NULL, &px, &py, NULL);
4025 x = CLAMP (x, 0, screen_width - w);
4026 y = CLAMP (y, 0, screen_height - h);
4033 } /* if (window->need_default_position) */
4035 if (window->need_default_position &&
4036 info->initial_pos_set)
4038 x = info->initial_x;
4039 y = info->initial_y;
4040 gtk_window_constrain_position (window, w, h, &x, &y);
4046 request->height = h;
4049 *geometry = new_geometry;
4055 gtk_window_constrain_position (GtkWindow *window,
4061 /* See long comments in gtk_window_move_resize()
4062 * on when it's safe to call this function.
4064 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4066 gint center_x, center_y;
4067 gint screen_width = gdk_screen_width ();
4068 gint screen_height = gdk_screen_height ();
4070 center_x = (screen_width - new_width) / 2;
4071 center_y = (screen_height - new_height) / 2;
4079 gtk_window_move_resize (GtkWindow *window)
4083 * First we determine whether any information has changed that would
4084 * cause us to revise our last configure request. If we would send
4085 * a different configure request from last time, then
4086 * configure_request_size_changed = TRUE or
4087 * configure_request_pos_changed = TRUE. configure_request_size_changed
4088 * may be true due to new hints, a gtk_window_resize(), or whatever.
4089 * configure_request_pos_changed may be true due to gtk_window_set_position()
4090 * or gtk_window_move().
4092 * If the configure request has changed, we send off a new one. To
4093 * ensure GTK invariants are maintained (resize queue does what it
4094 * should), we go ahead and size_allocate the requested size in this
4097 * If the configure request has not changed, we don't ever resend
4098 * it, because it could mean fighting the user or window manager.
4101 * To prepare the configure request, we come up with a base size/pos:
4102 * - the one from gtk_window_move()/gtk_window_resize()
4103 * - else default_width, default_height if we haven't ever
4105 * - else the size request if we haven't ever been mapped,
4106 * as a substitute default size
4107 * - else the current size of the window, as received from
4108 * configure notifies (i.e. the current allocation)
4110 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4111 * the position request to be centered.
4114 GtkContainer *container;
4115 GtkWindowGeometryInfo *info;
4116 GdkGeometry new_geometry;
4118 GdkRectangle new_request;
4119 gboolean configure_request_size_changed;
4120 gboolean configure_request_pos_changed;
4121 gboolean hints_changed; /* do we need to send these again */
4122 GtkWindowLastGeometryInfo saved_last_info;
4124 widget = GTK_WIDGET (window);
4125 container = GTK_CONTAINER (widget);
4126 info = gtk_window_get_geometry_info (window, TRUE);
4128 configure_request_size_changed = FALSE;
4129 configure_request_pos_changed = FALSE;
4131 gtk_window_compute_configure_request (window, &new_request,
4132 &new_geometry, &new_flags);
4134 /* This check implies the invariant that we never set info->last
4135 * without setting the hints and sending off a configure request.
4137 * If we change info->last without sending the request, we may
4140 if (info->last.configure_request.x != new_request.x ||
4141 info->last.configure_request.y != new_request.y)
4142 configure_request_pos_changed = TRUE;
4144 if ((info->last.configure_request.width != new_request.width ||
4145 info->last.configure_request.height != new_request.height))
4146 configure_request_size_changed = TRUE;
4148 hints_changed = FALSE;
4150 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4151 &new_geometry, new_flags))
4153 hints_changed = TRUE;
4156 /* Position Constraints
4157 * ====================
4159 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4160 * a default. The other POS_ values are used only when the
4161 * window is shown, not after that.
4163 * However, we can't implement a position constraint as
4164 * "anytime the window size changes, center the window"
4165 * because this may well end up fighting the WM or user. In
4166 * fact it gets in an infinite loop with at least one WM.
4168 * Basically, applications are in no way in a position to
4169 * constrain the position of a window, with one exception:
4170 * override redirect windows. (Really the intended purpose
4171 * of CENTER_ALWAYS anyhow, I would think.)
4173 * So the way we implement this "constraint" is to say that when WE
4174 * cause a move or resize, i.e. we make a configure request changing
4175 * window size, we recompute the CENTER_ALWAYS position to reflect
4176 * the new window size, and include it in our request. Also, if we
4177 * just turned on CENTER_ALWAYS we snap to center with a new
4178 * request. Otherwise, if we are just NOTIFIED of a move or resize
4179 * done by someone else e.g. the window manager, we do NOT send a
4180 * new configure request.
4182 * For override redirect windows, this works fine; all window
4183 * sizes are from our configure requests. For managed windows,
4184 * it is at least semi-sane, though who knows what the
4185 * app author is thinking.
4188 /* This condition should be kept in sync with the condition later on
4189 * that determines whether we send a configure request. i.e. we
4190 * should do this position constraining anytime we were going to
4191 * send a configure request anyhow, plus when constraints have
4194 if (configure_request_pos_changed ||
4195 configure_request_size_changed ||
4197 info->position_constraints_changed)
4199 /* We request the constrained position if:
4200 * - we were changing position, and need to clamp
4201 * the change to the constraint
4202 * - we're changing the size anyway
4203 * - set_position() was called to toggle CENTER_ALWAYS on
4206 gtk_window_constrain_position (window,
4212 /* Update whether we need to request a move */
4213 if (info->last.configure_request.x != new_request.x ||
4214 info->last.configure_request.y != new_request.y)
4215 configure_request_pos_changed = TRUE;
4217 configure_request_pos_changed = FALSE;
4222 int notify_x, notify_y;
4224 /* this is the position from the last configure notify */
4225 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4227 g_print ("--- %s ---\n"
4228 "last : %d,%d\t%d x %d\n"
4229 "this : %d,%d\t%d x %d\n"
4230 "alloc: %d,%d\t%d x %d\n"
4232 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4233 "configure_notify_received: %d\n"
4234 "configure_request_count: %d\n"
4235 "position_constraints_changed: %d\n",
4236 window->title ? window->title : "(no title)",
4237 info->last.configure_request.x,
4238 info->last.configure_request.y,
4239 info->last.configure_request.width,
4240 info->last.configure_request.height,
4246 widget->allocation.width,
4247 widget->allocation.height,
4248 widget->requisition.width,
4249 widget->requisition.height,
4250 configure_request_pos_changed,
4251 configure_request_size_changed,
4253 window->configure_notify_received,
4254 window->configure_request_count,
4255 info->position_constraints_changed);
4259 saved_last_info = info->last;
4260 info->last.geometry = new_geometry;
4261 info->last.flags = new_flags;
4262 info->last.configure_request = new_request;
4264 /* need to set PPosition so the WM will look at our position,
4265 * but we don't want to count PPosition coming and going as a hints
4266 * change for future iterations. So we saved info->last prior to
4270 /* Also, if the initial position was explicitly set, then we always
4271 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4275 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4276 * this is an initial map
4279 if ((configure_request_pos_changed ||
4280 info->initial_pos_set ||
4281 (window->need_default_position &&
4282 window->position != GTK_WIN_POS_NONE)) &&
4283 (new_flags & GDK_HINT_POS) == 0)
4285 new_flags |= GDK_HINT_POS;
4286 hints_changed = TRUE;
4289 /* Set hints if necessary
4292 gdk_window_set_geometry_hints (widget->window,
4296 /* handle resizing/moving and widget tree allocation
4298 if (window->configure_notify_received)
4300 GtkAllocation allocation;
4302 /* If we have received a configure event since
4303 * the last time in this function, we need to
4304 * accept our new size and size_allocate child widgets.
4305 * (see gtk_window_configure_event() for more details).
4307 * 1 or more configure notifies may have been received.
4308 * Also, configure_notify_received will only be TRUE
4309 * if all expected configure notifies have been received
4310 * (one per configure request), as an optimization.
4313 window->configure_notify_received = FALSE;
4315 /* gtk_window_configure_event() filled in widget->allocation */
4316 allocation = widget->allocation;
4317 gtk_widget_size_allocate (widget, &allocation);
4319 /* If the configure request changed, it means that
4321 * 1) coincidentally changed hints or widget properties
4322 * impacting the configure request before getting
4323 * a configure notify, or
4324 * 2) some broken widget is changing its size request
4325 * during size allocation, resulting in
4326 * a false appearance of changed configure request.
4328 * For 1), we could just go ahead and ask for the
4329 * new size right now, but doing that for 2)
4330 * might well be fighting the user (and can even
4331 * trigger a loop). Since we really don't want to
4332 * do that, we requeue a resize in hopes that
4333 * by the time it gets handled, the child has seen
4334 * the light and is willing to go along with the
4335 * new size. (this happens for the zvt widget, since
4336 * the size_allocate() above will have stored the
4337 * requisition corresponding to the new size in the
4340 * This doesn't buy us anything for 1), but it shouldn't
4341 * hurt us too badly, since it is what would have
4342 * happened if we had gotten the configure event before
4343 * the new size had been set.
4346 if (configure_request_size_changed ||
4347 configure_request_pos_changed)
4349 /* Don't change the recorded last info after all, because we
4350 * haven't actually updated to the new info yet - we decided
4351 * to postpone our configure request until later.
4353 info->last = saved_last_info;
4355 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
4358 else if ((configure_request_size_changed || hints_changed) &&
4359 (widget->allocation.width != new_request.width ||
4360 widget->allocation.height != new_request.height))
4363 /* We are in one of the following situations:
4364 * A. configure_request_size_changed
4365 * our requisition has changed and we need a different window size,
4366 * so we request it from the window manager.
4367 * B. !configure_request_size_changed && hints_changed
4368 * the window manager rejects our size, but we have just changed the
4369 * window manager hints, so there's a chance our request will
4370 * be honoured this time, so we try again.
4372 * However, if the new requisition is the same as the current allocation,
4373 * we don't request it again, since we won't get a ConfigureNotify back from
4374 * the window manager unless it decides to change our requisition. If
4375 * we don't get the ConfigureNotify back, the resize queue will never be run.
4378 /* Now send the configure request */
4379 if (configure_request_pos_changed)
4383 gdk_window_move_resize (window->frame,
4384 new_request.x - window->frame_left,
4385 new_request.y - window->frame_top,
4386 new_request.width + window->frame_left + window->frame_right,
4387 new_request.height + window->frame_top + window->frame_bottom);
4388 gdk_window_resize (GTK_WIDGET (window)->window,
4389 new_request.width, new_request.height);
4392 gdk_window_move_resize (widget->window,
4393 new_request.x, new_request.y,
4394 new_request.width, new_request.height);
4396 else /* only size changed */
4399 gdk_window_resize (window->frame,
4400 new_request.width + window->frame_left + window->frame_right,
4401 new_request.height + window->frame_top + window->frame_bottom);
4402 gdk_window_resize (widget->window,
4403 new_request.width, new_request.height);
4406 /* Increment the number of have-not-yet-received-notify requests */
4407 window->configure_request_count += 1;
4409 /* We have now sent a request since the last position constraint
4410 * change and definitely don't need a an initial size again (not
4411 * resetting this here can lead to infinite loops for
4412 * GTK_RESIZE_IMMEDIATE containers)
4414 info->position_constraints_changed = FALSE;
4415 window->need_default_position = FALSE;
4417 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
4418 * configure event in response to our resizing request.
4419 * the configure event will cause a new resize with
4420 * ->configure_notify_received=TRUE.
4421 * until then, we want to
4422 * - discard expose events
4423 * - coalesce resizes for our children
4424 * - defer any window resizes until the configure event arrived
4425 * to achieve this, we queue a resize for the window, but remove its
4426 * resizing handler, so resizing will not be handled from the next
4427 * idle handler but when the configure event arrives.
4429 * FIXME: we should also dequeue the pending redraws here, since
4430 * we handle those ourselves upon ->configure_notify_received==TRUE.
4432 if (container->resize_mode == GTK_RESIZE_QUEUE)
4434 gtk_widget_queue_resize (widget);
4435 _gtk_container_dequeue_resize_handler (container);
4440 /* Handle any position changes.
4442 if (configure_request_pos_changed)
4446 gdk_window_move (window->frame,
4447 new_request.x - window->frame_left,
4448 new_request.y - window->frame_top);
4451 gdk_window_move (widget->window,
4452 new_request.x, new_request.y);
4455 /* And run the resize queue.
4457 gtk_container_resize_children (container);
4461 /* Compare two sets of Geometry hints for equality.
4464 gtk_window_compare_hints (GdkGeometry *geometry_a,
4466 GdkGeometry *geometry_b,
4469 if (flags_a != flags_b)
4472 if ((flags_a & GDK_HINT_MIN_SIZE) &&
4473 (geometry_a->min_width != geometry_b->min_width ||
4474 geometry_a->min_height != geometry_b->min_height))
4477 if ((flags_a & GDK_HINT_MAX_SIZE) &&
4478 (geometry_a->max_width != geometry_b->max_width ||
4479 geometry_a->max_height != geometry_b->max_height))
4482 if ((flags_a & GDK_HINT_BASE_SIZE) &&
4483 (geometry_a->base_width != geometry_b->base_width ||
4484 geometry_a->base_height != geometry_b->base_height))
4487 if ((flags_a & GDK_HINT_ASPECT) &&
4488 (geometry_a->min_aspect != geometry_b->min_aspect ||
4489 geometry_a->max_aspect != geometry_b->max_aspect))
4492 if ((flags_a & GDK_HINT_RESIZE_INC) &&
4493 (geometry_a->width_inc != geometry_b->width_inc ||
4494 geometry_a->height_inc != geometry_b->height_inc))
4497 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
4498 geometry_a->win_gravity != geometry_b->win_gravity)
4505 _gtk_window_constrain_size (GtkWindow *window,
4511 GtkWindowGeometryInfo *info;
4513 g_return_if_fail (GTK_IS_WINDOW (window));
4515 info = window->geometry_info;
4518 GdkWindowHints flags = info->last.flags;
4519 GdkGeometry *geometry = &info->last.geometry;
4521 gtk_window_constrain_size (window,
4532 gtk_window_constrain_size (GtkWindow *window,
4533 GdkGeometry *geometry,
4540 gdk_window_constrain_size (geometry, flags, width, height,
4541 new_width, new_height);
4544 /* Compute the set of geometry hints and flags for a window
4545 * based on the application set geometry, and requisiition
4546 * of the window. gtk_widget_size_request() must have been
4550 gtk_window_compute_hints (GtkWindow *window,
4551 GdkGeometry *new_geometry,
4555 gint extra_width = 0;
4556 gint extra_height = 0;
4557 GtkWindowGeometryInfo *geometry_info;
4558 GtkRequisition requisition;
4560 g_return_if_fail (GTK_IS_WINDOW (window));
4562 widget = GTK_WIDGET (window);
4564 gtk_widget_get_child_requisition (widget, &requisition);
4565 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
4569 *new_flags = geometry_info->mask;
4570 *new_geometry = geometry_info->geometry;
4577 if (geometry_info && geometry_info->widget)
4579 extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
4580 extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
4583 /* We don't want to set GDK_HINT_POS in here, we just set it
4584 * in gtk_window_move_resize() when we want the position
4588 if (*new_flags & GDK_HINT_BASE_SIZE)
4590 new_geometry->base_width += extra_width;
4591 new_geometry->base_height += extra_height;
4593 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
4594 (*new_flags & GDK_HINT_RESIZE_INC) &&
4595 ((extra_width != 0) || (extra_height != 0)))
4597 *new_flags |= GDK_HINT_BASE_SIZE;
4599 new_geometry->base_width = extra_width;
4600 new_geometry->base_height = extra_height;
4603 if (*new_flags & GDK_HINT_MIN_SIZE)
4605 if (new_geometry->min_width < 0)
4606 new_geometry->min_width = requisition.width;
4608 new_geometry->min_width += extra_width;
4610 if (new_geometry->min_height < 0)
4611 new_geometry->min_height = requisition.height;
4613 new_geometry->min_height += extra_height;
4615 else if (!window->allow_shrink)
4617 *new_flags |= GDK_HINT_MIN_SIZE;
4619 new_geometry->min_width = requisition.width;
4620 new_geometry->min_height = requisition.height;
4623 if (*new_flags & GDK_HINT_MAX_SIZE)
4625 if (new_geometry->max_width < 0)
4626 new_geometry->max_width = requisition.width;
4628 new_geometry->max_width += extra_width;
4630 if (new_geometry->max_height < 0)
4631 new_geometry->max_width = requisition.height;
4633 new_geometry->max_height += extra_height;
4635 else if (!window->allow_grow)
4637 *new_flags |= GDK_HINT_MAX_SIZE;
4639 new_geometry->max_width = requisition.width;
4640 new_geometry->max_height = requisition.height;
4643 *new_flags |= GDK_HINT_WIN_GRAVITY;
4644 new_geometry->win_gravity = window->gravity;
4647 /***********************
4648 * Redrawing functions *
4649 ***********************/
4652 gtk_window_paint (GtkWidget *widget,
4655 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
4656 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
4660 gtk_window_expose (GtkWidget *widget,
4661 GdkEventExpose *event)
4663 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
4664 g_return_val_if_fail (event != NULL, FALSE);
4666 if (!GTK_WIDGET_APP_PAINTABLE (widget))
4667 gtk_window_paint (widget, &event->area);
4669 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
4670 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
4676 * gtk_window_set_has_frame:
4677 * @window: a #GtkWindow
4678 * @setting: a boolean
4680 * (Note: this is a special-purpose function for the framebuffer port,
4681 * that causes GTK+ to draw its own window border. For most applications,
4682 * you want gtk_window_set_decorated() instead, which tells the window
4683 * manager whether to draw the window border.)
4685 * If this function is called on a window with setting of TRUE, before
4686 * it is realized or showed, it will have a "frame" window around
4687 * widget->window, accessible in window->frame. Using the signal
4688 * frame_event you can recieve all events targeted at the frame.
4690 * This function is used by the linux-fb port to implement managed
4691 * windows, but it could concievably be used by X-programs that
4692 * want to do their own window decorations.
4696 gtk_window_set_has_frame (GtkWindow *window,
4699 g_return_if_fail (GTK_IS_WINDOW (window));
4700 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
4702 window->has_frame = setting != FALSE;
4706 * gtk_window_get_has_frame:
4707 * @window: a #GtkWindow
4709 * Accessor for whether the window has a frame window exterior to
4710 * widget->window. Gets the value set by gtk_window_set_has_frame ().
4712 * Return value: %TRUE if a frame has been added to the window
4713 * via gtk_widow_has_frame
4716 gtk_window_get_has_frame (GtkWindow *window)
4718 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4720 return window->has_frame;
4724 * gtk_window_set_frame_dimensions:
4725 * @window: a #GtkWindow that has a frame
4726 * @left: The width of the left border
4727 * @top: The height of the top border
4728 * @right: The width of the right border
4729 * @bottom: The height of the bottom border
4731 * (Note: this is a special-purpose function intended for the framebuffer
4732 * port; see gtk_window_set_has_frame(). It will have no effect on the
4733 * window border drawn by the window manager, which is the normal
4734 * case when using the X Window system.)
4736 * For windows with frames (see #gtk_window_set_has_frame) this function
4737 * can be used to change the size of the frame border.
4740 gtk_window_set_frame_dimensions (GtkWindow *window,
4746 GtkWidget *widget = GTK_WIDGET (window);
4748 g_return_if_fail (GTK_IS_WINDOW (window));
4750 if (window->frame_left == left &&
4751 window->frame_top == top &&
4752 window->frame_right == right &&
4753 window->frame_bottom == bottom)
4756 window->frame_left = left;
4757 window->frame_top = top;
4758 window->frame_right = right;
4759 window->frame_bottom = bottom;
4761 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4763 gint width = widget->allocation.width + left + right;
4764 gint height = widget->allocation.height + top + bottom;
4765 gdk_window_resize (window->frame, width, height);
4766 gtk_decorated_window_move_resize_window (window,
4768 widget->allocation.width,
4769 widget->allocation.height);
4774 * gtk_window_present:
4775 * @window: a #GtkWindow
4777 * Presents a window to the user. This may mean raising the window
4778 * in the stacking order, deiconifying it, moving it to the current
4779 * desktop, and/or giving it the keyboard focus, possibly dependent
4780 * on the user's platform, window manager, and preferences.
4782 * If @window is hidden, this function calls gtk_widget_show()
4785 * This function should be used when the user tries to open a window
4786 * that's already open. Say for example the preferences dialog is
4787 * currently open, and the user chooses Preferences from the menu
4788 * a second time; use gtk_window_present() to move the already-open dialog
4789 * where the user can see it.
4793 gtk_window_present (GtkWindow *window)
4797 g_return_if_fail (GTK_IS_WINDOW (window));
4799 widget = GTK_WIDGET (window);
4801 if (GTK_WIDGET_VISIBLE (window))
4803 g_assert (widget->window != NULL);
4805 gdk_window_show (widget->window);
4807 /* note that gdk_window_focus() will also move the window to
4808 * the current desktop, for WM spec compliant window managers.
4810 gdk_window_focus (widget->window,
4811 gtk_get_current_event_time ());
4815 gtk_widget_show (widget);
4820 * gtk_window_iconify:
4821 * @window: a #GtkWindow
4823 * Asks to iconify (i.e. minimize) the specified @window. Note that you
4824 * shouldn't assume the window is definitely iconified afterward,
4825 * because other entities (e.g. the user or window manager) could
4826 * deiconify it again, or there may not be a window manager in which
4827 * case iconification isn't possible, etc. But normally the window
4828 * will end up iconified. Just don't write code that crashes if not.
4830 * It's permitted to call this function before showing a window,
4831 * in which case the window will be iconified before it ever appears
4834 * You can track iconification via the "window_state_event" signal
4839 gtk_window_iconify (GtkWindow *window)
4842 GdkWindow *toplevel;
4844 g_return_if_fail (GTK_IS_WINDOW (window));
4846 widget = GTK_WIDGET (window);
4848 window->iconify_initially = TRUE;
4851 toplevel = window->frame;
4853 toplevel = widget->window;
4855 if (toplevel != NULL)
4856 gdk_window_iconify (toplevel);
4860 * gtk_window_deiconify:
4861 * @window: a #GtkWindow
4863 * Asks to deiconify (i.e. unminimize) the specified @window. Note
4864 * that you shouldn't assume the window is definitely deiconified
4865 * afterward, because other entities (e.g. the user or window manager)
4866 * could iconify it again before your code which assumes
4867 * deiconification gets to run.
4869 * You can track iconification via the "window_state_event" signal
4873 gtk_window_deiconify (GtkWindow *window)
4876 GdkWindow *toplevel;
4878 g_return_if_fail (GTK_IS_WINDOW (window));
4880 widget = GTK_WIDGET (window);
4882 window->iconify_initially = FALSE;
4885 toplevel = window->frame;
4887 toplevel = widget->window;
4889 if (toplevel != NULL)
4890 gdk_window_deiconify (toplevel);
4895 * @window: a #GtkWindow
4897 * Asks to stick @window, which means that it will appear on all user
4898 * desktops. Note that you shouldn't assume the window is definitely
4899 * stuck afterward, because other entities (e.g. the user or window
4900 * manager) could unstick it again, and some window managers do not
4901 * support sticking windows. But normally the window will end up
4902 * stuck. Just don't write code that crashes if not.
4904 * It's permitted to call this function before showing a window.
4906 * You can track stickiness via the "window_state_event" signal
4911 gtk_window_stick (GtkWindow *window)
4914 GdkWindow *toplevel;
4916 g_return_if_fail (GTK_IS_WINDOW (window));
4918 widget = GTK_WIDGET (window);
4920 window->stick_initially = TRUE;
4923 toplevel = window->frame;
4925 toplevel = widget->window;
4927 if (toplevel != NULL)
4928 gdk_window_stick (toplevel);
4932 * gtk_window_unstick:
4933 * @window: a #GtkWindow
4935 * Asks to unstick @window, which means that it will appear on only
4936 * one of the user's desktops. Note that you shouldn't assume the
4937 * window is definitely unstuck afterward, because other entities
4938 * (e.g. the user or window manager) could stick it again. But
4939 * normally the window will end up stuck. Just don't write code that
4942 * You can track stickiness via the "window_state_event" signal
4947 gtk_window_unstick (GtkWindow *window)
4950 GdkWindow *toplevel;
4952 g_return_if_fail (GTK_IS_WINDOW (window));
4954 widget = GTK_WIDGET (window);
4956 window->stick_initially = FALSE;
4959 toplevel = window->frame;
4961 toplevel = widget->window;
4963 if (toplevel != NULL)
4964 gdk_window_unstick (toplevel);
4968 * gtk_window_maximize:
4969 * @window: a #GtkWindow
4971 * Asks to maximize @window, so that it becomes full-screen. Note that
4972 * you shouldn't assume the window is definitely maximized afterward,
4973 * because other entities (e.g. the user or window manager) could
4974 * unmaximize it again, and not all window managers support
4975 * maximization. But normally the window will end up maximized. Just
4976 * don't write code that crashes if not.
4978 * It's permitted to call this function before showing a window,
4979 * in which case the window will be maximized when it appears onscreen
4982 * You can track maximization via the "window_state_event" signal
4987 gtk_window_maximize (GtkWindow *window)
4990 GdkWindow *toplevel;
4992 g_return_if_fail (GTK_IS_WINDOW (window));
4994 widget = GTK_WIDGET (window);
4996 window->maximize_initially = TRUE;
4999 toplevel = window->frame;
5001 toplevel = widget->window;
5003 if (toplevel != NULL)
5004 gdk_window_maximize (toplevel);
5008 * gtk_window_unmaximize:
5009 * @window: a #GtkWindow
5011 * Asks to unmaximize @window. Note that you shouldn't assume the
5012 * window is definitely unmaximized afterward, because other entities
5013 * (e.g. the user or window manager) could maximize it again, and not
5014 * all window managers honor requests to unmaximize. But normally the
5015 * window will end up unmaximized. Just don't write code that crashes
5018 * You can track maximization via the "window_state_event" signal
5023 gtk_window_unmaximize (GtkWindow *window)
5026 GdkWindow *toplevel;
5028 g_return_if_fail (GTK_IS_WINDOW (window));
5030 widget = GTK_WIDGET (window);
5032 window->maximize_initially = FALSE;
5035 toplevel = window->frame;
5037 toplevel = widget->window;
5039 if (toplevel != NULL)
5040 gdk_window_unmaximize (toplevel);
5044 * gtk_window_set_resizable:
5045 * @window: a #GtkWindow
5046 * @resizable: %TRUE if the user can resize this window
5048 * Sets whether the user can resize a window. Windows are user resizable
5052 gtk_window_set_resizable (GtkWindow *window,
5055 g_return_if_fail (GTK_IS_WINDOW (window));
5057 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5061 * gtk_window_get_resizable:
5062 * @window: a #GtkWindow
5064 * Gets the value set by gtk_window_set_resizable().
5066 * Return value: %TRUE if the user can resize the window
5069 gtk_window_get_resizable (GtkWindow *window)
5071 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5073 /* allow_grow is most likely to indicate the semantic concept we
5074 * mean by "resizable" (and will be a reliable indicator if
5075 * set_policy() hasn't been called)
5077 return window->allow_grow;
5081 * gtk_window_set_gravity:
5082 * @window: a #GtkWindow
5083 * @gravity: window gravity
5085 * Window gravity defines the meaning of coordinates passed to
5086 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5089 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5090 * typically "do what you mean."
5094 gtk_window_set_gravity (GtkWindow *window,
5097 g_return_if_fail (GTK_IS_WINDOW (window));
5099 if (gravity != window->gravity)
5101 window->gravity = gravity;
5103 /* gtk_window_move_resize() will adapt gravity
5105 gtk_widget_queue_resize (GTK_WIDGET (window));
5110 * gtk_window_get_gravity:
5111 * @window: a #GtkWindow
5113 * Gets the value set by gtk_window_set_gravity().
5115 * Return value: window gravity
5118 gtk_window_get_gravity (GtkWindow *window)
5120 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5122 return window->gravity;
5126 * gtk_window_begin_resize_drag:
5127 * @window: a #GtkWindow
5128 * @button: mouse button that initiated the drag
5129 * @edge: position of the resize control
5130 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5131 * @root_y: Y position where the user clicked to initiate the drag
5132 * @timestamp: timestamp from the click event that initiated the drag
5134 * Starts resizing a window. This function is used if an application
5135 * has window resizing controls. When GDK can support it, the resize
5136 * will be done using the standard mechanism for the window manager or
5137 * windowing system. Otherwise, GDK will try to emulate window
5138 * resizing, potentially not all that well, depending on the windowing system.
5142 gtk_window_begin_resize_drag (GtkWindow *window,
5150 GdkWindow *toplevel;
5152 g_return_if_fail (GTK_IS_WINDOW (window));
5153 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5155 widget = GTK_WIDGET (window);
5158 toplevel = window->frame;
5160 toplevel = widget->window;
5162 gdk_window_begin_resize_drag (toplevel,
5169 * gtk_window_get_frame_dimensions:
5170 * @window: a #GtkWindow
5171 * @left: location to store the width of the frame at the left, or %NULL
5172 * @top: location to store the height of the frame at the top, or %NULL
5173 * @right: location to store the width of the frame at the returns, or %NULL
5174 * @bottom: location to store the height of the frame at the bottom, or %NULL
5176 * (Note: this is a special-purpose function intended for the
5177 * framebuffer port; see gtk_window_set_has_frame(). It will not
5178 * return the size of the window border drawn by the window manager,
5179 * which is the normal case when using a windowing system.
5180 * See gdk_window_get_frame_extents() to get the standard
5181 * window border extents.)
5183 * Retrieves the dimensions of the frame window for this toplevel.
5184 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5187 gtk_window_get_frame_dimensions (GtkWindow *window,
5193 g_return_if_fail (GTK_IS_WINDOW (window));
5196 *left = window->frame_left;
5198 *top = window->frame_top;
5200 *right = window->frame_right;
5202 *bottom = window->frame_bottom;
5206 * gtk_window_begin_move_drag:
5207 * @window: a #GtkWindow
5208 * @button: mouse button that initiated the drag
5209 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5210 * @root_y: Y position where the user clicked to initiate the drag
5211 * @timestamp: timestamp from the click event that initiated the drag
5213 * Starts moving a window. This function is used if an application
5214 * has window movement grips. When GDK can support it, the window movement
5215 * will be done using the standard mechanism for the window manager or
5216 * windowing system. Otherwise, GDK will try to emulate window
5217 * movement, potentially not all that well, depending on the windowing system.
5221 gtk_window_begin_move_drag (GtkWindow *window,
5228 GdkWindow *toplevel;
5230 g_return_if_fail (GTK_IS_WINDOW (window));
5231 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5233 widget = GTK_WIDGET (window);
5236 toplevel = window->frame;
5238 toplevel = widget->window;
5240 gdk_window_begin_move_drag (toplevel,
5248 gtk_window_group_class_init (GtkWindowGroupClass *klass)
5253 gtk_window_group_get_type (void)
5255 static GtkType window_group_type = 0;
5257 if (!window_group_type)
5259 static const GTypeInfo window_group_info =
5261 sizeof (GtkWindowGroupClass),
5262 NULL, /* base_init */
5263 NULL, /* base_finalize */
5264 (GClassInitFunc) gtk_window_group_class_init,
5265 NULL, /* class_finalize */
5266 NULL, /* class_data */
5267 sizeof (GtkWindowGroup),
5268 16, /* n_preallocs */
5269 (GInstanceInitFunc) NULL,
5272 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
5275 return window_group_type;
5279 * gtk_window_group_new:
5281 * Creates a new #GtkWindowGroup object. Grabs added with
5282 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
5284 * Return value: a new #GtkWindowGroup.
5287 gtk_window_group_new (void)
5289 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
5293 window_group_cleanup_grabs (GtkWindowGroup *group,
5297 GSList *to_remove = NULL;
5299 tmp_list = group->grabs;
5302 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
5303 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
5304 tmp_list = tmp_list->next;
5309 gtk_grab_remove (to_remove->data);
5310 g_object_unref (to_remove->data);
5311 to_remove = g_slist_delete_link (to_remove, to_remove);
5316 * gtk_window_group_add_window:
5317 * @window_group: a #GtkWindowGroup
5318 * @window: the #GtkWindow to add
5320 * Adds a window to a #GtkWindowGroup.
5323 gtk_window_group_add_window (GtkWindowGroup *window_group,
5326 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5327 g_return_if_fail (GTK_IS_WINDOW (window));
5329 if (window->group != window_group)
5331 g_object_ref (window);
5332 g_object_ref (window_group);
5335 gtk_window_group_remove_window (window->group, window);
5337 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
5339 window->group = window_group;
5341 g_object_unref (window);
5346 * gtk_window_group_remove_window:
5347 * @window_group: a #GtkWindowGroup
5348 * @window: the #GtkWindow to remove
5350 * Removes a window from a #GtkWindowGroup.
5353 gtk_window_group_remove_window (GtkWindowGroup *window_group,
5356 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5357 g_return_if_fail (GTK_IS_WIDGET (window));
5358 g_return_if_fail (window->group == window_group);
5360 g_object_ref (window);
5362 window_group_cleanup_grabs (window_group, window);
5363 window->group = NULL;
5365 g_object_unref (G_OBJECT (window_group));
5366 g_object_unref (window);
5369 /* Return the group for the window or the default group
5372 _gtk_window_get_group (GtkWindow *window)
5374 if (window && window->group)
5375 return window->group;
5378 static GtkWindowGroup *default_group = NULL;
5381 default_group = gtk_window_group_new ();
5383 return default_group;
5389 Derived from XParseGeometry() in XFree86
5391 Copyright 1985, 1986, 1987,1998 The Open Group
5393 All Rights Reserved.
5395 The above copyright notice and this permission notice shall be included
5396 in all copies or substantial portions of the Software.
5398 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5399 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5400 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
5401 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
5402 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
5403 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
5404 OTHER DEALINGS IN THE SOFTWARE.
5406 Except as contained in this notice, the name of The Open Group shall
5407 not be used in advertising or otherwise to promote the sale, use or
5408 other dealings in this Software without prior written authorization
5409 from The Open Group.
5414 * XParseGeometry parses strings of the form
5415 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5416 * width, height, xoffset, and yoffset are unsigned integers.
5417 * Example: "=80x24+300-49"
5418 * The equal sign is optional.
5419 * It returns a bitmask that indicates which of the four values
5420 * were actually found in the string. For each value found,
5421 * the corresponding argument is updated; for each value
5422 * not found, the corresponding argument is left unchanged.
5425 /* The following code is from Xlib, and is minimally modified, so we
5426 * can track any upstream changes if required. Don't change this
5427 * code. Or if you do, put in a huge comment marking which thing
5432 read_int (gchar *string,
5440 else if (*string == '-')
5446 for (; (*string >= '0') && (*string <= '9'); string++)
5448 result = (result * 10) + (*string - '0');
5460 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
5461 * value (x, y, width, height) was found in the parsed string.
5463 #define NoValue 0x0000
5464 #define XValue 0x0001
5465 #define YValue 0x0002
5466 #define WidthValue 0x0004
5467 #define HeightValue 0x0008
5468 #define AllValues 0x000F
5469 #define XNegative 0x0010
5470 #define YNegative 0x0020
5472 /* Try not to reformat/modify, so we can compare/sync with X sources */
5474 gtk_XParseGeometry (const char *string,
5477 unsigned int *width,
5478 unsigned int *height)
5482 unsigned int tempWidth, tempHeight;
5484 char *nextCharacter;
5486 /* These initializations are just to silence gcc */
5492 if ( (string == NULL) || (*string == '\0')) return(mask);
5494 string++; /* ignore possible '=' at beg of geometry spec */
5496 strind = (char *)string;
5497 if (*strind != '+' && *strind != '-' && *strind != 'x') {
5498 tempWidth = read_int(strind, &nextCharacter);
5499 if (strind == nextCharacter)
5501 strind = nextCharacter;
5505 if (*strind == 'x' || *strind == 'X') {
5507 tempHeight = read_int(strind, &nextCharacter);
5508 if (strind == nextCharacter)
5510 strind = nextCharacter;
5511 mask |= HeightValue;
5514 if ((*strind == '+') || (*strind == '-')) {
5515 if (*strind == '-') {
5517 tempX = -read_int(strind, &nextCharacter);
5518 if (strind == nextCharacter)
5520 strind = nextCharacter;
5526 tempX = read_int(strind, &nextCharacter);
5527 if (strind == nextCharacter)
5529 strind = nextCharacter;
5532 if ((*strind == '+') || (*strind == '-')) {
5533 if (*strind == '-') {
5535 tempY = -read_int(strind, &nextCharacter);
5536 if (strind == nextCharacter)
5538 strind = nextCharacter;
5545 tempY = read_int(strind, &nextCharacter);
5546 if (strind == nextCharacter)
5548 strind = nextCharacter;
5554 /* If strind isn't at the end of the string the it's an invalid
5555 geometry specification. */
5557 if (*strind != '\0') return (0);
5563 if (mask & WidthValue)
5565 if (mask & HeightValue)
5566 *height = tempHeight;
5571 * gtk_window_parse_geometry:
5572 * @window: a #GtkWindow
5573 * @geometry: geometry string
5575 * Parses a standard X Window System geometry string - see the
5576 * manual page for X (type 'man X') for details on this.
5577 * gtk_window_parse_geometry() does work on all GTK+ ports
5578 * including Win32 but is primarily intended for an X environment.
5580 * If either a size or a position can be extracted from the
5581 * geometry string, gtk_window_parse_geometry() returns %TRUE
5582 * and calls gtk_window_set_default_size() and/or gtk_window_move()
5583 * to resize/move the window.
5585 * If gtk_window_parse_geometry() returns %TRUE, it will also
5586 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
5587 * indicating to the window manager that the size/position of
5588 * the window was user-specified. This causes most window
5589 * managers to honor the geometry.
5591 * Return value: %TRUE if string was parsed successfully
5594 gtk_window_parse_geometry (GtkWindow *window,
5595 const gchar *geometry)
5600 gboolean size_set, pos_set;
5602 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5603 g_return_val_if_fail (geometry != NULL, FALSE);
5605 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
5607 if ((result & WidthValue) == 0 ||
5610 if ((result & HeightValue) == 0 ||
5615 if ((result & WidthValue) || (result & HeightValue))
5617 gtk_window_set_default_size (window, w, h);
5621 gtk_window_get_size (window, &w, &h);
5623 grav = GDK_GRAVITY_NORTH_WEST;
5625 if ((result & XNegative) && (result & YNegative))
5626 grav = GDK_GRAVITY_SOUTH_EAST;
5627 else if (result & XNegative)
5628 grav = GDK_GRAVITY_NORTH_EAST;
5629 else if (result & YNegative)
5630 grav = GDK_GRAVITY_SOUTH_WEST;
5632 if ((result & XValue) == 0)
5635 if ((result & YValue) == 0)
5638 if (grav == GDK_GRAVITY_SOUTH_WEST ||
5639 grav == GDK_GRAVITY_SOUTH_EAST)
5640 y = gdk_screen_height () - h;
5642 if (grav == GDK_GRAVITY_SOUTH_EAST ||
5643 grav == GDK_GRAVITY_NORTH_EAST)
5644 x = gdk_screen_width () - w;
5653 if ((result & XValue) || (result & YValue))
5655 gtk_window_set_gravity (window, grav);
5656 gtk_window_move (window, x, y);
5660 if (size_set || pos_set)
5662 /* Set USSize, USPosition hints */
5663 GtkWindowGeometryInfo *info;
5665 info = gtk_window_get_geometry_info (window, TRUE);
5668 info->mask |= GDK_HINT_USER_POS;
5670 info->mask |= GDK_HINT_USER_SIZE;