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_window_remove_accel_group:
1095 * @window: a #GtkWindow
1096 * @accel_group: a #GtkAccelGroup
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:
1265 * @window: a #GtkWindow.
1266 * @position: a position constraint.
1268 * Sets a position constraint for this window. If the old or new
1269 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1270 * the window to be repositioned to satisfy the new constraint.
1273 gtk_window_set_position (GtkWindow *window,
1274 GtkWindowPosition position)
1276 g_return_if_fail (GTK_IS_WINDOW (window));
1278 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1279 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1281 GtkWindowGeometryInfo *info;
1283 info = gtk_window_get_geometry_info (window, TRUE);
1285 /* this flag causes us to re-request the CENTER_ALWAYS
1286 * constraint in gtk_window_move_resize(), see
1287 * comment in that function.
1289 info->position_constraints_changed = TRUE;
1291 gtk_widget_queue_resize (GTK_WIDGET (window));
1294 window->position = position;
1296 g_object_notify (G_OBJECT (window), "window_position");
1300 gtk_window_activate_focus (GtkWindow *window)
1302 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1304 if (window->focus_widget)
1306 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1307 gtk_widget_activate (window->focus_widget);
1315 * gtk_window_get_focus:
1316 * @window: a #GtkWindow
1318 * Retrieves the current focused widget within the window.
1319 * Note that this is the widget that would have the focus
1320 * if the toplevel window focused; if the toplevel window
1321 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1322 * not be %TRUE for the widget.
1324 * Return value: the currently focused widget.
1327 gtk_window_get_focus (GtkWindow *window)
1329 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1331 return window->focus_widget;
1335 gtk_window_activate_default (GtkWindow *window)
1337 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1339 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1340 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1342 gtk_widget_activate (window->default_widget);
1345 else if (window->focus_widget)
1347 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1348 gtk_widget_activate (window->focus_widget);
1356 * gtk_window_set_modal:
1357 * @window: a #GtkWindow
1358 * @modal: whether the window is modal
1360 * Sets a window modal or non-modal. Modal windows prevent interaction
1361 * with other windows in the same application. To keep modal dialogs
1362 * on top of main application windows, use
1363 * gtk_window_set_transient_for() to make the dialog transient for the
1364 * parent; most window managers will then disallow lowering the dialog
1370 gtk_window_set_modal (GtkWindow *window,
1373 g_return_if_fail (GTK_IS_WINDOW (window));
1375 window->modal = modal != FALSE;
1377 /* adjust desired modality state */
1378 if (GTK_WIDGET_VISIBLE (window) && window->modal)
1379 gtk_grab_add (GTK_WIDGET (window));
1381 gtk_grab_remove (GTK_WIDGET (window));
1383 g_object_notify (G_OBJECT (window), "modal");
1387 * gtk_window_get_modal:
1388 * @window: a #GtkWindow
1390 * Returns whether the window is modal. See gtk_window_set_modal().
1392 * Return value: %TRUE if the window is set to be modal and
1393 * establishes a grab when shown
1396 gtk_window_get_modal (GtkWindow *window)
1398 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1400 return window->modal;
1404 * gtk_window_list_toplevels:
1406 * Returns a list of all existing toplevel windows. The widgets
1407 * in the list are not individually referenced. If you want
1408 * to iterate through the list and perform actions involving
1409 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1410 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1411 * then unref all the widgets afterwards.
1413 * Return value: list of toplevel widgets
1416 gtk_window_list_toplevels (void)
1421 for (slist = toplevel_list; slist; slist = slist->next)
1422 list = g_list_prepend (list, slist->data);
1428 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1430 GList *embedded_windows;
1432 g_return_if_fail (GTK_IS_WINDOW (window));
1434 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1435 if (embedded_windows)
1436 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1437 g_quark_from_static_string ("gtk-embedded"));
1438 embedded_windows = g_list_prepend (embedded_windows,
1439 GUINT_TO_POINTER (xid));
1441 gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
1444 (GtkDestroyNotify) g_list_free : NULL);
1448 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1450 GList *embedded_windows;
1453 g_return_if_fail (GTK_IS_WINDOW (window));
1455 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1456 if (embedded_windows)
1457 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1458 g_quark_from_static_string ("gtk-embedded"));
1460 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1463 embedded_windows = g_list_remove_link (embedded_windows, node);
1464 g_list_free_1 (node);
1467 gtk_object_set_data_full (GTK_OBJECT (window),
1468 "gtk-embedded", embedded_windows,
1470 (GtkDestroyNotify) g_list_free : NULL);
1474 _gtk_window_reposition (GtkWindow *window,
1478 g_return_if_fail (GTK_IS_WINDOW (window));
1480 gtk_window_move (window, x, y);
1484 gtk_window_dispose (GObject *object)
1488 g_return_if_fail (GTK_IS_WINDOW (object));
1490 window = GTK_WINDOW (object);
1492 gtk_window_set_focus (window, NULL);
1493 gtk_window_set_default (window, NULL);
1495 G_OBJECT_CLASS (parent_class)->dispose (object);
1499 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1501 gtk_widget_destroy (GTK_WIDGET (child));
1505 connect_parent_destroyed (GtkWindow *window)
1507 if (window->transient_parent)
1509 gtk_signal_connect (GTK_OBJECT (window->transient_parent),
1511 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1517 disconnect_parent_destroyed (GtkWindow *window)
1519 if (window->transient_parent)
1521 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1522 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1528 gtk_window_transient_parent_realized (GtkWidget *parent,
1531 if (GTK_WIDGET_REALIZED (window))
1532 gdk_window_set_transient_for (window->window, parent->window);
1536 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1539 if (GTK_WIDGET_REALIZED (window))
1540 gdk_property_delete (window->window,
1541 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1545 gtk_window_unset_transient_for (GtkWindow *window)
1547 if (window->transient_parent)
1549 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1550 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1552 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1553 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1555 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1556 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1557 &window->transient_parent);
1559 if (window->destroy_with_parent)
1560 disconnect_parent_destroyed (window);
1562 window->transient_parent = NULL;
1567 * gtk_window_set_transient_for:
1568 * @window: a #GtkWindow
1569 * @parent: parent window
1571 * Dialog windows should be set transient for the main application
1572 * window they were spawned from. This allows window managers to
1573 * e.g. keep the dialog on top of the main window, or center the
1574 * dialog over the main window. gtk_dialog_new_with_buttons() and
1575 * other convenience functions in GTK+ will sometimes call
1576 * gtk_window_set_transient_for() on your behalf.
1580 gtk_window_set_transient_for (GtkWindow *window,
1583 g_return_if_fail (GTK_IS_WINDOW (window));
1584 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1585 g_return_if_fail (window != parent);
1588 if (window->transient_parent)
1590 if (GTK_WIDGET_REALIZED (window) &&
1591 GTK_WIDGET_REALIZED (window->transient_parent) &&
1592 (!parent || !GTK_WIDGET_REALIZED (parent)))
1593 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1594 GTK_WIDGET (window));
1596 gtk_window_unset_transient_for (window);
1599 window->transient_parent = parent;
1603 gtk_signal_connect (GTK_OBJECT (parent), "destroy",
1604 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1605 &window->transient_parent);
1606 gtk_signal_connect (GTK_OBJECT (parent), "realize",
1607 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1609 gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
1610 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1613 if (window->destroy_with_parent)
1614 connect_parent_destroyed (window);
1616 if (GTK_WIDGET_REALIZED (window) &&
1617 GTK_WIDGET_REALIZED (parent))
1618 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1619 GTK_WIDGET (window));
1624 * gtk_window_get_transient_for:
1625 * @window: a #GtkWindow
1627 * Fetches the transient parent for this window. See
1628 * gtk_window_set_transient_for().
1630 * Return value: the transient parent for this window, or %NULL
1631 * if no transient parent has been set.
1634 gtk_window_get_transient_for (GtkWindow *window)
1636 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1638 return window->transient_parent;
1642 * gtk_window_set_type_hint:
1643 * @window: a #GtkWindow
1644 * @hint: the window type
1646 * By setting the type hint for the window, you allow the window
1647 * manager to decorate and handle the window in a way which is
1648 * suitable to the function of the window in your application.
1650 * This function should be called before the window becomes visible.
1652 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1653 * will sometimes call gtk_window_set_type_hint() on your behalf.
1657 gtk_window_set_type_hint (GtkWindow *window,
1658 GdkWindowTypeHint hint)
1660 g_return_if_fail (GTK_IS_WINDOW (window));
1661 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1662 window->type_hint = hint;
1666 * gtk_window_get_type_hint:
1667 * @window: a #GtkWindow
1669 * Gets the type hint for this window. See gtk_window_set_type_hint().
1671 * Return value: the type hint for @window.
1674 gtk_window_get_type_hint (GtkWindow *window)
1676 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1678 return window->type_hint;
1682 * gtk_window_set_destroy_with_parent:
1683 * @window: a #GtkWindow
1684 * @setting: whether to destroy @window with its transient parent
1686 * If @setting is %TRUE, then destroying the transient parent of @window
1687 * will also destroy @window itself. This is useful for dialogs that
1688 * shouldn't persist beyond the lifetime of the main window they're
1689 * associated with, for example.
1692 gtk_window_set_destroy_with_parent (GtkWindow *window,
1695 g_return_if_fail (GTK_IS_WINDOW (window));
1697 if (window->destroy_with_parent == (setting != FALSE))
1700 if (window->destroy_with_parent)
1702 disconnect_parent_destroyed (window);
1706 connect_parent_destroyed (window);
1709 window->destroy_with_parent = setting;
1711 g_object_notify (G_OBJECT (window), "destroy_with_parent");
1715 * gtk_window_get_destroy_with_parent:
1716 * @window: a #GtkWindow
1718 * Returns whether the window will be destroyed with its transient parent. See
1719 * gtk_window_set_destroy_with_parent ().
1721 * Return value: %TRUE if the window will be destroyed with its transient parent.
1724 gtk_window_get_destroy_with_parent (GtkWindow *window)
1726 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1728 return window->destroy_with_parent;
1731 static GtkWindowGeometryInfo*
1732 gtk_window_get_geometry_info (GtkWindow *window,
1735 GtkWindowGeometryInfo *info;
1737 info = window->geometry_info;
1738 if (!info && create)
1740 info = g_new0 (GtkWindowGeometryInfo, 1);
1742 info->default_width = -1;
1743 info->default_height = -1;
1744 info->resize_width = -1;
1745 info->resize_height = -1;
1746 info->initial_x = 0;
1747 info->initial_y = 0;
1748 info->initial_pos_set = FALSE;
1749 info->position_constraints_changed = FALSE;
1750 info->last.configure_request.x = 0;
1751 info->last.configure_request.y = 0;
1752 info->last.configure_request.width = -1;
1753 info->last.configure_request.height = -1;
1754 info->widget = NULL;
1756 window->geometry_info = info;
1763 * gtk_window_set_geometry_hints:
1764 * @window: a #GtkWindow
1765 * @geometry_widget: widget the geometry hints will be applied to
1766 * @geometry: struct containing geometry information
1767 * @geom_mask: mask indicating which struct fields should be paid attention to
1769 * This function sets up hints about how a window can be resized by
1770 * the user. You can set a minimum and maximum size; allowed resize
1771 * increments (e.g. for xterm, you can only resize by the size of a
1772 * character); aspect ratios; and more. See the #GdkGeometry struct.
1776 gtk_window_set_geometry_hints (GtkWindow *window,
1777 GtkWidget *geometry_widget,
1778 GdkGeometry *geometry,
1779 GdkWindowHints geom_mask)
1781 GtkWindowGeometryInfo *info;
1783 g_return_if_fail (window != NULL);
1785 info = gtk_window_get_geometry_info (window, TRUE);
1788 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1789 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1792 info->widget = geometry_widget;
1794 gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
1795 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1799 info->geometry = *geometry;
1801 /* We store gravity in window->gravity not in the hints. */
1802 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
1804 if (geom_mask & GDK_HINT_WIN_GRAVITY)
1806 gtk_window_set_gravity (window, geometry->win_gravity);
1809 gtk_widget_queue_resize (GTK_WIDGET (window));
1813 * gtk_window_set_decorated:
1814 * @window: a #GtkWindow
1815 * @setting: %TRUE to decorate the window
1817 * By default, windows are decorated with a title bar, resize
1818 * controls, etc. Some window managers allow GTK+ to disable these
1819 * decorations, creating a borderless window. If you set the decorated
1820 * property to %FALSE using this function, GTK+ will do its best to
1821 * convince the window manager not to decorate the window.
1825 gtk_window_set_decorated (GtkWindow *window,
1828 g_return_if_fail (GTK_IS_WINDOW (window));
1830 setting = setting != FALSE;
1832 if (setting == window->decorated)
1835 window->decorated = setting;
1837 if (GTK_WIDGET (window)->window)
1839 if (window->decorated)
1840 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1843 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1849 * gtk_window_get_decorated:
1850 * @window: a #GtkWindow
1852 * Returns whether the window has been set to have decorations
1853 * such as a title bar via gtk_window_set_decorated().
1855 * Return value: %TRUE if the window has been set to have decorations
1858 gtk_window_get_decorated (GtkWindow *window)
1860 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
1862 return window->decorated;
1865 static GtkWindowIconInfo*
1866 get_icon_info (GtkWindow *window)
1868 return g_object_get_data (G_OBJECT (window),
1869 "gtk-window-icon-info");
1872 static GtkWindowIconInfo*
1873 ensure_icon_info (GtkWindow *window)
1875 GtkWindowIconInfo *info;
1877 info = get_icon_info (window);
1881 info = g_new0 (GtkWindowIconInfo, 1);
1882 g_object_set_data_full (G_OBJECT (window),
1883 "gtk-window-icon-info",
1892 get_pixmap_and_mask (GtkWindowIconInfo *parent_info,
1893 gboolean is_default_list,
1895 GdkPixmap **pmap_return,
1896 GdkBitmap **mask_return)
1898 GdkPixbuf *best_icon;
1902 *pmap_return = NULL;
1903 *mask_return = NULL;
1905 if (is_default_list &&
1906 default_icon_pixmap != NULL)
1908 /* Use shared icon pixmap (eventually will be stored on the
1911 if (default_icon_pixmap)
1912 g_object_ref (G_OBJECT (default_icon_pixmap));
1913 if (default_icon_mask)
1914 g_object_ref (G_OBJECT (default_icon_mask));
1916 *pmap_return = default_icon_pixmap;
1917 *mask_return = default_icon_mask;
1919 else if (parent_info && parent_info->icon_pixmap)
1921 if (parent_info->icon_pixmap)
1922 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1923 if (parent_info->icon_mask)
1924 g_object_ref (G_OBJECT (parent_info->icon_mask));
1926 *pmap_return = parent_info->icon_pixmap;
1927 *mask_return = parent_info->icon_mask;
1931 #define IDEAL_SIZE 48
1933 best_size = G_MAXINT;
1935 tmp_list = icon_list;
1936 while (tmp_list != NULL)
1938 GdkPixbuf *pixbuf = tmp_list->data;
1941 /* average width and height - if someone passes in a rectangular
1942 * icon they deserve what they get.
1944 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
1947 if (best_icon == NULL)
1954 /* icon is better if it's 32 pixels or larger, and closer to
1955 * the ideal size than the current best.
1958 (ABS (best_size - IDEAL_SIZE) <
1959 ABS (this - IDEAL_SIZE)))
1966 tmp_list = tmp_list->next;
1970 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
1971 gdk_colormap_get_system (),
1976 /* Save pmap/mask for others to use if appropriate */
1979 parent_info->icon_pixmap = *pmap_return;
1980 parent_info->icon_mask = *mask_return;
1982 if (parent_info->icon_pixmap)
1983 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1984 if (parent_info->icon_mask)
1985 g_object_ref (G_OBJECT (parent_info->icon_mask));
1987 else if (is_default_list)
1989 default_icon_pixmap = *pmap_return;
1990 default_icon_mask = *mask_return;
1992 if (default_icon_pixmap)
1993 g_object_add_weak_pointer (G_OBJECT (default_icon_pixmap),
1994 (gpointer*)&default_icon_pixmap);
1995 if (default_icon_mask)
1996 g_object_add_weak_pointer (G_OBJECT (default_icon_mask),
1997 (gpointer*)&default_icon_mask);
2003 gtk_window_realize_icon (GtkWindow *window)
2006 GtkWindowIconInfo *info;
2009 widget = GTK_WIDGET (window);
2011 g_return_if_fail (widget->window != NULL);
2013 /* no point setting an icon on override-redirect */
2014 if (window->type == GTK_WINDOW_POPUP)
2019 info = ensure_icon_info (window);
2024 g_return_if_fail (info->icon_pixmap == NULL);
2025 g_return_if_fail (info->icon_mask == NULL);
2027 info->using_default_icon = FALSE;
2028 info->using_parent_icon = FALSE;
2030 icon_list = info->icon_list;
2032 /* Inherit from transient parent */
2033 if (icon_list == NULL && window->transient_parent)
2035 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2037 info->using_parent_icon = TRUE;
2040 /* Inherit from default */
2041 if (icon_list == NULL)
2043 icon_list = default_icon_list;
2045 info->using_default_icon = TRUE;
2048 gdk_window_set_icon_list (widget->window, icon_list);
2050 get_pixmap_and_mask (info->using_parent_icon ?
2051 ensure_icon_info (window->transient_parent) : NULL,
2052 info->using_default_icon,
2057 /* This is a slight ICCCM violation since it's a color pixmap not
2058 * a bitmap, but everyone does it.
2060 gdk_window_set_icon (widget->window,
2065 info->realized = TRUE;
2069 gtk_window_unrealize_icon (GtkWindow *window)
2071 GtkWindowIconInfo *info;
2074 widget = GTK_WIDGET (window);
2076 info = get_icon_info (window);
2081 if (info->icon_pixmap)
2082 g_object_unref (G_OBJECT (info->icon_pixmap));
2084 if (info->icon_mask)
2085 g_object_unref (G_OBJECT (info->icon_mask));
2087 info->icon_pixmap = NULL;
2088 info->icon_mask = NULL;
2090 /* We don't clear the properties on the window, just figure the
2091 * window is going away.
2094 info->realized = FALSE;
2098 * gtk_window_set_icon_list:
2099 * @window: a #GtkWindow
2100 * @list: list of #GdkPixbuf
2102 * Sets up the icon representing a #GtkWindow. The icon is used when
2103 * the window is minimized (also known as iconified). Some window
2104 * managers or desktop environments may also place it in the window
2105 * frame, or display it in other contexts.
2107 * gtk_window_set_icon_list() allows you to pass in the same icon in
2108 * several hand-drawn sizes. The list should contain the natural sizes
2109 * your icon is available in; that is, don't scale the image before
2110 * passing it to GTK+. Scaling is postponed until the last minute,
2111 * when the desired final size is known, to allow best quality.
2113 * By passing several sizes, you may improve the final image quality
2114 * of the icon, by reducing or eliminating automatic image scaling.
2116 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2117 * larger images (64x64, 128x128) if you have them.
2119 * See also gtk_window_set_default_icon_list() to set the icon
2120 * for all windows in your application in one go.
2122 * Note that transient windows (those who have been set transient for another
2123 * window using gtk_window_set_transient_for()) will inherit their
2124 * icon from their transient parent. So there's no need to explicitly
2125 * set the icon on transient windows.
2128 gtk_window_set_icon_list (GtkWindow *window,
2131 GtkWindowIconInfo *info;
2133 g_return_if_fail (GTK_IS_WINDOW (window));
2135 info = ensure_icon_info (window);
2137 if (info->icon_list == list) /* check for NULL mostly */
2140 g_list_foreach (info->icon_list,
2141 (GFunc) g_object_unref, NULL);
2143 g_list_free (info->icon_list);
2145 info->icon_list = g_list_copy (list);
2146 g_list_foreach (info->icon_list,
2147 (GFunc) g_object_ref, NULL);
2149 g_object_notify (G_OBJECT (window), "icon");
2151 gtk_window_unrealize_icon (window);
2153 if (GTK_WIDGET_REALIZED (window))
2154 gtk_window_realize_icon (window);
2156 /* We could try to update our transient children, but I don't think
2157 * it's really worth it. If we did it, the best way would probably
2158 * be to have children connect to notify::icon_list
2163 * gtk_window_get_icon_list:
2164 * @window: a #GtkWindow
2166 * Retrieves the list of icons set by gtk_window_set_icon_list().
2167 * The list is copied, but the reference count on each
2168 * member won't be incremented.
2170 * Return value: copy of window's icon list
2173 gtk_window_get_icon_list (GtkWindow *window)
2175 GtkWindowIconInfo *info;
2177 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2179 info = get_icon_info (window);
2182 return g_list_copy (info->icon_list);
2188 * gtk_window_set_icon:
2189 * @window: a #GtkWindow
2190 * @icon: icon image, or %NULL
2192 * Sets up the icon representing a #GtkWindow. This icon is used when
2193 * the window is minimized (also known as iconified). Some window
2194 * managers or desktop environments may also place it in the window
2195 * frame, or display it in other contexts.
2197 * The icon should be provided in whatever size it was naturally
2198 * drawn; that is, don't scale the image before passing it to
2199 * GTK+. Scaling is postponed until the last minute, when the desired
2200 * final size is known, to allow best quality.
2202 * If you have your icon hand-drawn in multiple sizes, use
2203 * gtk_window_set_icon_list(). Then the best size will be used.
2205 * This function is equivalent to calling gtk_window_set_icon_list()
2206 * with a 1-element list.
2208 * See also gtk_window_set_default_icon_list() to set the icon
2209 * for all windows in your application in one go.
2212 gtk_window_set_icon (GtkWindow *window,
2217 g_return_if_fail (GTK_IS_WINDOW (window));
2218 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2221 list = g_list_append (list, icon);
2222 gtk_window_set_icon_list (window, list);
2227 * gtk_window_get_icon:
2228 * @window: a #GtkWindow
2230 * Gets the value set by gtk_window_set_icon() (or if you've
2231 * called gtk_window_set_icon_list(), gets the first icon in
2234 * Return value: icon for window
2237 gtk_window_get_icon (GtkWindow *window)
2239 GtkWindowIconInfo *info;
2241 info = get_icon_info (window);
2242 if (info && info->icon_list)
2243 return GDK_PIXBUF (info->icon_list->data);
2249 * gtk_window_set_default_icon_list:
2250 * @list: a list of #GdkPixbuf
2252 * Sets an icon list to be used as fallback for windows that haven't
2253 * had gtk_window_set_icon_list() called on them to set up a
2254 * window-specific icon list. This function allows you to set up the
2255 * icon for all windows in your app at once.
2257 * See gtk_window_set_icon_list() for more details.
2261 gtk_window_set_default_icon_list (GList *list)
2265 if (list == default_icon_list)
2268 if (default_icon_pixmap)
2269 g_object_unref (G_OBJECT (default_icon_pixmap));
2270 if (default_icon_mask)
2271 g_object_unref (G_OBJECT (default_icon_mask));
2273 default_icon_pixmap = NULL;
2274 default_icon_mask = NULL;
2276 g_list_foreach (default_icon_list,
2277 (GFunc) g_object_unref, NULL);
2279 g_list_free (default_icon_list);
2281 default_icon_list = g_list_copy (list);
2282 g_list_foreach (default_icon_list,
2283 (GFunc) g_object_ref, NULL);
2285 /* Update all toplevels */
2286 toplevels = gtk_window_list_toplevels ();
2287 tmp_list = toplevels;
2288 while (tmp_list != NULL)
2290 GtkWindowIconInfo *info;
2291 GtkWindow *w = tmp_list->data;
2293 info = get_icon_info (w);
2294 if (info && info->using_default_icon)
2296 gtk_window_unrealize_icon (w);
2297 if (GTK_WIDGET_REALIZED (w))
2298 gtk_window_realize_icon (w);
2301 tmp_list = tmp_list->next;
2303 g_list_free (toplevels);
2307 * gtk_window_get_default_icon_list:
2309 * Gets the value set by gtk_window_set_default_icon_list().
2310 * The list is a copy and should be freed with g_list_free(),
2311 * but the pixbufs in the list have not had their reference count
2314 * Return value: copy of default icon list
2317 gtk_window_get_default_icon_list (void)
2319 return g_list_copy (default_icon_list);
2323 gtk_window_set_default_size_internal (GtkWindow *window,
2324 gboolean change_width,
2326 gboolean change_height,
2329 GtkWindowGeometryInfo *info;
2331 g_return_if_fail (GTK_IS_WINDOW (window));
2332 g_return_if_fail (change_width == FALSE || width >= -1);
2333 g_return_if_fail (change_height == FALSE || height >= -1);
2335 info = gtk_window_get_geometry_info (window, TRUE);
2337 g_object_freeze_notify (G_OBJECT (window));
2347 info->default_width = width;
2349 g_object_notify (G_OBJECT (window), "default_width");
2360 info->default_height = height;
2362 g_object_notify (G_OBJECT (window), "default_height");
2365 g_object_thaw_notify (G_OBJECT (window));
2367 gtk_widget_queue_resize (GTK_WIDGET (window));
2371 * gtk_window_set_default_size:
2372 * @window: a #GtkWindow
2373 * @width: width in pixels, or -1 to unset the default width
2374 * @height: height in pixels, or -1 to unset the default height
2376 * Sets the default size of a window. If the window's "natural" size
2377 * (its size request) is larger than the default, the default will be
2378 * ignored. More generally, if the default size does not obey the
2379 * geometry hints for the window (gtk_window_set_geometry_hints() can
2380 * be used to set these explicitly), the default size will be clamped
2381 * to the nearest permitted size.
2383 * Unlike gtk_widget_set_size_request(), which sets a size request for
2384 * a widget and thus would keep users from shrinking the window, this
2385 * function only sets the initial size, just as if the user had
2386 * resized the window themselves. Users can still shrink the window
2387 * again as they normally would. Setting a default size of -1 means to
2388 * use the "natural" default size (the size request of the window).
2390 * For more control over a window's initial size and how resizing works,
2391 * investigate gtk_window_set_geometry_hints().
2393 * A useful feature: if you set the "geometry widget" via
2394 * gtk_window_set_geometry_hints(), the default size specified by
2395 * gtk_window_set_default_size() will be the default size of that
2396 * widget, not of the entire window.
2398 * For some uses, gtk_window_resize() is a more appropriate function.
2399 * gtk_window_resize() changes the current size of the window, rather
2400 * than the size to be used on initial display. gtk_window_resize() always
2401 * affects the window itself, not the geometry widget.
2403 * The default size of a window only affects the first time a window is
2404 * shown; if a window is hidden and re-shown, it will remember the size
2405 * it had prior to hiding, rather than using the default size.
2407 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2408 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2411 gtk_window_set_default_size (GtkWindow *window,
2415 g_return_if_fail (GTK_IS_WINDOW (window));
2416 g_return_if_fail (width >= -1);
2417 g_return_if_fail (height >= -1);
2419 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height);
2423 * gtk_window_get_default_size:
2424 * @window: a #GtkWindow
2425 * @width: location to store the default width, or %NULL
2426 * @height: location to store the default height, or %NULL
2428 * Gets the default size of the window. A value of -1 for the width or
2429 * height indicates that a default size has not been explicitly set
2430 * for that dimension, so the "natural" size of the window will be
2435 gtk_window_get_default_size (GtkWindow *window,
2439 GtkWindowGeometryInfo *info;
2441 g_return_if_fail (GTK_IS_WINDOW (window));
2443 info = gtk_window_get_geometry_info (window, FALSE);
2446 *width = info->default_width;
2449 *height = info->default_height;
2453 * gtk_window_resize:
2454 * @window: a #GtkWindow
2455 * @width: width to resize the window to
2456 * @height: height to resize the window to
2458 * Resizes the window as if the user had done so, obeying geometry
2459 * constraints. The default geometry constraint is that windows may
2460 * not be smaller than their size request; to override this
2461 * constraint, call gtk_widget_set_size_request() to set the window's
2462 * request to a smaller value.
2464 * If gtk_window_resize() is called before showing a window for the
2465 * first time, it overrides any default size set with
2466 * gtk_window_set_default_size().
2468 * Windows may not be resized smaller than 1 by 1 pixels.
2472 gtk_window_resize (GtkWindow *window,
2476 GtkWindowGeometryInfo *info;
2478 g_return_if_fail (GTK_IS_WINDOW (window));
2479 g_return_if_fail (width > 0);
2480 g_return_if_fail (height > 0);
2482 info = gtk_window_get_geometry_info (window, TRUE);
2484 info->resize_width = width;
2485 info->resize_height = height;
2487 gtk_widget_queue_resize (GTK_WIDGET (window));
2491 * gtk_window_get_size:
2492 * @window: a #GtkWindow
2493 * @width: return location for width, or %NULL
2494 * @height: return location for height, or %NULL
2496 * Obtains the current size of @window. If @window is not onscreen,
2497 * it returns the size GTK+ will suggest to the window manager for the
2498 * initial window size (but this is not reliably the same as the size
2499 * the window manager will actually select). The size obtained by
2500 * gtk_window_get_size() is the last size received in a
2501 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2502 * rather than querying the X server for the size. As a result, if you
2503 * call gtk_window_resize() then immediately call
2504 * gtk_window_get_size(), the size won't have taken effect yet. After
2505 * the window manager processes the resize request, GTK+ receives
2506 * notification that the size has changed via a configure event, and
2507 * the size of the window gets updated.
2509 * Note 1: Nearly any use of this function creates a race condition,
2510 * because the size of the window may change between the time that you
2511 * get the size and the time that you perform some action assuming
2512 * that size is the current size. To avoid race conditions, connect to
2513 * "configure_event" on the window and adjust your size-dependent
2514 * state to match the size delivered in the #GdkEventConfigure.
2516 * Note 2: The returned size does <emphasis>not</emphasis> include the size of the window
2517 * manager decorations (aka the window frame or border). Those
2518 * are not drawn by GTK+ and GTK+ has no reliable method of
2519 * determining their size.
2521 * Note 3: If you are getting a window size in order to position
2522 * the window onscreen, there may be a better way. The preferred
2523 * way is to simply set the window's semantic type with
2524 * gtk_window_set_type_hint(), which allows the window manager to
2525 * e.g. center dialogs. Also, if you set the transient parent of
2526 * dialogs with gtk_window_set_transient_for() window managers
2527 * will often center the dialog over its parent window. It's
2528 * much preferred to let the window manager handle these
2529 * things rather than doing it yourself, because all apps will
2530 * behave consistently and according to user prefs if the window
2531 * manager handles it. Also, the window manager can take the size
2532 * of the window decorations/border into account, while your
2533 * application cannot.
2535 * In any case, if you insist on application-specified window
2536 * positioning, there's <emphasis>still</emphasis> a better way than doing it yourself -
2537 * gtk_window_set_position() will frequently handle the details
2542 gtk_window_get_size (GtkWindow *window,
2549 g_return_if_fail (GTK_IS_WINDOW (window));
2551 widget = GTK_WIDGET (window);
2553 if (width == NULL && height == NULL)
2556 if (GTK_WIDGET_MAPPED (window))
2558 gdk_drawable_get_size (GTK_WIDGET (window)->window,
2563 GdkRectangle configure_request;
2565 gtk_window_compute_configure_request (window,
2569 w = configure_request.width;
2570 h = configure_request.height;
2581 * @window: a #GtkWindow
2582 * @x: X coordinate to move window to
2583 * @y: Y coordinate to move window to
2585 * Asks the window manager to move @window to the given position.
2586 * Window managers are free to ignore this; most window managers
2587 * ignore requests for initial window positions (instead using a
2588 * user-defined placement algorithm) and honor requests after the
2589 * window has already been shown.
2591 * Note: the position is the position of the gravity-determined
2592 * reference point for the window. The gravity determines two things:
2593 * first, the location of the reference point in root window
2594 * coordinates; and second, which point on the window is positioned at
2595 * the reference point.
2597 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
2598 * point is simply the @x, @y supplied to gtk_window_move(). The
2599 * top-left corner of the window decorations (aka window frame or
2600 * border) will be placed at @x, @y. Therefore, to position a window
2601 * at the top left of the screen, you want to use the default gravity
2602 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
2604 * To position a window at the bottom right corner of the screen, you
2605 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
2606 * point is at @x + the window width and @y + the window height, and
2607 * the bottom-right corner of the window border will be placed at that
2608 * reference point. So, to place a window in the bottom right corner
2609 * you would first set gravity to south east, then write:
2610 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
2611 * gdk_screen_height () - window_height)</literal>.
2613 * The extended window manager hints specification at <ulink
2614 * url="http://www.freedesktop.org/standards/wm-spec.html"
2615 * >http://www.freedesktop.org/standards/wm-spec.html</ulink> has a
2616 * nice table of gravities in the "implementation notes" section.
2618 * The gtk_window_get_position() documentation may also be relevant.
2622 gtk_window_move (GtkWindow *window,
2626 GtkWindowGeometryInfo *info;
2629 g_return_if_fail (GTK_IS_WINDOW (window));
2631 widget = GTK_WIDGET (window);
2633 info = gtk_window_get_geometry_info (window, TRUE);
2635 if (GTK_WIDGET_MAPPED (window))
2637 /* we have now sent a request with this position
2638 * with currently-active constraints, so toggle flag.
2640 info->position_constraints_changed = FALSE;
2642 /* we only constrain if mapped - if not mapped,
2643 * then gtk_window_compute_configure_request()
2644 * will apply the constraints later, and we
2645 * don't want to lose information about
2646 * what position the user set before then.
2647 * i.e. if you do a move() then turn off POS_CENTER
2648 * then show the window, your move() will work.
2650 gtk_window_constrain_position (window,
2651 widget->allocation.width,
2652 widget->allocation.height,
2655 /* Note that this request doesn't go through our standard request
2656 * framework, e.g. doesn't increment configure_request_count,
2657 * doesn't set info->last, etc.; that's because
2658 * we don't save the info needed to arrive at this same request
2661 * To gtk_window_move_resize(), this will end up looking exactly
2662 * the same as the position being changed by the window
2666 /* FIXME are we handling gravity properly for framed windows? */
2668 gdk_window_move (window->frame,
2669 x - window->frame_left,
2670 y - window->frame_top);
2672 gdk_window_move (GTK_WIDGET (window)->window,
2677 /* Save this position to apply on mapping */
2678 info->initial_x = x;
2679 info->initial_y = y;
2680 info->initial_pos_set = TRUE;
2685 * gtk_window_get_position:
2686 * @window: a #GtkWindow
2687 * @root_x: return location for X coordinate of gravity-determined reference p\oint
2688 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
2690 * This function returns the position you need to pass to
2691 * gtk_window_move() to keep @window in its current position. This
2692 * means that the meaning of the returned value varies with window
2693 * gravity. See gtk_window_move() for more details.
2695 * If you haven't changed the window gravity, its gravity will be
2696 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
2697 * gets the position of the top-left corner of the window manager
2698 * frame for the window. gtk_window_move() sets the position of this
2699 * same top-left corner.
2701 * gtk_window_get_position() is not 100% reliable because the X Window System
2702 * does not specify a way to obtain the geometry of the
2703 * decorations placed on a window by the window manager.
2704 * Thus GTK+ is using a "best guess" that works with most
2707 * Moreover, nearly all window managers are broken with respect to
2708 * their handling of window gravity. So moving a window to its current
2709 * position as returned by gtk_window_get_position() tends to
2710 * result in moving the window slightly.
2712 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
2713 * frame is not relevant, and thus gtk_window_get_position() will
2714 * always produce accurate results. However you can't use static
2715 * gravity to do things like place a window in a corner of the screen,
2716 * because static gravity ignores the window manager decorations.
2718 * If you are saving and restoring your application's window
2719 * positions, you should know that it's impossible for applications to
2720 * do this without getting it somewhat wrong because applications do
2721 * not have sufficient knowledge of window manager state. The Correct
2722 * Mechanism is to support the session management protocol (see the
2723 * "GnomeClient" object in the GNOME libraries for example) and allow
2724 * the window manager to save your window sizes and positions.
2729 gtk_window_get_position (GtkWindow *window,
2735 g_return_if_fail (GTK_IS_WINDOW (window));
2737 widget = GTK_WIDGET (window);
2739 if (window->gravity == GDK_GRAVITY_STATIC)
2741 if (GTK_WIDGET_MAPPED (widget))
2743 /* This does a server round-trip, which is sort of wrong;
2744 * but a server round-trip is inevitable for
2745 * gdk_window_get_frame_extents() in the usual
2746 * NorthWestGravity case below, so not sure what else to
2747 * do. We should likely be consistent about whether we get
2748 * the client-side info or the server-side info.
2750 gdk_window_get_origin (widget->window, root_x, root_y);
2754 GdkRectangle configure_request;
2756 gtk_window_compute_configure_request (window,
2760 *root_x = configure_request.x;
2761 *root_y = configure_request.y;
2766 GdkRectangle frame_extents;
2771 if (GTK_WIDGET_MAPPED (widget))
2774 gdk_window_get_frame_extents (window->frame, &frame_extents);
2776 gdk_window_get_frame_extents (widget->window, &frame_extents);
2777 x = frame_extents.x;
2778 y = frame_extents.y;
2779 gtk_window_get_size (window, &w, &h);
2783 /* We just say the frame has 0 size on all sides.
2784 * Not sure what else to do.
2786 gtk_window_compute_configure_request (window,
2789 x = frame_extents.x;
2790 y = frame_extents.y;
2791 w = frame_extents.width;
2792 h = frame_extents.height;
2795 switch (window->gravity)
2797 case GDK_GRAVITY_NORTH:
2798 case GDK_GRAVITY_CENTER:
2799 case GDK_GRAVITY_SOUTH:
2800 /* Find center of frame. */
2801 x += frame_extents.width / 2;
2802 /* Center client window on that point. */
2806 case GDK_GRAVITY_SOUTH_EAST:
2807 case GDK_GRAVITY_EAST:
2808 case GDK_GRAVITY_NORTH_EAST:
2809 /* Find right edge of frame */
2810 x += frame_extents.width;
2811 /* Align left edge of client at that point. */
2818 switch (window->gravity)
2820 case GDK_GRAVITY_WEST:
2821 case GDK_GRAVITY_CENTER:
2822 case GDK_GRAVITY_EAST:
2823 /* Find center of frame. */
2824 y += frame_extents.height / 2;
2825 /* Center client window there. */
2828 case GDK_GRAVITY_SOUTH_WEST:
2829 case GDK_GRAVITY_SOUTH:
2830 case GDK_GRAVITY_SOUTH_EAST:
2831 /* Find south edge of frame */
2832 y += frame_extents.height;
2833 /* Place bottom edge of client there */
2848 * gtk_window_reshow_with_initial_size:
2849 * @window: a #GtkWindow
2851 * Hides @window, then reshows it, resetting the
2852 * default size and position of the window. Used
2853 * by GUI builders only.
2856 gtk_window_reshow_with_initial_size (GtkWindow *window)
2860 g_return_if_fail (GTK_IS_WINDOW (window));
2862 widget = GTK_WIDGET (window);
2864 gtk_widget_hide (widget);
2865 gtk_widget_unrealize (widget);
2866 gtk_widget_show (widget);
2870 gtk_window_destroy (GtkObject *object)
2874 g_return_if_fail (GTK_IS_WINDOW (object));
2876 window = GTK_WINDOW (object);
2878 if (window->transient_parent)
2879 gtk_window_set_transient_for (window, NULL);
2881 /* frees the icons */
2882 gtk_window_set_icon_list (window, NULL);
2884 if (window->has_user_ref_count)
2886 window->has_user_ref_count = FALSE;
2887 gtk_widget_unref (GTK_WIDGET (window));
2891 gtk_window_group_remove_window (window->group, window);
2893 GTK_OBJECT_CLASS (parent_class)->destroy (object);
2897 gtk_window_mnemonic_hash_remove (gpointer key,
2901 GtkWindowMnemonic *mnemonic = key;
2902 GtkWindow *window = user;
2904 if (mnemonic->window == window)
2906 if (mnemonic->targets)
2908 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
2910 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
2911 name, mnemonic->targets->data);
2914 g_slist_free (mnemonic->targets);
2923 gtk_window_finalize (GObject *object)
2927 g_return_if_fail (GTK_IS_WINDOW (object));
2929 window = GTK_WINDOW (object);
2931 toplevel_list = g_slist_remove (toplevel_list, window);
2933 g_free (window->title);
2934 g_free (window->wmclass_name);
2935 g_free (window->wmclass_class);
2936 g_free (window->wm_role);
2938 g_hash_table_foreach_remove (mnemonic_hash_table,
2939 gtk_window_mnemonic_hash_remove,
2941 if (window->geometry_info)
2943 if (window->geometry_info->widget)
2944 gtk_signal_disconnect_by_func (GTK_OBJECT (window->geometry_info->widget),
2945 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
2946 &window->geometry_info->widget);
2947 g_free (window->geometry_info);
2950 if (window->keys_changed_handler)
2952 gtk_idle_remove (window->keys_changed_handler);
2953 window->keys_changed_handler = 0;
2956 G_OBJECT_CLASS (parent_class)->finalize (object);
2960 gtk_window_show (GtkWidget *widget)
2962 GtkWindow *window = GTK_WINDOW (widget);
2963 GtkContainer *container = GTK_CONTAINER (window);
2964 gboolean need_resize;
2966 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
2968 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
2969 container->need_resize = FALSE;
2973 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
2974 GtkAllocation allocation = { 0, 0 };
2975 GdkRectangle configure_request;
2976 GdkGeometry new_geometry;
2978 gboolean was_realized;
2980 /* We are going to go ahead and perform this configure request
2981 * and then emulate a configure notify by going ahead and
2982 * doing a size allocate. Sort of a synchronous
2983 * mini-copy of gtk_window_move_resize() here.
2985 gtk_window_compute_configure_request (window,
2990 /* We update this because we are going to go ahead
2991 * and gdk_window_resize() below, rather than
2994 info->last.configure_request.width = configure_request.width;
2995 info->last.configure_request.height = configure_request.height;
2997 /* and allocate the window - this is normally done
2998 * in move_resize in response to configure notify
3000 allocation.width = configure_request.width;
3001 allocation.height = configure_request.height;
3002 gtk_widget_size_allocate (widget, &allocation);
3004 /* Then we guarantee we have a realize */
3005 was_realized = FALSE;
3006 if (!GTK_WIDGET_REALIZED (widget))
3008 gtk_widget_realize (widget);
3009 was_realized = TRUE;
3012 /* Must be done after the windows are realized,
3013 * so that the decorations can be read
3015 gtk_decorated_window_calculate_frame_size (window);
3017 /* We only send configure request if we didn't just finish
3018 * creating the window; if we just created the window
3019 * then we created it with widget->allocation anyhow.
3022 gdk_window_resize (widget->window,
3023 configure_request.width,
3024 configure_request.height);
3027 gtk_container_check_resize (container);
3029 gtk_widget_map (widget);
3032 gtk_grab_add (widget);
3036 gtk_window_hide (GtkWidget *widget)
3040 g_return_if_fail (GTK_IS_WINDOW (widget));
3042 window = GTK_WINDOW (widget);
3044 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3045 gtk_widget_unmap (widget);
3048 gtk_grab_remove (widget);
3052 gtk_window_map (GtkWidget *widget)
3055 GdkWindow *toplevel;
3057 g_return_if_fail (GTK_IS_WINDOW (widget));
3059 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3061 window = GTK_WINDOW (widget);
3063 if (window->bin.child &&
3064 GTK_WIDGET_VISIBLE (window->bin.child) &&
3065 !GTK_WIDGET_MAPPED (window->bin.child))
3066 gtk_widget_map (window->bin.child);
3069 toplevel = window->frame;
3071 toplevel = widget->window;
3073 if (window->maximize_initially)
3074 gdk_window_maximize (toplevel);
3076 gdk_window_unmaximize (toplevel);
3078 if (window->stick_initially)
3079 gdk_window_stick (toplevel);
3081 gdk_window_unstick (toplevel);
3083 if (window->iconify_initially)
3084 gdk_window_iconify (toplevel);
3086 gdk_window_deiconify (toplevel);
3088 /* No longer use the default settings */
3089 window->need_default_size = FALSE;
3090 window->need_default_position = FALSE;
3092 gdk_window_show (widget->window);
3095 gdk_window_show (window->frame);
3099 gtk_window_unmap (GtkWidget *widget)
3102 GtkWindowGeometryInfo *info;
3104 window = GTK_WINDOW (widget);
3106 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3108 gdk_window_withdraw (window->frame);
3110 gdk_window_withdraw (widget->window);
3112 window->configure_request_count = 0;
3113 window->configure_notify_received = FALSE;
3115 /* on unmap, we reset the default positioning of the window,
3116 * so it's placed again, but we don't reset the default
3117 * size of the window, so it's remembered.
3119 window->need_default_position = TRUE;
3121 info = gtk_window_get_geometry_info (window, FALSE);
3124 info->initial_pos_set = FALSE;
3125 info->position_constraints_changed = FALSE;
3130 gtk_window_realize (GtkWidget *widget)
3133 GdkWindow *parent_window;
3134 GdkWindowAttr attributes;
3135 gint attributes_mask;
3137 g_return_if_fail (GTK_IS_WINDOW (widget));
3139 window = GTK_WINDOW (widget);
3141 /* ensure widget tree is properly size allocated */
3142 if (widget->allocation.x == -1 &&
3143 widget->allocation.y == -1 &&
3144 widget->allocation.width == 1 &&
3145 widget->allocation.height == 1)
3147 GtkRequisition requisition;
3148 GtkAllocation allocation = { 0, 0, 200, 200 };
3150 gtk_widget_size_request (widget, &requisition);
3151 if (requisition.width || requisition.height)
3153 /* non-empty window */
3154 allocation.width = requisition.width;
3155 allocation.height = requisition.height;
3157 gtk_widget_size_allocate (widget, &allocation);
3159 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3161 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3164 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3166 switch (window->type)
3168 case GTK_WINDOW_TOPLEVEL:
3169 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3171 case GTK_WINDOW_POPUP:
3172 attributes.window_type = GDK_WINDOW_TEMP;
3175 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3179 attributes.title = window->title;
3180 attributes.wmclass_name = window->wmclass_name;
3181 attributes.wmclass_class = window->wmclass_class;
3182 attributes.wclass = GDK_INPUT_OUTPUT;
3183 attributes.visual = gtk_widget_get_visual (widget);
3184 attributes.colormap = gtk_widget_get_colormap (widget);
3186 if (window->has_frame)
3188 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3189 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3190 attributes.event_mask = (GDK_EXPOSURE_MASK |
3191 GDK_KEY_PRESS_MASK |
3192 GDK_ENTER_NOTIFY_MASK |
3193 GDK_LEAVE_NOTIFY_MASK |
3194 GDK_FOCUS_CHANGE_MASK |
3195 GDK_STRUCTURE_MASK |
3196 GDK_BUTTON_MOTION_MASK |
3197 GDK_POINTER_MOTION_HINT_MASK |
3198 GDK_BUTTON_PRESS_MASK |
3199 GDK_BUTTON_RELEASE_MASK);
3201 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3203 window->frame = gdk_window_new (NULL, &attributes, attributes_mask);
3204 gdk_window_set_user_data (window->frame, widget);
3206 attributes.window_type = GDK_WINDOW_CHILD;
3207 attributes.x = window->frame_left;
3208 attributes.y = window->frame_right;
3210 attributes_mask = GDK_WA_X | GDK_WA_Y;
3212 parent_window = window->frame;
3216 attributes_mask = 0;
3217 parent_window = NULL;
3220 attributes.width = widget->allocation.width;
3221 attributes.height = widget->allocation.height;
3222 attributes.event_mask = gtk_widget_get_events (widget);
3223 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3224 GDK_KEY_PRESS_MASK |
3225 GDK_KEY_RELEASE_MASK |
3226 GDK_ENTER_NOTIFY_MASK |
3227 GDK_LEAVE_NOTIFY_MASK |
3228 GDK_FOCUS_CHANGE_MASK |
3229 GDK_STRUCTURE_MASK);
3231 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3232 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3233 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3234 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3235 gdk_window_set_user_data (widget->window, window);
3237 widget->style = gtk_style_attach (widget->style, widget->window);
3238 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3240 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3242 /* This is a bad hack to set the window background. */
3243 gtk_window_paint (widget, NULL);
3245 if (window->transient_parent &&
3246 GTK_WIDGET_REALIZED (window->transient_parent))
3247 gdk_window_set_transient_for (widget->window,
3248 GTK_WIDGET (window->transient_parent)->window);
3250 if (window->wm_role)
3251 gdk_window_set_role (widget->window, window->wm_role);
3253 if (!window->decorated)
3254 gdk_window_set_decorations (widget->window, 0);
3256 gdk_window_set_type_hint (widget->window, window->type_hint);
3258 /* transient_for must be set to allow the modal hint */
3259 if (window->transient_parent && window->modal)
3260 gdk_window_set_modal_hint (widget->window, TRUE);
3262 gdk_window_set_modal_hint (widget->window, FALSE);
3265 gtk_window_realize_icon (window);
3269 gtk_window_unrealize (GtkWidget *widget)
3272 GtkWindowGeometryInfo *info;
3274 window = GTK_WINDOW (widget);
3276 /* On unrealize, we reset the size of the window such
3277 * that we will re-apply the default sizing stuff
3278 * next time we show the window.
3280 * Default positioning is reset on unmap, instead of unrealize.
3282 window->need_default_size = TRUE;
3283 info = gtk_window_get_geometry_info (window, FALSE);
3286 info->resize_width = -1;
3287 info->resize_height = -1;
3288 info->last.configure_request.x = 0;
3289 info->last.configure_request.y = 0;
3290 info->last.configure_request.width = -1;
3291 info->last.configure_request.height = -1;
3292 /* be sure we reset geom hints on re-realize */
3293 info->last.flags = 0;
3298 gdk_window_set_user_data (window->frame, NULL);
3299 gdk_window_destroy (window->frame);
3300 window->frame = NULL;
3304 gtk_window_unrealize_icon (window);
3306 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3310 gtk_window_size_request (GtkWidget *widget,
3311 GtkRequisition *requisition)
3316 g_return_if_fail (GTK_IS_WINDOW (widget));
3317 g_return_if_fail (requisition != NULL);
3319 window = GTK_WINDOW (widget);
3320 bin = GTK_BIN (window);
3322 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3323 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3325 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3327 GtkRequisition child_requisition;
3329 gtk_widget_size_request (bin->child, &child_requisition);
3331 requisition->width += child_requisition.width;
3332 requisition->height += child_requisition.height;
3337 gtk_window_size_allocate (GtkWidget *widget,
3338 GtkAllocation *allocation)
3341 GtkAllocation child_allocation;
3343 g_return_if_fail (GTK_IS_WINDOW (widget));
3344 g_return_if_fail (allocation != NULL);
3346 window = GTK_WINDOW (widget);
3347 widget->allocation = *allocation;
3349 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3351 child_allocation.x = GTK_CONTAINER (window)->border_width;
3352 child_allocation.y = GTK_CONTAINER (window)->border_width;
3353 child_allocation.width =
3354 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3355 child_allocation.height =
3356 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3358 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3361 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3363 gdk_window_resize (window->frame,
3364 allocation->width + window->frame_left + window->frame_right,
3365 allocation->height + window->frame_top + window->frame_bottom);
3370 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3373 gboolean return_val;
3376 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3377 g_return_val_if_fail (event != NULL, FALSE);
3379 window = GTK_WINDOW (widget);
3381 if (window->frame && (event->any.window == window->frame))
3383 if ((event->type != GDK_KEY_PRESS) &&
3384 (event->type != GDK_KEY_RELEASE) &&
3385 (event->type != GDK_FOCUS_CHANGE))
3387 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
3389 gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
3394 g_object_unref (event->any.window);
3395 event->any.window = g_object_ref (widget->window);
3403 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3405 GdkEventConfigure *configure_event;
3408 switch (event->type)
3411 configure_event = (GdkEventConfigure *)event;
3413 /* Invalidate the decorations */
3416 rect.width = configure_event->width;
3417 rect.height = configure_event->height;
3419 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3421 /* Pass on the (modified) configure event */
3422 configure_event->width -= window->frame_left + window->frame_right;
3423 configure_event->height -= window->frame_top + window->frame_bottom;
3424 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3433 gtk_window_configure_event (GtkWidget *widget,
3434 GdkEventConfigure *event)
3438 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3439 g_return_val_if_fail (event != NULL, FALSE);
3441 window = GTK_WINDOW (widget);
3443 /* window->configure_request_count incremented for each
3444 * configure request, and decremented to a min of 0 for
3445 * each configure notify.
3447 * All it means is that we know we will get at least
3448 * window->configure_request_count more configure notifies.
3449 * We could get more configure notifies than that; some
3450 * of the configure notifies we get may be unrelated to
3451 * the configure requests. But we will get at least
3452 * window->configure_request_count notifies.
3455 if (window->configure_request_count > 0)
3456 window->configure_request_count -= 1;
3458 /* As an optimization, we avoid a resize when possible.
3460 * The only times we can avoid a resize are:
3461 * - we know only the position changed, not the size
3462 * - we know we have made more requests and so will get more
3463 * notifies and can wait to resize when we get them
3466 if (window->configure_request_count > 0 ||
3467 (widget->allocation.width == event->width &&
3468 widget->allocation.height == event->height))
3472 * If we do need to resize, we do that by:
3473 * - filling in widget->allocation with the new size
3474 * - setting configure_notify_received to TRUE
3475 * for use in gtk_window_move_resize()
3476 * - queueing a resize, leading to invocation of
3477 * gtk_window_move_resize() in an idle handler
3481 window->configure_notify_received = TRUE;
3483 widget->allocation.width = event->width;
3484 widget->allocation.height = event->height;
3486 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3491 /* the accel_key and accel_mods fields of the key have to be setup
3492 * upon calling this function. it'll then return whether that key
3493 * is at all used as accelerator, and if so will OR in the
3494 * accel_flags member of the key.
3497 _gtk_window_query_nonaccels (GtkWindow *window,
3499 GdkModifierType accel_mods)
3501 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3503 /* movement keys are considered locked accels */
3506 static const guint bindings[] = {
3507 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
3508 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
3512 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
3513 if (bindings[i] == accel_key)
3517 /* mnemonics are considered locked accels */
3518 if (accel_mods == window->mnemonic_modifier)
3520 GtkWindowMnemonic mkey;
3522 mkey.window = window;
3523 mkey.keyval = accel_key;
3524 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
3532 gtk_window_key_press_event (GtkWidget *widget,
3539 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3540 g_return_val_if_fail (event != NULL, FALSE);
3542 window = GTK_WINDOW (widget);
3547 handled = gtk_window_mnemonic_activate (window,
3552 handled = gtk_accel_groups_activate (G_OBJECT (window), event->keyval, event->state);
3556 focus = window->focus_widget;
3558 g_object_ref (focus);
3561 focus && focus != widget &&
3562 gtk_widget_get_toplevel (focus) == widget)
3566 if (GTK_WIDGET_IS_SENSITIVE (focus))
3567 handled = gtk_widget_event (focus, (GdkEvent*) event);
3569 parent = focus->parent;
3571 g_object_ref (parent);
3573 g_object_unref (focus);
3579 g_object_unref (focus);
3582 /* Chain up, invokes binding set */
3583 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
3584 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
3590 gtk_window_key_release_event (GtkWidget *widget,
3596 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3597 g_return_val_if_fail (event != NULL, FALSE);
3599 window = GTK_WINDOW (widget);
3601 if (window->focus_widget &&
3602 window->focus_widget != widget &&
3603 GTK_WIDGET_SENSITIVE (window->focus_widget))
3605 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
3608 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
3609 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
3615 gtk_window_real_activate_default (GtkWindow *window)
3617 gtk_window_activate_default (window);
3621 gtk_window_real_activate_focus (GtkWindow *window)
3623 gtk_window_activate_focus (window);
3627 gtk_window_move_focus (GtkWindow *window,
3628 GtkDirectionType dir)
3630 gtk_widget_child_focus (GTK_WIDGET (window), dir);
3632 if (!GTK_CONTAINER (window)->focus_child)
3633 gtk_window_set_focus (window, NULL);
3637 gtk_window_enter_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_leave_notify_event (GtkWidget *widget,
3648 GdkEventCrossing *event)
3650 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3651 g_return_val_if_fail (event != NULL, FALSE);
3657 gtk_window_focus_in_event (GtkWidget *widget,
3658 GdkEventFocus *event)
3660 GtkWindow *window = GTK_WINDOW (widget);
3661 GdkEventFocus fevent;
3663 /* It appears spurious focus in events can occur when
3664 * the window is hidden. So we'll just check to see if
3665 * the window is visible before actually handling the
3668 if (GTK_WIDGET_VISIBLE (widget))
3670 window->has_focus = TRUE;
3672 if (window->focus_widget &&
3673 window->focus_widget != widget &&
3674 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3676 fevent.type = GDK_FOCUS_CHANGE;
3677 fevent.window = window->focus_widget->window;
3680 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
3688 gtk_window_focus_out_event (GtkWidget *widget,
3689 GdkEventFocus *event)
3691 GtkWindow *window = GTK_WINDOW (widget);
3692 GdkEventFocus fevent;
3694 window->has_focus = FALSE;
3696 if (window->focus_widget &&
3697 window->focus_widget != widget &&
3698 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3700 fevent.type = GDK_FOCUS_CHANGE;
3701 fevent.window = window->focus_widget->window;
3704 gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
3710 static GdkAtom atom_rcfiles = GDK_NONE;
3713 gtk_window_read_rcfiles (GtkWidget *widget,
3714 GdkEventClient *event)
3716 GList *embedded_windows;
3718 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
3719 if (embedded_windows)
3724 for (i = 0; i < 5; i++)
3726 sev.data_format = 32;
3727 sev.message_type = atom_rcfiles;
3729 while (embedded_windows)
3731 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
3732 gdk_event_send_client_message ((GdkEvent *) &sev, xid);
3733 embedded_windows = embedded_windows->next;
3737 gtk_rc_reparse_all ();
3741 gtk_window_client_event (GtkWidget *widget,
3742 GdkEventClient *event)
3744 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3745 g_return_val_if_fail (event != NULL, FALSE);
3748 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
3750 if (event->message_type == atom_rcfiles)
3751 gtk_window_read_rcfiles (widget, event);
3757 gtk_window_check_resize (GtkContainer *container)
3761 g_return_if_fail (GTK_IS_WINDOW (container));
3763 window = GTK_WINDOW (container);
3765 if (GTK_WIDGET_VISIBLE (container))
3766 gtk_window_move_resize (window);
3770 gtk_window_focus (GtkWidget *widget,
3771 GtkDirectionType direction)
3775 GtkContainer *container;
3776 GtkWidget *old_focus_child;
3779 container = GTK_CONTAINER (widget);
3780 window = GTK_WINDOW (widget);
3781 bin = GTK_BIN (widget);
3783 old_focus_child = container->focus_child;
3785 /* We need a special implementation here to deal properly with wrapping
3786 * around in the tab chain without the danger of going into an
3789 if (old_focus_child)
3791 if (gtk_widget_child_focus (old_focus_child, direction))
3795 if (window->focus_widget)
3797 /* Wrapped off the end, clear the focus setting for the toplpevel */
3798 parent = window->focus_widget->parent;
3801 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
3802 parent = GTK_WIDGET (parent)->parent;
3805 gtk_window_set_focus (GTK_WINDOW (container), NULL);
3808 /* Now try to focus the first widget in the window */
3811 if (gtk_widget_child_focus (bin->child, direction))
3819 gtk_window_real_set_focus (GtkWindow *window,
3822 GdkEventFocus event;
3823 gboolean def_flags = 0;
3825 g_return_if_fail (GTK_IS_WINDOW (window));
3827 if (window->default_widget)
3828 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
3830 if (window->focus_widget)
3832 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3833 (window->focus_widget != window->default_widget))
3835 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3837 if (window->default_widget)
3838 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3841 if (window->has_focus)
3843 event.type = GDK_FOCUS_CHANGE;
3844 event.window = window->focus_widget->window;
3847 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
3851 window->focus_widget = focus;
3853 if (window->focus_widget)
3855 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3856 (window->focus_widget != window->default_widget))
3858 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
3859 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3861 if (window->default_widget)
3862 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3865 if (window->has_focus)
3867 event.type = GDK_FOCUS_CHANGE;
3868 event.window = window->focus_widget->window;
3871 gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
3875 if (window->default_widget &&
3876 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
3877 gtk_widget_queue_draw (window->default_widget);
3880 /*********************************
3881 * Functions related to resizing *
3882 *********************************/
3884 /* This function doesn't constrain to geometry hints */
3886 gtk_window_compute_configure_request_size (GtkWindow *window,
3890 GtkRequisition requisition;
3891 GtkWindowGeometryInfo *info;
3895 * - we've done a size request
3898 widget = GTK_WIDGET (window);
3900 info = gtk_window_get_geometry_info (window, FALSE);
3902 if (window->need_default_size)
3904 gtk_widget_get_child_requisition (widget, &requisition);
3906 /* Default to requisition */
3907 *width = requisition.width;
3908 *height = requisition.height;
3910 /* If window is empty so requests 0, default to random nonzero size */
3911 if (*width == 0 && *height == 0)
3917 /* Override requisition with default size */
3921 if (info->default_width > 0)
3922 *width = info->default_width;
3924 if (info->default_height > 0)
3925 *height = info->default_height;
3930 /* Default to keeping current size */
3931 *width = widget->allocation.width;
3932 *height = widget->allocation.height;
3935 /* Override any size with gtk_window_resize() values */
3938 if (info->resize_width > 0)
3939 *width = info->resize_width;
3941 if (info->resize_height > 0)
3942 *height = info->resize_height;
3947 gtk_window_compute_configure_request (GtkWindow *window,
3948 GdkRectangle *request,
3949 GdkGeometry *geometry,
3952 GdkGeometry new_geometry;
3956 GtkWindowPosition pos;
3957 GtkWidget *parent_widget;
3958 GtkWindowGeometryInfo *info;
3961 widget = GTK_WIDGET (window);
3963 gtk_widget_size_request (widget, NULL);
3964 gtk_window_compute_configure_request_size (window, &w, &h);
3966 gtk_window_compute_hints (window, &new_geometry, &new_flags);
3967 gtk_window_constrain_size (window,
3968 &new_geometry, new_flags,
3972 parent_widget = (GtkWidget*) window->transient_parent;
3974 pos = window->position;
3975 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
3976 (parent_widget == NULL ||
3977 !GTK_WIDGET_MAPPED (parent_widget)))
3978 pos = GTK_WIN_POS_NONE;
3980 info = gtk_window_get_geometry_info (window, TRUE);
3982 /* by default, don't change position requested */
3983 x = info->last.configure_request.x;
3984 y = info->last.configure_request.y;
3986 if (window->need_default_position)
3989 /* FIXME this all interrelates with window gravity.
3990 * For most of them I think we want to set GRAVITY_CENTER.
3992 * Not sure how to go about that.
3997 /* here we are only handling CENTER_ALWAYS
3998 * as it relates to default positioning,
3999 * where it's equivalent to simply CENTER
4001 case GTK_WIN_POS_CENTER_ALWAYS:
4002 case GTK_WIN_POS_CENTER:
4004 gint screen_width = gdk_screen_width ();
4005 gint screen_height = gdk_screen_height ();
4007 x = (screen_width - w) / 2;
4008 y = (screen_height - h) / 2;
4012 case GTK_WIN_POS_CENTER_ON_PARENT:
4016 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
4018 gdk_window_get_origin (parent_widget->window,
4021 x = ox + (parent_widget->allocation.width - w) / 2;
4022 y = oy + (parent_widget->allocation.height - h) / 2;
4026 case GTK_WIN_POS_MOUSE:
4028 gint screen_width = gdk_screen_width ();
4029 gint screen_height = gdk_screen_height ();
4032 gdk_window_get_pointer (NULL, &px, &py, NULL);
4035 x = CLAMP (x, 0, screen_width - w);
4036 y = CLAMP (y, 0, screen_height - h);
4043 } /* if (window->need_default_position) */
4045 if (window->need_default_position &&
4046 info->initial_pos_set)
4048 x = info->initial_x;
4049 y = info->initial_y;
4050 gtk_window_constrain_position (window, w, h, &x, &y);
4056 request->height = h;
4059 *geometry = new_geometry;
4065 gtk_window_constrain_position (GtkWindow *window,
4071 /* See long comments in gtk_window_move_resize()
4072 * on when it's safe to call this function.
4074 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4076 gint center_x, center_y;
4077 gint screen_width = gdk_screen_width ();
4078 gint screen_height = gdk_screen_height ();
4080 center_x = (screen_width - new_width) / 2;
4081 center_y = (screen_height - new_height) / 2;
4089 gtk_window_move_resize (GtkWindow *window)
4093 * First we determine whether any information has changed that would
4094 * cause us to revise our last configure request. If we would send
4095 * a different configure request from last time, then
4096 * configure_request_size_changed = TRUE or
4097 * configure_request_pos_changed = TRUE. configure_request_size_changed
4098 * may be true due to new hints, a gtk_window_resize(), or whatever.
4099 * configure_request_pos_changed may be true due to gtk_window_set_position()
4100 * or gtk_window_move().
4102 * If the configure request has changed, we send off a new one. To
4103 * ensure GTK+ invariants are maintained (resize queue does what it
4104 * should), we go ahead and size_allocate the requested size in this
4107 * If the configure request has not changed, we don't ever resend
4108 * it, because it could mean fighting the user or window manager.
4111 * To prepare the configure request, we come up with a base size/pos:
4112 * - the one from gtk_window_move()/gtk_window_resize()
4113 * - else default_width, default_height if we haven't ever
4115 * - else the size request if we haven't ever been mapped,
4116 * as a substitute default size
4117 * - else the current size of the window, as received from
4118 * configure notifies (i.e. the current allocation)
4120 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4121 * the position request to be centered.
4124 GtkContainer *container;
4125 GtkWindowGeometryInfo *info;
4126 GdkGeometry new_geometry;
4128 GdkRectangle new_request;
4129 gboolean configure_request_size_changed;
4130 gboolean configure_request_pos_changed;
4131 gboolean hints_changed; /* do we need to send these again */
4132 GtkWindowLastGeometryInfo saved_last_info;
4134 widget = GTK_WIDGET (window);
4135 container = GTK_CONTAINER (widget);
4136 info = gtk_window_get_geometry_info (window, TRUE);
4138 configure_request_size_changed = FALSE;
4139 configure_request_pos_changed = FALSE;
4141 gtk_window_compute_configure_request (window, &new_request,
4142 &new_geometry, &new_flags);
4144 /* This check implies the invariant that we never set info->last
4145 * without setting the hints and sending off a configure request.
4147 * If we change info->last without sending the request, we may
4150 if (info->last.configure_request.x != new_request.x ||
4151 info->last.configure_request.y != new_request.y)
4152 configure_request_pos_changed = TRUE;
4154 if ((info->last.configure_request.width != new_request.width ||
4155 info->last.configure_request.height != new_request.height))
4156 configure_request_size_changed = TRUE;
4158 hints_changed = FALSE;
4160 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4161 &new_geometry, new_flags))
4163 hints_changed = TRUE;
4166 /* Position Constraints
4167 * ====================
4169 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4170 * a default. The other POS_ values are used only when the
4171 * window is shown, not after that.
4173 * However, we can't implement a position constraint as
4174 * "anytime the window size changes, center the window"
4175 * because this may well end up fighting the WM or user. In
4176 * fact it gets in an infinite loop with at least one WM.
4178 * Basically, applications are in no way in a position to
4179 * constrain the position of a window, with one exception:
4180 * override redirect windows. (Really the intended purpose
4181 * of CENTER_ALWAYS anyhow, I would think.)
4183 * So the way we implement this "constraint" is to say that when WE
4184 * cause a move or resize, i.e. we make a configure request changing
4185 * window size, we recompute the CENTER_ALWAYS position to reflect
4186 * the new window size, and include it in our request. Also, if we
4187 * just turned on CENTER_ALWAYS we snap to center with a new
4188 * request. Otherwise, if we are just NOTIFIED of a move or resize
4189 * done by someone else e.g. the window manager, we do NOT send a
4190 * new configure request.
4192 * For override redirect windows, this works fine; all window
4193 * sizes are from our configure requests. For managed windows,
4194 * it is at least semi-sane, though who knows what the
4195 * app author is thinking.
4198 /* This condition should be kept in sync with the condition later on
4199 * that determines whether we send a configure request. i.e. we
4200 * should do this position constraining anytime we were going to
4201 * send a configure request anyhow, plus when constraints have
4204 if (configure_request_pos_changed ||
4205 configure_request_size_changed ||
4207 info->position_constraints_changed)
4209 /* We request the constrained position if:
4210 * - we were changing position, and need to clamp
4211 * the change to the constraint
4212 * - we're changing the size anyway
4213 * - set_position() was called to toggle CENTER_ALWAYS on
4216 gtk_window_constrain_position (window,
4222 /* Update whether we need to request a move */
4223 if (info->last.configure_request.x != new_request.x ||
4224 info->last.configure_request.y != new_request.y)
4225 configure_request_pos_changed = TRUE;
4227 configure_request_pos_changed = FALSE;
4232 int notify_x, notify_y;
4234 /* this is the position from the last configure notify */
4235 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4237 g_print ("--- %s ---\n"
4238 "last : %d,%d\t%d x %d\n"
4239 "this : %d,%d\t%d x %d\n"
4240 "alloc: %d,%d\t%d x %d\n"
4242 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4243 "configure_notify_received: %d\n"
4244 "configure_request_count: %d\n"
4245 "position_constraints_changed: %d\n",
4246 window->title ? window->title : "(no title)",
4247 info->last.configure_request.x,
4248 info->last.configure_request.y,
4249 info->last.configure_request.width,
4250 info->last.configure_request.height,
4256 widget->allocation.width,
4257 widget->allocation.height,
4258 widget->requisition.width,
4259 widget->requisition.height,
4260 configure_request_pos_changed,
4261 configure_request_size_changed,
4263 window->configure_notify_received,
4264 window->configure_request_count,
4265 info->position_constraints_changed);
4269 saved_last_info = info->last;
4270 info->last.geometry = new_geometry;
4271 info->last.flags = new_flags;
4272 info->last.configure_request = new_request;
4274 /* need to set PPosition so the WM will look at our position,
4275 * but we don't want to count PPosition coming and going as a hints
4276 * change for future iterations. So we saved info->last prior to
4280 /* Also, if the initial position was explicitly set, then we always
4281 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4285 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4286 * this is an initial map
4289 if ((configure_request_pos_changed ||
4290 info->initial_pos_set ||
4291 (window->need_default_position &&
4292 window->position != GTK_WIN_POS_NONE)) &&
4293 (new_flags & GDK_HINT_POS) == 0)
4295 new_flags |= GDK_HINT_POS;
4296 hints_changed = TRUE;
4299 /* Set hints if necessary
4302 gdk_window_set_geometry_hints (widget->window,
4306 /* handle resizing/moving and widget tree allocation
4308 if (window->configure_notify_received)
4310 GtkAllocation allocation;
4312 /* If we have received a configure event since
4313 * the last time in this function, we need to
4314 * accept our new size and size_allocate child widgets.
4315 * (see gtk_window_configure_event() for more details).
4317 * 1 or more configure notifies may have been received.
4318 * Also, configure_notify_received will only be TRUE
4319 * if all expected configure notifies have been received
4320 * (one per configure request), as an optimization.
4323 window->configure_notify_received = FALSE;
4325 /* gtk_window_configure_event() filled in widget->allocation */
4326 allocation = widget->allocation;
4327 gtk_widget_size_allocate (widget, &allocation);
4329 /* If the configure request changed, it means that
4331 * 1) coincidentally changed hints or widget properties
4332 * impacting the configure request before getting
4333 * a configure notify, or
4334 * 2) some broken widget is changing its size request
4335 * during size allocation, resulting in
4336 * a false appearance of changed configure request.
4338 * For 1), we could just go ahead and ask for the
4339 * new size right now, but doing that for 2)
4340 * might well be fighting the user (and can even
4341 * trigger a loop). Since we really don't want to
4342 * do that, we requeue a resize in hopes that
4343 * by the time it gets handled, the child has seen
4344 * the light and is willing to go along with the
4345 * new size. (this happens for the zvt widget, since
4346 * the size_allocate() above will have stored the
4347 * requisition corresponding to the new size in the
4350 * This doesn't buy us anything for 1), but it shouldn't
4351 * hurt us too badly, since it is what would have
4352 * happened if we had gotten the configure event before
4353 * the new size had been set.
4356 if (configure_request_size_changed ||
4357 configure_request_pos_changed)
4359 /* Don't change the recorded last info after all, because we
4360 * haven't actually updated to the new info yet - we decided
4361 * to postpone our configure request until later.
4363 info->last = saved_last_info;
4365 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
4368 else if ((configure_request_size_changed || hints_changed) &&
4369 (widget->allocation.width != new_request.width ||
4370 widget->allocation.height != new_request.height))
4373 /* We are in one of the following situations:
4374 * A. configure_request_size_changed
4375 * our requisition has changed and we need a different window size,
4376 * so we request it from the window manager.
4377 * B. !configure_request_size_changed && hints_changed
4378 * the window manager rejects our size, but we have just changed the
4379 * window manager hints, so there's a chance our request will
4380 * be honoured this time, so we try again.
4382 * However, if the new requisition is the same as the current allocation,
4383 * we don't request it again, since we won't get a ConfigureNotify back from
4384 * the window manager unless it decides to change our requisition. If
4385 * we don't get the ConfigureNotify back, the resize queue will never be run.
4388 /* Now send the configure request */
4389 if (configure_request_pos_changed)
4393 gdk_window_move_resize (window->frame,
4394 new_request.x - window->frame_left,
4395 new_request.y - window->frame_top,
4396 new_request.width + window->frame_left + window->frame_right,
4397 new_request.height + window->frame_top + window->frame_bottom);
4398 gdk_window_resize (GTK_WIDGET (window)->window,
4399 new_request.width, new_request.height);
4402 gdk_window_move_resize (widget->window,
4403 new_request.x, new_request.y,
4404 new_request.width, new_request.height);
4406 else /* only size changed */
4409 gdk_window_resize (window->frame,
4410 new_request.width + window->frame_left + window->frame_right,
4411 new_request.height + window->frame_top + window->frame_bottom);
4412 gdk_window_resize (widget->window,
4413 new_request.width, new_request.height);
4416 /* Increment the number of have-not-yet-received-notify requests */
4417 window->configure_request_count += 1;
4419 /* We have now sent a request since the last position constraint
4420 * change and definitely don't need a an initial size again (not
4421 * resetting this here can lead to infinite loops for
4422 * GTK_RESIZE_IMMEDIATE containers)
4424 info->position_constraints_changed = FALSE;
4425 window->need_default_position = FALSE;
4427 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
4428 * configure event in response to our resizing request.
4429 * the configure event will cause a new resize with
4430 * ->configure_notify_received=TRUE.
4431 * until then, we want to
4432 * - discard expose events
4433 * - coalesce resizes for our children
4434 * - defer any window resizes until the configure event arrived
4435 * to achieve this, we queue a resize for the window, but remove its
4436 * resizing handler, so resizing will not be handled from the next
4437 * idle handler but when the configure event arrives.
4439 * FIXME: we should also dequeue the pending redraws here, since
4440 * we handle those ourselves upon ->configure_notify_received==TRUE.
4442 if (container->resize_mode == GTK_RESIZE_QUEUE)
4444 gtk_widget_queue_resize (widget);
4445 _gtk_container_dequeue_resize_handler (container);
4450 /* Handle any position changes.
4452 if (configure_request_pos_changed)
4456 gdk_window_move (window->frame,
4457 new_request.x - window->frame_left,
4458 new_request.y - window->frame_top);
4461 gdk_window_move (widget->window,
4462 new_request.x, new_request.y);
4465 /* And run the resize queue.
4467 gtk_container_resize_children (container);
4471 /* Compare two sets of Geometry hints for equality.
4474 gtk_window_compare_hints (GdkGeometry *geometry_a,
4476 GdkGeometry *geometry_b,
4479 if (flags_a != flags_b)
4482 if ((flags_a & GDK_HINT_MIN_SIZE) &&
4483 (geometry_a->min_width != geometry_b->min_width ||
4484 geometry_a->min_height != geometry_b->min_height))
4487 if ((flags_a & GDK_HINT_MAX_SIZE) &&
4488 (geometry_a->max_width != geometry_b->max_width ||
4489 geometry_a->max_height != geometry_b->max_height))
4492 if ((flags_a & GDK_HINT_BASE_SIZE) &&
4493 (geometry_a->base_width != geometry_b->base_width ||
4494 geometry_a->base_height != geometry_b->base_height))
4497 if ((flags_a & GDK_HINT_ASPECT) &&
4498 (geometry_a->min_aspect != geometry_b->min_aspect ||
4499 geometry_a->max_aspect != geometry_b->max_aspect))
4502 if ((flags_a & GDK_HINT_RESIZE_INC) &&
4503 (geometry_a->width_inc != geometry_b->width_inc ||
4504 geometry_a->height_inc != geometry_b->height_inc))
4507 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
4508 geometry_a->win_gravity != geometry_b->win_gravity)
4515 _gtk_window_constrain_size (GtkWindow *window,
4521 GtkWindowGeometryInfo *info;
4523 g_return_if_fail (GTK_IS_WINDOW (window));
4525 info = window->geometry_info;
4528 GdkWindowHints flags = info->last.flags;
4529 GdkGeometry *geometry = &info->last.geometry;
4531 gtk_window_constrain_size (window,
4542 gtk_window_constrain_size (GtkWindow *window,
4543 GdkGeometry *geometry,
4550 gdk_window_constrain_size (geometry, flags, width, height,
4551 new_width, new_height);
4554 /* Compute the set of geometry hints and flags for a window
4555 * based on the application set geometry, and requisiition
4556 * of the window. gtk_widget_size_request() must have been
4560 gtk_window_compute_hints (GtkWindow *window,
4561 GdkGeometry *new_geometry,
4565 gint extra_width = 0;
4566 gint extra_height = 0;
4567 GtkWindowGeometryInfo *geometry_info;
4568 GtkRequisition requisition;
4570 g_return_if_fail (GTK_IS_WINDOW (window));
4572 widget = GTK_WIDGET (window);
4574 gtk_widget_get_child_requisition (widget, &requisition);
4575 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
4579 *new_flags = geometry_info->mask;
4580 *new_geometry = geometry_info->geometry;
4587 if (geometry_info && geometry_info->widget)
4589 extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
4590 extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
4593 /* We don't want to set GDK_HINT_POS in here, we just set it
4594 * in gtk_window_move_resize() when we want the position
4598 if (*new_flags & GDK_HINT_BASE_SIZE)
4600 new_geometry->base_width += extra_width;
4601 new_geometry->base_height += extra_height;
4603 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
4604 (*new_flags & GDK_HINT_RESIZE_INC) &&
4605 ((extra_width != 0) || (extra_height != 0)))
4607 *new_flags |= GDK_HINT_BASE_SIZE;
4609 new_geometry->base_width = extra_width;
4610 new_geometry->base_height = extra_height;
4613 if (*new_flags & GDK_HINT_MIN_SIZE)
4615 if (new_geometry->min_width < 0)
4616 new_geometry->min_width = requisition.width;
4618 new_geometry->min_width += extra_width;
4620 if (new_geometry->min_height < 0)
4621 new_geometry->min_height = requisition.height;
4623 new_geometry->min_height += extra_height;
4625 else if (!window->allow_shrink)
4627 *new_flags |= GDK_HINT_MIN_SIZE;
4629 new_geometry->min_width = requisition.width;
4630 new_geometry->min_height = requisition.height;
4633 if (*new_flags & GDK_HINT_MAX_SIZE)
4635 if (new_geometry->max_width < 0)
4636 new_geometry->max_width = requisition.width;
4638 new_geometry->max_width += extra_width;
4640 if (new_geometry->max_height < 0)
4641 new_geometry->max_width = requisition.height;
4643 new_geometry->max_height += extra_height;
4645 else if (!window->allow_grow)
4647 *new_flags |= GDK_HINT_MAX_SIZE;
4649 new_geometry->max_width = requisition.width;
4650 new_geometry->max_height = requisition.height;
4653 *new_flags |= GDK_HINT_WIN_GRAVITY;
4654 new_geometry->win_gravity = window->gravity;
4657 /***********************
4658 * Redrawing functions *
4659 ***********************/
4662 gtk_window_paint (GtkWidget *widget,
4665 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
4666 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
4670 gtk_window_expose (GtkWidget *widget,
4671 GdkEventExpose *event)
4673 g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
4674 g_return_val_if_fail (event != NULL, FALSE);
4676 if (!GTK_WIDGET_APP_PAINTABLE (widget))
4677 gtk_window_paint (widget, &event->area);
4679 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
4680 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
4686 * gtk_window_set_has_frame:
4687 * @window: a #GtkWindow
4688 * @setting: a boolean
4690 * (Note: this is a special-purpose function for the framebuffer port,
4691 * that causes GTK+ to draw its own window border. For most applications,
4692 * you want gtk_window_set_decorated() instead, which tells the window
4693 * manager whether to draw the window border.)
4695 * If this function is called on a window with setting of %TRUE, before
4696 * it is realized or showed, it will have a "frame" window around
4697 * @window->window, accessible in @window->frame. Using the signal
4698 * frame_event you can recieve all events targeted at the frame.
4700 * This function is used by the linux-fb port to implement managed
4701 * windows, but it could concievably be used by X-programs that
4702 * want to do their own window decorations.
4706 gtk_window_set_has_frame (GtkWindow *window,
4709 g_return_if_fail (GTK_IS_WINDOW (window));
4710 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
4712 window->has_frame = setting != FALSE;
4716 * gtk_window_get_has_frame:
4717 * @window: a #GtkWindow
4719 * Accessor for whether the window has a frame window exterior to
4720 * @window->window. Gets the value set by gtk_window_set_has_frame ().
4722 * Return value: %TRUE if a frame has been added to the window
4723 * via gtk_window_set_has_frame().
4726 gtk_window_get_has_frame (GtkWindow *window)
4728 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4730 return window->has_frame;
4734 * gtk_window_set_frame_dimensions:
4735 * @window: a #GtkWindow that has a frame
4736 * @left: The width of the left border
4737 * @top: The height of the top border
4738 * @right: The width of the right border
4739 * @bottom: The height of the bottom border
4741 * (Note: this is a special-purpose function intended for the framebuffer
4742 * port; see gtk_window_set_has_frame(). It will have no effect on the
4743 * window border drawn by the window manager, which is the normal
4744 * case when using the X Window system.)
4746 * For windows with frames (see gtk_window_set_has_frame()) this function
4747 * can be used to change the size of the frame border.
4750 gtk_window_set_frame_dimensions (GtkWindow *window,
4756 GtkWidget *widget = GTK_WIDGET (window);
4758 g_return_if_fail (GTK_IS_WINDOW (window));
4760 if (window->frame_left == left &&
4761 window->frame_top == top &&
4762 window->frame_right == right &&
4763 window->frame_bottom == bottom)
4766 window->frame_left = left;
4767 window->frame_top = top;
4768 window->frame_right = right;
4769 window->frame_bottom = bottom;
4771 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4773 gint width = widget->allocation.width + left + right;
4774 gint height = widget->allocation.height + top + bottom;
4775 gdk_window_resize (window->frame, width, height);
4776 gtk_decorated_window_move_resize_window (window,
4778 widget->allocation.width,
4779 widget->allocation.height);
4784 * gtk_window_present:
4785 * @window: a #GtkWindow
4787 * Presents a window to the user. This may mean raising the window
4788 * in the stacking order, deiconifying it, moving it to the current
4789 * desktop, and/or giving it the keyboard focus, possibly dependent
4790 * on the user's platform, window manager, and preferences.
4792 * If @window is hidden, this function calls gtk_widget_show()
4795 * This function should be used when the user tries to open a window
4796 * that's already open. Say for example the preferences dialog is
4797 * currently open, and the user chooses Preferences from the menu
4798 * a second time; use gtk_window_present() to move the already-open dialog
4799 * where the user can see it.
4803 gtk_window_present (GtkWindow *window)
4807 g_return_if_fail (GTK_IS_WINDOW (window));
4809 widget = GTK_WIDGET (window);
4811 if (GTK_WIDGET_VISIBLE (window))
4813 g_assert (widget->window != NULL);
4815 gdk_window_show (widget->window);
4817 /* note that gdk_window_focus() will also move the window to
4818 * the current desktop, for WM spec compliant window managers.
4820 gdk_window_focus (widget->window,
4821 gtk_get_current_event_time ());
4825 gtk_widget_show (widget);
4830 * gtk_window_iconify:
4831 * @window: a #GtkWindow
4833 * Asks to iconify (i.e. minimize) the specified @window. Note that you
4834 * shouldn't assume the window is definitely iconified afterward,
4835 * because other entities (e.g. the user or window manager) could
4836 * deiconify it again, or there may not be a window manager in which
4837 * case iconification isn't possible, etc. But normally the window
4838 * will end up iconified. Just don't write code that crashes if not.
4840 * It's permitted to call this function before showing a window,
4841 * in which case the window will be iconified before it ever appears
4844 * You can track iconification via the "window_state_event" signal
4849 gtk_window_iconify (GtkWindow *window)
4852 GdkWindow *toplevel;
4854 g_return_if_fail (GTK_IS_WINDOW (window));
4856 widget = GTK_WIDGET (window);
4858 window->iconify_initially = TRUE;
4861 toplevel = window->frame;
4863 toplevel = widget->window;
4865 if (toplevel != NULL)
4866 gdk_window_iconify (toplevel);
4870 * gtk_window_deiconify:
4871 * @window: a #GtkWindow
4873 * Asks to deiconify (i.e. unminimize) the specified @window. Note
4874 * that you shouldn't assume the window is definitely deiconified
4875 * afterward, because other entities (e.g. the user or window manager)
4876 * could iconify it again before your code which assumes
4877 * deiconification gets to run.
4879 * You can track iconification via the "window_state_event" signal
4883 gtk_window_deiconify (GtkWindow *window)
4886 GdkWindow *toplevel;
4888 g_return_if_fail (GTK_IS_WINDOW (window));
4890 widget = GTK_WIDGET (window);
4892 window->iconify_initially = FALSE;
4895 toplevel = window->frame;
4897 toplevel = widget->window;
4899 if (toplevel != NULL)
4900 gdk_window_deiconify (toplevel);
4905 * @window: a #GtkWindow
4907 * Asks to stick @window, which means that it will appear on all user
4908 * desktops. Note that you shouldn't assume the window is definitely
4909 * stuck afterward, because other entities (e.g. the user or window
4910 * manager) could unstick it again, and some window managers do not
4911 * support sticking windows. But normally the window will end up
4912 * stuck. Just don't write code that crashes if not.
4914 * It's permitted to call this function before showing a window.
4916 * You can track stickiness via the "window_state_event" signal
4921 gtk_window_stick (GtkWindow *window)
4924 GdkWindow *toplevel;
4926 g_return_if_fail (GTK_IS_WINDOW (window));
4928 widget = GTK_WIDGET (window);
4930 window->stick_initially = TRUE;
4933 toplevel = window->frame;
4935 toplevel = widget->window;
4937 if (toplevel != NULL)
4938 gdk_window_stick (toplevel);
4942 * gtk_window_unstick:
4943 * @window: a #GtkWindow
4945 * Asks to unstick @window, which means that it will appear on only
4946 * one of the user's desktops. Note that you shouldn't assume the
4947 * window is definitely unstuck afterward, because other entities
4948 * (e.g. the user or window manager) could stick it again. But
4949 * normally the window will end up stuck. Just don't write code that
4952 * You can track stickiness via the "window_state_event" signal
4957 gtk_window_unstick (GtkWindow *window)
4960 GdkWindow *toplevel;
4962 g_return_if_fail (GTK_IS_WINDOW (window));
4964 widget = GTK_WIDGET (window);
4966 window->stick_initially = FALSE;
4969 toplevel = window->frame;
4971 toplevel = widget->window;
4973 if (toplevel != NULL)
4974 gdk_window_unstick (toplevel);
4978 * gtk_window_maximize:
4979 * @window: a #GtkWindow
4981 * Asks to maximize @window, so that it becomes full-screen. Note that
4982 * you shouldn't assume the window is definitely maximized afterward,
4983 * because other entities (e.g. the user or window manager) could
4984 * unmaximize it again, and not all window managers support
4985 * maximization. But normally the window will end up maximized. Just
4986 * don't write code that crashes if not.
4988 * It's permitted to call this function before showing a window,
4989 * in which case the window will be maximized when it appears onscreen
4992 * You can track maximization via the "window_state_event" signal
4997 gtk_window_maximize (GtkWindow *window)
5000 GdkWindow *toplevel;
5002 g_return_if_fail (GTK_IS_WINDOW (window));
5004 widget = GTK_WIDGET (window);
5006 window->maximize_initially = TRUE;
5009 toplevel = window->frame;
5011 toplevel = widget->window;
5013 if (toplevel != NULL)
5014 gdk_window_maximize (toplevel);
5018 * gtk_window_unmaximize:
5019 * @window: a #GtkWindow
5021 * Asks to unmaximize @window. Note that you shouldn't assume the
5022 * window is definitely unmaximized afterward, because other entities
5023 * (e.g. the user or window manager) could maximize it again, and not
5024 * all window managers honor requests to unmaximize. But normally the
5025 * window will end up unmaximized. Just don't write code that crashes
5028 * You can track maximization via the "window_state_event" signal
5033 gtk_window_unmaximize (GtkWindow *window)
5036 GdkWindow *toplevel;
5038 g_return_if_fail (GTK_IS_WINDOW (window));
5040 widget = GTK_WIDGET (window);
5042 window->maximize_initially = FALSE;
5045 toplevel = window->frame;
5047 toplevel = widget->window;
5049 if (toplevel != NULL)
5050 gdk_window_unmaximize (toplevel);
5054 * gtk_window_set_resizable:
5055 * @window: a #GtkWindow
5056 * @resizable: %TRUE if the user can resize this window
5058 * Sets whether the user can resize a window. Windows are user resizable
5062 gtk_window_set_resizable (GtkWindow *window,
5065 g_return_if_fail (GTK_IS_WINDOW (window));
5067 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5071 * gtk_window_get_resizable:
5072 * @window: a #GtkWindow
5074 * Gets the value set by gtk_window_set_resizable().
5076 * Return value: %TRUE if the user can resize the window
5079 gtk_window_get_resizable (GtkWindow *window)
5081 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5083 /* allow_grow is most likely to indicate the semantic concept we
5084 * mean by "resizable" (and will be a reliable indicator if
5085 * set_policy() hasn't been called)
5087 return window->allow_grow;
5091 * gtk_window_set_gravity:
5092 * @window: a #GtkWindow
5093 * @gravity: window gravity
5095 * Window gravity defines the meaning of coordinates passed to
5096 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5099 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5100 * typically "do what you mean."
5104 gtk_window_set_gravity (GtkWindow *window,
5107 g_return_if_fail (GTK_IS_WINDOW (window));
5109 if (gravity != window->gravity)
5111 window->gravity = gravity;
5113 /* gtk_window_move_resize() will adapt gravity
5115 gtk_widget_queue_resize (GTK_WIDGET (window));
5120 * gtk_window_get_gravity:
5121 * @window: a #GtkWindow
5123 * Gets the value set by gtk_window_set_gravity().
5125 * Return value: window gravity
5128 gtk_window_get_gravity (GtkWindow *window)
5130 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5132 return window->gravity;
5136 * gtk_window_begin_resize_drag:
5137 * @window: a #GtkWindow
5138 * @button: mouse button that initiated the drag
5139 * @edge: position of the resize control
5140 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5141 * @root_y: Y position where the user clicked to initiate the drag
5142 * @timestamp: timestamp from the click event that initiated the drag
5144 * Starts resizing a window. This function is used if an application
5145 * has window resizing controls. When GDK can support it, the resize
5146 * will be done using the standard mechanism for the window manager or
5147 * windowing system. Otherwise, GDK will try to emulate window
5148 * resizing, potentially not all that well, depending on the windowing system.
5152 gtk_window_begin_resize_drag (GtkWindow *window,
5160 GdkWindow *toplevel;
5162 g_return_if_fail (GTK_IS_WINDOW (window));
5163 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5165 widget = GTK_WIDGET (window);
5168 toplevel = window->frame;
5170 toplevel = widget->window;
5172 gdk_window_begin_resize_drag (toplevel,
5179 * gtk_window_get_frame_dimensions:
5180 * @window: a #GtkWindow
5181 * @left: location to store the width of the frame at the left, or %NULL
5182 * @top: location to store the height of the frame at the top, or %NULL
5183 * @right: location to store the width of the frame at the returns, or %NULL
5184 * @bottom: location to store the height of the frame at the bottom, or %NULL
5186 * (Note: this is a special-purpose function intended for the
5187 * framebuffer port; see gtk_window_set_has_frame(). It will not
5188 * return the size of the window border drawn by the window manager,
5189 * which is the normal case when using a windowing system.
5190 * See gdk_window_get_frame_extents() to get the standard
5191 * window border extents.)
5193 * Retrieves the dimensions of the frame window for this toplevel.
5194 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5197 gtk_window_get_frame_dimensions (GtkWindow *window,
5203 g_return_if_fail (GTK_IS_WINDOW (window));
5206 *left = window->frame_left;
5208 *top = window->frame_top;
5210 *right = window->frame_right;
5212 *bottom = window->frame_bottom;
5216 * gtk_window_begin_move_drag:
5217 * @window: a #GtkWindow
5218 * @button: mouse button that initiated the drag
5219 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5220 * @root_y: Y position where the user clicked to initiate the drag
5221 * @timestamp: timestamp from the click event that initiated the drag
5223 * Starts moving a window. This function is used if an application
5224 * has window movement grips. When GDK can support it, the window movement
5225 * will be done using the standard mechanism for the window manager or
5226 * windowing system. Otherwise, GDK will try to emulate window
5227 * movement, potentially not all that well, depending on the windowing system.
5231 gtk_window_begin_move_drag (GtkWindow *window,
5238 GdkWindow *toplevel;
5240 g_return_if_fail (GTK_IS_WINDOW (window));
5241 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5243 widget = GTK_WIDGET (window);
5246 toplevel = window->frame;
5248 toplevel = widget->window;
5250 gdk_window_begin_move_drag (toplevel,
5258 gtk_window_group_class_init (GtkWindowGroupClass *klass)
5263 gtk_window_group_get_type (void)
5265 static GtkType window_group_type = 0;
5267 if (!window_group_type)
5269 static const GTypeInfo window_group_info =
5271 sizeof (GtkWindowGroupClass),
5272 NULL, /* base_init */
5273 NULL, /* base_finalize */
5274 (GClassInitFunc) gtk_window_group_class_init,
5275 NULL, /* class_finalize */
5276 NULL, /* class_data */
5277 sizeof (GtkWindowGroup),
5278 16, /* n_preallocs */
5279 (GInstanceInitFunc) NULL,
5282 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
5285 return window_group_type;
5289 * gtk_window_group_new:
5291 * Creates a new #GtkWindowGroup object. Grabs added with
5292 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
5294 * Return value: a new #GtkWindowGroup.
5297 gtk_window_group_new (void)
5299 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
5303 window_group_cleanup_grabs (GtkWindowGroup *group,
5307 GSList *to_remove = NULL;
5309 tmp_list = group->grabs;
5312 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
5313 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
5314 tmp_list = tmp_list->next;
5319 gtk_grab_remove (to_remove->data);
5320 g_object_unref (to_remove->data);
5321 to_remove = g_slist_delete_link (to_remove, to_remove);
5326 * gtk_window_group_add_window:
5327 * @window_group: a #GtkWindowGroup
5328 * @window: the #GtkWindow to add
5330 * Adds a window to a #GtkWindowGroup.
5333 gtk_window_group_add_window (GtkWindowGroup *window_group,
5336 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5337 g_return_if_fail (GTK_IS_WINDOW (window));
5339 if (window->group != window_group)
5341 g_object_ref (window);
5342 g_object_ref (window_group);
5345 gtk_window_group_remove_window (window->group, window);
5347 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
5349 window->group = window_group;
5351 g_object_unref (window);
5356 * gtk_window_group_remove_window:
5357 * @window_group: a #GtkWindowGroup
5358 * @window: the #GtkWindow to remove
5360 * Removes a window from a #GtkWindowGroup.
5363 gtk_window_group_remove_window (GtkWindowGroup *window_group,
5366 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5367 g_return_if_fail (GTK_IS_WIDGET (window));
5368 g_return_if_fail (window->group == window_group);
5370 g_object_ref (window);
5372 window_group_cleanup_grabs (window_group, window);
5373 window->group = NULL;
5375 g_object_unref (G_OBJECT (window_group));
5376 g_object_unref (window);
5379 /* Return the group for the window or the default group
5382 _gtk_window_get_group (GtkWindow *window)
5384 if (window && window->group)
5385 return window->group;
5388 static GtkWindowGroup *default_group = NULL;
5391 default_group = gtk_window_group_new ();
5393 return default_group;
5399 Derived from XParseGeometry() in XFree86
5401 Copyright 1985, 1986, 1987,1998 The Open Group
5403 All Rights Reserved.
5405 The above copyright notice and this permission notice shall be included
5406 in all copies or substantial portions of the Software.
5408 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5409 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5410 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
5411 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
5412 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
5413 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
5414 OTHER DEALINGS IN THE SOFTWARE.
5416 Except as contained in this notice, the name of The Open Group shall
5417 not be used in advertising or otherwise to promote the sale, use or
5418 other dealings in this Software without prior written authorization
5419 from The Open Group.
5424 * XParseGeometry parses strings of the form
5425 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5426 * width, height, xoffset, and yoffset are unsigned integers.
5427 * Example: "=80x24+300-49"
5428 * The equal sign is optional.
5429 * It returns a bitmask that indicates which of the four values
5430 * were actually found in the string. For each value found,
5431 * the corresponding argument is updated; for each value
5432 * not found, the corresponding argument is left unchanged.
5435 /* The following code is from Xlib, and is minimally modified, so we
5436 * can track any upstream changes if required. Don't change this
5437 * code. Or if you do, put in a huge comment marking which thing
5442 read_int (gchar *string,
5450 else if (*string == '-')
5456 for (; (*string >= '0') && (*string <= '9'); string++)
5458 result = (result * 10) + (*string - '0');
5470 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
5471 * value (x, y, width, height) was found in the parsed string.
5473 #define NoValue 0x0000
5474 #define XValue 0x0001
5475 #define YValue 0x0002
5476 #define WidthValue 0x0004
5477 #define HeightValue 0x0008
5478 #define AllValues 0x000F
5479 #define XNegative 0x0010
5480 #define YNegative 0x0020
5482 /* Try not to reformat/modify, so we can compare/sync with X sources */
5484 gtk_XParseGeometry (const char *string,
5487 unsigned int *width,
5488 unsigned int *height)
5492 unsigned int tempWidth, tempHeight;
5494 char *nextCharacter;
5496 /* These initializations are just to silence gcc */
5502 if ( (string == NULL) || (*string == '\0')) return(mask);
5504 string++; /* ignore possible '=' at beg of geometry spec */
5506 strind = (char *)string;
5507 if (*strind != '+' && *strind != '-' && *strind != 'x') {
5508 tempWidth = read_int(strind, &nextCharacter);
5509 if (strind == nextCharacter)
5511 strind = nextCharacter;
5515 if (*strind == 'x' || *strind == 'X') {
5517 tempHeight = read_int(strind, &nextCharacter);
5518 if (strind == nextCharacter)
5520 strind = nextCharacter;
5521 mask |= HeightValue;
5524 if ((*strind == '+') || (*strind == '-')) {
5525 if (*strind == '-') {
5527 tempX = -read_int(strind, &nextCharacter);
5528 if (strind == nextCharacter)
5530 strind = nextCharacter;
5536 tempX = read_int(strind, &nextCharacter);
5537 if (strind == nextCharacter)
5539 strind = nextCharacter;
5542 if ((*strind == '+') || (*strind == '-')) {
5543 if (*strind == '-') {
5545 tempY = -read_int(strind, &nextCharacter);
5546 if (strind == nextCharacter)
5548 strind = nextCharacter;
5555 tempY = read_int(strind, &nextCharacter);
5556 if (strind == nextCharacter)
5558 strind = nextCharacter;
5564 /* If strind isn't at the end of the string the it's an invalid
5565 geometry specification. */
5567 if (*strind != '\0') return (0);
5573 if (mask & WidthValue)
5575 if (mask & HeightValue)
5576 *height = tempHeight;
5581 * gtk_window_parse_geometry:
5582 * @window: a #GtkWindow
5583 * @geometry: geometry string
5585 * Parses a standard X Window System geometry string - see the
5586 * manual page for X (type 'man X') for details on this.
5587 * gtk_window_parse_geometry() does work on all GTK+ ports
5588 * including Win32 but is primarily intended for an X environment.
5590 * If either a size or a position can be extracted from the
5591 * geometry string, gtk_window_parse_geometry() returns %TRUE
5592 * and calls gtk_window_set_default_size() and/or gtk_window_move()
5593 * to resize/move the window.
5595 * If gtk_window_parse_geometry() returns %TRUE, it will also
5596 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
5597 * indicating to the window manager that the size/position of
5598 * the window was user-specified. This causes most window
5599 * managers to honor the geometry.
5601 * Return value: %TRUE if string was parsed successfully
5604 gtk_window_parse_geometry (GtkWindow *window,
5605 const gchar *geometry)
5610 gboolean size_set, pos_set;
5612 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5613 g_return_val_if_fail (geometry != NULL, FALSE);
5615 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
5617 if ((result & WidthValue) == 0 ||
5620 if ((result & HeightValue) == 0 ||
5625 if ((result & WidthValue) || (result & HeightValue))
5627 gtk_window_set_default_size (window, w, h);
5631 gtk_window_get_size (window, &w, &h);
5633 grav = GDK_GRAVITY_NORTH_WEST;
5635 if ((result & XNegative) && (result & YNegative))
5636 grav = GDK_GRAVITY_SOUTH_EAST;
5637 else if (result & XNegative)
5638 grav = GDK_GRAVITY_NORTH_EAST;
5639 else if (result & YNegative)
5640 grav = GDK_GRAVITY_SOUTH_WEST;
5642 if ((result & XValue) == 0)
5645 if ((result & YValue) == 0)
5648 if (grav == GDK_GRAVITY_SOUTH_WEST ||
5649 grav == GDK_GRAVITY_SOUTH_EAST)
5650 y = gdk_screen_height () - h;
5652 if (grav == GDK_GRAVITY_SOUTH_EAST ||
5653 grav == GDK_GRAVITY_NORTH_EAST)
5654 x = gdk_screen_width () - w;
5663 if ((result & XValue) || (result & YValue))
5665 gtk_window_set_gravity (window, grav);
5666 gtk_window_move (window, x, y);
5670 if (size_set || pos_set)
5672 /* Set USSize, USPosition hints */
5673 GtkWindowGeometryInfo *info;
5675 info = gtk_window_get_geometry_info (window, TRUE);
5678 info->mask |= GDK_HINT_USER_POS;
5680 info->mask |= GDK_HINT_USER_SIZE;