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"
38 #include "gtkkeyhash.h"
40 #include "gtkiconfactory.h"
42 #include "gtkmarshalers.h"
69 PROP_DESTROY_WITH_PARENT,
78 GdkPixmap *icon_pixmap;
81 guint using_default_icon : 1;
82 guint using_parent_icon : 1;
86 GdkGeometry geometry; /* Last set of geometry hints we set */
88 GdkRectangle configure_request;
89 } GtkWindowLastGeometryInfo;
91 struct _GtkWindowGeometryInfo
93 /* Properties that the app has set on the window
95 GdkGeometry geometry; /* Geometry hints */
97 GtkWidget *widget; /* subwidget to which hints apply */
98 /* from last gtk_window_resize () - if > 0, indicates that
99 * we should resize to this size.
104 /* From last gtk_window_move () prior to mapping -
105 * only used if initial_pos_set
110 /* Default size - used only the FIRST time we map a window,
115 /* whether to use initial_x, initial_y */
116 guint initial_pos_set : 1;
117 /* CENTER_ALWAYS or other position constraint changed since
118 * we sent the last configure request.
120 guint position_constraints_changed : 1;
122 GtkWindowLastGeometryInfo last;
133 static void gtk_window_class_init (GtkWindowClass *klass);
134 static void gtk_window_init (GtkWindow *window);
135 static void gtk_window_dispose (GObject *object);
136 static void gtk_window_destroy (GtkObject *object);
137 static void gtk_window_finalize (GObject *object);
138 static void gtk_window_show (GtkWidget *widget);
139 static void gtk_window_hide (GtkWidget *widget);
140 static void gtk_window_map (GtkWidget *widget);
141 static void gtk_window_unmap (GtkWidget *widget);
142 static void gtk_window_realize (GtkWidget *widget);
143 static void gtk_window_unrealize (GtkWidget *widget);
144 static void gtk_window_size_request (GtkWidget *widget,
145 GtkRequisition *requisition);
146 static void gtk_window_size_allocate (GtkWidget *widget,
147 GtkAllocation *allocation);
148 static gint gtk_window_event (GtkWidget *widget,
150 static gboolean gtk_window_frame_event (GtkWindow *window,
152 static gint gtk_window_configure_event (GtkWidget *widget,
153 GdkEventConfigure *event);
154 static gint gtk_window_key_press_event (GtkWidget *widget,
156 static gint gtk_window_key_release_event (GtkWidget *widget,
158 static gint gtk_window_enter_notify_event (GtkWidget *widget,
159 GdkEventCrossing *event);
160 static gint gtk_window_leave_notify_event (GtkWidget *widget,
161 GdkEventCrossing *event);
162 static gint gtk_window_focus_in_event (GtkWidget *widget,
163 GdkEventFocus *event);
164 static gint gtk_window_focus_out_event (GtkWidget *widget,
165 GdkEventFocus *event);
166 static gint gtk_window_client_event (GtkWidget *widget,
167 GdkEventClient *event);
168 static void gtk_window_check_resize (GtkContainer *container);
169 static gint gtk_window_focus (GtkWidget *widget,
170 GtkDirectionType direction);
171 static void gtk_window_real_set_focus (GtkWindow *window,
174 static void gtk_window_real_activate_default (GtkWindow *window);
175 static void gtk_window_real_activate_focus (GtkWindow *window);
176 static void gtk_window_move_focus (GtkWindow *window,
177 GtkDirectionType dir);
178 static void gtk_window_keys_changed (GtkWindow *window);
179 static void gtk_window_read_rcfiles (GtkWidget *widget,
180 GdkEventClient *event);
181 static void gtk_window_paint (GtkWidget *widget,
183 static gint gtk_window_expose (GtkWidget *widget,
184 GdkEventExpose *event);
185 static void gtk_window_unset_transient_for (GtkWindow *window);
186 static void gtk_window_transient_parent_realized (GtkWidget *parent,
188 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
191 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
194 static void gtk_window_move_resize (GtkWindow *window);
195 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
197 GdkGeometry *geometry_b,
199 static void gtk_window_constrain_size (GtkWindow *window,
200 GdkGeometry *geometry,
206 static void gtk_window_constrain_position (GtkWindow *window,
211 static void gtk_window_compute_hints (GtkWindow *window,
212 GdkGeometry *new_geometry,
214 static void gtk_window_compute_configure_request (GtkWindow *window,
215 GdkRectangle *request,
216 GdkGeometry *geometry,
219 static void gtk_window_set_default_size_internal (GtkWindow *window,
220 gboolean change_width,
222 gboolean change_height,
225 static void gtk_window_realize_icon (GtkWindow *window);
226 static void gtk_window_unrealize_icon (GtkWindow *window);
228 static void gtk_window_notify_keys_changed (GtkWindow *window);
229 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
230 static void gtk_window_free_key_hash (GtkWindow *window);
232 static GSList *toplevel_list = NULL;
233 static GHashTable *mnemonic_hash_table = NULL;
234 static GtkBinClass *parent_class = NULL;
235 static guint window_signals[LAST_SIGNAL] = { 0 };
236 static GList *default_icon_list = NULL;
237 /* FIXME need to be per-screen */
238 static GdkPixmap *default_icon_pixmap = NULL;
239 static GdkPixmap *default_icon_mask = NULL;
241 static void gtk_window_set_property (GObject *object,
245 static void gtk_window_get_property (GObject *object,
252 mnemonic_hash (gconstpointer key)
254 const GtkWindowMnemonic *k;
257 k = (GtkWindowMnemonic *)key;
259 h = (gulong) k->window;
260 h ^= k->keyval << 16;
261 h ^= k->keyval >> 16;
267 mnemonic_equal (gconstpointer a, gconstpointer b)
269 const GtkWindowMnemonic *ka;
270 const GtkWindowMnemonic *kb;
272 ka = (GtkWindowMnemonic *)a;
273 kb = (GtkWindowMnemonic *)b;
276 (ka->window == kb->window) &&
277 (ka->keyval == kb->keyval);
281 gtk_window_get_type (void)
283 static GtkType window_type = 0;
287 static const GtkTypeInfo window_info =
291 sizeof (GtkWindowClass),
292 (GtkClassInitFunc) gtk_window_class_init,
293 (GtkObjectInitFunc) gtk_window_init,
294 /* reserved_1 */ NULL,
295 /* reserved_2 */ NULL,
296 (GtkClassInitFunc) NULL,
299 window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
306 add_tab_bindings (GtkBindingSet *binding_set,
307 GdkModifierType modifiers,
308 GtkDirectionType direction)
310 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
312 GTK_TYPE_DIRECTION_TYPE, direction);
313 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
315 GTK_TYPE_DIRECTION_TYPE, direction);
319 add_arrow_bindings (GtkBindingSet *binding_set,
321 GtkDirectionType direction)
323 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
325 gtk_binding_entry_add_signal (binding_set, keysym, 0,
327 GTK_TYPE_DIRECTION_TYPE, direction);
328 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
330 GTK_TYPE_DIRECTION_TYPE, direction);
331 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
333 GTK_TYPE_DIRECTION_TYPE, direction);
334 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
336 GTK_TYPE_DIRECTION_TYPE, direction);
341 gtk_window_class_init (GtkWindowClass *klass)
343 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
344 GtkObjectClass *object_class;
345 GtkWidgetClass *widget_class;
346 GtkContainerClass *container_class;
347 GtkBindingSet *binding_set;
349 object_class = (GtkObjectClass*) klass;
350 widget_class = (GtkWidgetClass*) klass;
351 container_class = (GtkContainerClass*) klass;
353 parent_class = gtk_type_class (gtk_bin_get_type ());
355 mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
357 gobject_class->dispose = gtk_window_dispose;
358 gobject_class->finalize = gtk_window_finalize;
360 gobject_class->set_property = gtk_window_set_property;
361 gobject_class->get_property = gtk_window_get_property;
363 object_class->destroy = gtk_window_destroy;
365 widget_class->show = gtk_window_show;
366 widget_class->hide = gtk_window_hide;
367 widget_class->map = gtk_window_map;
368 widget_class->unmap = gtk_window_unmap;
369 widget_class->realize = gtk_window_realize;
370 widget_class->unrealize = gtk_window_unrealize;
371 widget_class->size_request = gtk_window_size_request;
372 widget_class->size_allocate = gtk_window_size_allocate;
373 widget_class->configure_event = gtk_window_configure_event;
374 widget_class->key_press_event = gtk_window_key_press_event;
375 widget_class->key_release_event = gtk_window_key_release_event;
376 widget_class->enter_notify_event = gtk_window_enter_notify_event;
377 widget_class->leave_notify_event = gtk_window_leave_notify_event;
378 widget_class->focus_in_event = gtk_window_focus_in_event;
379 widget_class->focus_out_event = gtk_window_focus_out_event;
380 widget_class->client_event = gtk_window_client_event;
381 widget_class->focus = gtk_window_focus;
383 widget_class->expose_event = gtk_window_expose;
385 container_class->check_resize = gtk_window_check_resize;
387 klass->set_focus = gtk_window_real_set_focus;
388 klass->frame_event = gtk_window_frame_event;
390 klass->activate_default = gtk_window_real_activate_default;
391 klass->activate_focus = gtk_window_real_activate_focus;
392 klass->move_focus = gtk_window_move_focus;
393 klass->keys_changed = gtk_window_keys_changed;
396 g_object_class_install_property (gobject_class,
398 g_param_spec_enum ("type",
400 _("The type of the window"),
401 GTK_TYPE_WINDOW_TYPE,
403 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
406 g_object_class_install_property (gobject_class,
408 g_param_spec_string ("title",
410 _("The title of the window"),
414 g_object_class_install_property (gobject_class,
416 g_param_spec_boolean ("allow_shrink",
418 /* xgettext:no-c-format */
419 _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea."),
423 g_object_class_install_property (gobject_class,
425 g_param_spec_boolean ("allow_grow",
427 _("If TRUE, users can expand the window beyond its minimum size."),
431 g_object_class_install_property (gobject_class,
433 g_param_spec_boolean ("resizable",
435 _("If TRUE, users can resize the window."),
439 g_object_class_install_property (gobject_class,
441 g_param_spec_boolean ("modal",
443 _("If TRUE, the window is modal (other windows are not usable while this one is up)."),
447 g_object_class_install_property (gobject_class,
449 g_param_spec_enum ("window_position",
450 _("Window Position"),
451 _("The initial position of the window."),
452 GTK_TYPE_WINDOW_POSITION,
456 g_object_class_install_property (gobject_class,
458 g_param_spec_int ("default_width",
460 _("The default width of the window, used when initially showing the window."),
466 g_object_class_install_property (gobject_class,
468 g_param_spec_int ("default_height",
470 _("The default height of the window, used when initially showing the window."),
476 g_object_class_install_property (gobject_class,
477 PROP_DESTROY_WITH_PARENT,
478 g_param_spec_boolean ("destroy_with_parent",
479 _("Destroy with Parent"),
480 _("If this window should be destroyed when the parent is destroyed"),
484 g_object_class_install_property (gobject_class,
486 g_param_spec_object ("icon",
488 _("Icon for this window"),
492 window_signals[SET_FOCUS] =
493 g_signal_new ("set_focus",
494 G_TYPE_FROM_CLASS (object_class),
496 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
498 _gtk_marshal_VOID__OBJECT,
502 window_signals[FRAME_EVENT] =
503 g_signal_new ("frame_event",
504 G_TYPE_FROM_CLASS(object_class),
506 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
507 _gtk_boolean_handled_accumulator, NULL,
508 _gtk_marshal_BOOLEAN__BOXED,
512 window_signals[ACTIVATE_FOCUS] =
513 g_signal_new ("activate_focus",
514 G_OBJECT_CLASS_TYPE (object_class),
515 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
516 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_focus),
518 _gtk_marshal_VOID__VOID,
522 window_signals[ACTIVATE_DEFAULT] =
523 g_signal_new ("activate_default",
524 G_OBJECT_CLASS_TYPE (object_class),
525 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
526 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_default),
528 _gtk_marshal_VOID__VOID,
532 window_signals[MOVE_FOCUS] =
533 g_signal_new ("move_focus",
534 G_OBJECT_CLASS_TYPE (object_class),
535 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
536 GTK_SIGNAL_OFFSET (GtkWindowClass, move_focus),
538 _gtk_marshal_VOID__ENUM,
541 GTK_TYPE_DIRECTION_TYPE);
543 window_signals[KEYS_CHANGED] =
544 g_signal_new ("keys_changed",
545 G_OBJECT_CLASS_TYPE (object_class),
547 GTK_SIGNAL_OFFSET (GtkWindowClass, keys_changed),
549 gtk_marshal_VOID__VOID,
557 binding_set = gtk_binding_set_by_class (klass);
559 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
560 "activate_focus", 0);
561 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
562 "activate_focus", 0);
564 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
565 "activate_default", 0);
567 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
568 "activate_default", 0);
570 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
571 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
572 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
573 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
575 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
576 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
577 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
578 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
582 gtk_window_init (GtkWindow *window)
584 GdkColormap *colormap;
586 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
587 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
589 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
591 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
593 window->title = NULL;
594 window->wmclass_name = g_strdup (g_get_prgname ());
595 window->wmclass_class = g_strdup (gdk_get_program_class ());
596 window->wm_role = NULL;
597 window->geometry_info = NULL;
598 window->type = GTK_WINDOW_TOPLEVEL;
599 window->focus_widget = NULL;
600 window->default_widget = NULL;
601 window->configure_request_count = 0;
602 window->allow_shrink = FALSE;
603 window->allow_grow = TRUE;
604 window->configure_notify_received = FALSE;
605 window->position = GTK_WIN_POS_NONE;
606 window->need_default_size = TRUE;
607 window->need_default_position = TRUE;
608 window->modal = FALSE;
609 window->frame = NULL;
610 window->has_frame = FALSE;
611 window->frame_left = 0;
612 window->frame_right = 0;
613 window->frame_top = 0;
614 window->frame_bottom = 0;
615 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
616 window->gravity = GDK_GRAVITY_NORTH_WEST;
617 window->decorated = TRUE;
618 window->mnemonic_modifier = GDK_MOD1_MASK;
620 colormap = _gtk_widget_peek_colormap ();
622 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
624 gtk_widget_ref (GTK_WIDGET (window));
625 gtk_object_sink (GTK_OBJECT (window));
626 window->has_user_ref_count = TRUE;
627 toplevel_list = g_slist_prepend (toplevel_list, window);
629 gtk_decorated_window_init (window);
631 gtk_signal_connect (GTK_OBJECT (window),
633 GTK_SIGNAL_FUNC (gtk_window_event),
638 gtk_window_set_property (GObject *object,
645 window = GTK_WINDOW (object);
650 window->type = g_value_get_enum (value);
653 gtk_window_set_title (window, g_value_get_string (value));
655 case PROP_ALLOW_SHRINK:
656 window->allow_shrink = g_value_get_boolean (value);
657 gtk_widget_queue_resize (GTK_WIDGET (window));
659 case PROP_ALLOW_GROW:
660 window->allow_grow = g_value_get_boolean (value);
661 gtk_widget_queue_resize (GTK_WIDGET (window));
662 g_object_notify (G_OBJECT (window), "resizable");
665 window->allow_grow = g_value_get_boolean (value);
666 gtk_widget_queue_resize (GTK_WIDGET (window));
667 g_object_notify (G_OBJECT (window), "allow_grow");
670 gtk_window_set_modal (window, g_value_get_boolean (value));
673 gtk_window_set_position (window, g_value_get_enum (value));
675 case PROP_DEFAULT_WIDTH:
676 gtk_window_set_default_size_internal (window,
677 TRUE, g_value_get_int (value),
680 case PROP_DEFAULT_HEIGHT:
681 gtk_window_set_default_size_internal (window,
683 TRUE, g_value_get_int (value));
685 case PROP_DESTROY_WITH_PARENT:
686 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
689 gtk_window_set_icon (window,
690 g_value_get_object (value));
699 gtk_window_get_property (GObject *object,
706 window = GTK_WINDOW (object);
710 GtkWindowGeometryInfo *info;
712 g_value_set_enum (value, window->type);
715 g_value_set_string (value, window->title);
717 case PROP_ALLOW_SHRINK:
718 g_value_set_boolean (value, window->allow_shrink);
720 case PROP_ALLOW_GROW:
721 g_value_set_boolean (value, window->allow_grow);
724 g_value_set_boolean (value, window->allow_grow);
727 g_value_set_boolean (value, window->modal);
730 g_value_set_enum (value, window->position);
732 case PROP_DEFAULT_WIDTH:
733 info = gtk_window_get_geometry_info (window, FALSE);
735 g_value_set_int (value, -1);
737 g_value_set_int (value, info->default_width);
739 case PROP_DEFAULT_HEIGHT:
740 info = gtk_window_get_geometry_info (window, FALSE);
742 g_value_set_int (value, -1);
744 g_value_set_int (value, info->default_height);
746 case PROP_DESTROY_WITH_PARENT:
747 g_value_set_boolean (value, window->destroy_with_parent);
750 g_value_set_object (value, gtk_window_get_icon (window));
753 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
760 * @type: type of window
762 * Creates a new #GtkWindow, which is a toplevel window that can
763 * contain other widgets. Nearly always, the type of the window should
764 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
765 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
766 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
767 * dialogs, though in some other toolkits dialogs are called "popups".
768 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
769 * On X11, popup windows are not controlled by the <link
770 * linkend="gtk-X11-arch">window manager</link>.
772 * If you simply want an undecorated window (no window borders), use
773 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
775 * Return value: a new #GtkWindow.
778 gtk_window_new (GtkWindowType type)
782 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
784 window = gtk_type_new (GTK_TYPE_WINDOW);
788 return GTK_WIDGET (window);
792 * gtk_window_set_title:
793 * @window: a #GtkWindow
794 * @title: title of the window
796 * Sets the title of the #GtkWindow. The title of a window will be
797 * displayed in its title bar; on the X Window System, the title bar
798 * is rendered by the <link linkend="gtk-X11-arch">window
799 * manager</link>, so exactly how the title appears to users may vary
800 * according to a user's exact configuration. The title should help a
801 * user distinguish this window from other windows they may have
802 * open. A good title might include the application name and current
803 * document filename, for example.
807 gtk_window_set_title (GtkWindow *window,
810 g_return_if_fail (GTK_IS_WINDOW (window));
813 g_free (window->title);
814 window->title = g_strdup (title);
816 if (GTK_WIDGET_REALIZED (window))
818 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
820 gtk_decorated_window_set_title (window, title);
823 g_object_notify (G_OBJECT (window), "title");
827 * gtk_window_get_title:
828 * @window: a #GtkWindow
830 * Retrieves the title of the window. See gtk_window_set_title().
832 * Return value: the title of the window, or %NULL if none has
833 * been set explicitely. The returned string is owned by the widget
834 * and must not be modified or freed.
836 G_CONST_RETURN gchar *
837 gtk_window_get_title (GtkWindow *window)
839 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
841 return window->title;
845 * gtk_window_set_wmclass:
846 * @window: a #GtkWindow
847 * @wmclass_name: window name hint
848 * @wmclass_class: window class hint
850 * Don't use this function. It sets the X Window System "class" and
851 * "name" hints for a window. According to the ICCCM, you should
852 * always set these to the same value for all windows in an
853 * application, and GTK+ sets them to that value by default, so calling
854 * this function is sort of pointless. However, you may want to call
855 * gtk_window_set_role() on each window in your application, for the
856 * benefit of the session manager. Setting the role allows the window
857 * manager to restore window positions when loading a saved session.
861 gtk_window_set_wmclass (GtkWindow *window,
862 const gchar *wmclass_name,
863 const gchar *wmclass_class)
865 g_return_if_fail (GTK_IS_WINDOW (window));
867 g_free (window->wmclass_name);
868 window->wmclass_name = g_strdup (wmclass_name);
870 g_free (window->wmclass_class);
871 window->wmclass_class = g_strdup (wmclass_class);
873 if (GTK_WIDGET_REALIZED (window))
874 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
878 * gtk_window_set_role:
879 * @window: a #GtkWindow
880 * @role: unique identifier for the window to be used when restoring a session
882 * This function is only useful on X11, not with other GTK+ targets.
884 * In combination with the window title, the window role allows a
885 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
886 * same" window when an application is restarted. So for example you
887 * might set the "toolbox" role on your app's toolbox window, so that
888 * when the user restarts their session, the window manager can put
889 * the toolbox back in the same place.
891 * If a window already has a unique title, you don't need to set the
892 * role, since the WM can use the title to identify the window when
893 * restoring the session.
897 gtk_window_set_role (GtkWindow *window,
900 g_return_if_fail (GTK_IS_WINDOW (window));
902 if (role == window->wm_role)
905 g_free (window->wm_role);
906 window->wm_role = g_strdup (role);
908 if (GTK_WIDGET_REALIZED (window))
909 g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
913 * gtk_window_get_role:
914 * @window: a #GtkWindow
916 * Returns the role of the window. See gtk_window_set_role() for
917 * further explanation.
919 * Return value: the role of the window if set, or %NULL. The
920 * returned is owned by the widget and must not be modified
923 G_CONST_RETURN gchar *
924 gtk_window_get_role (GtkWindow *window)
926 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
928 return window->wm_role;
932 * gtk_window_set_focus:
933 * @window: a #GtkWindow
934 * @focus: widget to be the new focus widget, or %NULL to unset
935 * any focus widget for the toplevel window.
937 * If @focus is not the current focus widget, and is focusable, sets
938 * it as the focus widget for the window. If @focus is %NULL, unsets
939 * the focus widget for this window. To set the focus to a particular
940 * widget in the toplevel, it is usually more convenient to use
941 * gtk_widget_grab_focus() instead of this function.
944 gtk_window_set_focus (GtkWindow *window,
947 g_return_if_fail (GTK_IS_WINDOW (window));
950 g_return_if_fail (GTK_IS_WIDGET (focus));
951 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
955 gtk_widget_grab_focus (focus);
957 _gtk_window_internal_set_focus (window, NULL);
961 _gtk_window_internal_set_focus (GtkWindow *window,
964 g_return_if_fail (GTK_IS_WINDOW (window));
966 if ((window->focus_widget != focus) ||
967 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
968 gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
972 * gtk_window_set_default:
973 * @window: a #GtkWindow
974 * @default_widget: widget to be the default, or %NULL to unset the
975 * default widget for the toplevel.
977 * The default widget is the widget that's activated when the user
978 * presses Enter in a dialog (for example). This function sets or
979 * unsets the default widget for a #GtkWindow about. When setting
980 * (rather than unsetting) the default widget it's generally easier to
981 * call gtk_widget_grab_focus() on the widget. Before making a widget
982 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
983 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
986 gtk_window_set_default (GtkWindow *window,
987 GtkWidget *default_widget)
989 g_return_if_fail (GTK_IS_WINDOW (window));
992 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
994 if (window->default_widget != default_widget)
996 GtkWidget *old_default_widget = NULL;
999 g_object_ref (default_widget);
1001 if (window->default_widget)
1003 old_default_widget = window->default_widget;
1005 if (window->focus_widget != window->default_widget ||
1006 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1007 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1008 gtk_widget_queue_draw (window->default_widget);
1011 window->default_widget = default_widget;
1013 if (window->default_widget)
1015 if (window->focus_widget == NULL ||
1016 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1017 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1018 gtk_widget_queue_draw (window->default_widget);
1021 if (old_default_widget)
1022 g_object_notify (G_OBJECT (old_default_widget), "has_default");
1026 g_object_notify (G_OBJECT (default_widget), "has_default");
1027 g_object_unref (default_widget);
1033 gtk_window_set_policy (GtkWindow *window,
1034 gboolean allow_shrink,
1035 gboolean allow_grow,
1036 gboolean auto_shrink)
1038 g_return_if_fail (GTK_IS_WINDOW (window));
1040 window->allow_shrink = (allow_shrink != FALSE);
1041 window->allow_grow = (allow_grow != FALSE);
1043 g_object_freeze_notify (G_OBJECT (window));
1044 g_object_notify (G_OBJECT (window), "allow_shrink");
1045 g_object_notify (G_OBJECT (window), "allow_grow");
1046 g_object_notify (G_OBJECT (window), "resizable");
1047 g_object_thaw_notify (G_OBJECT (window));
1049 gtk_widget_queue_resize (GTK_WIDGET (window));
1053 handle_keys_changed (gpointer data)
1057 GDK_THREADS_ENTER ();
1058 window = GTK_WINDOW (data);
1060 if (window->keys_changed_handler)
1062 gtk_idle_remove (window->keys_changed_handler);
1063 window->keys_changed_handler = 0;
1066 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1067 GDK_THREADS_LEAVE ();
1073 gtk_window_notify_keys_changed (GtkWindow *window)
1075 if (!window->keys_changed_handler)
1076 window->keys_changed_handler = gtk_idle_add (handle_keys_changed, window);
1080 * gtk_window_add_accel_group:
1081 * @window: window to attach accelerator group to
1082 * @accel_group: a #GtkAccelGroup
1084 * Associate @accel_group with @window, such that calling
1085 * gtk_accel_groups_activate() on @window will activate accelerators
1089 gtk_window_add_accel_group (GtkWindow *window,
1090 GtkAccelGroup *accel_group)
1092 g_return_if_fail (GTK_IS_WINDOW (window));
1093 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1095 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1096 g_signal_connect_object (accel_group, "accel_changed",
1097 G_CALLBACK (gtk_window_notify_keys_changed),
1098 window, G_CONNECT_SWAPPED);
1102 * gtk_window_remove_accel_group:
1103 * @window: a #GtkWindow
1104 * @accel_group: a #GtkAccelGroup
1106 * Reverses the effects of gtk_window_add_accel_group().
1109 gtk_window_remove_accel_group (GtkWindow *window,
1110 GtkAccelGroup *accel_group)
1112 g_return_if_fail (GTK_IS_WINDOW (window));
1113 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1115 g_signal_handlers_disconnect_by_func (accel_group,
1116 G_CALLBACK (gtk_window_notify_keys_changed),
1118 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1122 gtk_window_add_mnemonic (GtkWindow *window,
1126 GtkWindowMnemonic key;
1127 GtkWindowMnemonic *mnemonic;
1129 g_return_if_fail (GTK_IS_WINDOW (window));
1130 g_return_if_fail (GTK_IS_WIDGET (target));
1132 key.window = window;
1133 key.keyval = keyval;
1134 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1138 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1139 mnemonic->targets = g_slist_prepend (mnemonic->targets, target);
1143 mnemonic = g_new (GtkWindowMnemonic, 1);
1145 mnemonic->targets = g_slist_prepend (NULL, target);
1146 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1148 gtk_window_notify_keys_changed (window);
1152 gtk_window_remove_mnemonic (GtkWindow *window,
1156 GtkWindowMnemonic key;
1157 GtkWindowMnemonic *mnemonic;
1159 g_return_if_fail (GTK_IS_WINDOW (window));
1160 g_return_if_fail (GTK_IS_WIDGET (target));
1162 key.window = window;
1163 key.keyval = keyval;
1164 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1166 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1168 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1169 if (mnemonic->targets == NULL)
1171 g_hash_table_remove (mnemonic_hash_table, mnemonic);
1174 gtk_window_notify_keys_changed (window);
1178 gtk_window_mnemonic_activate (GtkWindow *window,
1180 GdkModifierType modifier)
1182 GtkWindowMnemonic key;
1183 GtkWindowMnemonic *mnemonic;
1185 GtkWidget *widget, *chosen_widget;
1186 gboolean overloaded;
1188 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1190 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1193 key.window = window;
1194 key.keyval = keyval;
1195 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1201 chosen_widget = NULL;
1202 list = mnemonic->targets;
1205 widget = GTK_WIDGET (list->data);
1207 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1208 GTK_WIDGET_MAPPED (widget))
1216 chosen_widget = widget;
1218 list = g_slist_next (list);
1223 /* For round robin we put the activated entry on
1224 * the end of the list after activation
1226 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1227 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1229 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1235 * gtk_window_set_mnemonic_modifier:
1236 * @window: a #GtkWindow
1237 * @modifier: the modifier mask used to activate
1238 * mnemonics on this window.
1240 * Sets the mnemonic modifier for this window.
1243 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1244 GdkModifierType modifier)
1246 g_return_if_fail (GTK_IS_WINDOW (window));
1247 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1249 window->mnemonic_modifier = modifier;
1250 gtk_window_notify_keys_changed (window);
1254 * gtk_window_get_mnemonic_modifier:
1255 * @window: a #GtkWindow
1257 * Returns the mnemonic modifier for this window. See
1258 * gtk_window_set_mnemonic_modifier().
1260 * Return value: the modifier mask used to activate
1261 * mnemonics on this window.
1264 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1266 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1268 return window->mnemonic_modifier;
1272 * gtk_window_set_position:
1273 * @window: a #GtkWindow.
1274 * @position: a position constraint.
1276 * Sets a position constraint for this window. If the old or new
1277 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1278 * the window to be repositioned to satisfy the new constraint.
1281 gtk_window_set_position (GtkWindow *window,
1282 GtkWindowPosition position)
1284 g_return_if_fail (GTK_IS_WINDOW (window));
1286 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1287 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1289 GtkWindowGeometryInfo *info;
1291 info = gtk_window_get_geometry_info (window, TRUE);
1293 /* this flag causes us to re-request the CENTER_ALWAYS
1294 * constraint in gtk_window_move_resize(), see
1295 * comment in that function.
1297 info->position_constraints_changed = TRUE;
1299 gtk_widget_queue_resize (GTK_WIDGET (window));
1302 window->position = position;
1304 g_object_notify (G_OBJECT (window), "window_position");
1308 gtk_window_activate_focus (GtkWindow *window)
1310 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1312 if (window->focus_widget)
1314 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1315 gtk_widget_activate (window->focus_widget);
1323 * gtk_window_get_focus:
1324 * @window: a #GtkWindow
1326 * Retrieves the current focused widget within the window.
1327 * Note that this is the widget that would have the focus
1328 * if the toplevel window focused; if the toplevel window
1329 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1330 * not be %TRUE for the widget.
1332 * Return value: the currently focused widget.
1335 gtk_window_get_focus (GtkWindow *window)
1337 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1339 return window->focus_widget;
1343 gtk_window_activate_default (GtkWindow *window)
1345 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1347 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1348 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1350 gtk_widget_activate (window->default_widget);
1353 else if (window->focus_widget)
1355 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1356 gtk_widget_activate (window->focus_widget);
1364 * gtk_window_set_modal:
1365 * @window: a #GtkWindow
1366 * @modal: whether the window is modal
1368 * Sets a window modal or non-modal. Modal windows prevent interaction
1369 * with other windows in the same application. To keep modal dialogs
1370 * on top of main application windows, use
1371 * gtk_window_set_transient_for() to make the dialog transient for the
1372 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1373 * will then disallow lowering the dialog below the parent.
1378 gtk_window_set_modal (GtkWindow *window,
1381 g_return_if_fail (GTK_IS_WINDOW (window));
1383 window->modal = modal != FALSE;
1385 /* adjust desired modality state */
1386 if (GTK_WIDGET_VISIBLE (window) && window->modal)
1387 gtk_grab_add (GTK_WIDGET (window));
1389 gtk_grab_remove (GTK_WIDGET (window));
1391 g_object_notify (G_OBJECT (window), "modal");
1395 * gtk_window_get_modal:
1396 * @window: a #GtkWindow
1398 * Returns whether the window is modal. See gtk_window_set_modal().
1400 * Return value: %TRUE if the window is set to be modal and
1401 * establishes a grab when shown
1404 gtk_window_get_modal (GtkWindow *window)
1406 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1408 return window->modal;
1412 * gtk_window_list_toplevels:
1414 * Returns a list of all existing toplevel windows. The widgets
1415 * in the list are not individually referenced. If you want
1416 * to iterate through the list and perform actions involving
1417 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1418 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1419 * then unref all the widgets afterwards.
1421 * Return value: list of toplevel widgets
1424 gtk_window_list_toplevels (void)
1429 for (slist = toplevel_list; slist; slist = slist->next)
1430 list = g_list_prepend (list, slist->data);
1436 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1438 GList *embedded_windows;
1440 g_return_if_fail (GTK_IS_WINDOW (window));
1442 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1443 if (embedded_windows)
1444 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1445 g_quark_from_static_string ("gtk-embedded"));
1446 embedded_windows = g_list_prepend (embedded_windows,
1447 GUINT_TO_POINTER (xid));
1449 gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
1452 (GtkDestroyNotify) g_list_free : NULL);
1456 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1458 GList *embedded_windows;
1461 g_return_if_fail (GTK_IS_WINDOW (window));
1463 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1464 if (embedded_windows)
1465 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1466 g_quark_from_static_string ("gtk-embedded"));
1468 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1471 embedded_windows = g_list_remove_link (embedded_windows, node);
1472 g_list_free_1 (node);
1475 gtk_object_set_data_full (GTK_OBJECT (window),
1476 "gtk-embedded", embedded_windows,
1478 (GtkDestroyNotify) g_list_free : NULL);
1482 _gtk_window_reposition (GtkWindow *window,
1486 g_return_if_fail (GTK_IS_WINDOW (window));
1488 gtk_window_move (window, x, y);
1492 gtk_window_dispose (GObject *object)
1494 GtkWindow *window = GTK_WINDOW (object);
1496 gtk_window_set_focus (window, NULL);
1497 gtk_window_set_default (window, NULL);
1499 G_OBJECT_CLASS (parent_class)->dispose (object);
1503 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1505 gtk_widget_destroy (GTK_WIDGET (child));
1509 connect_parent_destroyed (GtkWindow *window)
1511 if (window->transient_parent)
1513 gtk_signal_connect (GTK_OBJECT (window->transient_parent),
1515 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1521 disconnect_parent_destroyed (GtkWindow *window)
1523 if (window->transient_parent)
1525 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1526 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1532 gtk_window_transient_parent_realized (GtkWidget *parent,
1535 if (GTK_WIDGET_REALIZED (window))
1536 gdk_window_set_transient_for (window->window, parent->window);
1540 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1543 if (GTK_WIDGET_REALIZED (window))
1544 gdk_property_delete (window->window,
1545 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1549 gtk_window_unset_transient_for (GtkWindow *window)
1551 if (window->transient_parent)
1553 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1554 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1556 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1557 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1559 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1560 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1561 &window->transient_parent);
1563 if (window->destroy_with_parent)
1564 disconnect_parent_destroyed (window);
1566 window->transient_parent = NULL;
1571 * gtk_window_set_transient_for:
1572 * @window: a #GtkWindow
1573 * @parent: parent window
1575 * Dialog windows should be set transient for the main application
1576 * window they were spawned from. This allows <link
1577 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1578 * dialog on top of the main window, or center the dialog over the
1579 * main window. gtk_dialog_new_with_buttons() and other convenience
1580 * functions in GTK+ will sometimes call
1581 * gtk_window_set_transient_for() on your behalf.
1583 * On Windows, this function will and put the child window
1584 * on top of the parent, much as the window manager would have
1589 gtk_window_set_transient_for (GtkWindow *window,
1592 g_return_if_fail (GTK_IS_WINDOW (window));
1593 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1594 g_return_if_fail (window != parent);
1597 if (window->transient_parent)
1599 if (GTK_WIDGET_REALIZED (window) &&
1600 GTK_WIDGET_REALIZED (window->transient_parent) &&
1601 (!parent || !GTK_WIDGET_REALIZED (parent)))
1602 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1603 GTK_WIDGET (window));
1605 gtk_window_unset_transient_for (window);
1608 window->transient_parent = parent;
1612 gtk_signal_connect (GTK_OBJECT (parent), "destroy",
1613 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1614 &window->transient_parent);
1615 gtk_signal_connect (GTK_OBJECT (parent), "realize",
1616 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1618 gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
1619 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1622 if (window->destroy_with_parent)
1623 connect_parent_destroyed (window);
1625 if (GTK_WIDGET_REALIZED (window) &&
1626 GTK_WIDGET_REALIZED (parent))
1627 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1628 GTK_WIDGET (window));
1633 * gtk_window_get_transient_for:
1634 * @window: a #GtkWindow
1636 * Fetches the transient parent for this window. See
1637 * gtk_window_set_transient_for().
1639 * Return value: the transient parent for this window, or %NULL
1640 * if no transient parent has been set.
1643 gtk_window_get_transient_for (GtkWindow *window)
1645 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1647 return window->transient_parent;
1651 * gtk_window_set_type_hint:
1652 * @window: a #GtkWindow
1653 * @hint: the window type
1655 * By setting the type hint for the window, you allow the window
1656 * manager to decorate and handle the window in a way which is
1657 * suitable to the function of the window in your application.
1659 * This function should be called before the window becomes visible.
1661 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1662 * will sometimes call gtk_window_set_type_hint() on your behalf.
1666 gtk_window_set_type_hint (GtkWindow *window,
1667 GdkWindowTypeHint hint)
1669 g_return_if_fail (GTK_IS_WINDOW (window));
1670 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1671 window->type_hint = hint;
1675 * gtk_window_get_type_hint:
1676 * @window: a #GtkWindow
1678 * Gets the type hint for this window. See gtk_window_set_type_hint().
1680 * Return value: the type hint for @window.
1683 gtk_window_get_type_hint (GtkWindow *window)
1685 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1687 return window->type_hint;
1691 * gtk_window_set_destroy_with_parent:
1692 * @window: a #GtkWindow
1693 * @setting: whether to destroy @window with its transient parent
1695 * If @setting is %TRUE, then destroying the transient parent of @window
1696 * will also destroy @window itself. This is useful for dialogs that
1697 * shouldn't persist beyond the lifetime of the main window they're
1698 * associated with, for example.
1701 gtk_window_set_destroy_with_parent (GtkWindow *window,
1704 g_return_if_fail (GTK_IS_WINDOW (window));
1706 if (window->destroy_with_parent == (setting != FALSE))
1709 if (window->destroy_with_parent)
1711 disconnect_parent_destroyed (window);
1715 connect_parent_destroyed (window);
1718 window->destroy_with_parent = setting;
1720 g_object_notify (G_OBJECT (window), "destroy_with_parent");
1724 * gtk_window_get_destroy_with_parent:
1725 * @window: a #GtkWindow
1727 * Returns whether the window will be destroyed with its transient parent. See
1728 * gtk_window_set_destroy_with_parent ().
1730 * Return value: %TRUE if the window will be destroyed with its transient parent.
1733 gtk_window_get_destroy_with_parent (GtkWindow *window)
1735 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1737 return window->destroy_with_parent;
1740 static GtkWindowGeometryInfo*
1741 gtk_window_get_geometry_info (GtkWindow *window,
1744 GtkWindowGeometryInfo *info;
1746 info = window->geometry_info;
1747 if (!info && create)
1749 info = g_new0 (GtkWindowGeometryInfo, 1);
1751 info->default_width = -1;
1752 info->default_height = -1;
1753 info->resize_width = -1;
1754 info->resize_height = -1;
1755 info->initial_x = 0;
1756 info->initial_y = 0;
1757 info->initial_pos_set = FALSE;
1758 info->position_constraints_changed = FALSE;
1759 info->last.configure_request.x = 0;
1760 info->last.configure_request.y = 0;
1761 info->last.configure_request.width = -1;
1762 info->last.configure_request.height = -1;
1763 info->widget = NULL;
1765 window->geometry_info = info;
1772 * gtk_window_set_geometry_hints:
1773 * @window: a #GtkWindow
1774 * @geometry_widget: widget the geometry hints will be applied to
1775 * @geometry: struct containing geometry information
1776 * @geom_mask: mask indicating which struct fields should be paid attention to
1778 * This function sets up hints about how a window can be resized by
1779 * the user. You can set a minimum and maximum size; allowed resize
1780 * increments (e.g. for xterm, you can only resize by the size of a
1781 * character); aspect ratios; and more. See the #GdkGeometry struct.
1785 gtk_window_set_geometry_hints (GtkWindow *window,
1786 GtkWidget *geometry_widget,
1787 GdkGeometry *geometry,
1788 GdkWindowHints geom_mask)
1790 GtkWindowGeometryInfo *info;
1792 g_return_if_fail (GTK_IS_WINDOW (window));
1793 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
1795 info = gtk_window_get_geometry_info (window, TRUE);
1798 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1799 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1802 info->widget = geometry_widget;
1804 gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
1805 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1809 info->geometry = *geometry;
1811 /* We store gravity in window->gravity not in the hints. */
1812 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
1814 if (geom_mask & GDK_HINT_WIN_GRAVITY)
1816 gtk_window_set_gravity (window, geometry->win_gravity);
1819 gtk_widget_queue_resize (GTK_WIDGET (window));
1823 * gtk_window_set_decorated:
1824 * @window: a #GtkWindow
1825 * @setting: %TRUE to decorate the window
1827 * By default, windows are decorated with a title bar, resize
1828 * controls, etc. Some <link linkend="gtk-X11-arch">window
1829 * managers</link> allow GTK+ to disable these decorations, creating a
1830 * borderless window. If you set the decorated property to %FALSE
1831 * using this function, GTK+ will do its best to convince the window
1832 * manager not to decorate the window.
1834 * On Windows, this function always works, since there's no window manager
1839 gtk_window_set_decorated (GtkWindow *window,
1842 g_return_if_fail (GTK_IS_WINDOW (window));
1844 setting = setting != FALSE;
1846 if (setting == window->decorated)
1849 window->decorated = setting;
1851 if (GTK_WIDGET (window)->window)
1853 if (window->decorated)
1854 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1857 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1863 * gtk_window_get_decorated:
1864 * @window: a #GtkWindow
1866 * Returns whether the window has been set to have decorations
1867 * such as a title bar via gtk_window_set_decorated().
1869 * Return value: %TRUE if the window has been set to have decorations
1872 gtk_window_get_decorated (GtkWindow *window)
1874 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
1876 return window->decorated;
1879 static GtkWindowIconInfo*
1880 get_icon_info (GtkWindow *window)
1882 return g_object_get_data (G_OBJECT (window),
1883 "gtk-window-icon-info");
1886 static GtkWindowIconInfo*
1887 ensure_icon_info (GtkWindow *window)
1889 GtkWindowIconInfo *info;
1891 info = get_icon_info (window);
1895 info = g_new0 (GtkWindowIconInfo, 1);
1896 g_object_set_data_full (G_OBJECT (window),
1897 "gtk-window-icon-info",
1906 get_pixmap_and_mask (GtkWindowIconInfo *parent_info,
1907 gboolean is_default_list,
1909 GdkPixmap **pmap_return,
1910 GdkBitmap **mask_return)
1912 GdkPixbuf *best_icon;
1916 *pmap_return = NULL;
1917 *mask_return = NULL;
1919 if (is_default_list &&
1920 default_icon_pixmap != NULL)
1922 /* Use shared icon pixmap (eventually will be stored on the
1925 if (default_icon_pixmap)
1926 g_object_ref (G_OBJECT (default_icon_pixmap));
1927 if (default_icon_mask)
1928 g_object_ref (G_OBJECT (default_icon_mask));
1930 *pmap_return = default_icon_pixmap;
1931 *mask_return = default_icon_mask;
1933 else if (parent_info && parent_info->icon_pixmap)
1935 if (parent_info->icon_pixmap)
1936 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1937 if (parent_info->icon_mask)
1938 g_object_ref (G_OBJECT (parent_info->icon_mask));
1940 *pmap_return = parent_info->icon_pixmap;
1941 *mask_return = parent_info->icon_mask;
1945 #define IDEAL_SIZE 48
1947 best_size = G_MAXINT;
1949 tmp_list = icon_list;
1950 while (tmp_list != NULL)
1952 GdkPixbuf *pixbuf = tmp_list->data;
1955 /* average width and height - if someone passes in a rectangular
1956 * icon they deserve what they get.
1958 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
1961 if (best_icon == NULL)
1968 /* icon is better if it's 32 pixels or larger, and closer to
1969 * the ideal size than the current best.
1972 (ABS (best_size - IDEAL_SIZE) <
1973 ABS (this - IDEAL_SIZE)))
1980 tmp_list = tmp_list->next;
1984 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
1985 gdk_colormap_get_system (),
1990 /* Save pmap/mask for others to use if appropriate */
1993 parent_info->icon_pixmap = *pmap_return;
1994 parent_info->icon_mask = *mask_return;
1996 if (parent_info->icon_pixmap)
1997 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
1998 if (parent_info->icon_mask)
1999 g_object_ref (G_OBJECT (parent_info->icon_mask));
2001 else if (is_default_list)
2003 default_icon_pixmap = *pmap_return;
2004 default_icon_mask = *mask_return;
2006 if (default_icon_pixmap)
2007 g_object_add_weak_pointer (G_OBJECT (default_icon_pixmap),
2008 (gpointer*)&default_icon_pixmap);
2009 if (default_icon_mask)
2010 g_object_add_weak_pointer (G_OBJECT (default_icon_mask),
2011 (gpointer*)&default_icon_mask);
2017 gtk_window_realize_icon (GtkWindow *window)
2020 GtkWindowIconInfo *info;
2023 widget = GTK_WIDGET (window);
2025 g_return_if_fail (widget->window != NULL);
2027 /* no point setting an icon on override-redirect */
2028 if (window->type == GTK_WINDOW_POPUP)
2033 info = ensure_icon_info (window);
2038 g_return_if_fail (info->icon_pixmap == NULL);
2039 g_return_if_fail (info->icon_mask == NULL);
2041 info->using_default_icon = FALSE;
2042 info->using_parent_icon = FALSE;
2044 icon_list = info->icon_list;
2046 /* Inherit from transient parent */
2047 if (icon_list == NULL && window->transient_parent)
2049 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2051 info->using_parent_icon = TRUE;
2054 /* Inherit from default */
2055 if (icon_list == NULL)
2057 icon_list = default_icon_list;
2059 info->using_default_icon = TRUE;
2062 gdk_window_set_icon_list (widget->window, icon_list);
2064 get_pixmap_and_mask (info->using_parent_icon ?
2065 ensure_icon_info (window->transient_parent) : NULL,
2066 info->using_default_icon,
2071 /* This is a slight ICCCM violation since it's a color pixmap not
2072 * a bitmap, but everyone does it.
2074 gdk_window_set_icon (widget->window,
2079 info->realized = TRUE;
2083 gtk_window_unrealize_icon (GtkWindow *window)
2085 GtkWindowIconInfo *info;
2088 widget = GTK_WIDGET (window);
2090 info = get_icon_info (window);
2095 if (info->icon_pixmap)
2096 g_object_unref (G_OBJECT (info->icon_pixmap));
2098 if (info->icon_mask)
2099 g_object_unref (G_OBJECT (info->icon_mask));
2101 info->icon_pixmap = NULL;
2102 info->icon_mask = NULL;
2104 /* We don't clear the properties on the window, just figure the
2105 * window is going away.
2108 info->realized = FALSE;
2112 * gtk_window_set_icon_list:
2113 * @window: a #GtkWindow
2114 * @list: list of #GdkPixbuf
2116 * Sets up the icon representing a #GtkWindow. The icon is used when
2117 * the window is minimized (also known as iconified). Some window
2118 * managers or desktop environments may also place it in the window
2119 * frame, or display it in other contexts.
2121 * gtk_window_set_icon_list() allows you to pass in the same icon in
2122 * several hand-drawn sizes. The list should contain the natural sizes
2123 * your icon is available in; that is, don't scale the image before
2124 * passing it to GTK+. Scaling is postponed until the last minute,
2125 * when the desired final size is known, to allow best quality.
2127 * By passing several sizes, you may improve the final image quality
2128 * of the icon, by reducing or eliminating automatic image scaling.
2130 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2131 * larger images (64x64, 128x128) if you have them.
2133 * See also gtk_window_set_default_icon_list() to set the icon
2134 * for all windows in your application in one go.
2136 * Note that transient windows (those who have been set transient for another
2137 * window using gtk_window_set_transient_for()) will inherit their
2138 * icon from their transient parent. So there's no need to explicitly
2139 * set the icon on transient windows.
2142 gtk_window_set_icon_list (GtkWindow *window,
2145 GtkWindowIconInfo *info;
2147 g_return_if_fail (GTK_IS_WINDOW (window));
2149 info = ensure_icon_info (window);
2151 if (info->icon_list == list) /* check for NULL mostly */
2154 g_list_foreach (info->icon_list,
2155 (GFunc) g_object_unref, NULL);
2157 g_list_free (info->icon_list);
2159 info->icon_list = g_list_copy (list);
2160 g_list_foreach (info->icon_list,
2161 (GFunc) g_object_ref, NULL);
2163 g_object_notify (G_OBJECT (window), "icon");
2165 gtk_window_unrealize_icon (window);
2167 if (GTK_WIDGET_REALIZED (window))
2168 gtk_window_realize_icon (window);
2170 /* We could try to update our transient children, but I don't think
2171 * it's really worth it. If we did it, the best way would probably
2172 * be to have children connect to notify::icon_list
2177 * gtk_window_get_icon_list:
2178 * @window: a #GtkWindow
2180 * Retrieves the list of icons set by gtk_window_set_icon_list().
2181 * The list is copied, but the reference count on each
2182 * member won't be incremented.
2184 * Return value: copy of window's icon list
2187 gtk_window_get_icon_list (GtkWindow *window)
2189 GtkWindowIconInfo *info;
2191 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2193 info = get_icon_info (window);
2196 return g_list_copy (info->icon_list);
2202 * gtk_window_set_icon:
2203 * @window: a #GtkWindow
2204 * @icon: icon image, or %NULL
2206 * Sets up the icon representing a #GtkWindow. This icon is used when
2207 * the window is minimized (also known as iconified). Some window
2208 * managers or desktop environments may also place it in the window
2209 * frame, or display it in other contexts.
2211 * The icon should be provided in whatever size it was naturally
2212 * drawn; that is, don't scale the image before passing it to
2213 * GTK+. Scaling is postponed until the last minute, when the desired
2214 * final size is known, to allow best quality.
2216 * If you have your icon hand-drawn in multiple sizes, use
2217 * gtk_window_set_icon_list(). Then the best size will be used.
2219 * This function is equivalent to calling gtk_window_set_icon_list()
2220 * with a 1-element list.
2222 * See also gtk_window_set_default_icon_list() to set the icon
2223 * for all windows in your application in one go.
2226 gtk_window_set_icon (GtkWindow *window,
2231 g_return_if_fail (GTK_IS_WINDOW (window));
2232 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2235 list = g_list_append (list, icon);
2236 gtk_window_set_icon_list (window, list);
2241 * gtk_window_get_icon:
2242 * @window: a #GtkWindow
2244 * Gets the value set by gtk_window_set_icon() (or if you've
2245 * called gtk_window_set_icon_list(), gets the first icon in
2248 * Return value: icon for window
2251 gtk_window_get_icon (GtkWindow *window)
2253 GtkWindowIconInfo *info;
2255 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2257 info = get_icon_info (window);
2258 if (info && info->icon_list)
2259 return GDK_PIXBUF (info->icon_list->data);
2265 * gtk_window_set_default_icon_list:
2266 * @list: a list of #GdkPixbuf
2268 * Sets an icon list to be used as fallback for windows that haven't
2269 * had gtk_window_set_icon_list() called on them to set up a
2270 * window-specific icon list. This function allows you to set up the
2271 * icon for all windows in your app at once.
2273 * See gtk_window_set_icon_list() for more details.
2277 gtk_window_set_default_icon_list (GList *list)
2281 if (list == default_icon_list)
2284 if (default_icon_pixmap)
2285 g_object_unref (G_OBJECT (default_icon_pixmap));
2286 if (default_icon_mask)
2287 g_object_unref (G_OBJECT (default_icon_mask));
2289 default_icon_pixmap = NULL;
2290 default_icon_mask = NULL;
2292 g_list_foreach (default_icon_list,
2293 (GFunc) g_object_unref, NULL);
2295 g_list_free (default_icon_list);
2297 default_icon_list = g_list_copy (list);
2298 g_list_foreach (default_icon_list,
2299 (GFunc) g_object_ref, NULL);
2301 /* Update all toplevels */
2302 toplevels = gtk_window_list_toplevels ();
2303 tmp_list = toplevels;
2304 while (tmp_list != NULL)
2306 GtkWindowIconInfo *info;
2307 GtkWindow *w = tmp_list->data;
2309 info = get_icon_info (w);
2310 if (info && info->using_default_icon)
2312 gtk_window_unrealize_icon (w);
2313 if (GTK_WIDGET_REALIZED (w))
2314 gtk_window_realize_icon (w);
2317 tmp_list = tmp_list->next;
2319 g_list_free (toplevels);
2323 * gtk_window_get_default_icon_list:
2325 * Gets the value set by gtk_window_set_default_icon_list().
2326 * The list is a copy and should be freed with g_list_free(),
2327 * but the pixbufs in the list have not had their reference count
2330 * Return value: copy of default icon list
2333 gtk_window_get_default_icon_list (void)
2335 return g_list_copy (default_icon_list);
2339 gtk_window_set_default_size_internal (GtkWindow *window,
2340 gboolean change_width,
2342 gboolean change_height,
2345 GtkWindowGeometryInfo *info;
2347 g_return_if_fail (change_width == FALSE || width >= -1);
2348 g_return_if_fail (change_height == FALSE || height >= -1);
2350 info = gtk_window_get_geometry_info (window, TRUE);
2352 g_object_freeze_notify (G_OBJECT (window));
2362 info->default_width = width;
2364 g_object_notify (G_OBJECT (window), "default_width");
2375 info->default_height = height;
2377 g_object_notify (G_OBJECT (window), "default_height");
2380 g_object_thaw_notify (G_OBJECT (window));
2382 gtk_widget_queue_resize (GTK_WIDGET (window));
2386 * gtk_window_set_default_size:
2387 * @window: a #GtkWindow
2388 * @width: width in pixels, or -1 to unset the default width
2389 * @height: height in pixels, or -1 to unset the default height
2391 * Sets the default size of a window. If the window's "natural" size
2392 * (its size request) is larger than the default, the default will be
2393 * ignored. More generally, if the default size does not obey the
2394 * geometry hints for the window (gtk_window_set_geometry_hints() can
2395 * be used to set these explicitly), the default size will be clamped
2396 * to the nearest permitted size.
2398 * Unlike gtk_widget_set_size_request(), which sets a size request for
2399 * a widget and thus would keep users from shrinking the window, this
2400 * function only sets the initial size, just as if the user had
2401 * resized the window themselves. Users can still shrink the window
2402 * again as they normally would. Setting a default size of -1 means to
2403 * use the "natural" default size (the size request of the window).
2405 * For more control over a window's initial size and how resizing works,
2406 * investigate gtk_window_set_geometry_hints().
2408 * For some uses, gtk_window_resize() is a more appropriate function.
2409 * gtk_window_resize() changes the current size of the window, rather
2410 * than the size to be used on initial display. gtk_window_resize() always
2411 * affects the window itself, not the geometry widget.
2413 * The default size of a window only affects the first time a window is
2414 * shown; if a window is hidden and re-shown, it will remember the size
2415 * it had prior to hiding, rather than using the default size.
2417 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2418 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2421 gtk_window_set_default_size (GtkWindow *window,
2425 g_return_if_fail (GTK_IS_WINDOW (window));
2426 g_return_if_fail (width >= -1);
2427 g_return_if_fail (height >= -1);
2429 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height);
2433 * gtk_window_get_default_size:
2434 * @window: a #GtkWindow
2435 * @width: location to store the default width, or %NULL
2436 * @height: location to store the default height, or %NULL
2438 * Gets the default size of the window. A value of -1 for the width or
2439 * height indicates that a default size has not been explicitly set
2440 * for that dimension, so the "natural" size of the window will be
2445 gtk_window_get_default_size (GtkWindow *window,
2449 GtkWindowGeometryInfo *info;
2451 g_return_if_fail (GTK_IS_WINDOW (window));
2453 info = gtk_window_get_geometry_info (window, FALSE);
2456 *width = info->default_width;
2459 *height = info->default_height;
2463 * gtk_window_resize:
2464 * @window: a #GtkWindow
2465 * @width: width in pixels to resize the window to
2466 * @height: height in pixels to resize the window to
2468 * Resizes the window as if the user had done so, obeying geometry
2469 * constraints. The default geometry constraint is that windows may
2470 * not be smaller than their size request; to override this
2471 * constraint, call gtk_widget_set_size_request() to set the window's
2472 * request to a smaller value.
2474 * If gtk_window_resize() is called before showing a window for the
2475 * first time, it overrides any default size set with
2476 * gtk_window_set_default_size().
2478 * Windows may not be resized smaller than 1 by 1 pixels.
2482 gtk_window_resize (GtkWindow *window,
2486 GtkWindowGeometryInfo *info;
2488 g_return_if_fail (GTK_IS_WINDOW (window));
2489 g_return_if_fail (width > 0);
2490 g_return_if_fail (height > 0);
2492 info = gtk_window_get_geometry_info (window, TRUE);
2494 info->resize_width = width;
2495 info->resize_height = height;
2497 gtk_widget_queue_resize (GTK_WIDGET (window));
2501 * gtk_window_get_size:
2502 * @window: a #GtkWindow
2503 * @width: return location for width, or %NULL
2504 * @height: return location for height, or %NULL
2506 * Obtains the current size of @window. If @window is not onscreen,
2507 * it returns the size GTK+ will suggest to the <link
2508 * linkend="gtk-X11-arch">window manager</link> for the initial window
2509 * size (but this is not reliably the same as the size the window
2510 * manager will actually select). The size obtained by
2511 * gtk_window_get_size() is the last size received in a
2512 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2513 * rather than querying the X server for the size. As a result, if you
2514 * call gtk_window_resize() then immediately call
2515 * gtk_window_get_size(), the size won't have taken effect yet. After
2516 * the window manager processes the resize request, GTK+ receives
2517 * notification that the size has changed via a configure event, and
2518 * the size of the window gets updated.
2520 * Note 1: Nearly any use of this function creates a race condition,
2521 * because the size of the window may change between the time that you
2522 * get the size and the time that you perform some action assuming
2523 * that size is the current size. To avoid race conditions, connect to
2524 * "configure_event" on the window and adjust your size-dependent
2525 * state to match the size delivered in the #GdkEventConfigure.
2527 * Note 2: The returned size does <emphasis>not</emphasis> include the
2528 * size of the window manager decorations (aka the window frame or
2529 * border). Those are not drawn by GTK+ and GTK+ has no reliable
2530 * method of determining their size.
2532 * Note 3: If you are getting a window size in order to position
2533 * the window onscreen, there may be a better way. The preferred
2534 * way is to simply set the window's semantic type with
2535 * gtk_window_set_type_hint(), which allows the window manager to
2536 * e.g. center dialogs. Also, if you set the transient parent of
2537 * dialogs with gtk_window_set_transient_for() window managers
2538 * will often center the dialog over its parent window. It's
2539 * much preferred to let the window manager handle these
2540 * things rather than doing it yourself, because all apps will
2541 * behave consistently and according to user prefs if the window
2542 * manager handles it. Also, the window manager can take the size
2543 * of the window decorations/border into account, while your
2544 * application cannot.
2546 * In any case, if you insist on application-specified window
2547 * positioning, there's <emphasis>still</emphasis> a better way than
2548 * doing it yourself - gtk_window_set_position() will frequently
2549 * handle the details for you.
2553 gtk_window_get_size (GtkWindow *window,
2560 g_return_if_fail (GTK_IS_WINDOW (window));
2562 widget = GTK_WIDGET (window);
2564 if (width == NULL && height == NULL)
2567 if (GTK_WIDGET_MAPPED (window))
2569 gdk_drawable_get_size (GTK_WIDGET (window)->window,
2574 GdkRectangle configure_request;
2576 gtk_window_compute_configure_request (window,
2580 w = configure_request.width;
2581 h = configure_request.height;
2592 * @window: a #GtkWindow
2593 * @x: X coordinate to move window to
2594 * @y: Y coordinate to move window to
2596 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
2597 * @window to the given position. Window managers are free to ignore
2598 * this; most window managers ignore requests for initial window
2599 * positions (instead using a user-defined placement algorithm) and
2600 * honor requests after the window has already been shown.
2602 * Note: the position is the position of the gravity-determined
2603 * reference point for the window. The gravity determines two things:
2604 * first, the location of the reference point in root window
2605 * coordinates; and second, which point on the window is positioned at
2606 * the reference point.
2608 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
2609 * point is simply the @x, @y supplied to gtk_window_move(). The
2610 * top-left corner of the window decorations (aka window frame or
2611 * border) will be placed at @x, @y. Therefore, to position a window
2612 * at the top left of the screen, you want to use the default gravity
2613 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
2615 * To position a window at the bottom right corner of the screen, you
2616 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
2617 * point is at @x + the window width and @y + the window height, and
2618 * the bottom-right corner of the window border will be placed at that
2619 * reference point. So, to place a window in the bottom right corner
2620 * you would first set gravity to south east, then write:
2621 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
2622 * gdk_screen_height () - window_height)</literal>.
2624 * The extended window manager hints specification at <ulink
2625 * url="http://www.freedesktop.org/standards/wm-spec.html"
2626 * >http://www.freedesktop.org/standards/wm-spec.html</ulink> has a
2627 * nice table of gravities in the "implementation notes" section.
2629 * The gtk_window_get_position() documentation may also be relevant.
2633 gtk_window_move (GtkWindow *window,
2637 GtkWindowGeometryInfo *info;
2640 g_return_if_fail (GTK_IS_WINDOW (window));
2642 widget = GTK_WIDGET (window);
2644 info = gtk_window_get_geometry_info (window, TRUE);
2646 if (GTK_WIDGET_MAPPED (window))
2648 /* we have now sent a request with this position
2649 * with currently-active constraints, so toggle flag.
2651 info->position_constraints_changed = FALSE;
2653 /* we only constrain if mapped - if not mapped,
2654 * then gtk_window_compute_configure_request()
2655 * will apply the constraints later, and we
2656 * don't want to lose information about
2657 * what position the user set before then.
2658 * i.e. if you do a move() then turn off POS_CENTER
2659 * then show the window, your move() will work.
2661 gtk_window_constrain_position (window,
2662 widget->allocation.width,
2663 widget->allocation.height,
2666 /* Note that this request doesn't go through our standard request
2667 * framework, e.g. doesn't increment configure_request_count,
2668 * doesn't set info->last, etc.; that's because
2669 * we don't save the info needed to arrive at this same request
2672 * To gtk_window_move_resize(), this will end up looking exactly
2673 * the same as the position being changed by the window
2677 /* FIXME are we handling gravity properly for framed windows? */
2679 gdk_window_move (window->frame,
2680 x - window->frame_left,
2681 y - window->frame_top);
2683 gdk_window_move (GTK_WIDGET (window)->window,
2688 /* Save this position to apply on mapping */
2689 info->initial_x = x;
2690 info->initial_y = y;
2691 info->initial_pos_set = TRUE;
2696 * gtk_window_get_position:
2697 * @window: a #GtkWindow
2698 * @root_x: return location for X coordinate of gravity-determined reference p\oint
2699 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
2701 * This function returns the position you need to pass to
2702 * gtk_window_move() to keep @window in its current position. This
2703 * means that the meaning of the returned value varies with window
2704 * gravity. See gtk_window_move() for more details.
2706 * If you haven't changed the window gravity, its gravity will be
2707 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
2708 * gets the position of the top-left corner of the window manager
2709 * frame for the window. gtk_window_move() sets the position of this
2710 * same top-left corner.
2712 * gtk_window_get_position() is not 100% reliable because the X Window System
2713 * does not specify a way to obtain the geometry of the
2714 * decorations placed on a window by the window manager.
2715 * Thus GTK+ is using a "best guess" that works with most
2718 * Moreover, nearly all window managers are historically broken with
2719 * respect to their handling of window gravity. So moving a window to
2720 * its current position as returned by gtk_window_get_position() tends
2721 * to result in moving the window slightly. Window managers are
2722 * slowly getting better over time.
2724 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
2725 * frame is not relevant, and thus gtk_window_get_position() will
2726 * always produce accurate results. However you can't use static
2727 * gravity to do things like place a window in a corner of the screen,
2728 * because static gravity ignores the window manager decorations.
2730 * If you are saving and restoring your application's window
2731 * positions, you should know that it's impossible for applications to
2732 * do this without getting it somewhat wrong because applications do
2733 * not have sufficient knowledge of window manager state. The Correct
2734 * Mechanism is to support the session management protocol (see the
2735 * "GnomeClient" object in the GNOME libraries for example) and allow
2736 * the window manager to save your window sizes and positions.
2741 gtk_window_get_position (GtkWindow *window,
2747 g_return_if_fail (GTK_IS_WINDOW (window));
2749 widget = GTK_WIDGET (window);
2751 if (window->gravity == GDK_GRAVITY_STATIC)
2753 if (GTK_WIDGET_MAPPED (widget))
2755 /* This does a server round-trip, which is sort of wrong;
2756 * but a server round-trip is inevitable for
2757 * gdk_window_get_frame_extents() in the usual
2758 * NorthWestGravity case below, so not sure what else to
2759 * do. We should likely be consistent about whether we get
2760 * the client-side info or the server-side info.
2762 gdk_window_get_origin (widget->window, root_x, root_y);
2766 GdkRectangle configure_request;
2768 gtk_window_compute_configure_request (window,
2772 *root_x = configure_request.x;
2773 *root_y = configure_request.y;
2778 GdkRectangle frame_extents;
2783 if (GTK_WIDGET_MAPPED (widget))
2786 gdk_window_get_frame_extents (window->frame, &frame_extents);
2788 gdk_window_get_frame_extents (widget->window, &frame_extents);
2789 x = frame_extents.x;
2790 y = frame_extents.y;
2791 gtk_window_get_size (window, &w, &h);
2795 /* We just say the frame has 0 size on all sides.
2796 * Not sure what else to do.
2798 gtk_window_compute_configure_request (window,
2801 x = frame_extents.x;
2802 y = frame_extents.y;
2803 w = frame_extents.width;
2804 h = frame_extents.height;
2807 switch (window->gravity)
2809 case GDK_GRAVITY_NORTH:
2810 case GDK_GRAVITY_CENTER:
2811 case GDK_GRAVITY_SOUTH:
2812 /* Find center of frame. */
2813 x += frame_extents.width / 2;
2814 /* Center client window on that point. */
2818 case GDK_GRAVITY_SOUTH_EAST:
2819 case GDK_GRAVITY_EAST:
2820 case GDK_GRAVITY_NORTH_EAST:
2821 /* Find right edge of frame */
2822 x += frame_extents.width;
2823 /* Align left edge of client at that point. */
2830 switch (window->gravity)
2832 case GDK_GRAVITY_WEST:
2833 case GDK_GRAVITY_CENTER:
2834 case GDK_GRAVITY_EAST:
2835 /* Find center of frame. */
2836 y += frame_extents.height / 2;
2837 /* Center client window there. */
2840 case GDK_GRAVITY_SOUTH_WEST:
2841 case GDK_GRAVITY_SOUTH:
2842 case GDK_GRAVITY_SOUTH_EAST:
2843 /* Find south edge of frame */
2844 y += frame_extents.height;
2845 /* Place bottom edge of client there */
2860 * gtk_window_reshow_with_initial_size:
2861 * @window: a #GtkWindow
2863 * Hides @window, then reshows it, resetting the
2864 * default size and position of the window. Used
2865 * by GUI builders only.
2868 gtk_window_reshow_with_initial_size (GtkWindow *window)
2872 g_return_if_fail (GTK_IS_WINDOW (window));
2874 widget = GTK_WIDGET (window);
2876 gtk_widget_hide (widget);
2877 gtk_widget_unrealize (widget);
2878 gtk_widget_show (widget);
2882 gtk_window_destroy (GtkObject *object)
2884 GtkWindow *window = GTK_WINDOW (object);
2886 if (window->transient_parent)
2887 gtk_window_set_transient_for (window, NULL);
2889 /* frees the icons */
2890 gtk_window_set_icon_list (window, NULL);
2892 if (window->has_user_ref_count)
2894 window->has_user_ref_count = FALSE;
2895 gtk_widget_unref (GTK_WIDGET (window));
2899 gtk_window_group_remove_window (window->group, window);
2901 gtk_window_free_key_hash (window);
2903 GTK_OBJECT_CLASS (parent_class)->destroy (object);
2907 gtk_window_mnemonic_hash_remove (gpointer key,
2911 GtkWindowMnemonic *mnemonic = key;
2912 GtkWindow *window = user;
2914 if (mnemonic->window == window)
2916 if (mnemonic->targets)
2918 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
2920 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
2921 name, mnemonic->targets->data);
2924 g_slist_free (mnemonic->targets);
2933 gtk_window_finalize (GObject *object)
2935 GtkWindow *window = GTK_WINDOW (object);
2937 toplevel_list = g_slist_remove (toplevel_list, window);
2939 g_free (window->title);
2940 g_free (window->wmclass_name);
2941 g_free (window->wmclass_class);
2942 g_free (window->wm_role);
2944 g_hash_table_foreach_remove (mnemonic_hash_table,
2945 gtk_window_mnemonic_hash_remove,
2947 if (window->geometry_info)
2949 if (window->geometry_info->widget)
2950 gtk_signal_disconnect_by_func (GTK_OBJECT (window->geometry_info->widget),
2951 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
2952 &window->geometry_info->widget);
2953 g_free (window->geometry_info);
2956 if (window->keys_changed_handler)
2958 gtk_idle_remove (window->keys_changed_handler);
2959 window->keys_changed_handler = 0;
2962 G_OBJECT_CLASS (parent_class)->finalize (object);
2966 gtk_window_show (GtkWidget *widget)
2968 GtkWindow *window = GTK_WINDOW (widget);
2969 GtkContainer *container = GTK_CONTAINER (window);
2970 gboolean need_resize;
2972 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
2974 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
2975 container->need_resize = FALSE;
2979 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
2980 GtkAllocation allocation = { 0, 0 };
2981 GdkRectangle configure_request;
2982 GdkGeometry new_geometry;
2984 gboolean was_realized;
2986 /* We are going to go ahead and perform this configure request
2987 * and then emulate a configure notify by going ahead and
2988 * doing a size allocate. Sort of a synchronous
2989 * mini-copy of gtk_window_move_resize() here.
2991 gtk_window_compute_configure_request (window,
2996 /* We update this because we are going to go ahead
2997 * and gdk_window_resize() below, rather than
3000 info->last.configure_request.width = configure_request.width;
3001 info->last.configure_request.height = configure_request.height;
3003 /* and allocate the window - this is normally done
3004 * in move_resize in response to configure notify
3006 allocation.width = configure_request.width;
3007 allocation.height = configure_request.height;
3008 gtk_widget_size_allocate (widget, &allocation);
3010 /* Then we guarantee we have a realize */
3011 was_realized = FALSE;
3012 if (!GTK_WIDGET_REALIZED (widget))
3014 gtk_widget_realize (widget);
3015 was_realized = TRUE;
3018 /* Must be done after the windows are realized,
3019 * so that the decorations can be read
3021 gtk_decorated_window_calculate_frame_size (window);
3023 /* We only send configure request if we didn't just finish
3024 * creating the window; if we just created the window
3025 * then we created it with widget->allocation anyhow.
3028 gdk_window_resize (widget->window,
3029 configure_request.width,
3030 configure_request.height);
3033 gtk_container_check_resize (container);
3035 gtk_widget_map (widget);
3037 /* Try to make sure that we have some focused widget
3039 if (!window->focus_widget)
3040 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
3043 gtk_grab_add (widget);
3047 gtk_window_hide (GtkWidget *widget)
3049 GtkWindow *window = GTK_WINDOW (widget);
3051 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3052 gtk_widget_unmap (widget);
3055 gtk_grab_remove (widget);
3059 gtk_window_map (GtkWidget *widget)
3061 GtkWindow *window = GTK_WINDOW (widget);
3062 GdkWindow *toplevel;
3064 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3066 if (window->bin.child &&
3067 GTK_WIDGET_VISIBLE (window->bin.child) &&
3068 !GTK_WIDGET_MAPPED (window->bin.child))
3069 gtk_widget_map (window->bin.child);
3072 toplevel = window->frame;
3074 toplevel = widget->window;
3076 if (window->maximize_initially)
3077 gdk_window_maximize (toplevel);
3079 gdk_window_unmaximize (toplevel);
3081 if (window->stick_initially)
3082 gdk_window_stick (toplevel);
3084 gdk_window_unstick (toplevel);
3086 if (window->iconify_initially)
3087 gdk_window_iconify (toplevel);
3089 gdk_window_deiconify (toplevel);
3091 /* No longer use the default settings */
3092 window->need_default_size = FALSE;
3093 window->need_default_position = FALSE;
3095 gdk_window_show (widget->window);
3098 gdk_window_show (window->frame);
3102 gtk_window_unmap (GtkWidget *widget)
3104 GtkWindow *window = GTK_WINDOW (widget);
3105 GtkWindowGeometryInfo *info;
3107 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3109 gdk_window_withdraw (window->frame);
3111 gdk_window_withdraw (widget->window);
3113 window->configure_request_count = 0;
3114 window->configure_notify_received = FALSE;
3116 /* on unmap, we reset the default positioning of the window,
3117 * so it's placed again, but we don't reset the default
3118 * size of the window, so it's remembered.
3120 window->need_default_position = TRUE;
3122 info = gtk_window_get_geometry_info (window, FALSE);
3125 info->initial_pos_set = FALSE;
3126 info->position_constraints_changed = FALSE;
3131 gtk_window_realize (GtkWidget *widget)
3134 GdkWindow *parent_window;
3135 GdkWindowAttr attributes;
3136 gint attributes_mask;
3138 window = GTK_WINDOW (widget);
3140 /* ensure widget tree is properly size allocated */
3141 if (widget->allocation.x == -1 &&
3142 widget->allocation.y == -1 &&
3143 widget->allocation.width == 1 &&
3144 widget->allocation.height == 1)
3146 GtkRequisition requisition;
3147 GtkAllocation allocation = { 0, 0, 200, 200 };
3149 gtk_widget_size_request (widget, &requisition);
3150 if (requisition.width || requisition.height)
3152 /* non-empty window */
3153 allocation.width = requisition.width;
3154 allocation.height = requisition.height;
3156 gtk_widget_size_allocate (widget, &allocation);
3158 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3160 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3163 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3165 switch (window->type)
3167 case GTK_WINDOW_TOPLEVEL:
3168 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3170 case GTK_WINDOW_POPUP:
3171 attributes.window_type = GDK_WINDOW_TEMP;
3174 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3178 attributes.title = window->title;
3179 attributes.wmclass_name = window->wmclass_name;
3180 attributes.wmclass_class = window->wmclass_class;
3181 attributes.wclass = GDK_INPUT_OUTPUT;
3182 attributes.visual = gtk_widget_get_visual (widget);
3183 attributes.colormap = gtk_widget_get_colormap (widget);
3185 if (window->has_frame)
3187 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3188 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3189 attributes.event_mask = (GDK_EXPOSURE_MASK |
3190 GDK_KEY_PRESS_MASK |
3191 GDK_ENTER_NOTIFY_MASK |
3192 GDK_LEAVE_NOTIFY_MASK |
3193 GDK_FOCUS_CHANGE_MASK |
3194 GDK_STRUCTURE_MASK |
3195 GDK_BUTTON_MOTION_MASK |
3196 GDK_POINTER_MOTION_HINT_MASK |
3197 GDK_BUTTON_PRESS_MASK |
3198 GDK_BUTTON_RELEASE_MASK);
3200 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3202 window->frame = gdk_window_new (NULL, &attributes, attributes_mask);
3203 gdk_window_set_user_data (window->frame, widget);
3205 attributes.window_type = GDK_WINDOW_CHILD;
3206 attributes.x = window->frame_left;
3207 attributes.y = window->frame_right;
3209 attributes_mask = GDK_WA_X | GDK_WA_Y;
3211 parent_window = window->frame;
3215 attributes_mask = 0;
3216 parent_window = NULL;
3219 attributes.width = widget->allocation.width;
3220 attributes.height = widget->allocation.height;
3221 attributes.event_mask = gtk_widget_get_events (widget);
3222 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3223 GDK_KEY_PRESS_MASK |
3224 GDK_KEY_RELEASE_MASK |
3225 GDK_ENTER_NOTIFY_MASK |
3226 GDK_LEAVE_NOTIFY_MASK |
3227 GDK_FOCUS_CHANGE_MASK |
3228 GDK_STRUCTURE_MASK);
3230 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3231 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3232 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3233 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3234 gdk_window_set_user_data (widget->window, window);
3236 widget->style = gtk_style_attach (widget->style, widget->window);
3237 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3239 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3241 /* This is a bad hack to set the window background. */
3242 gtk_window_paint (widget, NULL);
3244 if (window->transient_parent &&
3245 GTK_WIDGET_REALIZED (window->transient_parent))
3246 gdk_window_set_transient_for (widget->window,
3247 GTK_WIDGET (window->transient_parent)->window);
3249 if (window->wm_role)
3250 gdk_window_set_role (widget->window, window->wm_role);
3252 if (!window->decorated)
3253 gdk_window_set_decorations (widget->window, 0);
3255 gdk_window_set_type_hint (widget->window, window->type_hint);
3257 /* transient_for must be set to allow the modal hint */
3258 if (window->transient_parent && window->modal)
3259 gdk_window_set_modal_hint (widget->window, TRUE);
3261 gdk_window_set_modal_hint (widget->window, FALSE);
3264 gtk_window_realize_icon (window);
3268 gtk_window_unrealize (GtkWidget *widget)
3271 GtkWindowGeometryInfo *info;
3273 window = GTK_WINDOW (widget);
3275 /* On unrealize, we reset the size of the window such
3276 * that we will re-apply the default sizing stuff
3277 * next time we show the window.
3279 * Default positioning is reset on unmap, instead of unrealize.
3281 window->need_default_size = TRUE;
3282 info = gtk_window_get_geometry_info (window, FALSE);
3285 info->resize_width = -1;
3286 info->resize_height = -1;
3287 info->last.configure_request.x = 0;
3288 info->last.configure_request.y = 0;
3289 info->last.configure_request.width = -1;
3290 info->last.configure_request.height = -1;
3291 /* be sure we reset geom hints on re-realize */
3292 info->last.flags = 0;
3297 gdk_window_set_user_data (window->frame, NULL);
3298 gdk_window_destroy (window->frame);
3299 window->frame = NULL;
3303 gtk_window_unrealize_icon (window);
3305 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3309 gtk_window_size_request (GtkWidget *widget,
3310 GtkRequisition *requisition)
3315 window = GTK_WINDOW (widget);
3316 bin = GTK_BIN (window);
3318 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3319 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3321 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3323 GtkRequisition child_requisition;
3325 gtk_widget_size_request (bin->child, &child_requisition);
3327 requisition->width += child_requisition.width;
3328 requisition->height += child_requisition.height;
3333 gtk_window_size_allocate (GtkWidget *widget,
3334 GtkAllocation *allocation)
3337 GtkAllocation child_allocation;
3339 window = GTK_WINDOW (widget);
3340 widget->allocation = *allocation;
3342 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3344 child_allocation.x = GTK_CONTAINER (window)->border_width;
3345 child_allocation.y = GTK_CONTAINER (window)->border_width;
3346 child_allocation.width =
3347 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3348 child_allocation.height =
3349 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3351 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3354 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3356 gdk_window_resize (window->frame,
3357 allocation->width + window->frame_left + window->frame_right,
3358 allocation->height + window->frame_top + window->frame_bottom);
3363 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3366 gboolean return_val;
3368 window = GTK_WINDOW (widget);
3370 if (window->frame && (event->any.window == window->frame))
3372 if ((event->type != GDK_KEY_PRESS) &&
3373 (event->type != GDK_KEY_RELEASE) &&
3374 (event->type != GDK_FOCUS_CHANGE))
3376 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
3378 gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
3383 g_object_unref (event->any.window);
3384 event->any.window = g_object_ref (widget->window);
3392 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3394 GdkEventConfigure *configure_event;
3397 switch (event->type)
3400 configure_event = (GdkEventConfigure *)event;
3402 /* Invalidate the decorations */
3405 rect.width = configure_event->width;
3406 rect.height = configure_event->height;
3408 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3410 /* Pass on the (modified) configure event */
3411 configure_event->width -= window->frame_left + window->frame_right;
3412 configure_event->height -= window->frame_top + window->frame_bottom;
3413 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3422 gtk_window_configure_event (GtkWidget *widget,
3423 GdkEventConfigure *event)
3425 GtkWindow *window = GTK_WINDOW (widget);
3427 /* window->configure_request_count incremented for each
3428 * configure request, and decremented to a min of 0 for
3429 * each configure notify.
3431 * All it means is that we know we will get at least
3432 * window->configure_request_count more configure notifies.
3433 * We could get more configure notifies than that; some
3434 * of the configure notifies we get may be unrelated to
3435 * the configure requests. But we will get at least
3436 * window->configure_request_count notifies.
3439 if (window->configure_request_count > 0)
3440 window->configure_request_count -= 1;
3442 /* As an optimization, we avoid a resize when possible.
3444 * The only times we can avoid a resize are:
3445 * - we know only the position changed, not the size
3446 * - we know we have made more requests and so will get more
3447 * notifies and can wait to resize when we get them
3450 if (window->configure_request_count > 0 ||
3451 (widget->allocation.width == event->width &&
3452 widget->allocation.height == event->height))
3456 * If we do need to resize, we do that by:
3457 * - filling in widget->allocation with the new size
3458 * - setting configure_notify_received to TRUE
3459 * for use in gtk_window_move_resize()
3460 * - queueing a resize, leading to invocation of
3461 * gtk_window_move_resize() in an idle handler
3465 window->configure_notify_received = TRUE;
3467 widget->allocation.width = event->width;
3468 widget->allocation.height = event->height;
3470 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3475 /* the accel_key and accel_mods fields of the key have to be setup
3476 * upon calling this function. it'll then return whether that key
3477 * is at all used as accelerator, and if so will OR in the
3478 * accel_flags member of the key.
3481 _gtk_window_query_nonaccels (GtkWindow *window,
3483 GdkModifierType accel_mods)
3485 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3487 /* movement keys are considered locked accels */
3490 static const guint bindings[] = {
3491 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
3492 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
3496 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
3497 if (bindings[i] == accel_key)
3501 /* mnemonics are considered locked accels */
3502 if (accel_mods == window->mnemonic_modifier)
3504 GtkWindowMnemonic mkey;
3506 mkey.window = window;
3507 mkey.keyval = accel_key;
3508 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
3516 gtk_window_key_press_event (GtkWidget *widget,
3523 window = GTK_WINDOW (widget);
3527 /* Check for mnemonics and accelerators
3530 handled = _gtk_window_activate_key (window, event);
3534 focus = window->focus_widget;
3536 g_object_ref (focus);
3539 focus && focus != widget &&
3540 gtk_widget_get_toplevel (focus) == widget)
3544 if (GTK_WIDGET_IS_SENSITIVE (focus))
3545 handled = gtk_widget_event (focus, (GdkEvent*) event);
3547 parent = focus->parent;
3549 g_object_ref (parent);
3551 g_object_unref (focus);
3557 g_object_unref (focus);
3560 /* Chain up, invokes binding set */
3561 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
3562 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
3568 gtk_window_key_release_event (GtkWidget *widget,
3574 window = GTK_WINDOW (widget);
3576 if (window->focus_widget &&
3577 window->focus_widget != widget &&
3578 GTK_WIDGET_SENSITIVE (window->focus_widget))
3580 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
3583 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
3584 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
3590 gtk_window_real_activate_default (GtkWindow *window)
3592 gtk_window_activate_default (window);
3596 gtk_window_real_activate_focus (GtkWindow *window)
3598 gtk_window_activate_focus (window);
3602 gtk_window_move_focus (GtkWindow *window,
3603 GtkDirectionType dir)
3605 gtk_widget_child_focus (GTK_WIDGET (window), dir);
3607 if (!GTK_CONTAINER (window)->focus_child)
3608 gtk_window_set_focus (window, NULL);
3612 gtk_window_enter_notify_event (GtkWidget *widget,
3613 GdkEventCrossing *event)
3619 gtk_window_leave_notify_event (GtkWidget *widget,
3620 GdkEventCrossing *event)
3626 do_focus_change (GtkWidget *widget,
3629 GdkEventFocus fevent;
3631 g_object_ref (widget);
3634 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
3636 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
3638 fevent.type = GDK_FOCUS_CHANGE;
3639 fevent.window = widget->window;
3642 gtk_widget_event (widget, (GdkEvent*) &fevent);
3644 g_object_notify (G_OBJECT (widget), "has_focus");
3646 g_object_unref (widget);
3650 gtk_window_focus_in_event (GtkWidget *widget,
3651 GdkEventFocus *event)
3653 GtkWindow *window = GTK_WINDOW (widget);
3655 /* It appears spurious focus in events can occur when
3656 * the window is hidden. So we'll just check to see if
3657 * the window is visible before actually handling the
3660 if (GTK_WIDGET_VISIBLE (widget))
3662 window->has_focus = TRUE;
3664 if (window->focus_widget &&
3665 window->focus_widget != widget &&
3666 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3667 do_focus_change (window->focus_widget, TRUE);
3674 gtk_window_focus_out_event (GtkWidget *widget,
3675 GdkEventFocus *event)
3677 GtkWindow *window = GTK_WINDOW (widget);
3679 window->has_focus = FALSE;
3681 if (window->focus_widget &&
3682 window->focus_widget != widget &&
3683 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3684 do_focus_change (window->focus_widget, FALSE);
3689 static GdkAtom atom_rcfiles = GDK_NONE;
3692 gtk_window_read_rcfiles (GtkWidget *widget,
3693 GdkEventClient *event)
3695 GList *embedded_windows;
3697 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
3698 if (embedded_windows)
3703 for (i = 0; i < 5; i++)
3705 sev.data_format = 32;
3706 sev.message_type = atom_rcfiles;
3708 while (embedded_windows)
3710 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
3711 gdk_event_send_client_message ((GdkEvent *) &sev, xid);
3712 embedded_windows = embedded_windows->next;
3716 gtk_rc_reparse_all ();
3720 gtk_window_client_event (GtkWidget *widget,
3721 GdkEventClient *event)
3724 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
3726 if (event->message_type == atom_rcfiles)
3727 gtk_window_read_rcfiles (widget, event);
3733 gtk_window_check_resize (GtkContainer *container)
3735 GtkWindow *window = GTK_WINDOW (container);
3737 if (GTK_WIDGET_VISIBLE (container))
3738 gtk_window_move_resize (window);
3742 gtk_window_focus (GtkWidget *widget,
3743 GtkDirectionType direction)
3747 GtkContainer *container;
3748 GtkWidget *old_focus_child;
3751 container = GTK_CONTAINER (widget);
3752 window = GTK_WINDOW (widget);
3753 bin = GTK_BIN (widget);
3755 old_focus_child = container->focus_child;
3757 /* We need a special implementation here to deal properly with wrapping
3758 * around in the tab chain without the danger of going into an
3761 if (old_focus_child)
3763 if (gtk_widget_child_focus (old_focus_child, direction))
3767 if (window->focus_widget)
3769 /* Wrapped off the end, clear the focus setting for the toplpevel */
3770 parent = window->focus_widget->parent;
3773 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
3774 parent = GTK_WIDGET (parent)->parent;
3777 gtk_window_set_focus (GTK_WINDOW (container), NULL);
3780 /* Now try to focus the first widget in the window */
3783 if (gtk_widget_child_focus (bin->child, direction))
3791 gtk_window_real_set_focus (GtkWindow *window,
3794 gboolean def_flags = 0;
3796 if (window->default_widget)
3797 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
3799 if (window->focus_widget)
3801 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3802 (window->focus_widget != window->default_widget))
3804 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3806 if (window->default_widget)
3807 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3810 if (window->has_focus)
3811 do_focus_change (window->focus_widget, FALSE);
3814 window->focus_widget = focus;
3816 if (window->focus_widget)
3818 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3819 (window->focus_widget != window->default_widget))
3821 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
3822 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3824 if (window->default_widget)
3825 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3828 if (window->has_focus)
3829 do_focus_change (window->focus_widget, TRUE);
3832 if (window->default_widget &&
3833 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
3834 gtk_widget_queue_draw (window->default_widget);
3837 /*********************************
3838 * Functions related to resizing *
3839 *********************************/
3841 /* This function doesn't constrain to geometry hints */
3843 gtk_window_compute_configure_request_size (GtkWindow *window,
3847 GtkRequisition requisition;
3848 GtkWindowGeometryInfo *info;
3852 * - we've done a size request
3855 widget = GTK_WIDGET (window);
3857 info = gtk_window_get_geometry_info (window, FALSE);
3859 if (window->need_default_size)
3861 gtk_widget_get_child_requisition (widget, &requisition);
3863 /* Default to requisition */
3864 *width = requisition.width;
3865 *height = requisition.height;
3867 /* If window is empty so requests 0, default to random nonzero size */
3868 if (*width == 0 && *height == 0)
3874 /* Override requisition with default size */
3878 if (info->default_width > 0)
3879 *width = info->default_width;
3881 if (info->default_height > 0)
3882 *height = info->default_height;
3887 /* Default to keeping current size */
3888 *width = widget->allocation.width;
3889 *height = widget->allocation.height;
3892 /* Override any size with gtk_window_resize() values */
3895 if (info->resize_width > 0)
3896 *width = info->resize_width;
3898 if (info->resize_height > 0)
3899 *height = info->resize_height;
3904 gtk_window_compute_configure_request (GtkWindow *window,
3905 GdkRectangle *request,
3906 GdkGeometry *geometry,
3909 GdkGeometry new_geometry;
3913 GtkWindowPosition pos;
3914 GtkWidget *parent_widget;
3915 GtkWindowGeometryInfo *info;
3918 widget = GTK_WIDGET (window);
3920 gtk_widget_size_request (widget, NULL);
3921 gtk_window_compute_configure_request_size (window, &w, &h);
3923 gtk_window_compute_hints (window, &new_geometry, &new_flags);
3924 gtk_window_constrain_size (window,
3925 &new_geometry, new_flags,
3929 parent_widget = (GtkWidget*) window->transient_parent;
3931 pos = window->position;
3932 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
3933 (parent_widget == NULL ||
3934 !GTK_WIDGET_MAPPED (parent_widget)))
3935 pos = GTK_WIN_POS_NONE;
3937 info = gtk_window_get_geometry_info (window, TRUE);
3939 /* by default, don't change position requested */
3940 x = info->last.configure_request.x;
3941 y = info->last.configure_request.y;
3943 if (window->need_default_position)
3946 /* FIXME this all interrelates with window gravity.
3947 * For most of them I think we want to set GRAVITY_CENTER.
3949 * Not sure how to go about that.
3954 /* here we are only handling CENTER_ALWAYS
3955 * as it relates to default positioning,
3956 * where it's equivalent to simply CENTER
3958 case GTK_WIN_POS_CENTER_ALWAYS:
3959 case GTK_WIN_POS_CENTER:
3961 gint screen_width = gdk_screen_width ();
3962 gint screen_height = gdk_screen_height ();
3964 x = (screen_width - w) / 2;
3965 y = (screen_height - h) / 2;
3969 case GTK_WIN_POS_CENTER_ON_PARENT:
3973 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
3975 gdk_window_get_origin (parent_widget->window,
3978 x = ox + (parent_widget->allocation.width - w) / 2;
3979 y = oy + (parent_widget->allocation.height - h) / 2;
3983 case GTK_WIN_POS_MOUSE:
3985 gint screen_width = gdk_screen_width ();
3986 gint screen_height = gdk_screen_height ();
3989 gdk_window_get_pointer (NULL, &px, &py, NULL);
3992 x = CLAMP (x, 0, screen_width - w);
3993 y = CLAMP (y, 0, screen_height - h);
4000 } /* if (window->need_default_position) */
4002 if (window->need_default_position &&
4003 info->initial_pos_set)
4005 x = info->initial_x;
4006 y = info->initial_y;
4007 gtk_window_constrain_position (window, w, h, &x, &y);
4013 request->height = h;
4016 *geometry = new_geometry;
4022 gtk_window_constrain_position (GtkWindow *window,
4028 /* See long comments in gtk_window_move_resize()
4029 * on when it's safe to call this function.
4031 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4033 gint center_x, center_y;
4034 gint screen_width = gdk_screen_width ();
4035 gint screen_height = gdk_screen_height ();
4037 center_x = (screen_width - new_width) / 2;
4038 center_y = (screen_height - new_height) / 2;
4046 gtk_window_move_resize (GtkWindow *window)
4050 * First we determine whether any information has changed that would
4051 * cause us to revise our last configure request. If we would send
4052 * a different configure request from last time, then
4053 * configure_request_size_changed = TRUE or
4054 * configure_request_pos_changed = TRUE. configure_request_size_changed
4055 * may be true due to new hints, a gtk_window_resize(), or whatever.
4056 * configure_request_pos_changed may be true due to gtk_window_set_position()
4057 * or gtk_window_move().
4059 * If the configure request has changed, we send off a new one. To
4060 * ensure GTK+ invariants are maintained (resize queue does what it
4061 * should), we go ahead and size_allocate the requested size in this
4064 * If the configure request has not changed, we don't ever resend
4065 * it, because it could mean fighting the user or window manager.
4068 * To prepare the configure request, we come up with a base size/pos:
4069 * - the one from gtk_window_move()/gtk_window_resize()
4070 * - else default_width, default_height if we haven't ever
4072 * - else the size request if we haven't ever been mapped,
4073 * as a substitute default size
4074 * - else the current size of the window, as received from
4075 * configure notifies (i.e. the current allocation)
4077 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4078 * the position request to be centered.
4081 GtkContainer *container;
4082 GtkWindowGeometryInfo *info;
4083 GdkGeometry new_geometry;
4085 GdkRectangle new_request;
4086 gboolean configure_request_size_changed;
4087 gboolean configure_request_pos_changed;
4088 gboolean hints_changed; /* do we need to send these again */
4089 GtkWindowLastGeometryInfo saved_last_info;
4091 widget = GTK_WIDGET (window);
4092 container = GTK_CONTAINER (widget);
4093 info = gtk_window_get_geometry_info (window, TRUE);
4095 configure_request_size_changed = FALSE;
4096 configure_request_pos_changed = FALSE;
4098 gtk_window_compute_configure_request (window, &new_request,
4099 &new_geometry, &new_flags);
4101 /* This check implies the invariant that we never set info->last
4102 * without setting the hints and sending off a configure request.
4104 * If we change info->last without sending the request, we may
4107 if (info->last.configure_request.x != new_request.x ||
4108 info->last.configure_request.y != new_request.y)
4109 configure_request_pos_changed = TRUE;
4111 if ((info->last.configure_request.width != new_request.width ||
4112 info->last.configure_request.height != new_request.height))
4113 configure_request_size_changed = TRUE;
4115 hints_changed = FALSE;
4117 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4118 &new_geometry, new_flags))
4120 hints_changed = TRUE;
4123 /* Position Constraints
4124 * ====================
4126 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4127 * a default. The other POS_ values are used only when the
4128 * window is shown, not after that.
4130 * However, we can't implement a position constraint as
4131 * "anytime the window size changes, center the window"
4132 * because this may well end up fighting the WM or user. In
4133 * fact it gets in an infinite loop with at least one WM.
4135 * Basically, applications are in no way in a position to
4136 * constrain the position of a window, with one exception:
4137 * override redirect windows. (Really the intended purpose
4138 * of CENTER_ALWAYS anyhow, I would think.)
4140 * So the way we implement this "constraint" is to say that when WE
4141 * cause a move or resize, i.e. we make a configure request changing
4142 * window size, we recompute the CENTER_ALWAYS position to reflect
4143 * the new window size, and include it in our request. Also, if we
4144 * just turned on CENTER_ALWAYS we snap to center with a new
4145 * request. Otherwise, if we are just NOTIFIED of a move or resize
4146 * done by someone else e.g. the window manager, we do NOT send a
4147 * new configure request.
4149 * For override redirect windows, this works fine; all window
4150 * sizes are from our configure requests. For managed windows,
4151 * it is at least semi-sane, though who knows what the
4152 * app author is thinking.
4155 /* This condition should be kept in sync with the condition later on
4156 * that determines whether we send a configure request. i.e. we
4157 * should do this position constraining anytime we were going to
4158 * send a configure request anyhow, plus when constraints have
4161 if (configure_request_pos_changed ||
4162 configure_request_size_changed ||
4164 info->position_constraints_changed)
4166 /* We request the constrained position if:
4167 * - we were changing position, and need to clamp
4168 * the change to the constraint
4169 * - we're changing the size anyway
4170 * - set_position() was called to toggle CENTER_ALWAYS on
4173 gtk_window_constrain_position (window,
4179 /* Update whether we need to request a move */
4180 if (info->last.configure_request.x != new_request.x ||
4181 info->last.configure_request.y != new_request.y)
4182 configure_request_pos_changed = TRUE;
4184 configure_request_pos_changed = FALSE;
4189 int notify_x, notify_y;
4191 /* this is the position from the last configure notify */
4192 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4194 g_print ("--- %s ---\n"
4195 "last : %d,%d\t%d x %d\n"
4196 "this : %d,%d\t%d x %d\n"
4197 "alloc: %d,%d\t%d x %d\n"
4199 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4200 "configure_notify_received: %d\n"
4201 "configure_request_count: %d\n"
4202 "position_constraints_changed: %d\n",
4203 window->title ? window->title : "(no title)",
4204 info->last.configure_request.x,
4205 info->last.configure_request.y,
4206 info->last.configure_request.width,
4207 info->last.configure_request.height,
4213 widget->allocation.width,
4214 widget->allocation.height,
4215 widget->requisition.width,
4216 widget->requisition.height,
4217 configure_request_pos_changed,
4218 configure_request_size_changed,
4220 window->configure_notify_received,
4221 window->configure_request_count,
4222 info->position_constraints_changed);
4226 saved_last_info = info->last;
4227 info->last.geometry = new_geometry;
4228 info->last.flags = new_flags;
4229 info->last.configure_request = new_request;
4231 /* need to set PPosition so the WM will look at our position,
4232 * but we don't want to count PPosition coming and going as a hints
4233 * change for future iterations. So we saved info->last prior to
4237 /* Also, if the initial position was explicitly set, then we always
4238 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4242 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4243 * this is an initial map
4246 if ((configure_request_pos_changed ||
4247 info->initial_pos_set ||
4248 (window->need_default_position &&
4249 window->position != GTK_WIN_POS_NONE)) &&
4250 (new_flags & GDK_HINT_POS) == 0)
4252 new_flags |= GDK_HINT_POS;
4253 hints_changed = TRUE;
4256 /* Set hints if necessary
4259 gdk_window_set_geometry_hints (widget->window,
4263 /* handle resizing/moving and widget tree allocation
4265 if (window->configure_notify_received)
4267 GtkAllocation allocation;
4269 /* If we have received a configure event since
4270 * the last time in this function, we need to
4271 * accept our new size and size_allocate child widgets.
4272 * (see gtk_window_configure_event() for more details).
4274 * 1 or more configure notifies may have been received.
4275 * Also, configure_notify_received will only be TRUE
4276 * if all expected configure notifies have been received
4277 * (one per configure request), as an optimization.
4280 window->configure_notify_received = FALSE;
4282 /* gtk_window_configure_event() filled in widget->allocation */
4283 allocation = widget->allocation;
4284 gtk_widget_size_allocate (widget, &allocation);
4286 /* If the configure request changed, it means that
4288 * 1) coincidentally changed hints or widget properties
4289 * impacting the configure request before getting
4290 * a configure notify, or
4291 * 2) some broken widget is changing its size request
4292 * during size allocation, resulting in
4293 * a false appearance of changed configure request.
4295 * For 1), we could just go ahead and ask for the
4296 * new size right now, but doing that for 2)
4297 * might well be fighting the user (and can even
4298 * trigger a loop). Since we really don't want to
4299 * do that, we requeue a resize in hopes that
4300 * by the time it gets handled, the child has seen
4301 * the light and is willing to go along with the
4302 * new size. (this happens for the zvt widget, since
4303 * the size_allocate() above will have stored the
4304 * requisition corresponding to the new size in the
4307 * This doesn't buy us anything for 1), but it shouldn't
4308 * hurt us too badly, since it is what would have
4309 * happened if we had gotten the configure event before
4310 * the new size had been set.
4313 if (configure_request_size_changed ||
4314 configure_request_pos_changed)
4316 /* Don't change the recorded last info after all, because we
4317 * haven't actually updated to the new info yet - we decided
4318 * to postpone our configure request until later.
4320 info->last = saved_last_info;
4322 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
4325 else if ((configure_request_size_changed || hints_changed) &&
4326 (widget->allocation.width != new_request.width ||
4327 widget->allocation.height != new_request.height))
4330 /* We are in one of the following situations:
4331 * A. configure_request_size_changed
4332 * our requisition has changed and we need a different window size,
4333 * so we request it from the window manager.
4334 * B. !configure_request_size_changed && hints_changed
4335 * the window manager rejects our size, but we have just changed the
4336 * window manager hints, so there's a chance our request will
4337 * be honoured this time, so we try again.
4339 * However, if the new requisition is the same as the current allocation,
4340 * we don't request it again, since we won't get a ConfigureNotify back from
4341 * the window manager unless it decides to change our requisition. If
4342 * we don't get the ConfigureNotify back, the resize queue will never be run.
4345 /* Now send the configure request */
4346 if (configure_request_pos_changed)
4350 gdk_window_move_resize (window->frame,
4351 new_request.x - window->frame_left,
4352 new_request.y - window->frame_top,
4353 new_request.width + window->frame_left + window->frame_right,
4354 new_request.height + window->frame_top + window->frame_bottom);
4355 gdk_window_resize (GTK_WIDGET (window)->window,
4356 new_request.width, new_request.height);
4359 gdk_window_move_resize (widget->window,
4360 new_request.x, new_request.y,
4361 new_request.width, new_request.height);
4363 else /* only size changed */
4366 gdk_window_resize (window->frame,
4367 new_request.width + window->frame_left + window->frame_right,
4368 new_request.height + window->frame_top + window->frame_bottom);
4369 gdk_window_resize (widget->window,
4370 new_request.width, new_request.height);
4373 /* Increment the number of have-not-yet-received-notify requests */
4374 window->configure_request_count += 1;
4376 /* We have now sent a request since the last position constraint
4377 * change and definitely don't need a an initial size again (not
4378 * resetting this here can lead to infinite loops for
4379 * GTK_RESIZE_IMMEDIATE containers)
4381 info->position_constraints_changed = FALSE;
4382 info->initial_pos_set = FALSE;
4383 info->resize_width = -1;
4384 info->resize_height = -1;
4386 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
4387 * configure event in response to our resizing request.
4388 * the configure event will cause a new resize with
4389 * ->configure_notify_received=TRUE.
4390 * until then, we want to
4391 * - discard expose events
4392 * - coalesce resizes for our children
4393 * - defer any window resizes until the configure event arrived
4394 * to achieve this, we queue a resize for the window, but remove its
4395 * resizing handler, so resizing will not be handled from the next
4396 * idle handler but when the configure event arrives.
4398 * FIXME: we should also dequeue the pending redraws here, since
4399 * we handle those ourselves upon ->configure_notify_received==TRUE.
4401 if (container->resize_mode == GTK_RESIZE_QUEUE)
4403 gtk_widget_queue_resize (widget);
4404 _gtk_container_dequeue_resize_handler (container);
4409 /* Handle any position changes.
4411 if (configure_request_pos_changed)
4415 gdk_window_move (window->frame,
4416 new_request.x - window->frame_left,
4417 new_request.y - window->frame_top);
4420 gdk_window_move (widget->window,
4421 new_request.x, new_request.y);
4424 /* And run the resize queue.
4426 gtk_container_resize_children (container);
4430 /* Compare two sets of Geometry hints for equality.
4433 gtk_window_compare_hints (GdkGeometry *geometry_a,
4435 GdkGeometry *geometry_b,
4438 if (flags_a != flags_b)
4441 if ((flags_a & GDK_HINT_MIN_SIZE) &&
4442 (geometry_a->min_width != geometry_b->min_width ||
4443 geometry_a->min_height != geometry_b->min_height))
4446 if ((flags_a & GDK_HINT_MAX_SIZE) &&
4447 (geometry_a->max_width != geometry_b->max_width ||
4448 geometry_a->max_height != geometry_b->max_height))
4451 if ((flags_a & GDK_HINT_BASE_SIZE) &&
4452 (geometry_a->base_width != geometry_b->base_width ||
4453 geometry_a->base_height != geometry_b->base_height))
4456 if ((flags_a & GDK_HINT_ASPECT) &&
4457 (geometry_a->min_aspect != geometry_b->min_aspect ||
4458 geometry_a->max_aspect != geometry_b->max_aspect))
4461 if ((flags_a & GDK_HINT_RESIZE_INC) &&
4462 (geometry_a->width_inc != geometry_b->width_inc ||
4463 geometry_a->height_inc != geometry_b->height_inc))
4466 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
4467 geometry_a->win_gravity != geometry_b->win_gravity)
4474 _gtk_window_constrain_size (GtkWindow *window,
4480 GtkWindowGeometryInfo *info;
4482 g_return_if_fail (GTK_IS_WINDOW (window));
4484 info = window->geometry_info;
4487 GdkWindowHints flags = info->last.flags;
4488 GdkGeometry *geometry = &info->last.geometry;
4490 gtk_window_constrain_size (window,
4501 gtk_window_constrain_size (GtkWindow *window,
4502 GdkGeometry *geometry,
4509 gdk_window_constrain_size (geometry, flags, width, height,
4510 new_width, new_height);
4513 /* Compute the set of geometry hints and flags for a window
4514 * based on the application set geometry, and requisiition
4515 * of the window. gtk_widget_size_request() must have been
4519 gtk_window_compute_hints (GtkWindow *window,
4520 GdkGeometry *new_geometry,
4524 gint extra_width = 0;
4525 gint extra_height = 0;
4526 GtkWindowGeometryInfo *geometry_info;
4527 GtkRequisition requisition;
4529 widget = GTK_WIDGET (window);
4531 gtk_widget_get_child_requisition (widget, &requisition);
4532 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
4536 *new_flags = geometry_info->mask;
4537 *new_geometry = geometry_info->geometry;
4544 if (geometry_info && geometry_info->widget)
4546 GtkRequisition child_requisition;
4548 /* FIXME: This really isn't right. It gets the min size wrong and forces
4549 * callers to do horrible hacks like set a huge usize on the child requisition
4550 * to get the base size right. We really want to find the answers to:
4552 * - If the geometry widget was infinitely big, how much extra space
4553 * would be needed for the stuff around it.
4555 * - If the geometry widget was infinitely small, how big would the
4556 * window still have to be.
4558 * Finding these answers would be a bit of a mess here. (Bug #68668)
4560 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
4562 extra_width = widget->requisition.width - child_requisition.width;
4563 extra_height = widget->requisition.height - child_requisition.height;
4566 /* We don't want to set GDK_HINT_POS in here, we just set it
4567 * in gtk_window_move_resize() when we want the position
4571 if (*new_flags & GDK_HINT_BASE_SIZE)
4573 new_geometry->base_width += extra_width;
4574 new_geometry->base_height += extra_height;
4576 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
4577 (*new_flags & GDK_HINT_RESIZE_INC) &&
4578 ((extra_width != 0) || (extra_height != 0)))
4580 *new_flags |= GDK_HINT_BASE_SIZE;
4582 new_geometry->base_width = extra_width;
4583 new_geometry->base_height = extra_height;
4586 if (*new_flags & GDK_HINT_MIN_SIZE)
4588 if (new_geometry->min_width < 0)
4589 new_geometry->min_width = requisition.width;
4591 new_geometry->min_width += extra_width;
4593 if (new_geometry->min_height < 0)
4594 new_geometry->min_height = requisition.height;
4596 new_geometry->min_height += extra_height;
4598 else if (!window->allow_shrink)
4600 *new_flags |= GDK_HINT_MIN_SIZE;
4602 new_geometry->min_width = requisition.width;
4603 new_geometry->min_height = requisition.height;
4606 if (*new_flags & GDK_HINT_MAX_SIZE)
4608 if (new_geometry->max_width < 0)
4609 new_geometry->max_width = requisition.width;
4611 new_geometry->max_width += extra_width;
4613 if (new_geometry->max_height < 0)
4614 new_geometry->max_width = requisition.height;
4616 new_geometry->max_height += extra_height;
4618 else if (!window->allow_grow)
4620 *new_flags |= GDK_HINT_MAX_SIZE;
4622 new_geometry->max_width = requisition.width;
4623 new_geometry->max_height = requisition.height;
4626 *new_flags |= GDK_HINT_WIN_GRAVITY;
4627 new_geometry->win_gravity = window->gravity;
4630 /***********************
4631 * Redrawing functions *
4632 ***********************/
4635 gtk_window_paint (GtkWidget *widget,
4638 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
4639 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
4643 gtk_window_expose (GtkWidget *widget,
4644 GdkEventExpose *event)
4646 if (!GTK_WIDGET_APP_PAINTABLE (widget))
4647 gtk_window_paint (widget, &event->area);
4649 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
4650 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
4656 * gtk_window_set_has_frame:
4657 * @window: a #GtkWindow
4658 * @setting: a boolean
4660 * (Note: this is a special-purpose function for the framebuffer port,
4661 * that causes GTK+ to draw its own window border. For most applications,
4662 * you want gtk_window_set_decorated() instead, which tells the window
4663 * manager whether to draw the window border.)
4665 * If this function is called on a window with setting of %TRUE, before
4666 * it is realized or showed, it will have a "frame" window around
4667 * @window->window, accessible in @window->frame. Using the signal
4668 * frame_event you can recieve all events targeted at the frame.
4670 * This function is used by the linux-fb port to implement managed
4671 * windows, but it could concievably be used by X-programs that
4672 * want to do their own window decorations.
4676 gtk_window_set_has_frame (GtkWindow *window,
4679 g_return_if_fail (GTK_IS_WINDOW (window));
4680 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
4682 window->has_frame = setting != FALSE;
4686 * gtk_window_get_has_frame:
4687 * @window: a #GtkWindow
4689 * Accessor for whether the window has a frame window exterior to
4690 * @window->window. Gets the value set by gtk_window_set_has_frame ().
4692 * Return value: %TRUE if a frame has been added to the window
4693 * via gtk_window_set_has_frame().
4696 gtk_window_get_has_frame (GtkWindow *window)
4698 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4700 return window->has_frame;
4704 * gtk_window_set_frame_dimensions:
4705 * @window: a #GtkWindow that has a frame
4706 * @left: The width of the left border
4707 * @top: The height of the top border
4708 * @right: The width of the right border
4709 * @bottom: The height of the bottom border
4711 * (Note: this is a special-purpose function intended for the framebuffer
4712 * port; see gtk_window_set_has_frame(). It will have no effect on the
4713 * window border drawn by the window manager, which is the normal
4714 * case when using the X Window system.)
4716 * For windows with frames (see gtk_window_set_has_frame()) this function
4717 * can be used to change the size of the frame border.
4720 gtk_window_set_frame_dimensions (GtkWindow *window,
4728 g_return_if_fail (GTK_IS_WINDOW (window));
4730 widget = GTK_WIDGET (window);
4732 if (window->frame_left == left &&
4733 window->frame_top == top &&
4734 window->frame_right == right &&
4735 window->frame_bottom == bottom)
4738 window->frame_left = left;
4739 window->frame_top = top;
4740 window->frame_right = right;
4741 window->frame_bottom = bottom;
4743 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4745 gint width = widget->allocation.width + left + right;
4746 gint height = widget->allocation.height + top + bottom;
4747 gdk_window_resize (window->frame, width, height);
4748 gtk_decorated_window_move_resize_window (window,
4750 widget->allocation.width,
4751 widget->allocation.height);
4756 * gtk_window_present:
4757 * @window: a #GtkWindow
4759 * Presents a window to the user. This may mean raising the window
4760 * in the stacking order, deiconifying it, moving it to the current
4761 * desktop, and/or giving it the keyboard focus, possibly dependent
4762 * on the user's platform, window manager, and preferences.
4764 * If @window is hidden, this function calls gtk_widget_show()
4767 * This function should be used when the user tries to open a window
4768 * that's already open. Say for example the preferences dialog is
4769 * currently open, and the user chooses Preferences from the menu
4770 * a second time; use gtk_window_present() to move the already-open dialog
4771 * where the user can see it.
4775 gtk_window_present (GtkWindow *window)
4779 g_return_if_fail (GTK_IS_WINDOW (window));
4781 widget = GTK_WIDGET (window);
4783 if (GTK_WIDGET_VISIBLE (window))
4785 g_assert (widget->window != NULL);
4787 gdk_window_show (widget->window);
4789 /* note that gdk_window_focus() will also move the window to
4790 * the current desktop, for WM spec compliant window managers.
4792 gdk_window_focus (widget->window,
4793 gtk_get_current_event_time ());
4797 gtk_widget_show (widget);
4802 * gtk_window_iconify:
4803 * @window: a #GtkWindow
4805 * Asks to iconify (i.e. minimize) the specified @window. Note that
4806 * you shouldn't assume the window is definitely iconified afterward,
4807 * because other entities (e.g. the user or <link
4808 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
4809 * again, or there may not be a window manager in which case
4810 * iconification isn't possible, etc. But normally the window will end
4811 * up iconified. Just don't write code that crashes if not.
4813 * It's permitted to call this function before showing a window,
4814 * in which case the window will be iconified before it ever appears
4817 * You can track iconification via the "window_state_event" signal
4822 gtk_window_iconify (GtkWindow *window)
4825 GdkWindow *toplevel;
4827 g_return_if_fail (GTK_IS_WINDOW (window));
4829 widget = GTK_WIDGET (window);
4831 window->iconify_initially = TRUE;
4834 toplevel = window->frame;
4836 toplevel = widget->window;
4838 if (toplevel != NULL)
4839 gdk_window_iconify (toplevel);
4843 * gtk_window_deiconify:
4844 * @window: a #GtkWindow
4846 * Asks to deiconify (i.e. unminimize) the specified @window. Note
4847 * that you shouldn't assume the window is definitely deiconified
4848 * afterward, because other entities (e.g. the user or <link
4849 * linkend="gtk-X11-arch">window manager</link>) could iconify it
4850 * again before your code which assumes deiconification gets to run.
4852 * You can track iconification via the "window_state_event" signal
4856 gtk_window_deiconify (GtkWindow *window)
4859 GdkWindow *toplevel;
4861 g_return_if_fail (GTK_IS_WINDOW (window));
4863 widget = GTK_WIDGET (window);
4865 window->iconify_initially = FALSE;
4868 toplevel = window->frame;
4870 toplevel = widget->window;
4872 if (toplevel != NULL)
4873 gdk_window_deiconify (toplevel);
4878 * @window: a #GtkWindow
4880 * Asks to stick @window, which means that it will appear on all user
4881 * desktops. Note that you shouldn't assume the window is definitely
4882 * stuck afterward, because other entities (e.g. the user or <link
4883 * linkend="gtk-X11-arch">window manager</link>) could unstick it
4884 * again, and some window managers do not support sticking
4885 * windows. But normally the window will end up stuck. Just don't
4886 * write code that crashes if not.
4888 * It's permitted to call this function before showing a window.
4890 * You can track stickiness via the "window_state_event" signal
4895 gtk_window_stick (GtkWindow *window)
4898 GdkWindow *toplevel;
4900 g_return_if_fail (GTK_IS_WINDOW (window));
4902 widget = GTK_WIDGET (window);
4904 window->stick_initially = TRUE;
4907 toplevel = window->frame;
4909 toplevel = widget->window;
4911 if (toplevel != NULL)
4912 gdk_window_stick (toplevel);
4916 * gtk_window_unstick:
4917 * @window: a #GtkWindow
4919 * Asks to unstick @window, which means that it will appear on only
4920 * one of the user's desktops. Note that you shouldn't assume the
4921 * window is definitely unstuck afterward, because other entities
4922 * (e.g. the user or <link linkend="gtk-X11-arch">window
4923 * manager</link>) could stick it again. But normally the window will
4924 * end up stuck. Just don't write code that crashes if not.
4926 * You can track stickiness via the "window_state_event" signal
4931 gtk_window_unstick (GtkWindow *window)
4934 GdkWindow *toplevel;
4936 g_return_if_fail (GTK_IS_WINDOW (window));
4938 widget = GTK_WIDGET (window);
4940 window->stick_initially = FALSE;
4943 toplevel = window->frame;
4945 toplevel = widget->window;
4947 if (toplevel != NULL)
4948 gdk_window_unstick (toplevel);
4952 * gtk_window_maximize:
4953 * @window: a #GtkWindow
4955 * Asks to maximize @window, so that it becomes full-screen. Note that
4956 * you shouldn't assume the window is definitely maximized afterward,
4957 * because other entities (e.g. the user or <link
4958 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
4959 * again, and not all window managers support maximization. But
4960 * normally the window will end up maximized. Just don't write code
4961 * that crashes if not.
4963 * It's permitted to call this function before showing a window,
4964 * in which case the window will be maximized when it appears onscreen
4967 * You can track maximization via the "window_state_event" signal
4972 gtk_window_maximize (GtkWindow *window)
4975 GdkWindow *toplevel;
4977 g_return_if_fail (GTK_IS_WINDOW (window));
4979 widget = GTK_WIDGET (window);
4981 window->maximize_initially = TRUE;
4984 toplevel = window->frame;
4986 toplevel = widget->window;
4988 if (toplevel != NULL)
4989 gdk_window_maximize (toplevel);
4993 * gtk_window_unmaximize:
4994 * @window: a #GtkWindow
4996 * Asks to unmaximize @window. Note that you shouldn't assume the
4997 * window is definitely unmaximized afterward, because other entities
4998 * (e.g. the user or <link linkend="gtk-X11-arch">window
4999 * manager</link>) could maximize it again, and not all window
5000 * managers honor requests to unmaximize. But normally the window will
5001 * end up unmaximized. Just don't write code that crashes if not.
5003 * You can track maximization via the "window_state_event" signal
5008 gtk_window_unmaximize (GtkWindow *window)
5011 GdkWindow *toplevel;
5013 g_return_if_fail (GTK_IS_WINDOW (window));
5015 widget = GTK_WIDGET (window);
5017 window->maximize_initially = FALSE;
5020 toplevel = window->frame;
5022 toplevel = widget->window;
5024 if (toplevel != NULL)
5025 gdk_window_unmaximize (toplevel);
5029 * gtk_window_set_resizable:
5030 * @window: a #GtkWindow
5031 * @resizable: %TRUE if the user can resize this window
5033 * Sets whether the user can resize a window. Windows are user resizable
5037 gtk_window_set_resizable (GtkWindow *window,
5040 g_return_if_fail (GTK_IS_WINDOW (window));
5042 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5046 * gtk_window_get_resizable:
5047 * @window: a #GtkWindow
5049 * Gets the value set by gtk_window_set_resizable().
5051 * Return value: %TRUE if the user can resize the window
5054 gtk_window_get_resizable (GtkWindow *window)
5056 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5058 /* allow_grow is most likely to indicate the semantic concept we
5059 * mean by "resizable" (and will be a reliable indicator if
5060 * set_policy() hasn't been called)
5062 return window->allow_grow;
5066 * gtk_window_set_gravity:
5067 * @window: a #GtkWindow
5068 * @gravity: window gravity
5070 * Window gravity defines the meaning of coordinates passed to
5071 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5074 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5075 * typically "do what you mean."
5079 gtk_window_set_gravity (GtkWindow *window,
5082 g_return_if_fail (GTK_IS_WINDOW (window));
5084 if (gravity != window->gravity)
5086 window->gravity = gravity;
5088 /* gtk_window_move_resize() will adapt gravity
5090 gtk_widget_queue_resize (GTK_WIDGET (window));
5095 * gtk_window_get_gravity:
5096 * @window: a #GtkWindow
5098 * Gets the value set by gtk_window_set_gravity().
5100 * Return value: window gravity
5103 gtk_window_get_gravity (GtkWindow *window)
5105 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5107 return window->gravity;
5111 * gtk_window_begin_resize_drag:
5112 * @window: a #GtkWindow
5113 * @button: mouse button that initiated the drag
5114 * @edge: position of the resize control
5115 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5116 * @root_y: Y position where the user clicked to initiate the drag
5117 * @timestamp: timestamp from the click event that initiated the drag
5119 * Starts resizing a window. This function is used if an application
5120 * has window resizing controls. When GDK can support it, the resize
5121 * will be done using the standard mechanism for the <link
5122 * linkend="gtk-X11-arch">window manager</link> or windowing
5123 * system. Otherwise, GDK will try to emulate window resizing,
5124 * potentially not all that well, depending on the windowing system.
5128 gtk_window_begin_resize_drag (GtkWindow *window,
5136 GdkWindow *toplevel;
5138 g_return_if_fail (GTK_IS_WINDOW (window));
5139 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5141 widget = GTK_WIDGET (window);
5144 toplevel = window->frame;
5146 toplevel = widget->window;
5148 gdk_window_begin_resize_drag (toplevel,
5155 * gtk_window_get_frame_dimensions:
5156 * @window: a #GtkWindow
5157 * @left: location to store the width of the frame at the left, or %NULL
5158 * @top: location to store the height of the frame at the top, or %NULL
5159 * @right: location to store the width of the frame at the returns, or %NULL
5160 * @bottom: location to store the height of the frame at the bottom, or %NULL
5162 * (Note: this is a special-purpose function intended for the
5163 * framebuffer port; see gtk_window_set_has_frame(). It will not
5164 * return the size of the window border drawn by the <link
5165 * linkend="gtk-X11-arch">window manager</link>, which is the normal
5166 * case when using a windowing system. See
5167 * gdk_window_get_frame_extents() to get the standard window border
5170 * Retrieves the dimensions of the frame window for this toplevel.
5171 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5174 gtk_window_get_frame_dimensions (GtkWindow *window,
5180 g_return_if_fail (GTK_IS_WINDOW (window));
5183 *left = window->frame_left;
5185 *top = window->frame_top;
5187 *right = window->frame_right;
5189 *bottom = window->frame_bottom;
5193 * gtk_window_begin_move_drag:
5194 * @window: a #GtkWindow
5195 * @button: mouse button that initiated the drag
5196 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5197 * @root_y: Y position where the user clicked to initiate the drag
5198 * @timestamp: timestamp from the click event that initiated the drag
5200 * Starts moving a window. This function is used if an application has
5201 * window movement grips. When GDK can support it, the window movement
5202 * will be done using the standard mechanism for the <link
5203 * linkend="gtk-X11-arch">window manager</link> or windowing
5204 * system. Otherwise, GDK will try to emulate window movement,
5205 * potentially not all that well, depending on the windowing system.
5209 gtk_window_begin_move_drag (GtkWindow *window,
5216 GdkWindow *toplevel;
5218 g_return_if_fail (GTK_IS_WINDOW (window));
5219 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5221 widget = GTK_WIDGET (window);
5224 toplevel = window->frame;
5226 toplevel = widget->window;
5228 gdk_window_begin_move_drag (toplevel,
5236 gtk_window_group_class_init (GtkWindowGroupClass *klass)
5241 gtk_window_group_get_type (void)
5243 static GtkType window_group_type = 0;
5245 if (!window_group_type)
5247 static const GTypeInfo window_group_info =
5249 sizeof (GtkWindowGroupClass),
5250 NULL, /* base_init */
5251 NULL, /* base_finalize */
5252 (GClassInitFunc) gtk_window_group_class_init,
5253 NULL, /* class_finalize */
5254 NULL, /* class_data */
5255 sizeof (GtkWindowGroup),
5256 16, /* n_preallocs */
5257 (GInstanceInitFunc) NULL,
5260 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
5263 return window_group_type;
5267 * gtk_window_group_new:
5269 * Creates a new #GtkWindowGroup object. Grabs added with
5270 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
5272 * Return value: a new #GtkWindowGroup.
5275 gtk_window_group_new (void)
5277 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
5281 window_group_cleanup_grabs (GtkWindowGroup *group,
5285 GSList *to_remove = NULL;
5287 tmp_list = group->grabs;
5290 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
5291 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
5292 tmp_list = tmp_list->next;
5297 gtk_grab_remove (to_remove->data);
5298 g_object_unref (to_remove->data);
5299 to_remove = g_slist_delete_link (to_remove, to_remove);
5304 * gtk_window_group_add_window:
5305 * @window_group: a #GtkWindowGroup
5306 * @window: the #GtkWindow to add
5308 * Adds a window to a #GtkWindowGroup.
5311 gtk_window_group_add_window (GtkWindowGroup *window_group,
5314 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5315 g_return_if_fail (GTK_IS_WINDOW (window));
5317 if (window->group != window_group)
5319 g_object_ref (window);
5320 g_object_ref (window_group);
5323 gtk_window_group_remove_window (window->group, window);
5325 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
5327 window->group = window_group;
5329 g_object_unref (window);
5334 * gtk_window_group_remove_window:
5335 * @window_group: a #GtkWindowGroup
5336 * @window: the #GtkWindow to remove
5338 * Removes a window from a #GtkWindowGroup.
5341 gtk_window_group_remove_window (GtkWindowGroup *window_group,
5344 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5345 g_return_if_fail (GTK_IS_WIDGET (window));
5346 g_return_if_fail (window->group == window_group);
5348 g_object_ref (window);
5350 window_group_cleanup_grabs (window_group, window);
5351 window->group = NULL;
5353 g_object_unref (G_OBJECT (window_group));
5354 g_object_unref (window);
5357 /* Return the group for the window or the default group
5360 _gtk_window_get_group (GtkWindow *window)
5362 if (window && window->group)
5363 return window->group;
5366 static GtkWindowGroup *default_group = NULL;
5369 default_group = gtk_window_group_new ();
5371 return default_group;
5377 Derived from XParseGeometry() in XFree86
5379 Copyright 1985, 1986, 1987,1998 The Open Group
5381 All Rights Reserved.
5383 The above copyright notice and this permission notice shall be included
5384 in all copies or substantial portions of the Software.
5386 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5387 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5388 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
5389 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
5390 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
5391 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
5392 OTHER DEALINGS IN THE SOFTWARE.
5394 Except as contained in this notice, the name of The Open Group shall
5395 not be used in advertising or otherwise to promote the sale, use or
5396 other dealings in this Software without prior written authorization
5397 from The Open Group.
5402 * XParseGeometry parses strings of the form
5403 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5404 * width, height, xoffset, and yoffset are unsigned integers.
5405 * Example: "=80x24+300-49"
5406 * The equal sign is optional.
5407 * It returns a bitmask that indicates which of the four values
5408 * were actually found in the string. For each value found,
5409 * the corresponding argument is updated; for each value
5410 * not found, the corresponding argument is left unchanged.
5413 /* The following code is from Xlib, and is minimally modified, so we
5414 * can track any upstream changes if required. Don't change this
5415 * code. Or if you do, put in a huge comment marking which thing
5420 read_int (gchar *string,
5428 else if (*string == '-')
5434 for (; (*string >= '0') && (*string <= '9'); string++)
5436 result = (result * 10) + (*string - '0');
5448 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
5449 * value (x, y, width, height) was found in the parsed string.
5451 #define NoValue 0x0000
5452 #define XValue 0x0001
5453 #define YValue 0x0002
5454 #define WidthValue 0x0004
5455 #define HeightValue 0x0008
5456 #define AllValues 0x000F
5457 #define XNegative 0x0010
5458 #define YNegative 0x0020
5460 /* Try not to reformat/modify, so we can compare/sync with X sources */
5462 gtk_XParseGeometry (const char *string,
5465 unsigned int *width,
5466 unsigned int *height)
5470 unsigned int tempWidth, tempHeight;
5472 char *nextCharacter;
5474 /* These initializations are just to silence gcc */
5480 if ( (string == NULL) || (*string == '\0')) return(mask);
5482 string++; /* ignore possible '=' at beg of geometry spec */
5484 strind = (char *)string;
5485 if (*strind != '+' && *strind != '-' && *strind != 'x') {
5486 tempWidth = read_int(strind, &nextCharacter);
5487 if (strind == nextCharacter)
5489 strind = nextCharacter;
5493 if (*strind == 'x' || *strind == 'X') {
5495 tempHeight = read_int(strind, &nextCharacter);
5496 if (strind == nextCharacter)
5498 strind = nextCharacter;
5499 mask |= HeightValue;
5502 if ((*strind == '+') || (*strind == '-')) {
5503 if (*strind == '-') {
5505 tempX = -read_int(strind, &nextCharacter);
5506 if (strind == nextCharacter)
5508 strind = nextCharacter;
5514 tempX = read_int(strind, &nextCharacter);
5515 if (strind == nextCharacter)
5517 strind = nextCharacter;
5520 if ((*strind == '+') || (*strind == '-')) {
5521 if (*strind == '-') {
5523 tempY = -read_int(strind, &nextCharacter);
5524 if (strind == nextCharacter)
5526 strind = nextCharacter;
5533 tempY = read_int(strind, &nextCharacter);
5534 if (strind == nextCharacter)
5536 strind = nextCharacter;
5542 /* If strind isn't at the end of the string the it's an invalid
5543 geometry specification. */
5545 if (*strind != '\0') return (0);
5551 if (mask & WidthValue)
5553 if (mask & HeightValue)
5554 *height = tempHeight;
5559 * gtk_window_parse_geometry:
5560 * @window: a #GtkWindow
5561 * @geometry: geometry string
5563 * Parses a standard X Window System geometry string - see the
5564 * manual page for X (type 'man X') for details on this.
5565 * gtk_window_parse_geometry() does work on all GTK+ ports
5566 * including Win32 but is primarily intended for an X environment.
5568 * If either a size or a position can be extracted from the
5569 * geometry string, gtk_window_parse_geometry() returns %TRUE
5570 * and calls gtk_window_set_default_size() and/or gtk_window_move()
5571 * to resize/move the window.
5573 * If gtk_window_parse_geometry() returns %TRUE, it will also
5574 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
5575 * indicating to the window manager that the size/position of
5576 * the window was user-specified. This causes most window
5577 * managers to honor the geometry.
5579 * Return value: %TRUE if string was parsed successfully
5582 gtk_window_parse_geometry (GtkWindow *window,
5583 const gchar *geometry)
5588 gboolean size_set, pos_set;
5590 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5591 g_return_val_if_fail (geometry != NULL, FALSE);
5593 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
5595 if ((result & WidthValue) == 0 ||
5598 if ((result & HeightValue) == 0 ||
5603 if ((result & WidthValue) || (result & HeightValue))
5605 GtkWindowGeometryInfo *info;
5606 info = gtk_window_get_geometry_info (window, FALSE);
5607 if (info && info->mask & GDK_HINT_RESIZE_INC)
5609 w *= info->geometry.width_inc;
5610 h *= info->geometry.height_inc;
5612 gtk_window_set_default_size (window, w, h);
5616 gtk_window_get_size (window, &w, &h);
5618 grav = GDK_GRAVITY_NORTH_WEST;
5620 if ((result & XNegative) && (result & YNegative))
5621 grav = GDK_GRAVITY_SOUTH_EAST;
5622 else if (result & XNegative)
5623 grav = GDK_GRAVITY_NORTH_EAST;
5624 else if (result & YNegative)
5625 grav = GDK_GRAVITY_SOUTH_WEST;
5627 if ((result & XValue) == 0)
5630 if ((result & YValue) == 0)
5633 if (grav == GDK_GRAVITY_SOUTH_WEST ||
5634 grav == GDK_GRAVITY_SOUTH_EAST)
5635 y = gdk_screen_height () - h + y;
5637 if (grav == GDK_GRAVITY_SOUTH_EAST ||
5638 grav == GDK_GRAVITY_NORTH_EAST)
5639 x = gdk_screen_width () - w + x;
5641 /* we don't let you put a window offscreen; maybe some people would
5642 * prefer to be able to, but it's kind of a bogus thing to do.
5651 if ((result & XValue) || (result & YValue))
5653 gtk_window_set_gravity (window, grav);
5654 gtk_window_move (window, x, y);
5658 if (size_set || pos_set)
5660 /* Set USSize, USPosition hints */
5661 GtkWindowGeometryInfo *info;
5663 info = gtk_window_get_geometry_info (window, TRUE);
5666 info->mask |= GDK_HINT_USER_POS;
5668 info->mask |= GDK_HINT_USER_SIZE;
5675 gtk_window_mnemonic_hash_foreach (gpointer key,
5681 GtkWindowKeysForeachFunc func;
5685 GtkWindowMnemonic *mnemonic = value;
5687 if (mnemonic->window == info->window)
5688 (*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
5692 _gtk_window_keys_foreach (GtkWindow *window,
5693 GtkWindowKeysForeachFunc func,
5700 GtkWindowKeysForeachFunc func;
5704 info.window = window;
5706 info.func_data = func_data;
5708 g_hash_table_foreach (mnemonic_hash_table,
5709 gtk_window_mnemonic_hash_foreach,
5712 groups = gtk_accel_groups_from_object (G_OBJECT (window));
5715 GtkAccelGroup *group = groups->data;
5718 for (i = 0; i < group->n_accels; i++)
5720 GtkAccelKey *key = &group->priv_accels[i].key;
5723 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
5726 groups = groups->next;
5731 gtk_window_keys_changed (GtkWindow *window)
5733 gtk_window_free_key_hash (window);
5734 gtk_window_get_key_hash (window);
5737 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
5739 struct _GtkWindowKeyEntry
5743 gboolean is_mnemonic;
5747 add_to_key_hash (GtkWindow *window,
5749 GdkModifierType modifiers,
5750 gboolean is_mnemonic,
5753 GtkKeyHash *key_hash = data;
5755 GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
5757 entry->keyval = keyval;
5758 entry->modifiers = modifiers;
5759 entry->is_mnemonic = is_mnemonic;
5761 /* GtkAccelGroup stores lowercased accelerators. To deal
5762 * with this, if <Shift> was specified, uppercase.
5764 if (modifiers & GDK_SHIFT_MASK)
5766 if (keyval == GDK_Tab)
5767 keyval = GDK_ISO_Left_Tab;
5769 keyval = gdk_keyval_to_upper (keyval);
5772 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
5776 gtk_window_get_key_hash (GtkWindow *window)
5778 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
5782 key_hash = _gtk_key_hash_new (gdk_keymap_get_default(), (GDestroyNotify)g_free);
5783 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
5784 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
5790 gtk_window_free_key_hash (GtkWindow *window)
5792 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
5795 _gtk_key_hash_free (key_hash);
5796 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
5801 * _gtk_window_activate_key:
5802 * @window: a #GtkWindow
5803 * @event: a #GdkEventKey
5805 * Activates mnemonics and accelerators for this #GtKWindow
5807 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
5810 _gtk_window_activate_key (GtkWindow *window,
5813 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
5814 GtkWindowKeyEntry *found_entry = NULL;
5818 gtk_window_keys_changed (window);
5819 key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
5824 GSList *entries = _gtk_key_hash_lookup (key_hash,
5825 event->hardware_keycode,
5826 event->state & gtk_accelerator_get_default_mod_mask (),
5830 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
5832 GtkWindowKeyEntry *entry = tmp_list->data;
5833 if (entry->is_mnemonic)
5835 found_entry = entry;
5840 if (!found_entry && entries)
5841 found_entry = entries->data;
5843 g_slist_free (entries);
5848 if (found_entry->is_mnemonic)
5849 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
5851 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);