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"
70 PROP_DESTROY_WITH_PARENT,
80 GdkPixmap *icon_pixmap;
83 guint using_default_icon : 1;
84 guint using_parent_icon : 1;
88 GdkGeometry geometry; /* Last set of geometry hints we set */
90 GdkRectangle configure_request;
91 } GtkWindowLastGeometryInfo;
93 struct _GtkWindowGeometryInfo
95 /* Properties that the app has set on the window
97 GdkGeometry geometry; /* Geometry hints */
99 GtkWidget *widget; /* subwidget to which hints apply */
100 /* from last gtk_window_resize () - if > 0, indicates that
101 * we should resize to this size.
106 /* From last gtk_window_move () prior to mapping -
107 * only used if initial_pos_set
112 /* Default size - used only the FIRST time we map a window,
117 /* whether to use initial_x, initial_y */
118 guint initial_pos_set : 1;
119 /* CENTER_ALWAYS or other position constraint changed since
120 * we sent the last configure request.
122 guint position_constraints_changed : 1;
124 /* if true, default_width, height come from gtk_window_parse_geometry,
125 * and thus should be multiplied by the increments and affect the
126 * geometry widget only
128 guint default_is_geometry : 1;
130 GtkWindowLastGeometryInfo last;
141 static void gtk_window_class_init (GtkWindowClass *klass);
142 static void gtk_window_init (GtkWindow *window);
143 static void gtk_window_dispose (GObject *object);
144 static void gtk_window_destroy (GtkObject *object);
145 static void gtk_window_finalize (GObject *object);
146 static void gtk_window_show (GtkWidget *widget);
147 static void gtk_window_hide (GtkWidget *widget);
148 static void gtk_window_map (GtkWidget *widget);
149 static void gtk_window_unmap (GtkWidget *widget);
150 static void gtk_window_realize (GtkWidget *widget);
151 static void gtk_window_unrealize (GtkWidget *widget);
152 static void gtk_window_size_request (GtkWidget *widget,
153 GtkRequisition *requisition);
154 static void gtk_window_size_allocate (GtkWidget *widget,
155 GtkAllocation *allocation);
156 static gint gtk_window_event (GtkWidget *widget,
158 static gboolean gtk_window_frame_event (GtkWindow *window,
160 static gint gtk_window_configure_event (GtkWidget *widget,
161 GdkEventConfigure *event);
162 static gint gtk_window_key_press_event (GtkWidget *widget,
164 static gint gtk_window_key_release_event (GtkWidget *widget,
166 static gint gtk_window_enter_notify_event (GtkWidget *widget,
167 GdkEventCrossing *event);
168 static gint gtk_window_leave_notify_event (GtkWidget *widget,
169 GdkEventCrossing *event);
170 static gint gtk_window_focus_in_event (GtkWidget *widget,
171 GdkEventFocus *event);
172 static gint gtk_window_focus_out_event (GtkWidget *widget,
173 GdkEventFocus *event);
174 static gint gtk_window_client_event (GtkWidget *widget,
175 GdkEventClient *event);
176 static void gtk_window_check_resize (GtkContainer *container);
177 static gint gtk_window_focus (GtkWidget *widget,
178 GtkDirectionType direction);
179 static void gtk_window_real_set_focus (GtkWindow *window,
182 static void gtk_window_real_activate_default (GtkWindow *window);
183 static void gtk_window_real_activate_focus (GtkWindow *window);
184 static void gtk_window_move_focus (GtkWindow *window,
185 GtkDirectionType dir);
186 static void gtk_window_keys_changed (GtkWindow *window);
187 static void gtk_window_read_rcfiles (GtkWidget *widget,
188 GdkEventClient *event);
189 static void gtk_window_paint (GtkWidget *widget,
191 static gint gtk_window_expose (GtkWidget *widget,
192 GdkEventExpose *event);
193 static void gtk_window_unset_transient_for (GtkWindow *window);
194 static void gtk_window_transient_parent_realized (GtkWidget *parent,
196 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
199 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
202 static void gtk_window_move_resize (GtkWindow *window);
203 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
205 GdkGeometry *geometry_b,
207 static void gtk_window_constrain_size (GtkWindow *window,
208 GdkGeometry *geometry,
214 static void gtk_window_constrain_position (GtkWindow *window,
219 static void gtk_window_compute_hints (GtkWindow *window,
220 GdkGeometry *new_geometry,
222 static void gtk_window_compute_configure_request (GtkWindow *window,
223 GdkRectangle *request,
224 GdkGeometry *geometry,
227 static void gtk_window_set_default_size_internal (GtkWindow *window,
228 gboolean change_width,
230 gboolean change_height,
232 gboolean is_geometry);
234 static void gtk_window_realize_icon (GtkWindow *window);
235 static void gtk_window_unrealize_icon (GtkWindow *window);
237 static void gtk_window_notify_keys_changed (GtkWindow *window);
238 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
239 static void gtk_window_free_key_hash (GtkWindow *window);
241 static GSList *toplevel_list = NULL;
242 static GHashTable *mnemonic_hash_table = NULL;
243 static GtkBinClass *parent_class = NULL;
244 static guint window_signals[LAST_SIGNAL] = { 0 };
245 static GList *default_icon_list = NULL;
246 static guint default_icon_serial = 0;
248 static void gtk_window_set_property (GObject *object,
252 static void gtk_window_get_property (GObject *object,
259 mnemonic_hash (gconstpointer key)
261 const GtkWindowMnemonic *k;
264 k = (GtkWindowMnemonic *)key;
266 h = (gulong) k->window;
267 h ^= k->keyval << 16;
268 h ^= k->keyval >> 16;
274 mnemonic_equal (gconstpointer a, gconstpointer b)
276 const GtkWindowMnemonic *ka;
277 const GtkWindowMnemonic *kb;
279 ka = (GtkWindowMnemonic *)a;
280 kb = (GtkWindowMnemonic *)b;
283 (ka->window == kb->window) &&
284 (ka->keyval == kb->keyval);
288 gtk_window_get_type (void)
290 static GtkType window_type = 0;
294 static const GtkTypeInfo window_info =
298 sizeof (GtkWindowClass),
299 (GtkClassInitFunc) gtk_window_class_init,
300 (GtkObjectInitFunc) gtk_window_init,
301 /* reserved_1 */ NULL,
302 /* reserved_2 */ NULL,
303 (GtkClassInitFunc) NULL,
306 window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
313 add_tab_bindings (GtkBindingSet *binding_set,
314 GdkModifierType modifiers,
315 GtkDirectionType direction)
317 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
319 GTK_TYPE_DIRECTION_TYPE, direction);
320 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
322 GTK_TYPE_DIRECTION_TYPE, direction);
326 add_arrow_bindings (GtkBindingSet *binding_set,
328 GtkDirectionType direction)
330 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
332 gtk_binding_entry_add_signal (binding_set, keysym, 0,
334 GTK_TYPE_DIRECTION_TYPE, direction);
335 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
337 GTK_TYPE_DIRECTION_TYPE, direction);
338 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
340 GTK_TYPE_DIRECTION_TYPE, direction);
341 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
343 GTK_TYPE_DIRECTION_TYPE, direction);
348 gtk_window_class_init (GtkWindowClass *klass)
350 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
351 GtkObjectClass *object_class;
352 GtkWidgetClass *widget_class;
353 GtkContainerClass *container_class;
354 GtkBindingSet *binding_set;
356 object_class = (GtkObjectClass*) klass;
357 widget_class = (GtkWidgetClass*) klass;
358 container_class = (GtkContainerClass*) klass;
360 parent_class = gtk_type_class (gtk_bin_get_type ());
362 mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
364 gobject_class->dispose = gtk_window_dispose;
365 gobject_class->finalize = gtk_window_finalize;
367 gobject_class->set_property = gtk_window_set_property;
368 gobject_class->get_property = gtk_window_get_property;
370 object_class->destroy = gtk_window_destroy;
372 widget_class->show = gtk_window_show;
373 widget_class->hide = gtk_window_hide;
374 widget_class->map = gtk_window_map;
375 widget_class->unmap = gtk_window_unmap;
376 widget_class->realize = gtk_window_realize;
377 widget_class->unrealize = gtk_window_unrealize;
378 widget_class->size_request = gtk_window_size_request;
379 widget_class->size_allocate = gtk_window_size_allocate;
380 widget_class->configure_event = gtk_window_configure_event;
381 widget_class->key_press_event = gtk_window_key_press_event;
382 widget_class->key_release_event = gtk_window_key_release_event;
383 widget_class->enter_notify_event = gtk_window_enter_notify_event;
384 widget_class->leave_notify_event = gtk_window_leave_notify_event;
385 widget_class->focus_in_event = gtk_window_focus_in_event;
386 widget_class->focus_out_event = gtk_window_focus_out_event;
387 widget_class->client_event = gtk_window_client_event;
388 widget_class->focus = gtk_window_focus;
390 widget_class->expose_event = gtk_window_expose;
392 container_class->check_resize = gtk_window_check_resize;
394 klass->set_focus = gtk_window_real_set_focus;
395 klass->frame_event = gtk_window_frame_event;
397 klass->activate_default = gtk_window_real_activate_default;
398 klass->activate_focus = gtk_window_real_activate_focus;
399 klass->move_focus = gtk_window_move_focus;
400 klass->keys_changed = gtk_window_keys_changed;
403 g_object_class_install_property (gobject_class,
405 g_param_spec_enum ("type",
407 _("The type of the window"),
408 GTK_TYPE_WINDOW_TYPE,
410 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
413 g_object_class_install_property (gobject_class,
415 g_param_spec_string ("title",
417 _("The title of the window"),
421 g_object_class_install_property (gobject_class,
423 g_param_spec_boolean ("allow_shrink",
425 /* xgettext:no-c-format */
426 _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea."),
430 g_object_class_install_property (gobject_class,
432 g_param_spec_boolean ("allow_grow",
434 _("If TRUE, users can expand the window beyond its minimum size."),
438 g_object_class_install_property (gobject_class,
440 g_param_spec_boolean ("resizable",
442 _("If TRUE, users can resize the window."),
446 g_object_class_install_property (gobject_class,
448 g_param_spec_boolean ("modal",
450 _("If TRUE, the window is modal (other windows are not usable while this one is up)."),
454 g_object_class_install_property (gobject_class,
456 g_param_spec_enum ("window_position",
457 _("Window Position"),
458 _("The initial position of the window."),
459 GTK_TYPE_WINDOW_POSITION,
463 g_object_class_install_property (gobject_class,
465 g_param_spec_int ("default_width",
467 _("The default width of the window, used when initially showing the window."),
473 g_object_class_install_property (gobject_class,
475 g_param_spec_int ("default_height",
477 _("The default height of the window, used when initially showing the window."),
483 g_object_class_install_property (gobject_class,
484 PROP_DESTROY_WITH_PARENT,
485 g_param_spec_boolean ("destroy_with_parent",
486 _("Destroy with Parent"),
487 _("If this window should be destroyed when the parent is destroyed"),
491 g_object_class_install_property (gobject_class,
493 g_param_spec_object ("icon",
495 _("Icon for this window"),
499 g_object_class_install_property (gobject_class,
501 g_param_spec_object ("screen",
503 _("The screen where this window will be displayed."),
507 window_signals[SET_FOCUS] =
508 g_signal_new ("set_focus",
509 G_TYPE_FROM_CLASS (object_class),
511 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
513 _gtk_marshal_VOID__OBJECT,
517 window_signals[FRAME_EVENT] =
518 g_signal_new ("frame_event",
519 G_TYPE_FROM_CLASS(object_class),
521 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
522 _gtk_boolean_handled_accumulator, NULL,
523 _gtk_marshal_BOOLEAN__BOXED,
527 window_signals[ACTIVATE_FOCUS] =
528 g_signal_new ("activate_focus",
529 G_OBJECT_CLASS_TYPE (object_class),
530 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
531 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_focus),
533 _gtk_marshal_VOID__VOID,
537 window_signals[ACTIVATE_DEFAULT] =
538 g_signal_new ("activate_default",
539 G_OBJECT_CLASS_TYPE (object_class),
540 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
541 GTK_SIGNAL_OFFSET (GtkWindowClass, activate_default),
543 _gtk_marshal_VOID__VOID,
547 window_signals[MOVE_FOCUS] =
548 g_signal_new ("move_focus",
549 G_OBJECT_CLASS_TYPE (object_class),
550 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
551 GTK_SIGNAL_OFFSET (GtkWindowClass, move_focus),
553 _gtk_marshal_VOID__ENUM,
556 GTK_TYPE_DIRECTION_TYPE);
558 window_signals[KEYS_CHANGED] =
559 g_signal_new ("keys_changed",
560 G_OBJECT_CLASS_TYPE (object_class),
562 GTK_SIGNAL_OFFSET (GtkWindowClass, keys_changed),
564 gtk_marshal_VOID__VOID,
572 binding_set = gtk_binding_set_by_class (klass);
574 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
575 "activate_focus", 0);
576 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
577 "activate_focus", 0);
579 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
580 "activate_default", 0);
582 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
583 "activate_default", 0);
585 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
586 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
587 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
588 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
590 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
591 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
592 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
593 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
597 gtk_window_init (GtkWindow *window)
599 GdkColormap *colormap;
601 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
602 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
604 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
606 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
608 window->title = NULL;
609 window->wmclass_name = g_strdup (g_get_prgname ());
610 window->wmclass_class = g_strdup (gdk_get_program_class ());
611 window->wm_role = NULL;
612 window->geometry_info = NULL;
613 window->type = GTK_WINDOW_TOPLEVEL;
614 window->focus_widget = NULL;
615 window->default_widget = NULL;
616 window->configure_request_count = 0;
617 window->allow_shrink = FALSE;
618 window->allow_grow = TRUE;
619 window->configure_notify_received = FALSE;
620 window->position = GTK_WIN_POS_NONE;
621 window->need_default_size = TRUE;
622 window->need_default_position = TRUE;
623 window->modal = FALSE;
624 window->frame = NULL;
625 window->has_frame = FALSE;
626 window->frame_left = 0;
627 window->frame_right = 0;
628 window->frame_top = 0;
629 window->frame_bottom = 0;
630 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
631 window->gravity = GDK_GRAVITY_NORTH_WEST;
632 window->decorated = TRUE;
633 window->mnemonic_modifier = GDK_MOD1_MASK;
634 window->screen = gdk_get_default_screen ();
636 colormap = _gtk_widget_peek_colormap ();
638 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
640 gtk_widget_ref (GTK_WIDGET (window));
641 gtk_object_sink (GTK_OBJECT (window));
642 window->has_user_ref_count = TRUE;
643 toplevel_list = g_slist_prepend (toplevel_list, window);
645 gtk_decorated_window_init (window);
647 gtk_signal_connect (GTK_OBJECT (window),
649 GTK_SIGNAL_FUNC (gtk_window_event),
654 gtk_window_set_property (GObject *object,
661 window = GTK_WINDOW (object);
666 window->type = g_value_get_enum (value);
669 gtk_window_set_title (window, g_value_get_string (value));
671 case PROP_ALLOW_SHRINK:
672 window->allow_shrink = g_value_get_boolean (value);
673 gtk_widget_queue_resize (GTK_WIDGET (window));
675 case PROP_ALLOW_GROW:
676 window->allow_grow = g_value_get_boolean (value);
677 gtk_widget_queue_resize (GTK_WIDGET (window));
678 g_object_notify (G_OBJECT (window), "resizable");
681 window->allow_grow = g_value_get_boolean (value);
682 gtk_widget_queue_resize (GTK_WIDGET (window));
683 g_object_notify (G_OBJECT (window), "allow_grow");
686 gtk_window_set_modal (window, g_value_get_boolean (value));
689 gtk_window_set_position (window, g_value_get_enum (value));
691 case PROP_DEFAULT_WIDTH:
692 gtk_window_set_default_size_internal (window,
693 TRUE, g_value_get_int (value),
696 case PROP_DEFAULT_HEIGHT:
697 gtk_window_set_default_size_internal (window,
699 TRUE, g_value_get_int (value), FALSE);
701 case PROP_DESTROY_WITH_PARENT:
702 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
705 gtk_window_set_icon (window,
706 g_value_get_object (value));
709 gtk_window_set_screen (window, g_value_get_object (value));
717 gtk_window_get_property (GObject *object,
724 window = GTK_WINDOW (object);
728 GtkWindowGeometryInfo *info;
730 g_value_set_enum (value, window->type);
733 g_value_set_string (value, window->title);
735 case PROP_ALLOW_SHRINK:
736 g_value_set_boolean (value, window->allow_shrink);
738 case PROP_ALLOW_GROW:
739 g_value_set_boolean (value, window->allow_grow);
742 g_value_set_boolean (value, window->allow_grow);
745 g_value_set_boolean (value, window->modal);
748 g_value_set_enum (value, window->position);
750 case PROP_DEFAULT_WIDTH:
751 info = gtk_window_get_geometry_info (window, FALSE);
753 g_value_set_int (value, -1);
755 g_value_set_int (value, info->default_width);
757 case PROP_DEFAULT_HEIGHT:
758 info = gtk_window_get_geometry_info (window, FALSE);
760 g_value_set_int (value, -1);
762 g_value_set_int (value, info->default_height);
764 case PROP_DESTROY_WITH_PARENT:
765 g_value_set_boolean (value, window->destroy_with_parent);
768 g_value_set_object (value, gtk_window_get_icon (window));
771 g_value_set_object (value, window->screen);
774 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
781 * @type: type of window
783 * Creates a new #GtkWindow, which is a toplevel window that can
784 * contain other widgets. Nearly always, the type of the window should
785 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
786 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
787 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
788 * dialogs, though in some other toolkits dialogs are called "popups".
789 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
790 * On X11, popup windows are not controlled by the <link
791 * linkend="gtk-X11-arch">window manager</link>.
793 * If you simply want an undecorated window (no window borders), use
794 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
796 * Return value: a new #GtkWindow.
799 gtk_window_new (GtkWindowType type)
803 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
805 window = gtk_type_new (GTK_TYPE_WINDOW);
809 return GTK_WIDGET (window);
813 * gtk_window_set_title:
814 * @window: a #GtkWindow
815 * @title: title of the window
817 * Sets the title of the #GtkWindow. The title of a window will be
818 * displayed in its title bar; on the X Window System, the title bar
819 * is rendered by the <link linkend="gtk-X11-arch">window
820 * manager</link>, so exactly how the title appears to users may vary
821 * according to a user's exact configuration. The title should help a
822 * user distinguish this window from other windows they may have
823 * open. A good title might include the application name and current
824 * document filename, for example.
828 gtk_window_set_title (GtkWindow *window,
831 g_return_if_fail (GTK_IS_WINDOW (window));
834 g_free (window->title);
835 window->title = g_strdup (title);
837 if (GTK_WIDGET_REALIZED (window))
839 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
841 gtk_decorated_window_set_title (window, title);
844 g_object_notify (G_OBJECT (window), "title");
848 * gtk_window_get_title:
849 * @window: a #GtkWindow
851 * Retrieves the title of the window. See gtk_window_set_title().
853 * Return value: the title of the window, or %NULL if none has
854 * been set explicitely. The returned string is owned by the widget
855 * and must not be modified or freed.
857 G_CONST_RETURN gchar *
858 gtk_window_get_title (GtkWindow *window)
860 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
862 return window->title;
866 * gtk_window_set_wmclass:
867 * @window: a #GtkWindow
868 * @wmclass_name: window name hint
869 * @wmclass_class: window class hint
871 * Don't use this function. It sets the X Window System "class" and
872 * "name" hints for a window. According to the ICCCM, you should
873 * always set these to the same value for all windows in an
874 * application, and GTK+ sets them to that value by default, so calling
875 * this function is sort of pointless. However, you may want to call
876 * gtk_window_set_role() on each window in your application, for the
877 * benefit of the session manager. Setting the role allows the window
878 * manager to restore window positions when loading a saved session.
882 gtk_window_set_wmclass (GtkWindow *window,
883 const gchar *wmclass_name,
884 const gchar *wmclass_class)
886 g_return_if_fail (GTK_IS_WINDOW (window));
888 g_free (window->wmclass_name);
889 window->wmclass_name = g_strdup (wmclass_name);
891 g_free (window->wmclass_class);
892 window->wmclass_class = g_strdup (wmclass_class);
894 if (GTK_WIDGET_REALIZED (window))
895 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
899 * gtk_window_set_role:
900 * @window: a #GtkWindow
901 * @role: unique identifier for the window to be used when restoring a session
903 * This function is only useful on X11, not with other GTK+ targets.
905 * In combination with the window title, the window role allows a
906 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
907 * same" window when an application is restarted. So for example you
908 * might set the "toolbox" role on your app's toolbox window, so that
909 * when the user restarts their session, the window manager can put
910 * the toolbox back in the same place.
912 * If a window already has a unique title, you don't need to set the
913 * role, since the WM can use the title to identify the window when
914 * restoring the session.
918 gtk_window_set_role (GtkWindow *window,
921 g_return_if_fail (GTK_IS_WINDOW (window));
923 if (role == window->wm_role)
926 g_free (window->wm_role);
927 window->wm_role = g_strdup (role);
929 if (GTK_WIDGET_REALIZED (window))
930 g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
934 * gtk_window_get_role:
935 * @window: a #GtkWindow
937 * Returns the role of the window. See gtk_window_set_role() for
938 * further explanation.
940 * Return value: the role of the window if set, or %NULL. The
941 * returned is owned by the widget and must not be modified
944 G_CONST_RETURN gchar *
945 gtk_window_get_role (GtkWindow *window)
947 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
949 return window->wm_role;
953 * gtk_window_set_focus:
954 * @window: a #GtkWindow
955 * @focus: widget to be the new focus widget, or %NULL to unset
956 * any focus widget for the toplevel window.
958 * If @focus is not the current focus widget, and is focusable, sets
959 * it as the focus widget for the window. If @focus is %NULL, unsets
960 * the focus widget for this window. To set the focus to a particular
961 * widget in the toplevel, it is usually more convenient to use
962 * gtk_widget_grab_focus() instead of this function.
965 gtk_window_set_focus (GtkWindow *window,
968 g_return_if_fail (GTK_IS_WINDOW (window));
971 g_return_if_fail (GTK_IS_WIDGET (focus));
972 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
976 gtk_widget_grab_focus (focus);
979 /* Clear the existing focus chain, so that when we focus into
980 * the window again, we start at the beginnning.
982 GtkWidget *widget = window->focus_widget;
985 while (widget->parent)
987 widget = widget->parent;
988 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
992 _gtk_window_internal_set_focus (window, NULL);
997 _gtk_window_internal_set_focus (GtkWindow *window,
1000 g_return_if_fail (GTK_IS_WINDOW (window));
1002 if ((window->focus_widget != focus) ||
1003 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1004 gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
1008 * gtk_window_set_default:
1009 * @window: a #GtkWindow
1010 * @default_widget: widget to be the default, or %NULL to unset the
1011 * default widget for the toplevel.
1013 * The default widget is the widget that's activated when the user
1014 * presses Enter in a dialog (for example). This function sets or
1015 * unsets the default widget for a #GtkWindow about. When setting
1016 * (rather than unsetting) the default widget it's generally easier to
1017 * call gtk_widget_grab_focus() on the widget. Before making a widget
1018 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1019 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1022 gtk_window_set_default (GtkWindow *window,
1023 GtkWidget *default_widget)
1025 g_return_if_fail (GTK_IS_WINDOW (window));
1028 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1030 if (window->default_widget != default_widget)
1032 GtkWidget *old_default_widget = NULL;
1035 g_object_ref (default_widget);
1037 if (window->default_widget)
1039 old_default_widget = window->default_widget;
1041 if (window->focus_widget != window->default_widget ||
1042 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1043 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1044 gtk_widget_queue_draw (window->default_widget);
1047 window->default_widget = default_widget;
1049 if (window->default_widget)
1051 if (window->focus_widget == NULL ||
1052 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1053 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1054 gtk_widget_queue_draw (window->default_widget);
1057 if (old_default_widget)
1058 g_object_notify (G_OBJECT (old_default_widget), "has_default");
1062 g_object_notify (G_OBJECT (default_widget), "has_default");
1063 g_object_unref (default_widget);
1069 gtk_window_set_policy (GtkWindow *window,
1070 gboolean allow_shrink,
1071 gboolean allow_grow,
1072 gboolean auto_shrink)
1074 g_return_if_fail (GTK_IS_WINDOW (window));
1076 window->allow_shrink = (allow_shrink != FALSE);
1077 window->allow_grow = (allow_grow != FALSE);
1079 g_object_freeze_notify (G_OBJECT (window));
1080 g_object_notify (G_OBJECT (window), "allow_shrink");
1081 g_object_notify (G_OBJECT (window), "allow_grow");
1082 g_object_notify (G_OBJECT (window), "resizable");
1083 g_object_thaw_notify (G_OBJECT (window));
1085 gtk_widget_queue_resize (GTK_WIDGET (window));
1089 handle_keys_changed (gpointer data)
1093 GDK_THREADS_ENTER ();
1094 window = GTK_WINDOW (data);
1096 if (window->keys_changed_handler)
1098 gtk_idle_remove (window->keys_changed_handler);
1099 window->keys_changed_handler = 0;
1102 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1103 GDK_THREADS_LEAVE ();
1109 gtk_window_notify_keys_changed (GtkWindow *window)
1111 if (!window->keys_changed_handler)
1112 window->keys_changed_handler = gtk_idle_add (handle_keys_changed, window);
1116 * gtk_window_add_accel_group:
1117 * @window: window to attach accelerator group to
1118 * @accel_group: a #GtkAccelGroup
1120 * Associate @accel_group with @window, such that calling
1121 * gtk_accel_groups_activate() on @window will activate accelerators
1125 gtk_window_add_accel_group (GtkWindow *window,
1126 GtkAccelGroup *accel_group)
1128 g_return_if_fail (GTK_IS_WINDOW (window));
1129 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1131 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1132 g_signal_connect_object (accel_group, "accel_changed",
1133 G_CALLBACK (gtk_window_notify_keys_changed),
1134 window, G_CONNECT_SWAPPED);
1138 * gtk_window_remove_accel_group:
1139 * @window: a #GtkWindow
1140 * @accel_group: a #GtkAccelGroup
1142 * Reverses the effects of gtk_window_add_accel_group().
1145 gtk_window_remove_accel_group (GtkWindow *window,
1146 GtkAccelGroup *accel_group)
1148 g_return_if_fail (GTK_IS_WINDOW (window));
1149 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1151 g_signal_handlers_disconnect_by_func (accel_group,
1152 (gpointer) gtk_window_notify_keys_changed,
1154 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1158 * gtk_window_add_mnemonic:
1159 * @window: a #GtkWindow
1160 * @keyval: the mnemonic
1161 * @target: the widget that gets activated by the mnemonic
1163 * Adds a mnemonic to this window.
1166 gtk_window_add_mnemonic (GtkWindow *window,
1170 GtkWindowMnemonic key;
1171 GtkWindowMnemonic *mnemonic;
1173 g_return_if_fail (GTK_IS_WINDOW (window));
1174 g_return_if_fail (GTK_IS_WIDGET (target));
1176 key.window = window;
1177 key.keyval = keyval;
1178 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1182 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1183 mnemonic->targets = g_slist_append (mnemonic->targets, target);
1187 mnemonic = g_new (GtkWindowMnemonic, 1);
1189 mnemonic->targets = g_slist_prepend (NULL, target);
1190 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1192 gtk_window_notify_keys_changed (window);
1196 * gtk_window_remove_mnemonic:
1197 * @window: a #GtkWindow
1198 * @keyval: the mnemonic
1199 * @target: the widget that gets activated by the mnemonic
1201 * Removes a mnemonic from this window.
1204 gtk_window_remove_mnemonic (GtkWindow *window,
1208 GtkWindowMnemonic key;
1209 GtkWindowMnemonic *mnemonic;
1211 g_return_if_fail (GTK_IS_WINDOW (window));
1212 g_return_if_fail (GTK_IS_WIDGET (target));
1214 key.window = window;
1215 key.keyval = keyval;
1216 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1218 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1220 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1221 if (mnemonic->targets == NULL)
1223 g_hash_table_remove (mnemonic_hash_table, mnemonic);
1226 gtk_window_notify_keys_changed (window);
1230 * gtk_window_mnemonic_activate:
1231 * @window: a #GtkWindow
1232 * @keyval: the mnemonic
1233 * @modifier: the modifiers
1234 * @returns: %TRUE if the activation is done.
1236 * Activates the targets associated with the mnemonic.
1239 gtk_window_mnemonic_activate (GtkWindow *window,
1241 GdkModifierType modifier)
1243 GtkWindowMnemonic key;
1244 GtkWindowMnemonic *mnemonic;
1246 GtkWidget *widget, *chosen_widget;
1247 gboolean overloaded;
1249 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1251 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1254 key.window = window;
1255 key.keyval = keyval;
1256 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1262 chosen_widget = NULL;
1263 list = mnemonic->targets;
1266 widget = GTK_WIDGET (list->data);
1268 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1269 GTK_WIDGET_MAPPED (widget))
1277 chosen_widget = widget;
1279 list = g_slist_next (list);
1284 /* For round robin we put the activated entry on
1285 * the end of the list after activation
1287 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1288 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1290 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1296 * gtk_window_set_mnemonic_modifier:
1297 * @window: a #GtkWindow
1298 * @modifier: the modifier mask used to activate
1299 * mnemonics on this window.
1301 * Sets the mnemonic modifier for this window.
1304 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1305 GdkModifierType modifier)
1307 g_return_if_fail (GTK_IS_WINDOW (window));
1308 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1310 window->mnemonic_modifier = modifier;
1311 gtk_window_notify_keys_changed (window);
1315 * gtk_window_get_mnemonic_modifier:
1316 * @window: a #GtkWindow
1318 * Returns the mnemonic modifier for this window. See
1319 * gtk_window_set_mnemonic_modifier().
1321 * Return value: the modifier mask used to activate
1322 * mnemonics on this window.
1325 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1327 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1329 return window->mnemonic_modifier;
1333 * gtk_window_set_position:
1334 * @window: a #GtkWindow.
1335 * @position: a position constraint.
1337 * Sets a position constraint for this window. If the old or new
1338 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1339 * the window to be repositioned to satisfy the new constraint.
1342 gtk_window_set_position (GtkWindow *window,
1343 GtkWindowPosition position)
1345 g_return_if_fail (GTK_IS_WINDOW (window));
1347 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1348 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1350 GtkWindowGeometryInfo *info;
1352 info = gtk_window_get_geometry_info (window, TRUE);
1354 /* this flag causes us to re-request the CENTER_ALWAYS
1355 * constraint in gtk_window_move_resize(), see
1356 * comment in that function.
1358 info->position_constraints_changed = TRUE;
1360 gtk_widget_queue_resize (GTK_WIDGET (window));
1363 window->position = position;
1365 g_object_notify (G_OBJECT (window), "window_position");
1369 gtk_window_activate_focus (GtkWindow *window)
1371 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1373 if (window->focus_widget)
1375 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1376 gtk_widget_activate (window->focus_widget);
1384 * gtk_window_get_focus:
1385 * @window: a #GtkWindow
1387 * Retrieves the current focused widget within the window.
1388 * Note that this is the widget that would have the focus
1389 * if the toplevel window focused; if the toplevel window
1390 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1391 * not be %TRUE for the widget.
1393 * Return value: the currently focused widget.
1396 gtk_window_get_focus (GtkWindow *window)
1398 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1400 return window->focus_widget;
1404 gtk_window_activate_default (GtkWindow *window)
1406 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1408 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1409 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1411 gtk_widget_activate (window->default_widget);
1414 else if (window->focus_widget)
1416 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1417 gtk_widget_activate (window->focus_widget);
1425 * gtk_window_set_modal:
1426 * @window: a #GtkWindow
1427 * @modal: whether the window is modal
1429 * Sets a window modal or non-modal. Modal windows prevent interaction
1430 * with other windows in the same application. To keep modal dialogs
1431 * on top of main application windows, use
1432 * gtk_window_set_transient_for() to make the dialog transient for the
1433 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1434 * will then disallow lowering the dialog below the parent.
1439 gtk_window_set_modal (GtkWindow *window,
1442 g_return_if_fail (GTK_IS_WINDOW (window));
1444 window->modal = modal != FALSE;
1446 /* adjust desired modality state */
1447 if (GTK_WIDGET_VISIBLE (window) && window->modal)
1448 gtk_grab_add (GTK_WIDGET (window));
1450 gtk_grab_remove (GTK_WIDGET (window));
1452 g_object_notify (G_OBJECT (window), "modal");
1456 * gtk_window_get_modal:
1457 * @window: a #GtkWindow
1459 * Returns whether the window is modal. See gtk_window_set_modal().
1461 * Return value: %TRUE if the window is set to be modal and
1462 * establishes a grab when shown
1465 gtk_window_get_modal (GtkWindow *window)
1467 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1469 return window->modal;
1473 * gtk_window_list_toplevels:
1475 * Returns a list of all existing toplevel windows. The widgets
1476 * in the list are not individually referenced. If you want
1477 * to iterate through the list and perform actions involving
1478 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1479 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1480 * then unref all the widgets afterwards.
1482 * Return value: list of toplevel widgets
1485 gtk_window_list_toplevels (void)
1490 for (slist = toplevel_list; slist; slist = slist->next)
1491 list = g_list_prepend (list, slist->data);
1497 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1499 GList *embedded_windows;
1501 g_return_if_fail (GTK_IS_WINDOW (window));
1503 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1504 if (embedded_windows)
1505 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1506 g_quark_from_static_string ("gtk-embedded"));
1507 embedded_windows = g_list_prepend (embedded_windows,
1508 GUINT_TO_POINTER (xid));
1510 gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
1513 (GtkDestroyNotify) g_list_free : NULL);
1517 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1519 GList *embedded_windows;
1522 g_return_if_fail (GTK_IS_WINDOW (window));
1524 embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1525 if (embedded_windows)
1526 gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
1527 g_quark_from_static_string ("gtk-embedded"));
1529 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1532 embedded_windows = g_list_remove_link (embedded_windows, node);
1533 g_list_free_1 (node);
1536 gtk_object_set_data_full (GTK_OBJECT (window),
1537 "gtk-embedded", embedded_windows,
1539 (GtkDestroyNotify) g_list_free : NULL);
1543 _gtk_window_reposition (GtkWindow *window,
1547 g_return_if_fail (GTK_IS_WINDOW (window));
1549 gtk_window_move (window, x, y);
1553 gtk_window_dispose (GObject *object)
1555 GtkWindow *window = GTK_WINDOW (object);
1557 gtk_window_set_focus (window, NULL);
1558 gtk_window_set_default (window, NULL);
1560 G_OBJECT_CLASS (parent_class)->dispose (object);
1564 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1566 gtk_widget_destroy (GTK_WIDGET (child));
1570 connect_parent_destroyed (GtkWindow *window)
1572 if (window->transient_parent)
1574 gtk_signal_connect (GTK_OBJECT (window->transient_parent),
1576 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1582 disconnect_parent_destroyed (GtkWindow *window)
1584 if (window->transient_parent)
1586 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1587 GTK_SIGNAL_FUNC (parent_destroyed_callback),
1593 gtk_window_transient_parent_realized (GtkWidget *parent,
1596 if (GTK_WIDGET_REALIZED (window))
1597 gdk_window_set_transient_for (window->window, parent->window);
1601 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1604 if (GTK_WIDGET_REALIZED (window))
1605 gdk_property_delete (window->window,
1606 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1610 gtk_window_unset_transient_for (GtkWindow *window)
1612 if (window->transient_parent)
1614 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1615 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1617 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1618 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1620 gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1621 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1622 &window->transient_parent);
1624 if (window->destroy_with_parent)
1625 disconnect_parent_destroyed (window);
1627 window->transient_parent = NULL;
1632 * gtk_window_set_transient_for:
1633 * @window: a #GtkWindow
1634 * @parent: parent window
1636 * Dialog windows should be set transient for the main application
1637 * window they were spawned from. This allows <link
1638 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1639 * dialog on top of the main window, or center the dialog over the
1640 * main window. gtk_dialog_new_with_buttons() and other convenience
1641 * functions in GTK+ will sometimes call
1642 * gtk_window_set_transient_for() on your behalf.
1644 * On Windows, this function will and put the child window
1645 * on top of the parent, much as the window manager would have
1650 gtk_window_set_transient_for (GtkWindow *window,
1653 g_return_if_fail (GTK_IS_WINDOW (window));
1654 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1655 g_return_if_fail (window != parent);
1658 if (window->transient_parent)
1660 if (GTK_WIDGET_REALIZED (window) &&
1661 GTK_WIDGET_REALIZED (window->transient_parent) &&
1662 (!parent || !GTK_WIDGET_REALIZED (parent)))
1663 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1664 GTK_WIDGET (window));
1666 gtk_window_unset_transient_for (window);
1669 window->transient_parent = parent;
1673 gtk_signal_connect (GTK_OBJECT (parent), "destroy",
1674 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1675 &window->transient_parent);
1676 gtk_signal_connect (GTK_OBJECT (parent), "realize",
1677 GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1679 gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
1680 GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1683 window->screen = parent->screen;
1685 if (window->destroy_with_parent)
1686 connect_parent_destroyed (window);
1688 if (GTK_WIDGET_REALIZED (window) &&
1689 GTK_WIDGET_REALIZED (parent))
1690 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1691 GTK_WIDGET (window));
1696 * gtk_window_get_transient_for:
1697 * @window: a #GtkWindow
1699 * Fetches the transient parent for this window. See
1700 * gtk_window_set_transient_for().
1702 * Return value: the transient parent for this window, or %NULL
1703 * if no transient parent has been set.
1706 gtk_window_get_transient_for (GtkWindow *window)
1708 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1710 return window->transient_parent;
1714 * gtk_window_set_type_hint:
1715 * @window: a #GtkWindow
1716 * @hint: the window type
1718 * By setting the type hint for the window, you allow the window
1719 * manager to decorate and handle the window in a way which is
1720 * suitable to the function of the window in your application.
1722 * This function should be called before the window becomes visible.
1724 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1725 * will sometimes call gtk_window_set_type_hint() on your behalf.
1729 gtk_window_set_type_hint (GtkWindow *window,
1730 GdkWindowTypeHint hint)
1732 g_return_if_fail (GTK_IS_WINDOW (window));
1733 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1734 window->type_hint = hint;
1738 * gtk_window_get_type_hint:
1739 * @window: a #GtkWindow
1741 * Gets the type hint for this window. See gtk_window_set_type_hint().
1743 * Return value: the type hint for @window.
1746 gtk_window_get_type_hint (GtkWindow *window)
1748 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1750 return window->type_hint;
1754 * gtk_window_set_destroy_with_parent:
1755 * @window: a #GtkWindow
1756 * @setting: whether to destroy @window with its transient parent
1758 * If @setting is %TRUE, then destroying the transient parent of @window
1759 * will also destroy @window itself. This is useful for dialogs that
1760 * shouldn't persist beyond the lifetime of the main window they're
1761 * associated with, for example.
1764 gtk_window_set_destroy_with_parent (GtkWindow *window,
1767 g_return_if_fail (GTK_IS_WINDOW (window));
1769 if (window->destroy_with_parent == (setting != FALSE))
1772 if (window->destroy_with_parent)
1774 disconnect_parent_destroyed (window);
1778 connect_parent_destroyed (window);
1781 window->destroy_with_parent = setting;
1783 g_object_notify (G_OBJECT (window), "destroy_with_parent");
1787 * gtk_window_get_destroy_with_parent:
1788 * @window: a #GtkWindow
1790 * Returns whether the window will be destroyed with its transient parent. See
1791 * gtk_window_set_destroy_with_parent ().
1793 * Return value: %TRUE if the window will be destroyed with its transient parent.
1796 gtk_window_get_destroy_with_parent (GtkWindow *window)
1798 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1800 return window->destroy_with_parent;
1803 static GtkWindowGeometryInfo*
1804 gtk_window_get_geometry_info (GtkWindow *window,
1807 GtkWindowGeometryInfo *info;
1809 info = window->geometry_info;
1810 if (!info && create)
1812 info = g_new0 (GtkWindowGeometryInfo, 1);
1814 info->default_width = -1;
1815 info->default_height = -1;
1816 info->resize_width = -1;
1817 info->resize_height = -1;
1818 info->initial_x = 0;
1819 info->initial_y = 0;
1820 info->initial_pos_set = FALSE;
1821 info->default_is_geometry = FALSE;
1822 info->position_constraints_changed = FALSE;
1823 info->last.configure_request.x = 0;
1824 info->last.configure_request.y = 0;
1825 info->last.configure_request.width = -1;
1826 info->last.configure_request.height = -1;
1827 info->widget = NULL;
1829 window->geometry_info = info;
1836 * gtk_window_set_geometry_hints:
1837 * @window: a #GtkWindow
1838 * @geometry_widget: widget the geometry hints will be applied to
1839 * @geometry: struct containing geometry information
1840 * @geom_mask: mask indicating which struct fields should be paid attention to
1842 * This function sets up hints about how a window can be resized by
1843 * the user. You can set a minimum and maximum size; allowed resize
1844 * increments (e.g. for xterm, you can only resize by the size of a
1845 * character); aspect ratios; and more. See the #GdkGeometry struct.
1849 gtk_window_set_geometry_hints (GtkWindow *window,
1850 GtkWidget *geometry_widget,
1851 GdkGeometry *geometry,
1852 GdkWindowHints geom_mask)
1854 GtkWindowGeometryInfo *info;
1856 g_return_if_fail (GTK_IS_WINDOW (window));
1857 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
1859 info = gtk_window_get_geometry_info (window, TRUE);
1862 gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1863 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1866 info->widget = geometry_widget;
1868 gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
1869 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1873 info->geometry = *geometry;
1875 /* We store gravity in window->gravity not in the hints. */
1876 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
1878 if (geom_mask & GDK_HINT_WIN_GRAVITY)
1880 gtk_window_set_gravity (window, geometry->win_gravity);
1883 gtk_widget_queue_resize (GTK_WIDGET (window));
1887 * gtk_window_set_decorated:
1888 * @window: a #GtkWindow
1889 * @setting: %TRUE to decorate the window
1891 * By default, windows are decorated with a title bar, resize
1892 * controls, etc. Some <link linkend="gtk-X11-arch">window
1893 * managers</link> allow GTK+ to disable these decorations, creating a
1894 * borderless window. If you set the decorated property to %FALSE
1895 * using this function, GTK+ will do its best to convince the window
1896 * manager not to decorate the window.
1898 * On Windows, this function always works, since there's no window manager
1903 gtk_window_set_decorated (GtkWindow *window,
1906 g_return_if_fail (GTK_IS_WINDOW (window));
1908 setting = setting != FALSE;
1910 if (setting == window->decorated)
1913 window->decorated = setting;
1915 if (GTK_WIDGET (window)->window)
1917 if (window->decorated)
1918 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1921 gdk_window_set_decorations (GTK_WIDGET (window)->window,
1927 * gtk_window_get_decorated:
1928 * @window: a #GtkWindow
1930 * Returns whether the window has been set to have decorations
1931 * such as a title bar via gtk_window_set_decorated().
1933 * Return value: %TRUE if the window has been set to have decorations
1936 gtk_window_get_decorated (GtkWindow *window)
1938 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
1940 return window->decorated;
1943 static GtkWindowIconInfo*
1944 get_icon_info (GtkWindow *window)
1946 return g_object_get_data (G_OBJECT (window),
1947 "gtk-window-icon-info");
1950 static GtkWindowIconInfo*
1951 ensure_icon_info (GtkWindow *window)
1953 GtkWindowIconInfo *info;
1955 info = get_icon_info (window);
1959 info = g_new0 (GtkWindowIconInfo, 1);
1960 g_object_set_data_full (G_OBJECT (window),
1961 "gtk-window-icon-info",
1976 get_screen_icon_info (GdkScreen *screen)
1978 ScreenIconInfo *info = g_object_get_data (G_OBJECT (screen),
1979 "gtk-window-default-icon-pixmap");
1982 info = g_new0 (ScreenIconInfo, 1);
1983 g_object_set_data (G_OBJECT (screen), "gtk-window-default-icon-pixmap", info);
1986 if (info->serial != default_icon_serial)
1990 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
1991 info->pixmap = NULL;
1996 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2000 info->serial = default_icon_serial;
2007 get_pixmap_and_mask (GdkWindow *window,
2008 GtkWindowIconInfo *parent_info,
2009 gboolean is_default_list,
2011 GdkPixmap **pmap_return,
2012 GdkBitmap **mask_return)
2014 GdkScreen *screen = gdk_drawable_get_screen (window);
2015 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2016 GdkPixbuf *best_icon;
2020 *pmap_return = NULL;
2021 *mask_return = NULL;
2023 if (is_default_list &&
2024 default_icon_info->pixmap != NULL)
2026 /* Use shared icon pixmap for all windows on this screen.
2028 if (default_icon_info->pixmap)
2029 g_object_ref (G_OBJECT (default_icon_info->pixmap));
2030 if (default_icon_info->mask)
2031 g_object_ref (G_OBJECT (default_icon_info->mask));
2033 *pmap_return = default_icon_info->pixmap;
2034 *mask_return = default_icon_info->mask;
2036 else if (parent_info && parent_info->icon_pixmap)
2038 if (parent_info->icon_pixmap)
2039 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
2040 if (parent_info->icon_mask)
2041 g_object_ref (G_OBJECT (parent_info->icon_mask));
2043 *pmap_return = parent_info->icon_pixmap;
2044 *mask_return = parent_info->icon_mask;
2048 #define IDEAL_SIZE 48
2050 best_size = G_MAXINT;
2052 tmp_list = icon_list;
2053 while (tmp_list != NULL)
2055 GdkPixbuf *pixbuf = tmp_list->data;
2058 /* average width and height - if someone passes in a rectangular
2059 * icon they deserve what they get.
2061 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2064 if (best_icon == NULL)
2071 /* icon is better if it's 32 pixels or larger, and closer to
2072 * the ideal size than the current best.
2075 (ABS (best_size - IDEAL_SIZE) <
2076 ABS (this - IDEAL_SIZE)))
2083 tmp_list = tmp_list->next;
2087 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2088 gdk_screen_get_system_colormap (screen),
2093 /* Save pmap/mask for others to use if appropriate */
2096 parent_info->icon_pixmap = *pmap_return;
2097 parent_info->icon_mask = *mask_return;
2099 if (parent_info->icon_pixmap)
2100 g_object_ref (G_OBJECT (parent_info->icon_pixmap));
2101 if (parent_info->icon_mask)
2102 g_object_ref (G_OBJECT (parent_info->icon_mask));
2104 else if (is_default_list)
2106 default_icon_info->pixmap = *pmap_return;
2107 default_icon_info->mask = *mask_return;
2109 if (default_icon_info->pixmap)
2110 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2111 (gpointer*)&default_icon_info->pixmap);
2112 if (default_icon_info->mask)
2113 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2114 (gpointer*)&default_icon_info->mask);
2120 gtk_window_realize_icon (GtkWindow *window)
2123 GtkWindowIconInfo *info;
2126 widget = GTK_WIDGET (window);
2128 g_return_if_fail (widget->window != NULL);
2130 /* no point setting an icon on override-redirect */
2131 if (window->type == GTK_WINDOW_POPUP)
2136 info = ensure_icon_info (window);
2141 g_return_if_fail (info->icon_pixmap == NULL);
2142 g_return_if_fail (info->icon_mask == NULL);
2144 info->using_default_icon = FALSE;
2145 info->using_parent_icon = FALSE;
2147 icon_list = info->icon_list;
2149 /* Inherit from transient parent */
2150 if (icon_list == NULL && window->transient_parent)
2152 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2154 info->using_parent_icon = TRUE;
2157 /* Inherit from default */
2158 if (icon_list == NULL)
2160 icon_list = default_icon_list;
2162 info->using_default_icon = TRUE;
2165 gdk_window_set_icon_list (widget->window, icon_list);
2167 get_pixmap_and_mask (widget->window,
2168 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2169 info->using_default_icon,
2174 /* This is a slight ICCCM violation since it's a color pixmap not
2175 * a bitmap, but everyone does it.
2177 gdk_window_set_icon (widget->window,
2182 info->realized = TRUE;
2186 gtk_window_unrealize_icon (GtkWindow *window)
2188 GtkWindowIconInfo *info;
2191 widget = GTK_WIDGET (window);
2193 info = get_icon_info (window);
2198 if (info->icon_pixmap)
2199 g_object_unref (G_OBJECT (info->icon_pixmap));
2201 if (info->icon_mask)
2202 g_object_unref (G_OBJECT (info->icon_mask));
2204 info->icon_pixmap = NULL;
2205 info->icon_mask = NULL;
2207 /* We don't clear the properties on the window, just figure the
2208 * window is going away.
2211 info->realized = FALSE;
2215 * gtk_window_set_icon_list:
2216 * @window: a #GtkWindow
2217 * @list: list of #GdkPixbuf
2219 * Sets up the icon representing a #GtkWindow. The icon is used when
2220 * the window is minimized (also known as iconified). Some window
2221 * managers or desktop environments may also place it in the window
2222 * frame, or display it in other contexts.
2224 * gtk_window_set_icon_list() allows you to pass in the same icon in
2225 * several hand-drawn sizes. The list should contain the natural sizes
2226 * your icon is available in; that is, don't scale the image before
2227 * passing it to GTK+. Scaling is postponed until the last minute,
2228 * when the desired final size is known, to allow best quality.
2230 * By passing several sizes, you may improve the final image quality
2231 * of the icon, by reducing or eliminating automatic image scaling.
2233 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2234 * larger images (64x64, 128x128) if you have them.
2236 * See also gtk_window_set_default_icon_list() to set the icon
2237 * for all windows in your application in one go.
2239 * Note that transient windows (those who have been set transient for another
2240 * window using gtk_window_set_transient_for()) will inherit their
2241 * icon from their transient parent. So there's no need to explicitly
2242 * set the icon on transient windows.
2245 gtk_window_set_icon_list (GtkWindow *window,
2248 GtkWindowIconInfo *info;
2250 g_return_if_fail (GTK_IS_WINDOW (window));
2252 info = ensure_icon_info (window);
2254 if (info->icon_list == list) /* check for NULL mostly */
2257 g_list_foreach (info->icon_list,
2258 (GFunc) g_object_unref, NULL);
2260 g_list_free (info->icon_list);
2262 info->icon_list = g_list_copy (list);
2263 g_list_foreach (info->icon_list,
2264 (GFunc) g_object_ref, NULL);
2266 g_object_notify (G_OBJECT (window), "icon");
2268 gtk_window_unrealize_icon (window);
2270 if (GTK_WIDGET_REALIZED (window))
2271 gtk_window_realize_icon (window);
2273 /* We could try to update our transient children, but I don't think
2274 * it's really worth it. If we did it, the best way would probably
2275 * be to have children connect to notify::icon_list
2280 * gtk_window_get_icon_list:
2281 * @window: a #GtkWindow
2283 * Retrieves the list of icons set by gtk_window_set_icon_list().
2284 * The list is copied, but the reference count on each
2285 * member won't be incremented.
2287 * Return value: copy of window's icon list
2290 gtk_window_get_icon_list (GtkWindow *window)
2292 GtkWindowIconInfo *info;
2294 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2296 info = get_icon_info (window);
2299 return g_list_copy (info->icon_list);
2305 * gtk_window_set_icon:
2306 * @window: a #GtkWindow
2307 * @icon: icon image, or %NULL
2309 * Sets up the icon representing a #GtkWindow. This icon is used when
2310 * the window is minimized (also known as iconified). Some window
2311 * managers or desktop environments may also place it in the window
2312 * frame, or display it in other contexts.
2314 * The icon should be provided in whatever size it was naturally
2315 * drawn; that is, don't scale the image before passing it to
2316 * GTK+. Scaling is postponed until the last minute, when the desired
2317 * final size is known, to allow best quality.
2319 * If you have your icon hand-drawn in multiple sizes, use
2320 * gtk_window_set_icon_list(). Then the best size will be used.
2322 * This function is equivalent to calling gtk_window_set_icon_list()
2323 * with a 1-element list.
2325 * See also gtk_window_set_default_icon_list() to set the icon
2326 * for all windows in your application in one go.
2329 gtk_window_set_icon (GtkWindow *window,
2334 g_return_if_fail (GTK_IS_WINDOW (window));
2335 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2338 list = g_list_append (list, icon);
2339 gtk_window_set_icon_list (window, list);
2344 * gtk_window_get_icon:
2345 * @window: a #GtkWindow
2347 * Gets the value set by gtk_window_set_icon() (or if you've
2348 * called gtk_window_set_icon_list(), gets the first icon in
2351 * Return value: icon for window
2354 gtk_window_get_icon (GtkWindow *window)
2356 GtkWindowIconInfo *info;
2358 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2360 info = get_icon_info (window);
2361 if (info && info->icon_list)
2362 return GDK_PIXBUF (info->icon_list->data);
2368 * gtk_window_set_default_icon_list:
2369 * @list: a list of #GdkPixbuf
2371 * Sets an icon list to be used as fallback for windows that haven't
2372 * had gtk_window_set_icon_list() called on them to set up a
2373 * window-specific icon list. This function allows you to set up the
2374 * icon for all windows in your app at once.
2376 * See gtk_window_set_icon_list() for more details.
2380 gtk_window_set_default_icon_list (GList *list)
2384 if (list == default_icon_list)
2387 /* Update serial so we don't used cached pixmaps/masks
2389 default_icon_serial++;
2391 g_list_foreach (default_icon_list,
2392 (GFunc) g_object_unref, NULL);
2394 g_list_free (default_icon_list);
2396 default_icon_list = g_list_copy (list);
2397 g_list_foreach (default_icon_list,
2398 (GFunc) g_object_ref, NULL);
2400 /* Update all toplevels */
2401 toplevels = gtk_window_list_toplevels ();
2402 tmp_list = toplevels;
2403 while (tmp_list != NULL)
2405 GtkWindowIconInfo *info;
2406 GtkWindow *w = tmp_list->data;
2408 info = get_icon_info (w);
2409 if (info && info->using_default_icon)
2411 gtk_window_unrealize_icon (w);
2412 if (GTK_WIDGET_REALIZED (w))
2413 gtk_window_realize_icon (w);
2416 tmp_list = tmp_list->next;
2418 g_list_free (toplevels);
2422 * gtk_window_get_default_icon_list:
2424 * Gets the value set by gtk_window_set_default_icon_list().
2425 * The list is a copy and should be freed with g_list_free(),
2426 * but the pixbufs in the list have not had their reference count
2429 * Return value: copy of default icon list
2432 gtk_window_get_default_icon_list (void)
2434 return g_list_copy (default_icon_list);
2438 gtk_window_set_default_size_internal (GtkWindow *window,
2439 gboolean change_width,
2441 gboolean change_height,
2443 gboolean is_geometry)
2445 GtkWindowGeometryInfo *info;
2447 g_return_if_fail (change_width == FALSE || width >= -1);
2448 g_return_if_fail (change_height == FALSE || height >= -1);
2450 info = gtk_window_get_geometry_info (window, TRUE);
2452 g_object_freeze_notify (G_OBJECT (window));
2454 info->default_is_geometry = is_geometry != FALSE;
2464 info->default_width = width;
2466 g_object_notify (G_OBJECT (window), "default_width");
2477 info->default_height = height;
2479 g_object_notify (G_OBJECT (window), "default_height");
2482 g_object_thaw_notify (G_OBJECT (window));
2484 gtk_widget_queue_resize (GTK_WIDGET (window));
2488 * gtk_window_set_default_size:
2489 * @window: a #GtkWindow
2490 * @width: width in pixels, or -1 to unset the default width
2491 * @height: height in pixels, or -1 to unset the default height
2493 * Sets the default size of a window. If the window's "natural" size
2494 * (its size request) is larger than the default, the default will be
2495 * ignored. More generally, if the default size does not obey the
2496 * geometry hints for the window (gtk_window_set_geometry_hints() can
2497 * be used to set these explicitly), the default size will be clamped
2498 * to the nearest permitted size.
2500 * Unlike gtk_widget_set_size_request(), which sets a size request for
2501 * a widget and thus would keep users from shrinking the window, this
2502 * function only sets the initial size, just as if the user had
2503 * resized the window themselves. Users can still shrink the window
2504 * again as they normally would. Setting a default size of -1 means to
2505 * use the "natural" default size (the size request of the window).
2507 * For more control over a window's initial size and how resizing works,
2508 * investigate gtk_window_set_geometry_hints().
2510 * For some uses, gtk_window_resize() is a more appropriate function.
2511 * gtk_window_resize() changes the current size of the window, rather
2512 * than the size to be used on initial display. gtk_window_resize() always
2513 * affects the window itself, not the geometry widget.
2515 * The default size of a window only affects the first time a window is
2516 * shown; if a window is hidden and re-shown, it will remember the size
2517 * it had prior to hiding, rather than using the default size.
2519 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2520 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2523 gtk_window_set_default_size (GtkWindow *window,
2527 g_return_if_fail (GTK_IS_WINDOW (window));
2528 g_return_if_fail (width >= -1);
2529 g_return_if_fail (height >= -1);
2531 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
2535 * gtk_window_get_default_size:
2536 * @window: a #GtkWindow
2537 * @width: location to store the default width, or %NULL
2538 * @height: location to store the default height, or %NULL
2540 * Gets the default size of the window. A value of -1 for the width or
2541 * height indicates that a default size has not been explicitly set
2542 * for that dimension, so the "natural" size of the window will be
2547 gtk_window_get_default_size (GtkWindow *window,
2551 GtkWindowGeometryInfo *info;
2553 g_return_if_fail (GTK_IS_WINDOW (window));
2555 info = gtk_window_get_geometry_info (window, FALSE);
2558 *width = info->default_width;
2561 *height = info->default_height;
2565 * gtk_window_resize:
2566 * @window: a #GtkWindow
2567 * @width: width in pixels to resize the window to
2568 * @height: height in pixels to resize the window to
2570 * Resizes the window as if the user had done so, obeying geometry
2571 * constraints. The default geometry constraint is that windows may
2572 * not be smaller than their size request; to override this
2573 * constraint, call gtk_widget_set_size_request() to set the window's
2574 * request to a smaller value.
2576 * If gtk_window_resize() is called before showing a window for the
2577 * first time, it overrides any default size set with
2578 * gtk_window_set_default_size().
2580 * Windows may not be resized smaller than 1 by 1 pixels.
2584 gtk_window_resize (GtkWindow *window,
2588 GtkWindowGeometryInfo *info;
2590 g_return_if_fail (GTK_IS_WINDOW (window));
2591 g_return_if_fail (width > 0);
2592 g_return_if_fail (height > 0);
2594 info = gtk_window_get_geometry_info (window, TRUE);
2596 info->resize_width = width;
2597 info->resize_height = height;
2599 gtk_widget_queue_resize (GTK_WIDGET (window));
2603 * gtk_window_get_size:
2604 * @window: a #GtkWindow
2605 * @width: return location for width, or %NULL
2606 * @height: return location for height, or %NULL
2608 * Obtains the current size of @window. If @window is not onscreen,
2609 * it returns the size GTK+ will suggest to the <link
2610 * linkend="gtk-X11-arch">window manager</link> for the initial window
2611 * size (but this is not reliably the same as the size the window
2612 * manager will actually select). The size obtained by
2613 * gtk_window_get_size() is the last size received in a
2614 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2615 * rather than querying the X server for the size. As a result, if you
2616 * call gtk_window_resize() then immediately call
2617 * gtk_window_get_size(), the size won't have taken effect yet. After
2618 * the window manager processes the resize request, GTK+ receives
2619 * notification that the size has changed via a configure event, and
2620 * the size of the window gets updated.
2622 * Note 1: Nearly any use of this function creates a race condition,
2623 * because the size of the window may change between the time that you
2624 * get the size and the time that you perform some action assuming
2625 * that size is the current size. To avoid race conditions, connect to
2626 * "configure_event" on the window and adjust your size-dependent
2627 * state to match the size delivered in the #GdkEventConfigure.
2629 * Note 2: The returned size does <emphasis>not</emphasis> include the
2630 * size of the window manager decorations (aka the window frame or
2631 * border). Those are not drawn by GTK+ and GTK+ has no reliable
2632 * method of determining their size.
2634 * Note 3: If you are getting a window size in order to position
2635 * the window onscreen, there may be a better way. The preferred
2636 * way is to simply set the window's semantic type with
2637 * gtk_window_set_type_hint(), which allows the window manager to
2638 * e.g. center dialogs. Also, if you set the transient parent of
2639 * dialogs with gtk_window_set_transient_for() window managers
2640 * will often center the dialog over its parent window. It's
2641 * much preferred to let the window manager handle these
2642 * things rather than doing it yourself, because all apps will
2643 * behave consistently and according to user prefs if the window
2644 * manager handles it. Also, the window manager can take the size
2645 * of the window decorations/border into account, while your
2646 * application cannot.
2648 * In any case, if you insist on application-specified window
2649 * positioning, there's <emphasis>still</emphasis> a better way than
2650 * doing it yourself - gtk_window_set_position() will frequently
2651 * handle the details for you.
2655 gtk_window_get_size (GtkWindow *window,
2662 g_return_if_fail (GTK_IS_WINDOW (window));
2664 widget = GTK_WIDGET (window);
2666 if (width == NULL && height == NULL)
2669 if (GTK_WIDGET_MAPPED (window))
2671 gdk_drawable_get_size (GTK_WIDGET (window)->window,
2676 GdkRectangle configure_request;
2678 gtk_window_compute_configure_request (window,
2682 w = configure_request.width;
2683 h = configure_request.height;
2694 * @window: a #GtkWindow
2695 * @x: X coordinate to move window to
2696 * @y: Y coordinate to move window to
2698 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
2699 * @window to the given position. Window managers are free to ignore
2700 * this; most window managers ignore requests for initial window
2701 * positions (instead using a user-defined placement algorithm) and
2702 * honor requests after the window has already been shown.
2704 * Note: the position is the position of the gravity-determined
2705 * reference point for the window. The gravity determines two things:
2706 * first, the location of the reference point in root window
2707 * coordinates; and second, which point on the window is positioned at
2708 * the reference point.
2710 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
2711 * point is simply the @x, @y supplied to gtk_window_move(). The
2712 * top-left corner of the window decorations (aka window frame or
2713 * border) will be placed at @x, @y. Therefore, to position a window
2714 * at the top left of the screen, you want to use the default gravity
2715 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
2717 * To position a window at the bottom right corner of the screen, you
2718 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
2719 * point is at @x + the window width and @y + the window height, and
2720 * the bottom-right corner of the window border will be placed at that
2721 * reference point. So, to place a window in the bottom right corner
2722 * you would first set gravity to south east, then write:
2723 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
2724 * gdk_screen_height () - window_height)</literal>.
2726 * The extended window manager hints specification at <ulink
2727 * url="http://www.freedesktop.org/standards/wm-spec.html">
2728 * http://www.freedesktop.org/standards/wm-spec.html</ulink> has a
2729 * nice table of gravities in the "implementation notes" section.
2731 * The gtk_window_get_position() documentation may also be relevant.
2735 gtk_window_move (GtkWindow *window,
2739 GtkWindowGeometryInfo *info;
2742 g_return_if_fail (GTK_IS_WINDOW (window));
2744 widget = GTK_WIDGET (window);
2746 info = gtk_window_get_geometry_info (window, TRUE);
2748 if (GTK_WIDGET_MAPPED (window))
2750 /* we have now sent a request with this position
2751 * with currently-active constraints, so toggle flag.
2753 info->position_constraints_changed = FALSE;
2755 /* we only constrain if mapped - if not mapped,
2756 * then gtk_window_compute_configure_request()
2757 * will apply the constraints later, and we
2758 * don't want to lose information about
2759 * what position the user set before then.
2760 * i.e. if you do a move() then turn off POS_CENTER
2761 * then show the window, your move() will work.
2763 gtk_window_constrain_position (window,
2764 widget->allocation.width,
2765 widget->allocation.height,
2768 /* Note that this request doesn't go through our standard request
2769 * framework, e.g. doesn't increment configure_request_count,
2770 * doesn't set info->last, etc.; that's because
2771 * we don't save the info needed to arrive at this same request
2774 * To gtk_window_move_resize(), this will end up looking exactly
2775 * the same as the position being changed by the window
2779 /* FIXME are we handling gravity properly for framed windows? */
2781 gdk_window_move (window->frame,
2782 x - window->frame_left,
2783 y - window->frame_top);
2785 gdk_window_move (GTK_WIDGET (window)->window,
2790 /* Save this position to apply on mapping */
2791 info->initial_x = x;
2792 info->initial_y = y;
2793 info->initial_pos_set = TRUE;
2798 * gtk_window_get_position:
2799 * @window: a #GtkWindow
2800 * @root_x: return location for X coordinate of gravity-determined reference p\oint
2801 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
2803 * This function returns the position you need to pass to
2804 * gtk_window_move() to keep @window in its current position. This
2805 * means that the meaning of the returned value varies with window
2806 * gravity. See gtk_window_move() for more details.
2808 * If you haven't changed the window gravity, its gravity will be
2809 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
2810 * gets the position of the top-left corner of the window manager
2811 * frame for the window. gtk_window_move() sets the position of this
2812 * same top-left corner.
2814 * gtk_window_get_position() is not 100% reliable because the X Window System
2815 * does not specify a way to obtain the geometry of the
2816 * decorations placed on a window by the window manager.
2817 * Thus GTK+ is using a "best guess" that works with most
2820 * Moreover, nearly all window managers are historically broken with
2821 * respect to their handling of window gravity. So moving a window to
2822 * its current position as returned by gtk_window_get_position() tends
2823 * to result in moving the window slightly. Window managers are
2824 * slowly getting better over time.
2826 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
2827 * frame is not relevant, and thus gtk_window_get_position() will
2828 * always produce accurate results. However you can't use static
2829 * gravity to do things like place a window in a corner of the screen,
2830 * because static gravity ignores the window manager decorations.
2832 * If you are saving and restoring your application's window
2833 * positions, you should know that it's impossible for applications to
2834 * do this without getting it somewhat wrong because applications do
2835 * not have sufficient knowledge of window manager state. The Correct
2836 * Mechanism is to support the session management protocol (see the
2837 * "GnomeClient" object in the GNOME libraries for example) and allow
2838 * the window manager to save your window sizes and positions.
2843 gtk_window_get_position (GtkWindow *window,
2849 g_return_if_fail (GTK_IS_WINDOW (window));
2851 widget = GTK_WIDGET (window);
2853 if (window->gravity == GDK_GRAVITY_STATIC)
2855 if (GTK_WIDGET_MAPPED (widget))
2857 /* This does a server round-trip, which is sort of wrong;
2858 * but a server round-trip is inevitable for
2859 * gdk_window_get_frame_extents() in the usual
2860 * NorthWestGravity case below, so not sure what else to
2861 * do. We should likely be consistent about whether we get
2862 * the client-side info or the server-side info.
2864 gdk_window_get_origin (widget->window, root_x, root_y);
2868 GdkRectangle configure_request;
2870 gtk_window_compute_configure_request (window,
2874 *root_x = configure_request.x;
2875 *root_y = configure_request.y;
2880 GdkRectangle frame_extents;
2885 if (GTK_WIDGET_MAPPED (widget))
2888 gdk_window_get_frame_extents (window->frame, &frame_extents);
2890 gdk_window_get_frame_extents (widget->window, &frame_extents);
2891 x = frame_extents.x;
2892 y = frame_extents.y;
2893 gtk_window_get_size (window, &w, &h);
2897 /* We just say the frame has 0 size on all sides.
2898 * Not sure what else to do.
2900 gtk_window_compute_configure_request (window,
2903 x = frame_extents.x;
2904 y = frame_extents.y;
2905 w = frame_extents.width;
2906 h = frame_extents.height;
2909 switch (window->gravity)
2911 case GDK_GRAVITY_NORTH:
2912 case GDK_GRAVITY_CENTER:
2913 case GDK_GRAVITY_SOUTH:
2914 /* Find center of frame. */
2915 x += frame_extents.width / 2;
2916 /* Center client window on that point. */
2920 case GDK_GRAVITY_SOUTH_EAST:
2921 case GDK_GRAVITY_EAST:
2922 case GDK_GRAVITY_NORTH_EAST:
2923 /* Find right edge of frame */
2924 x += frame_extents.width;
2925 /* Align left edge of client at that point. */
2932 switch (window->gravity)
2934 case GDK_GRAVITY_WEST:
2935 case GDK_GRAVITY_CENTER:
2936 case GDK_GRAVITY_EAST:
2937 /* Find center of frame. */
2938 y += frame_extents.height / 2;
2939 /* Center client window there. */
2942 case GDK_GRAVITY_SOUTH_WEST:
2943 case GDK_GRAVITY_SOUTH:
2944 case GDK_GRAVITY_SOUTH_EAST:
2945 /* Find south edge of frame */
2946 y += frame_extents.height;
2947 /* Place bottom edge of client there */
2962 * gtk_window_reshow_with_initial_size:
2963 * @window: a #GtkWindow
2965 * Hides @window, then reshows it, resetting the
2966 * default size and position of the window. Used
2967 * by GUI builders only.
2970 gtk_window_reshow_with_initial_size (GtkWindow *window)
2974 g_return_if_fail (GTK_IS_WINDOW (window));
2976 widget = GTK_WIDGET (window);
2978 gtk_widget_hide (widget);
2979 gtk_widget_unrealize (widget);
2980 gtk_widget_show (widget);
2984 gtk_window_destroy (GtkObject *object)
2986 GtkWindow *window = GTK_WINDOW (object);
2988 if (window->transient_parent)
2989 gtk_window_set_transient_for (window, NULL);
2991 /* frees the icons */
2992 gtk_window_set_icon_list (window, NULL);
2994 if (window->has_user_ref_count)
2996 window->has_user_ref_count = FALSE;
2997 gtk_widget_unref (GTK_WIDGET (window));
3001 gtk_window_group_remove_window (window->group, window);
3003 gtk_window_free_key_hash (window);
3005 GTK_OBJECT_CLASS (parent_class)->destroy (object);
3009 gtk_window_mnemonic_hash_remove (gpointer key,
3013 GtkWindowMnemonic *mnemonic = key;
3014 GtkWindow *window = user;
3016 if (mnemonic->window == window)
3018 if (mnemonic->targets)
3020 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
3022 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
3023 name, mnemonic->targets->data);
3026 g_slist_free (mnemonic->targets);
3035 gtk_window_finalize (GObject *object)
3037 GtkWindow *window = GTK_WINDOW (object);
3039 toplevel_list = g_slist_remove (toplevel_list, window);
3041 g_free (window->title);
3042 g_free (window->wmclass_name);
3043 g_free (window->wmclass_class);
3044 g_free (window->wm_role);
3046 g_hash_table_foreach_remove (mnemonic_hash_table,
3047 gtk_window_mnemonic_hash_remove,
3049 if (window->geometry_info)
3051 if (window->geometry_info->widget)
3052 gtk_signal_disconnect_by_func (GTK_OBJECT (window->geometry_info->widget),
3053 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
3054 &window->geometry_info->widget);
3055 g_free (window->geometry_info);
3058 if (window->keys_changed_handler)
3060 gtk_idle_remove (window->keys_changed_handler);
3061 window->keys_changed_handler = 0;
3064 G_OBJECT_CLASS (parent_class)->finalize (object);
3068 gtk_window_show (GtkWidget *widget)
3070 GtkWindow *window = GTK_WINDOW (widget);
3071 GtkContainer *container = GTK_CONTAINER (window);
3072 gboolean need_resize;
3074 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3076 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3077 container->need_resize = FALSE;
3081 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3082 GtkAllocation allocation = { 0, 0 };
3083 GdkRectangle configure_request;
3084 GdkGeometry new_geometry;
3086 gboolean was_realized;
3088 /* We are going to go ahead and perform this configure request
3089 * and then emulate a configure notify by going ahead and
3090 * doing a size allocate. Sort of a synchronous
3091 * mini-copy of gtk_window_move_resize() here.
3093 gtk_window_compute_configure_request (window,
3098 /* We update this because we are going to go ahead
3099 * and gdk_window_resize() below, rather than
3102 info->last.configure_request.width = configure_request.width;
3103 info->last.configure_request.height = configure_request.height;
3105 /* and allocate the window - this is normally done
3106 * in move_resize in response to configure notify
3108 allocation.width = configure_request.width;
3109 allocation.height = configure_request.height;
3110 gtk_widget_size_allocate (widget, &allocation);
3112 /* Then we guarantee we have a realize */
3113 was_realized = FALSE;
3114 if (!GTK_WIDGET_REALIZED (widget))
3116 gtk_widget_realize (widget);
3117 was_realized = TRUE;
3120 /* Must be done after the windows are realized,
3121 * so that the decorations can be read
3123 gtk_decorated_window_calculate_frame_size (window);
3125 /* We only send configure request if we didn't just finish
3126 * creating the window; if we just created the window
3127 * then we created it with widget->allocation anyhow.
3130 gdk_window_resize (widget->window,
3131 configure_request.width,
3132 configure_request.height);
3135 gtk_container_check_resize (container);
3137 gtk_widget_map (widget);
3139 /* Try to make sure that we have some focused widget
3141 if (!window->focus_widget && !GTK_IS_PLUG (window))
3142 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
3145 gtk_grab_add (widget);
3149 gtk_window_hide (GtkWidget *widget)
3151 GtkWindow *window = GTK_WINDOW (widget);
3153 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3154 gtk_widget_unmap (widget);
3157 gtk_grab_remove (widget);
3161 gtk_window_map (GtkWidget *widget)
3163 GtkWindow *window = GTK_WINDOW (widget);
3164 GdkWindow *toplevel;
3166 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3168 if (window->bin.child &&
3169 GTK_WIDGET_VISIBLE (window->bin.child) &&
3170 !GTK_WIDGET_MAPPED (window->bin.child))
3171 gtk_widget_map (window->bin.child);
3174 toplevel = window->frame;
3176 toplevel = widget->window;
3178 if (window->maximize_initially)
3179 gdk_window_maximize (toplevel);
3181 gdk_window_unmaximize (toplevel);
3183 if (window->stick_initially)
3184 gdk_window_stick (toplevel);
3186 gdk_window_unstick (toplevel);
3188 if (window->iconify_initially)
3189 gdk_window_iconify (toplevel);
3191 gdk_window_deiconify (toplevel);
3193 /* No longer use the default settings */
3194 window->need_default_size = FALSE;
3195 window->need_default_position = FALSE;
3197 gdk_window_show (widget->window);
3200 gdk_window_show (window->frame);
3204 gtk_window_unmap (GtkWidget *widget)
3206 GtkWindow *window = GTK_WINDOW (widget);
3207 GtkWindowGeometryInfo *info;
3208 GdkWindowState state;
3210 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3212 gdk_window_withdraw (window->frame);
3214 gdk_window_withdraw (widget->window);
3216 window->configure_request_count = 0;
3217 window->configure_notify_received = FALSE;
3219 /* on unmap, we reset the default positioning of the window,
3220 * so it's placed again, but we don't reset the default
3221 * size of the window, so it's remembered.
3223 window->need_default_position = TRUE;
3225 info = gtk_window_get_geometry_info (window, FALSE);
3228 info->initial_pos_set = FALSE;
3229 info->position_constraints_changed = FALSE;
3232 state = gdk_window_get_state (widget->window);
3233 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
3234 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
3235 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
3239 gtk_window_realize (GtkWidget *widget)
3242 GdkWindow *parent_window;
3243 GdkWindowAttr attributes;
3244 gint attributes_mask;
3246 window = GTK_WINDOW (widget);
3248 /* ensure widget tree is properly size allocated */
3249 if (widget->allocation.x == -1 &&
3250 widget->allocation.y == -1 &&
3251 widget->allocation.width == 1 &&
3252 widget->allocation.height == 1)
3254 GtkRequisition requisition;
3255 GtkAllocation allocation = { 0, 0, 200, 200 };
3257 gtk_widget_size_request (widget, &requisition);
3258 if (requisition.width || requisition.height)
3260 /* non-empty window */
3261 allocation.width = requisition.width;
3262 allocation.height = requisition.height;
3264 gtk_widget_size_allocate (widget, &allocation);
3266 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3268 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3271 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3273 switch (window->type)
3275 case GTK_WINDOW_TOPLEVEL:
3276 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3278 case GTK_WINDOW_POPUP:
3279 attributes.window_type = GDK_WINDOW_TEMP;
3282 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3286 attributes.title = window->title;
3287 attributes.wmclass_name = window->wmclass_name;
3288 attributes.wmclass_class = window->wmclass_class;
3289 attributes.wclass = GDK_INPUT_OUTPUT;
3290 attributes.visual = gtk_widget_get_visual (widget);
3291 attributes.colormap = gtk_widget_get_colormap (widget);
3293 if (window->has_frame)
3295 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3296 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3297 attributes.event_mask = (GDK_EXPOSURE_MASK |
3298 GDK_KEY_PRESS_MASK |
3299 GDK_ENTER_NOTIFY_MASK |
3300 GDK_LEAVE_NOTIFY_MASK |
3301 GDK_FOCUS_CHANGE_MASK |
3302 GDK_STRUCTURE_MASK |
3303 GDK_BUTTON_MOTION_MASK |
3304 GDK_POINTER_MOTION_HINT_MASK |
3305 GDK_BUTTON_PRESS_MASK |
3306 GDK_BUTTON_RELEASE_MASK);
3308 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3310 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
3311 &attributes, attributes_mask);
3313 gdk_window_set_user_data (window->frame, widget);
3315 attributes.window_type = GDK_WINDOW_CHILD;
3316 attributes.x = window->frame_left;
3317 attributes.y = window->frame_top;
3319 attributes_mask = GDK_WA_X | GDK_WA_Y;
3321 parent_window = window->frame;
3325 attributes_mask = 0;
3326 parent_window = gtk_widget_get_root_window (widget);
3329 attributes.width = widget->allocation.width;
3330 attributes.height = widget->allocation.height;
3331 attributes.event_mask = gtk_widget_get_events (widget);
3332 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3333 GDK_KEY_PRESS_MASK |
3334 GDK_KEY_RELEASE_MASK |
3335 GDK_ENTER_NOTIFY_MASK |
3336 GDK_LEAVE_NOTIFY_MASK |
3337 GDK_FOCUS_CHANGE_MASK |
3338 GDK_STRUCTURE_MASK);
3340 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3341 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3342 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3344 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3346 gdk_window_set_user_data (widget->window, window);
3348 widget->style = gtk_style_attach (widget->style, widget->window);
3349 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3351 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3353 /* This is a bad hack to set the window background. */
3354 gtk_window_paint (widget, NULL);
3356 if (window->transient_parent &&
3357 GTK_WIDGET_REALIZED (window->transient_parent))
3358 gdk_window_set_transient_for (widget->window,
3359 GTK_WIDGET (window->transient_parent)->window);
3361 if (window->wm_role)
3362 gdk_window_set_role (widget->window, window->wm_role);
3364 if (!window->decorated)
3365 gdk_window_set_decorations (widget->window, 0);
3367 gdk_window_set_type_hint (widget->window, window->type_hint);
3369 /* transient_for must be set to allow the modal hint */
3370 if (window->transient_parent && window->modal)
3371 gdk_window_set_modal_hint (widget->window, TRUE);
3373 gdk_window_set_modal_hint (widget->window, FALSE);
3376 gtk_window_realize_icon (window);
3380 gtk_window_unrealize (GtkWidget *widget)
3383 GtkWindowGeometryInfo *info;
3385 window = GTK_WINDOW (widget);
3387 /* On unrealize, we reset the size of the window such
3388 * that we will re-apply the default sizing stuff
3389 * next time we show the window.
3391 * Default positioning is reset on unmap, instead of unrealize.
3393 window->need_default_size = TRUE;
3394 info = gtk_window_get_geometry_info (window, FALSE);
3397 info->resize_width = -1;
3398 info->resize_height = -1;
3399 info->last.configure_request.x = 0;
3400 info->last.configure_request.y = 0;
3401 info->last.configure_request.width = -1;
3402 info->last.configure_request.height = -1;
3403 /* be sure we reset geom hints on re-realize */
3404 info->last.flags = 0;
3409 gdk_window_set_user_data (window->frame, NULL);
3410 gdk_window_destroy (window->frame);
3411 window->frame = NULL;
3415 gtk_window_unrealize_icon (window);
3417 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3421 gtk_window_size_request (GtkWidget *widget,
3422 GtkRequisition *requisition)
3427 window = GTK_WINDOW (widget);
3428 bin = GTK_BIN (window);
3430 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3431 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3433 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3435 GtkRequisition child_requisition;
3437 gtk_widget_size_request (bin->child, &child_requisition);
3439 requisition->width += child_requisition.width;
3440 requisition->height += child_requisition.height;
3445 gtk_window_size_allocate (GtkWidget *widget,
3446 GtkAllocation *allocation)
3449 GtkAllocation child_allocation;
3451 window = GTK_WINDOW (widget);
3452 widget->allocation = *allocation;
3454 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3456 child_allocation.x = GTK_CONTAINER (window)->border_width;
3457 child_allocation.y = GTK_CONTAINER (window)->border_width;
3458 child_allocation.width =
3459 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3460 child_allocation.height =
3461 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3463 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3466 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3468 gdk_window_resize (window->frame,
3469 allocation->width + window->frame_left + window->frame_right,
3470 allocation->height + window->frame_top + window->frame_bottom);
3475 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3478 gboolean return_val;
3480 window = GTK_WINDOW (widget);
3482 if (window->frame && (event->any.window == window->frame))
3484 if ((event->type != GDK_KEY_PRESS) &&
3485 (event->type != GDK_KEY_RELEASE) &&
3486 (event->type != GDK_FOCUS_CHANGE))
3488 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
3490 gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
3495 g_object_unref (event->any.window);
3496 event->any.window = g_object_ref (widget->window);
3504 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3506 GdkEventConfigure *configure_event;
3509 switch (event->type)
3512 configure_event = (GdkEventConfigure *)event;
3514 /* Invalidate the decorations */
3517 rect.width = configure_event->width;
3518 rect.height = configure_event->height;
3520 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3522 /* Pass on the (modified) configure event */
3523 configure_event->width -= window->frame_left + window->frame_right;
3524 configure_event->height -= window->frame_top + window->frame_bottom;
3525 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3534 gtk_window_configure_event (GtkWidget *widget,
3535 GdkEventConfigure *event)
3537 GtkWindow *window = GTK_WINDOW (widget);
3538 gboolean expected_reply = window->configure_request_count > 0;
3540 /* window->configure_request_count incremented for each
3541 * configure request, and decremented to a min of 0 for
3542 * each configure notify.
3544 * All it means is that we know we will get at least
3545 * window->configure_request_count more configure notifies.
3546 * We could get more configure notifies than that; some
3547 * of the configure notifies we get may be unrelated to
3548 * the configure requests. But we will get at least
3549 * window->configure_request_count notifies.
3552 if (window->configure_request_count > 0)
3553 window->configure_request_count -= 1;
3555 /* As an optimization, we avoid a resize when possible.
3557 * The only times we can avoid a resize are:
3558 * - we know only the position changed, not the size
3559 * - we know we have made more requests and so will get more
3560 * notifies and can wait to resize when we get them
3563 if (!expected_reply &&
3564 (widget->allocation.width == event->width &&
3565 widget->allocation.height == event->height))
3569 * If we do need to resize, we do that by:
3570 * - filling in widget->allocation with the new size
3571 * - setting configure_notify_received to TRUE
3572 * for use in gtk_window_move_resize()
3573 * - queueing a resize, leading to invocation of
3574 * gtk_window_move_resize() in an idle handler
3578 window->configure_notify_received = TRUE;
3580 widget->allocation.width = event->width;
3581 widget->allocation.height = event->height;
3583 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3588 /* the accel_key and accel_mods fields of the key have to be setup
3589 * upon calling this function. it'll then return whether that key
3590 * is at all used as accelerator, and if so will OR in the
3591 * accel_flags member of the key.
3594 _gtk_window_query_nonaccels (GtkWindow *window,
3596 GdkModifierType accel_mods)
3598 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3600 /* movement keys are considered locked accels */
3603 static const guint bindings[] = {
3604 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
3605 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
3609 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
3610 if (bindings[i] == accel_key)
3614 /* mnemonics are considered locked accels */
3615 if (accel_mods == window->mnemonic_modifier)
3617 GtkWindowMnemonic mkey;
3619 mkey.window = window;
3620 mkey.keyval = accel_key;
3621 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
3629 gtk_window_key_press_event (GtkWidget *widget,
3636 window = GTK_WINDOW (widget);
3640 /* Check for mnemonics and accelerators
3643 handled = _gtk_window_activate_key (window, event);
3647 focus = window->focus_widget;
3649 g_object_ref (focus);
3652 focus && focus != widget &&
3653 gtk_widget_get_toplevel (focus) == widget)
3657 if (GTK_WIDGET_IS_SENSITIVE (focus))
3658 handled = gtk_widget_event (focus, (GdkEvent*) event);
3660 parent = focus->parent;
3662 g_object_ref (parent);
3664 g_object_unref (focus);
3670 g_object_unref (focus);
3673 /* Chain up, invokes binding set */
3674 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
3675 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
3681 gtk_window_key_release_event (GtkWidget *widget,
3687 window = GTK_WINDOW (widget);
3689 if (window->focus_widget &&
3690 window->focus_widget != widget &&
3691 GTK_WIDGET_SENSITIVE (window->focus_widget))
3693 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
3696 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
3697 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
3703 gtk_window_real_activate_default (GtkWindow *window)
3705 gtk_window_activate_default (window);
3709 gtk_window_real_activate_focus (GtkWindow *window)
3711 gtk_window_activate_focus (window);
3715 gtk_window_move_focus (GtkWindow *window,
3716 GtkDirectionType dir)
3718 gtk_widget_child_focus (GTK_WIDGET (window), dir);
3720 if (!GTK_CONTAINER (window)->focus_child)
3721 gtk_window_set_focus (window, NULL);
3725 gtk_window_enter_notify_event (GtkWidget *widget,
3726 GdkEventCrossing *event)
3732 gtk_window_leave_notify_event (GtkWidget *widget,
3733 GdkEventCrossing *event)
3739 do_focus_change (GtkWidget *widget,
3742 GdkEventFocus fevent;
3744 g_object_ref (widget);
3747 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
3749 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
3751 fevent.type = GDK_FOCUS_CHANGE;
3752 fevent.window = widget->window;
3755 gtk_widget_event (widget, (GdkEvent*) &fevent);
3757 g_object_notify (G_OBJECT (widget), "has_focus");
3759 g_object_unref (widget);
3763 gtk_window_focus_in_event (GtkWidget *widget,
3764 GdkEventFocus *event)
3766 GtkWindow *window = GTK_WINDOW (widget);
3768 /* It appears spurious focus in events can occur when
3769 * the window is hidden. So we'll just check to see if
3770 * the window is visible before actually handling the
3773 if (GTK_WIDGET_VISIBLE (widget))
3775 window->has_focus = TRUE;
3777 if (window->focus_widget &&
3778 window->focus_widget != widget &&
3779 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3780 do_focus_change (window->focus_widget, TRUE);
3787 gtk_window_focus_out_event (GtkWidget *widget,
3788 GdkEventFocus *event)
3790 GtkWindow *window = GTK_WINDOW (widget);
3792 window->has_focus = FALSE;
3794 if (window->focus_widget &&
3795 window->focus_widget != widget &&
3796 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3797 do_focus_change (window->focus_widget, FALSE);
3802 static GdkAtom atom_rcfiles = GDK_NONE;
3805 gtk_window_read_rcfiles (GtkWidget *widget,
3806 GdkEventClient *event)
3808 GList *embedded_windows;
3810 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
3811 if (embedded_windows)
3816 for (i = 0; i < 5; i++)
3818 sev.data_format = 32;
3819 sev.message_type = atom_rcfiles;
3821 while (embedded_windows)
3823 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
3824 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), (GdkEvent *) &sev, xid);
3825 embedded_windows = embedded_windows->next;
3829 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
3833 gtk_window_client_event (GtkWidget *widget,
3834 GdkEventClient *event)
3837 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
3839 if (event->message_type == atom_rcfiles)
3840 gtk_window_read_rcfiles (widget, event);
3846 gtk_window_check_resize (GtkContainer *container)
3848 GtkWindow *window = GTK_WINDOW (container);
3850 if (GTK_WIDGET_VISIBLE (container))
3851 gtk_window_move_resize (window);
3855 gtk_window_focus (GtkWidget *widget,
3856 GtkDirectionType direction)
3860 GtkContainer *container;
3861 GtkWidget *old_focus_child;
3864 container = GTK_CONTAINER (widget);
3865 window = GTK_WINDOW (widget);
3866 bin = GTK_BIN (widget);
3868 old_focus_child = container->focus_child;
3870 /* We need a special implementation here to deal properly with wrapping
3871 * around in the tab chain without the danger of going into an
3874 if (old_focus_child)
3876 if (gtk_widget_child_focus (old_focus_child, direction))
3880 if (window->focus_widget)
3882 /* Wrapped off the end, clear the focus setting for the toplpevel */
3883 parent = window->focus_widget->parent;
3886 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
3887 parent = GTK_WIDGET (parent)->parent;
3890 gtk_window_set_focus (GTK_WINDOW (container), NULL);
3893 /* Now try to focus the first widget in the window */
3896 if (gtk_widget_child_focus (bin->child, direction))
3904 gtk_window_real_set_focus (GtkWindow *window,
3907 GtkWidget *old_focus = window->focus_widget;
3908 gboolean def_flags = 0;
3912 g_object_ref (old_focus);
3913 g_object_freeze_notify (G_OBJECT (old_focus));
3917 g_object_ref (focus);
3918 g_object_freeze_notify (G_OBJECT (focus));
3921 if (window->default_widget)
3922 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
3924 if (window->focus_widget)
3926 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3927 (window->focus_widget != window->default_widget))
3929 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3931 if (window->default_widget)
3932 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3935 if (window->has_focus)
3936 do_focus_change (window->focus_widget, FALSE);
3939 window->focus_widget = focus;
3941 if (window->focus_widget)
3943 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3944 (window->focus_widget != window->default_widget))
3946 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
3947 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3949 if (window->default_widget)
3950 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3953 if (window->has_focus)
3954 do_focus_change (window->focus_widget, TRUE);
3957 if (window->default_widget &&
3958 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
3959 gtk_widget_queue_draw (window->default_widget);
3963 g_object_thaw_notify (G_OBJECT (old_focus));
3964 g_object_unref (old_focus);
3968 g_object_thaw_notify (G_OBJECT (focus));
3969 g_object_unref (focus);
3973 /*********************************
3974 * Functions related to resizing *
3975 *********************************/
3977 /* This function doesn't constrain to geometry hints */
3979 gtk_window_compute_configure_request_size (GtkWindow *window,
3983 GtkRequisition requisition;
3984 GtkWindowGeometryInfo *info;
3988 * - we've done a size request
3991 widget = GTK_WIDGET (window);
3993 info = gtk_window_get_geometry_info (window, FALSE);
3995 if (window->need_default_size)
3997 gtk_widget_get_child_requisition (widget, &requisition);
3999 /* Default to requisition */
4000 *width = requisition.width;
4001 *height = requisition.height;
4003 /* If window is empty so requests 0, default to random nonzero size */
4004 if (*width == 0 && *height == 0)
4010 /* Override requisition with default size */
4014 gint base_width = 0;
4015 gint base_height = 0;
4017 gint height_inc = 1;
4019 if (info->default_is_geometry &&
4020 (info->default_width > 0 || info->default_height > 0))
4022 GdkGeometry geometry;
4025 gtk_window_compute_hints (window, &geometry, &flags);
4027 if (flags & GDK_HINT_BASE_SIZE)
4029 base_width = geometry.base_width;
4030 base_height = geometry.base_height;
4032 else if (flags & GDK_HINT_MIN_SIZE)
4034 base_width = geometry.min_width;
4035 base_height = geometry.min_height;
4037 if (flags & GDK_HINT_RESIZE_INC)
4039 width_inc = geometry.width_inc;
4040 height_inc = geometry.height_inc;
4044 if (info->default_width > 0)
4045 *width = info->default_width * width_inc + base_width;
4047 if (info->default_height > 0)
4048 *height = info->default_height * height_inc + base_height;
4053 /* Default to keeping current size */
4054 *width = widget->allocation.width;
4055 *height = widget->allocation.height;
4058 /* Override any size with gtk_window_resize() values */
4061 if (info->resize_width > 0)
4062 *width = info->resize_width;
4064 if (info->resize_height > 0)
4065 *height = info->resize_height;
4070 gtk_window_compute_configure_request (GtkWindow *window,
4071 GdkRectangle *request,
4072 GdkGeometry *geometry,
4075 GdkGeometry new_geometry;
4079 GtkWindowPosition pos;
4080 GtkWidget *parent_widget;
4081 GtkWindowGeometryInfo *info;
4084 widget = GTK_WIDGET (window);
4086 gtk_widget_size_request (widget, NULL);
4087 gtk_window_compute_configure_request_size (window, &w, &h);
4089 gtk_window_compute_hints (window, &new_geometry, &new_flags);
4090 gtk_window_constrain_size (window,
4091 &new_geometry, new_flags,
4095 parent_widget = (GtkWidget*) window->transient_parent;
4097 pos = window->position;
4098 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
4099 (parent_widget == NULL ||
4100 !GTK_WIDGET_MAPPED (parent_widget)))
4101 pos = GTK_WIN_POS_NONE;
4103 info = gtk_window_get_geometry_info (window, TRUE);
4105 /* by default, don't change position requested */
4106 x = info->last.configure_request.x;
4107 y = info->last.configure_request.y;
4109 if (window->need_default_position)
4112 /* FIXME this all interrelates with window gravity.
4113 * For most of them I think we want to set GRAVITY_CENTER.
4115 * Not sure how to go about that.
4120 /* here we are only handling CENTER_ALWAYS
4121 * as it relates to default positioning,
4122 * where it's equivalent to simply CENTER
4124 case GTK_WIN_POS_CENTER_ALWAYS:
4125 case GTK_WIN_POS_CENTER:
4127 gint px, py, monitor_num;
4128 GdkRectangle monitor;
4130 gdk_window_get_pointer (gdk_screen_get_root_window (window->screen),
4133 monitor_num = gdk_screen_get_monitor_at_point (window->screen, px, py);
4134 if (monitor_num == -1)
4137 gdk_screen_get_monitor_geometry (window->screen, monitor_num, &monitor);
4139 x = (monitor.width - w) / 2 + monitor.x;
4140 y = (monitor.height - h) / 2 + monitor.y;
4144 case GTK_WIN_POS_CENTER_ON_PARENT:
4148 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
4150 gdk_window_get_origin (parent_widget->window,
4153 x = ox + (parent_widget->allocation.width - w) / 2;
4154 y = oy + (parent_widget->allocation.height - h) / 2;
4158 case GTK_WIN_POS_MOUSE:
4160 gint screen_width = gdk_screen_get_width (window->screen);
4161 gint screen_height = gdk_screen_get_height (window->screen);
4164 gdk_window_get_pointer (NULL, &px, &py, NULL);
4167 x = CLAMP (x, 0, screen_width - w);
4168 y = CLAMP (y, 0, screen_height - h);
4175 } /* if (window->need_default_position) */
4177 if (window->need_default_position &&
4178 info->initial_pos_set)
4180 x = info->initial_x;
4181 y = info->initial_y;
4182 gtk_window_constrain_position (window, w, h, &x, &y);
4188 request->height = h;
4191 *geometry = new_geometry;
4197 gtk_window_constrain_position (GtkWindow *window,
4203 /* See long comments in gtk_window_move_resize()
4204 * on when it's safe to call this function.
4206 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4208 gint center_x, center_y;
4209 gint screen_width = gdk_screen_get_width (window->screen);
4210 gint screen_height = gdk_screen_get_height (window->screen);
4212 center_x = (screen_width - new_width) / 2;
4213 center_y = (screen_height - new_height) / 2;
4221 gtk_window_move_resize (GtkWindow *window)
4225 * First we determine whether any information has changed that would
4226 * cause us to revise our last configure request. If we would send
4227 * a different configure request from last time, then
4228 * configure_request_size_changed = TRUE or
4229 * configure_request_pos_changed = TRUE. configure_request_size_changed
4230 * may be true due to new hints, a gtk_window_resize(), or whatever.
4231 * configure_request_pos_changed may be true due to gtk_window_set_position()
4232 * or gtk_window_move().
4234 * If the configure request has changed, we send off a new one. To
4235 * ensure GTK+ invariants are maintained (resize queue does what it
4236 * should), we go ahead and size_allocate the requested size in this
4239 * If the configure request has not changed, we don't ever resend
4240 * it, because it could mean fighting the user or window manager.
4243 * To prepare the configure request, we come up with a base size/pos:
4244 * - the one from gtk_window_move()/gtk_window_resize()
4245 * - else default_width, default_height if we haven't ever
4247 * - else the size request if we haven't ever been mapped,
4248 * as a substitute default size
4249 * - else the current size of the window, as received from
4250 * configure notifies (i.e. the current allocation)
4252 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4253 * the position request to be centered.
4256 GtkContainer *container;
4257 GtkWindowGeometryInfo *info;
4258 GdkGeometry new_geometry;
4260 GdkRectangle new_request;
4261 gboolean configure_request_size_changed;
4262 gboolean configure_request_pos_changed;
4263 gboolean hints_changed; /* do we need to send these again */
4264 GtkWindowLastGeometryInfo saved_last_info;
4266 widget = GTK_WIDGET (window);
4267 container = GTK_CONTAINER (widget);
4268 info = gtk_window_get_geometry_info (window, TRUE);
4270 configure_request_size_changed = FALSE;
4271 configure_request_pos_changed = FALSE;
4273 gtk_window_compute_configure_request (window, &new_request,
4274 &new_geometry, &new_flags);
4276 /* This check implies the invariant that we never set info->last
4277 * without setting the hints and sending off a configure request.
4279 * If we change info->last without sending the request, we may
4282 if (info->last.configure_request.x != new_request.x ||
4283 info->last.configure_request.y != new_request.y)
4284 configure_request_pos_changed = TRUE;
4286 if ((info->last.configure_request.width != new_request.width ||
4287 info->last.configure_request.height != new_request.height))
4288 configure_request_size_changed = TRUE;
4290 hints_changed = FALSE;
4292 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4293 &new_geometry, new_flags))
4295 hints_changed = TRUE;
4298 /* Position Constraints
4299 * ====================
4301 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4302 * a default. The other POS_ values are used only when the
4303 * window is shown, not after that.
4305 * However, we can't implement a position constraint as
4306 * "anytime the window size changes, center the window"
4307 * because this may well end up fighting the WM or user. In
4308 * fact it gets in an infinite loop with at least one WM.
4310 * Basically, applications are in no way in a position to
4311 * constrain the position of a window, with one exception:
4312 * override redirect windows. (Really the intended purpose
4313 * of CENTER_ALWAYS anyhow, I would think.)
4315 * So the way we implement this "constraint" is to say that when WE
4316 * cause a move or resize, i.e. we make a configure request changing
4317 * window size, we recompute the CENTER_ALWAYS position to reflect
4318 * the new window size, and include it in our request. Also, if we
4319 * just turned on CENTER_ALWAYS we snap to center with a new
4320 * request. Otherwise, if we are just NOTIFIED of a move or resize
4321 * done by someone else e.g. the window manager, we do NOT send a
4322 * new configure request.
4324 * For override redirect windows, this works fine; all window
4325 * sizes are from our configure requests. For managed windows,
4326 * it is at least semi-sane, though who knows what the
4327 * app author is thinking.
4330 /* This condition should be kept in sync with the condition later on
4331 * that determines whether we send a configure request. i.e. we
4332 * should do this position constraining anytime we were going to
4333 * send a configure request anyhow, plus when constraints have
4336 if (configure_request_pos_changed ||
4337 configure_request_size_changed ||
4339 info->position_constraints_changed)
4341 /* We request the constrained position if:
4342 * - we were changing position, and need to clamp
4343 * the change to the constraint
4344 * - we're changing the size anyway
4345 * - set_position() was called to toggle CENTER_ALWAYS on
4348 gtk_window_constrain_position (window,
4354 /* Update whether we need to request a move */
4355 if (info->last.configure_request.x != new_request.x ||
4356 info->last.configure_request.y != new_request.y)
4357 configure_request_pos_changed = TRUE;
4359 configure_request_pos_changed = FALSE;
4363 if (window->type == GTK_WINDOW_TOPLEVEL)
4365 int notify_x, notify_y;
4367 /* this is the position from the last configure notify */
4368 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4370 g_message ("--- %s ---\n"
4371 "last : %d,%d\t%d x %d\n"
4372 "this : %d,%d\t%d x %d\n"
4373 "alloc : %d,%d\t%d x %d\n"
4375 "resize: \t%d x %d\n"
4376 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4377 "configure_notify_received: %d\n"
4378 "configure_request_count: %d\n"
4379 "position_constraints_changed: %d\n",
4380 window->title ? window->title : "(no title)",
4381 info->last.configure_request.x,
4382 info->last.configure_request.y,
4383 info->last.configure_request.width,
4384 info->last.configure_request.height,
4390 widget->allocation.width,
4391 widget->allocation.height,
4392 widget->requisition.width,
4393 widget->requisition.height,
4395 info->resize_height,
4396 configure_request_pos_changed,
4397 configure_request_size_changed,
4399 window->configure_notify_received,
4400 window->configure_request_count,
4401 info->position_constraints_changed);
4405 saved_last_info = info->last;
4406 info->last.geometry = new_geometry;
4407 info->last.flags = new_flags;
4408 info->last.configure_request = new_request;
4410 /* need to set PPosition so the WM will look at our position,
4411 * but we don't want to count PPosition coming and going as a hints
4412 * change for future iterations. So we saved info->last prior to
4416 /* Also, if the initial position was explicitly set, then we always
4417 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4421 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4422 * this is an initial map
4425 if ((configure_request_pos_changed ||
4426 info->initial_pos_set ||
4427 (window->need_default_position &&
4428 window->position != GTK_WIN_POS_NONE)) &&
4429 (new_flags & GDK_HINT_POS) == 0)
4431 new_flags |= GDK_HINT_POS;
4432 hints_changed = TRUE;
4435 /* Set hints if necessary
4438 gdk_window_set_geometry_hints (widget->window,
4442 /* handle resizing/moving and widget tree allocation
4444 if (window->configure_notify_received)
4446 GtkAllocation allocation;
4448 /* If we have received a configure event since
4449 * the last time in this function, we need to
4450 * accept our new size and size_allocate child widgets.
4451 * (see gtk_window_configure_event() for more details).
4453 * 1 or more configure notifies may have been received.
4454 * Also, configure_notify_received will only be TRUE
4455 * if all expected configure notifies have been received
4456 * (one per configure request), as an optimization.
4459 window->configure_notify_received = FALSE;
4461 /* gtk_window_configure_event() filled in widget->allocation */
4462 allocation = widget->allocation;
4463 gtk_widget_size_allocate (widget, &allocation);
4465 /* If the configure request changed, it means that
4467 * 1) coincidentally changed hints or widget properties
4468 * impacting the configure request before getting
4469 * a configure notify, or
4470 * 2) some broken widget is changing its size request
4471 * during size allocation, resulting in
4472 * a false appearance of changed configure request.
4474 * For 1), we could just go ahead and ask for the
4475 * new size right now, but doing that for 2)
4476 * might well be fighting the user (and can even
4477 * trigger a loop). Since we really don't want to
4478 * do that, we requeue a resize in hopes that
4479 * by the time it gets handled, the child has seen
4480 * the light and is willing to go along with the
4481 * new size. (this happens for the zvt widget, since
4482 * the size_allocate() above will have stored the
4483 * requisition corresponding to the new size in the
4486 * This doesn't buy us anything for 1), but it shouldn't
4487 * hurt us too badly, since it is what would have
4488 * happened if we had gotten the configure event before
4489 * the new size had been set.
4492 if (configure_request_size_changed ||
4493 configure_request_pos_changed)
4495 /* Don't change the recorded last info after all, because we
4496 * haven't actually updated to the new info yet - we decided
4497 * to postpone our configure request until later.
4499 info->last = saved_last_info;
4501 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
4504 else if ((configure_request_size_changed || hints_changed) &&
4505 (widget->allocation.width != new_request.width ||
4506 widget->allocation.height != new_request.height))
4509 /* We are in one of the following situations:
4510 * A. configure_request_size_changed
4511 * our requisition has changed and we need a different window size,
4512 * so we request it from the window manager.
4513 * B. !configure_request_size_changed && hints_changed
4514 * the window manager rejects our size, but we have just changed the
4515 * window manager hints, so there's a chance our request will
4516 * be honoured this time, so we try again.
4518 * However, if the new requisition is the same as the current allocation,
4519 * we don't request it again, since we won't get a ConfigureNotify back from
4520 * the window manager unless it decides to change our requisition. If
4521 * we don't get the ConfigureNotify back, the resize queue will never be run.
4524 /* Now send the configure request */
4525 if (configure_request_pos_changed)
4529 gdk_window_move_resize (window->frame,
4530 new_request.x - window->frame_left,
4531 new_request.y - window->frame_top,
4532 new_request.width + window->frame_left + window->frame_right,
4533 new_request.height + window->frame_top + window->frame_bottom);
4534 gdk_window_resize (widget->window,
4535 new_request.width, new_request.height);
4539 gdk_window_move_resize (widget->window,
4540 new_request.x, new_request.y,
4541 new_request.width, new_request.height);
4543 else /* only size changed */
4546 gdk_window_resize (window->frame,
4547 new_request.width + window->frame_left + window->frame_right,
4548 new_request.height + window->frame_top + window->frame_bottom);
4550 gdk_window_resize (widget->window,
4551 new_request.width, new_request.height);
4554 /* Increment the number of have-not-yet-received-notify requests */
4555 window->configure_request_count += 1;
4557 /* We have now sent a request since the last position constraint
4558 * change and definitely don't need a an initial size again (not
4559 * resetting this here can lead to infinite loops for
4560 * GTK_RESIZE_IMMEDIATE containers)
4562 info->position_constraints_changed = FALSE;
4563 info->initial_pos_set = FALSE;
4564 info->resize_width = -1;
4565 info->resize_height = -1;
4567 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
4568 * configure event in response to our resizing request.
4569 * the configure event will cause a new resize with
4570 * ->configure_notify_received=TRUE.
4571 * until then, we want to
4572 * - discard expose events
4573 * - coalesce resizes for our children
4574 * - defer any window resizes until the configure event arrived
4575 * to achieve this, we queue a resize for the window, but remove its
4576 * resizing handler, so resizing will not be handled from the next
4577 * idle handler but when the configure event arrives.
4579 * FIXME: we should also dequeue the pending redraws here, since
4580 * we handle those ourselves upon ->configure_notify_received==TRUE.
4582 if (container->resize_mode == GTK_RESIZE_QUEUE)
4584 gtk_widget_queue_resize (widget);
4585 _gtk_container_dequeue_resize_handler (container);
4590 /* Handle any position changes.
4592 if (configure_request_pos_changed)
4596 gdk_window_move (window->frame,
4597 new_request.x - window->frame_left,
4598 new_request.y - window->frame_top);
4601 gdk_window_move (widget->window,
4602 new_request.x, new_request.y);
4605 /* And run the resize queue.
4607 gtk_container_resize_children (container);
4611 /* Compare two sets of Geometry hints for equality.
4614 gtk_window_compare_hints (GdkGeometry *geometry_a,
4616 GdkGeometry *geometry_b,
4619 if (flags_a != flags_b)
4622 if ((flags_a & GDK_HINT_MIN_SIZE) &&
4623 (geometry_a->min_width != geometry_b->min_width ||
4624 geometry_a->min_height != geometry_b->min_height))
4627 if ((flags_a & GDK_HINT_MAX_SIZE) &&
4628 (geometry_a->max_width != geometry_b->max_width ||
4629 geometry_a->max_height != geometry_b->max_height))
4632 if ((flags_a & GDK_HINT_BASE_SIZE) &&
4633 (geometry_a->base_width != geometry_b->base_width ||
4634 geometry_a->base_height != geometry_b->base_height))
4637 if ((flags_a & GDK_HINT_ASPECT) &&
4638 (geometry_a->min_aspect != geometry_b->min_aspect ||
4639 geometry_a->max_aspect != geometry_b->max_aspect))
4642 if ((flags_a & GDK_HINT_RESIZE_INC) &&
4643 (geometry_a->width_inc != geometry_b->width_inc ||
4644 geometry_a->height_inc != geometry_b->height_inc))
4647 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
4648 geometry_a->win_gravity != geometry_b->win_gravity)
4655 _gtk_window_constrain_size (GtkWindow *window,
4661 GtkWindowGeometryInfo *info;
4663 g_return_if_fail (GTK_IS_WINDOW (window));
4665 info = window->geometry_info;
4668 GdkWindowHints flags = info->last.flags;
4669 GdkGeometry *geometry = &info->last.geometry;
4671 gtk_window_constrain_size (window,
4682 gtk_window_constrain_size (GtkWindow *window,
4683 GdkGeometry *geometry,
4690 gdk_window_constrain_size (geometry, flags, width, height,
4691 new_width, new_height);
4694 /* Compute the set of geometry hints and flags for a window
4695 * based on the application set geometry, and requisiition
4696 * of the window. gtk_widget_size_request() must have been
4700 gtk_window_compute_hints (GtkWindow *window,
4701 GdkGeometry *new_geometry,
4705 gint extra_width = 0;
4706 gint extra_height = 0;
4707 GtkWindowGeometryInfo *geometry_info;
4708 GtkRequisition requisition;
4710 widget = GTK_WIDGET (window);
4712 gtk_widget_get_child_requisition (widget, &requisition);
4713 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
4717 *new_flags = geometry_info->mask;
4718 *new_geometry = geometry_info->geometry;
4725 if (geometry_info && geometry_info->widget)
4727 GtkRequisition child_requisition;
4729 /* FIXME: This really isn't right. It gets the min size wrong and forces
4730 * callers to do horrible hacks like set a huge usize on the child requisition
4731 * to get the base size right. We really want to find the answers to:
4733 * - If the geometry widget was infinitely big, how much extra space
4734 * would be needed for the stuff around it.
4736 * - If the geometry widget was infinitely small, how big would the
4737 * window still have to be.
4739 * Finding these answers would be a bit of a mess here. (Bug #68668)
4741 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
4743 extra_width = widget->requisition.width - child_requisition.width;
4744 extra_height = widget->requisition.height - child_requisition.height;
4747 /* We don't want to set GDK_HINT_POS in here, we just set it
4748 * in gtk_window_move_resize() when we want the position
4752 if (*new_flags & GDK_HINT_BASE_SIZE)
4754 new_geometry->base_width += extra_width;
4755 new_geometry->base_height += extra_height;
4757 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
4758 (*new_flags & GDK_HINT_RESIZE_INC) &&
4759 ((extra_width != 0) || (extra_height != 0)))
4761 *new_flags |= GDK_HINT_BASE_SIZE;
4763 new_geometry->base_width = extra_width;
4764 new_geometry->base_height = extra_height;
4767 if (*new_flags & GDK_HINT_MIN_SIZE)
4769 if (new_geometry->min_width < 0)
4770 new_geometry->min_width = requisition.width;
4772 new_geometry->min_width += extra_width;
4774 if (new_geometry->min_height < 0)
4775 new_geometry->min_height = requisition.height;
4777 new_geometry->min_height += extra_height;
4779 else if (!window->allow_shrink)
4781 *new_flags |= GDK_HINT_MIN_SIZE;
4783 new_geometry->min_width = requisition.width;
4784 new_geometry->min_height = requisition.height;
4787 if (*new_flags & GDK_HINT_MAX_SIZE)
4789 if (new_geometry->max_width < 0)
4790 new_geometry->max_width = requisition.width;
4792 new_geometry->max_width += extra_width;
4794 if (new_geometry->max_height < 0)
4795 new_geometry->max_width = requisition.height;
4797 new_geometry->max_height += extra_height;
4799 else if (!window->allow_grow)
4801 *new_flags |= GDK_HINT_MAX_SIZE;
4803 new_geometry->max_width = requisition.width;
4804 new_geometry->max_height = requisition.height;
4807 *new_flags |= GDK_HINT_WIN_GRAVITY;
4808 new_geometry->win_gravity = window->gravity;
4811 /***********************
4812 * Redrawing functions *
4813 ***********************/
4816 gtk_window_paint (GtkWidget *widget,
4819 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
4820 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
4824 gtk_window_expose (GtkWidget *widget,
4825 GdkEventExpose *event)
4827 if (!GTK_WIDGET_APP_PAINTABLE (widget))
4828 gtk_window_paint (widget, &event->area);
4830 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
4831 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
4837 * gtk_window_set_has_frame:
4838 * @window: a #GtkWindow
4839 * @setting: a boolean
4841 * (Note: this is a special-purpose function for the framebuffer port,
4842 * that causes GTK+ to draw its own window border. For most applications,
4843 * you want gtk_window_set_decorated() instead, which tells the window
4844 * manager whether to draw the window border.)
4846 * If this function is called on a window with setting of %TRUE, before
4847 * it is realized or showed, it will have a "frame" window around
4848 * @window->window, accessible in @window->frame. Using the signal
4849 * frame_event you can recieve all events targeted at the frame.
4851 * This function is used by the linux-fb port to implement managed
4852 * windows, but it could concievably be used by X-programs that
4853 * want to do their own window decorations.
4857 gtk_window_set_has_frame (GtkWindow *window,
4860 g_return_if_fail (GTK_IS_WINDOW (window));
4861 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
4863 window->has_frame = setting != FALSE;
4867 * gtk_window_get_has_frame:
4868 * @window: a #GtkWindow
4870 * Accessor for whether the window has a frame window exterior to
4871 * @window->window. Gets the value set by gtk_window_set_has_frame ().
4873 * Return value: %TRUE if a frame has been added to the window
4874 * via gtk_window_set_has_frame().
4877 gtk_window_get_has_frame (GtkWindow *window)
4879 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4881 return window->has_frame;
4885 * gtk_window_set_frame_dimensions:
4886 * @window: a #GtkWindow that has a frame
4887 * @left: The width of the left border
4888 * @top: The height of the top border
4889 * @right: The width of the right border
4890 * @bottom: The height of the bottom border
4892 * (Note: this is a special-purpose function intended for the framebuffer
4893 * port; see gtk_window_set_has_frame(). It will have no effect on the
4894 * window border drawn by the window manager, which is the normal
4895 * case when using the X Window system.)
4897 * For windows with frames (see gtk_window_set_has_frame()) this function
4898 * can be used to change the size of the frame border.
4901 gtk_window_set_frame_dimensions (GtkWindow *window,
4909 g_return_if_fail (GTK_IS_WINDOW (window));
4911 widget = GTK_WIDGET (window);
4913 if (window->frame_left == left &&
4914 window->frame_top == top &&
4915 window->frame_right == right &&
4916 window->frame_bottom == bottom)
4919 window->frame_left = left;
4920 window->frame_top = top;
4921 window->frame_right = right;
4922 window->frame_bottom = bottom;
4924 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4926 gint width = widget->allocation.width + left + right;
4927 gint height = widget->allocation.height + top + bottom;
4928 gdk_window_resize (window->frame, width, height);
4929 gtk_decorated_window_move_resize_window (window,
4931 widget->allocation.width,
4932 widget->allocation.height);
4937 * gtk_window_present:
4938 * @window: a #GtkWindow
4940 * Presents a window to the user. This may mean raising the window
4941 * in the stacking order, deiconifying it, moving it to the current
4942 * desktop, and/or giving it the keyboard focus, possibly dependent
4943 * on the user's platform, window manager, and preferences.
4945 * If @window is hidden, this function calls gtk_widget_show()
4948 * This function should be used when the user tries to open a window
4949 * that's already open. Say for example the preferences dialog is
4950 * currently open, and the user chooses Preferences from the menu
4951 * a second time; use gtk_window_present() to move the already-open dialog
4952 * where the user can see it.
4956 gtk_window_present (GtkWindow *window)
4960 g_return_if_fail (GTK_IS_WINDOW (window));
4962 widget = GTK_WIDGET (window);
4964 if (GTK_WIDGET_VISIBLE (window))
4966 g_assert (widget->window != NULL);
4968 gdk_window_show (widget->window);
4970 /* note that gdk_window_focus() will also move the window to
4971 * the current desktop, for WM spec compliant window managers.
4973 gdk_window_focus (widget->window,
4974 gtk_get_current_event_time ());
4978 gtk_widget_show (widget);
4983 * gtk_window_iconify:
4984 * @window: a #GtkWindow
4986 * Asks to iconify (i.e. minimize) the specified @window. Note that
4987 * you shouldn't assume the window is definitely iconified afterward,
4988 * because other entities (e.g. the user or <link
4989 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
4990 * again, or there may not be a window manager in which case
4991 * iconification isn't possible, etc. But normally the window will end
4992 * up iconified. Just don't write code that crashes if not.
4994 * It's permitted to call this function before showing a window,
4995 * in which case the window will be iconified before it ever appears
4998 * You can track iconification via the "window_state_event" signal
5003 gtk_window_iconify (GtkWindow *window)
5006 GdkWindow *toplevel;
5008 g_return_if_fail (GTK_IS_WINDOW (window));
5010 widget = GTK_WIDGET (window);
5012 window->iconify_initially = TRUE;
5015 toplevel = window->frame;
5017 toplevel = widget->window;
5019 if (toplevel != NULL)
5020 gdk_window_iconify (toplevel);
5024 * gtk_window_deiconify:
5025 * @window: a #GtkWindow
5027 * Asks to deiconify (i.e. unminimize) the specified @window. Note
5028 * that you shouldn't assume the window is definitely deiconified
5029 * afterward, because other entities (e.g. the user or <link
5030 * linkend="gtk-X11-arch">window manager</link>) could iconify it
5031 * again before your code which assumes deiconification gets to run.
5033 * You can track iconification via the "window_state_event" signal
5037 gtk_window_deiconify (GtkWindow *window)
5040 GdkWindow *toplevel;
5042 g_return_if_fail (GTK_IS_WINDOW (window));
5044 widget = GTK_WIDGET (window);
5046 window->iconify_initially = FALSE;
5049 toplevel = window->frame;
5051 toplevel = widget->window;
5053 if (toplevel != NULL)
5054 gdk_window_deiconify (toplevel);
5059 * @window: a #GtkWindow
5061 * Asks to stick @window, which means that it will appear on all user
5062 * desktops. Note that you shouldn't assume the window is definitely
5063 * stuck afterward, because other entities (e.g. the user or <link
5064 * linkend="gtk-X11-arch">window manager</link>) could unstick it
5065 * again, and some window managers do not support sticking
5066 * windows. But normally the window will end up stuck. Just don't
5067 * write code that crashes if not.
5069 * It's permitted to call this function before showing a window.
5071 * You can track stickiness via the "window_state_event" signal
5076 gtk_window_stick (GtkWindow *window)
5079 GdkWindow *toplevel;
5081 g_return_if_fail (GTK_IS_WINDOW (window));
5083 widget = GTK_WIDGET (window);
5085 window->stick_initially = TRUE;
5088 toplevel = window->frame;
5090 toplevel = widget->window;
5092 if (toplevel != NULL)
5093 gdk_window_stick (toplevel);
5097 * gtk_window_unstick:
5098 * @window: a #GtkWindow
5100 * Asks to unstick @window, which means that it will appear on only
5101 * one of the user's desktops. Note that you shouldn't assume the
5102 * window is definitely unstuck afterward, because other entities
5103 * (e.g. the user or <link linkend="gtk-X11-arch">window
5104 * manager</link>) could stick it again. But normally the window will
5105 * end up stuck. Just don't write code that crashes if not.
5107 * You can track stickiness via the "window_state_event" signal
5112 gtk_window_unstick (GtkWindow *window)
5115 GdkWindow *toplevel;
5117 g_return_if_fail (GTK_IS_WINDOW (window));
5119 widget = GTK_WIDGET (window);
5121 window->stick_initially = FALSE;
5124 toplevel = window->frame;
5126 toplevel = widget->window;
5128 if (toplevel != NULL)
5129 gdk_window_unstick (toplevel);
5133 * gtk_window_maximize:
5134 * @window: a #GtkWindow
5136 * Asks to maximize @window, so that it becomes full-screen. Note that
5137 * you shouldn't assume the window is definitely maximized afterward,
5138 * because other entities (e.g. the user or <link
5139 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
5140 * again, and not all window managers support maximization. But
5141 * normally the window will end up maximized. Just don't write code
5142 * that crashes if not.
5144 * It's permitted to call this function before showing a window,
5145 * in which case the window will be maximized when it appears onscreen
5148 * You can track maximization via the "window_state_event" signal
5153 gtk_window_maximize (GtkWindow *window)
5156 GdkWindow *toplevel;
5158 g_return_if_fail (GTK_IS_WINDOW (window));
5160 widget = GTK_WIDGET (window);
5162 window->maximize_initially = TRUE;
5165 toplevel = window->frame;
5167 toplevel = widget->window;
5169 if (toplevel != NULL)
5170 gdk_window_maximize (toplevel);
5174 * gtk_window_unmaximize:
5175 * @window: a #GtkWindow
5177 * Asks to unmaximize @window. Note that you shouldn't assume the
5178 * window is definitely unmaximized afterward, because other entities
5179 * (e.g. the user or <link linkend="gtk-X11-arch">window
5180 * manager</link>) could maximize it again, and not all window
5181 * managers honor requests to unmaximize. But normally the window will
5182 * end up unmaximized. Just don't write code that crashes if not.
5184 * You can track maximization via the "window_state_event" signal
5189 gtk_window_unmaximize (GtkWindow *window)
5192 GdkWindow *toplevel;
5194 g_return_if_fail (GTK_IS_WINDOW (window));
5196 widget = GTK_WIDGET (window);
5198 window->maximize_initially = FALSE;
5201 toplevel = window->frame;
5203 toplevel = widget->window;
5205 if (toplevel != NULL)
5206 gdk_window_unmaximize (toplevel);
5210 * gtk_window_set_resizable:
5211 * @window: a #GtkWindow
5212 * @resizable: %TRUE if the user can resize this window
5214 * Sets whether the user can resize a window. Windows are user resizable
5218 gtk_window_set_resizable (GtkWindow *window,
5221 g_return_if_fail (GTK_IS_WINDOW (window));
5223 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5227 * gtk_window_get_resizable:
5228 * @window: a #GtkWindow
5230 * Gets the value set by gtk_window_set_resizable().
5232 * Return value: %TRUE if the user can resize the window
5235 gtk_window_get_resizable (GtkWindow *window)
5237 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5239 /* allow_grow is most likely to indicate the semantic concept we
5240 * mean by "resizable" (and will be a reliable indicator if
5241 * set_policy() hasn't been called)
5243 return window->allow_grow;
5247 * gtk_window_set_gravity:
5248 * @window: a #GtkWindow
5249 * @gravity: window gravity
5251 * Window gravity defines the meaning of coordinates passed to
5252 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5255 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5256 * typically "do what you mean."
5260 gtk_window_set_gravity (GtkWindow *window,
5263 g_return_if_fail (GTK_IS_WINDOW (window));
5265 if (gravity != window->gravity)
5267 window->gravity = gravity;
5269 /* gtk_window_move_resize() will adapt gravity
5271 gtk_widget_queue_resize (GTK_WIDGET (window));
5276 * gtk_window_get_gravity:
5277 * @window: a #GtkWindow
5279 * Gets the value set by gtk_window_set_gravity().
5281 * Return value: window gravity
5284 gtk_window_get_gravity (GtkWindow *window)
5286 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5288 return window->gravity;
5292 * gtk_window_begin_resize_drag:
5293 * @window: a #GtkWindow
5294 * @button: mouse button that initiated the drag
5295 * @edge: position of the resize control
5296 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5297 * @root_y: Y position where the user clicked to initiate the drag
5298 * @timestamp: timestamp from the click event that initiated the drag
5300 * Starts resizing a window. This function is used if an application
5301 * has window resizing controls. When GDK can support it, the resize
5302 * will be done using the standard mechanism for the <link
5303 * linkend="gtk-X11-arch">window manager</link> or windowing
5304 * system. Otherwise, GDK will try to emulate window resizing,
5305 * potentially not all that well, depending on the windowing system.
5309 gtk_window_begin_resize_drag (GtkWindow *window,
5317 GdkWindow *toplevel;
5319 g_return_if_fail (GTK_IS_WINDOW (window));
5320 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5322 widget = GTK_WIDGET (window);
5325 toplevel = window->frame;
5327 toplevel = widget->window;
5329 gdk_window_begin_resize_drag (toplevel,
5336 * gtk_window_get_frame_dimensions:
5337 * @window: a #GtkWindow
5338 * @left: location to store the width of the frame at the left, or %NULL
5339 * @top: location to store the height of the frame at the top, or %NULL
5340 * @right: location to store the width of the frame at the returns, or %NULL
5341 * @bottom: location to store the height of the frame at the bottom, or %NULL
5343 * (Note: this is a special-purpose function intended for the
5344 * framebuffer port; see gtk_window_set_has_frame(). It will not
5345 * return the size of the window border drawn by the <link
5346 * linkend="gtk-X11-arch">window manager</link>, which is the normal
5347 * case when using a windowing system. See
5348 * gdk_window_get_frame_extents() to get the standard window border
5351 * Retrieves the dimensions of the frame window for this toplevel.
5352 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5355 gtk_window_get_frame_dimensions (GtkWindow *window,
5361 g_return_if_fail (GTK_IS_WINDOW (window));
5364 *left = window->frame_left;
5366 *top = window->frame_top;
5368 *right = window->frame_right;
5370 *bottom = window->frame_bottom;
5374 * gtk_window_begin_move_drag:
5375 * @window: a #GtkWindow
5376 * @button: mouse button that initiated the drag
5377 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5378 * @root_y: Y position where the user clicked to initiate the drag
5379 * @timestamp: timestamp from the click event that initiated the drag
5381 * Starts moving a window. This function is used if an application has
5382 * window movement grips. When GDK can support it, the window movement
5383 * will be done using the standard mechanism for the <link
5384 * linkend="gtk-X11-arch">window manager</link> or windowing
5385 * system. Otherwise, GDK will try to emulate window movement,
5386 * potentially not all that well, depending on the windowing system.
5390 gtk_window_begin_move_drag (GtkWindow *window,
5397 GdkWindow *toplevel;
5399 g_return_if_fail (GTK_IS_WINDOW (window));
5400 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5402 widget = GTK_WIDGET (window);
5405 toplevel = window->frame;
5407 toplevel = widget->window;
5409 gdk_window_begin_move_drag (toplevel,
5416 * gtk_window_set_screen:
5417 * @window: a #GtkWindow.
5418 * @screen: a #GdkScreen.
5420 * Sets the #GdkScreen where the @window is displayed; if
5421 * the window is already mapped, it will be unmapped, and
5422 * then remapped on the new screen.
5425 gtk_window_set_screen (GtkWindow *window,
5429 gboolean was_mapped;
5431 g_return_if_fail (GTK_IS_WINDOW (window));
5432 g_return_if_fail (GDK_IS_SCREEN (screen));
5434 if (screen == window->screen)
5437 widget = GTK_WIDGET (window);
5439 was_mapped = GTK_WIDGET_MAPPED (widget);
5442 gtk_widget_unmap (widget);
5443 if (GTK_WIDGET_REALIZED (widget))
5444 gtk_widget_unrealize (widget);
5446 gtk_window_free_key_hash (window);
5447 window->screen = screen;
5448 gtk_widget_reset_rc_styles (widget);
5449 g_object_notify (G_OBJECT (window), "screen");
5452 gtk_widget_map (widget);
5456 * gtk_window_get_screen:
5457 * @window: a #GtkWindow.
5459 * Returns the #GdkScreen associated with @window.
5461 * Return value: a #GdkScreen.
5464 gtk_window_get_screen (GtkWindow *window)
5466 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
5468 return window->screen;
5473 gtk_window_group_class_init (GtkWindowGroupClass *klass)
5478 gtk_window_group_get_type (void)
5480 static GtkType window_group_type = 0;
5482 if (!window_group_type)
5484 static const GTypeInfo window_group_info =
5486 sizeof (GtkWindowGroupClass),
5487 NULL, /* base_init */
5488 NULL, /* base_finalize */
5489 (GClassInitFunc) gtk_window_group_class_init,
5490 NULL, /* class_finalize */
5491 NULL, /* class_data */
5492 sizeof (GtkWindowGroup),
5493 16, /* n_preallocs */
5494 (GInstanceInitFunc) NULL,
5497 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
5500 return window_group_type;
5504 * gtk_window_group_new:
5506 * Creates a new #GtkWindowGroup object. Grabs added with
5507 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
5509 * Return value: a new #GtkWindowGroup.
5512 gtk_window_group_new (void)
5514 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
5518 window_group_cleanup_grabs (GtkWindowGroup *group,
5522 GSList *to_remove = NULL;
5524 tmp_list = group->grabs;
5527 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
5528 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
5529 tmp_list = tmp_list->next;
5534 gtk_grab_remove (to_remove->data);
5535 g_object_unref (to_remove->data);
5536 to_remove = g_slist_delete_link (to_remove, to_remove);
5541 * gtk_window_group_add_window:
5542 * @window_group: a #GtkWindowGroup
5543 * @window: the #GtkWindow to add
5545 * Adds a window to a #GtkWindowGroup.
5548 gtk_window_group_add_window (GtkWindowGroup *window_group,
5551 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5552 g_return_if_fail (GTK_IS_WINDOW (window));
5554 if (window->group != window_group)
5556 g_object_ref (window);
5557 g_object_ref (window_group);
5560 gtk_window_group_remove_window (window->group, window);
5562 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
5564 window->group = window_group;
5566 g_object_unref (window);
5571 * gtk_window_group_remove_window:
5572 * @window_group: a #GtkWindowGroup
5573 * @window: the #GtkWindow to remove
5575 * Removes a window from a #GtkWindowGroup.
5578 gtk_window_group_remove_window (GtkWindowGroup *window_group,
5581 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5582 g_return_if_fail (GTK_IS_WIDGET (window));
5583 g_return_if_fail (window->group == window_group);
5585 g_object_ref (window);
5587 window_group_cleanup_grabs (window_group, window);
5588 window->group = NULL;
5590 g_object_unref (G_OBJECT (window_group));
5591 g_object_unref (window);
5594 /* Return the group for the window or the default group
5597 _gtk_window_get_group (GtkWindow *window)
5599 if (window && window->group)
5600 return window->group;
5603 static GtkWindowGroup *default_group = NULL;
5606 default_group = gtk_window_group_new ();
5608 return default_group;
5614 Derived from XParseGeometry() in XFree86
5616 Copyright 1985, 1986, 1987,1998 The Open Group
5618 All Rights Reserved.
5620 The above copyright notice and this permission notice shall be included
5621 in all copies or substantial portions of the Software.
5623 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5624 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5625 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
5626 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
5627 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
5628 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
5629 OTHER DEALINGS IN THE SOFTWARE.
5631 Except as contained in this notice, the name of The Open Group shall
5632 not be used in advertising or otherwise to promote the sale, use or
5633 other dealings in this Software without prior written authorization
5634 from The Open Group.
5639 * XParseGeometry parses strings of the form
5640 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5641 * width, height, xoffset, and yoffset are unsigned integers.
5642 * Example: "=80x24+300-49"
5643 * The equal sign is optional.
5644 * It returns a bitmask that indicates which of the four values
5645 * were actually found in the string. For each value found,
5646 * the corresponding argument is updated; for each value
5647 * not found, the corresponding argument is left unchanged.
5650 /* The following code is from Xlib, and is minimally modified, so we
5651 * can track any upstream changes if required. Don't change this
5652 * code. Or if you do, put in a huge comment marking which thing
5657 read_int (gchar *string,
5665 else if (*string == '-')
5671 for (; (*string >= '0') && (*string <= '9'); string++)
5673 result = (result * 10) + (*string - '0');
5685 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
5686 * value (x, y, width, height) was found in the parsed string.
5688 #define NoValue 0x0000
5689 #define XValue 0x0001
5690 #define YValue 0x0002
5691 #define WidthValue 0x0004
5692 #define HeightValue 0x0008
5693 #define AllValues 0x000F
5694 #define XNegative 0x0010
5695 #define YNegative 0x0020
5697 /* Try not to reformat/modify, so we can compare/sync with X sources */
5699 gtk_XParseGeometry (const char *string,
5702 unsigned int *width,
5703 unsigned int *height)
5707 unsigned int tempWidth, tempHeight;
5709 char *nextCharacter;
5711 /* These initializations are just to silence gcc */
5717 if ( (string == NULL) || (*string == '\0')) return(mask);
5719 string++; /* ignore possible '=' at beg of geometry spec */
5721 strind = (char *)string;
5722 if (*strind != '+' && *strind != '-' && *strind != 'x') {
5723 tempWidth = read_int(strind, &nextCharacter);
5724 if (strind == nextCharacter)
5726 strind = nextCharacter;
5730 if (*strind == 'x' || *strind == 'X') {
5732 tempHeight = read_int(strind, &nextCharacter);
5733 if (strind == nextCharacter)
5735 strind = nextCharacter;
5736 mask |= HeightValue;
5739 if ((*strind == '+') || (*strind == '-')) {
5740 if (*strind == '-') {
5742 tempX = -read_int(strind, &nextCharacter);
5743 if (strind == nextCharacter)
5745 strind = nextCharacter;
5751 tempX = read_int(strind, &nextCharacter);
5752 if (strind == nextCharacter)
5754 strind = nextCharacter;
5757 if ((*strind == '+') || (*strind == '-')) {
5758 if (*strind == '-') {
5760 tempY = -read_int(strind, &nextCharacter);
5761 if (strind == nextCharacter)
5763 strind = nextCharacter;
5770 tempY = read_int(strind, &nextCharacter);
5771 if (strind == nextCharacter)
5773 strind = nextCharacter;
5779 /* If strind isn't at the end of the string the it's an invalid
5780 geometry specification. */
5782 if (*strind != '\0') return (0);
5788 if (mask & WidthValue)
5790 if (mask & HeightValue)
5791 *height = tempHeight;
5796 * gtk_window_parse_geometry:
5797 * @window: a #GtkWindow
5798 * @geometry: geometry string
5800 * Parses a standard X Window System geometry string - see the
5801 * manual page for X (type 'man X') for details on this.
5802 * gtk_window_parse_geometry() does work on all GTK+ ports
5803 * including Win32 but is primarily intended for an X environment.
5805 * If either a size or a position can be extracted from the
5806 * geometry string, gtk_window_parse_geometry() returns %TRUE
5807 * and calls gtk_window_set_default_size() and/or gtk_window_move()
5808 * to resize/move the window.
5810 * If gtk_window_parse_geometry() returns %TRUE, it will also
5811 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
5812 * indicating to the window manager that the size/position of
5813 * the window was user-specified. This causes most window
5814 * managers to honor the geometry.
5816 * Return value: %TRUE if string was parsed successfully
5819 gtk_window_parse_geometry (GtkWindow *window,
5820 const gchar *geometry)
5825 gboolean size_set, pos_set;
5827 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5828 g_return_val_if_fail (geometry != NULL, FALSE);
5830 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
5832 if ((result & WidthValue) == 0 ||
5835 if ((result & HeightValue) == 0 ||
5840 if ((result & WidthValue) || (result & HeightValue))
5842 gtk_window_set_default_size_internal (window, TRUE, w, TRUE, h, TRUE);
5846 gtk_window_get_size (window, &w, &h);
5848 grav = GDK_GRAVITY_NORTH_WEST;
5850 if ((result & XNegative) && (result & YNegative))
5851 grav = GDK_GRAVITY_SOUTH_EAST;
5852 else if (result & XNegative)
5853 grav = GDK_GRAVITY_NORTH_EAST;
5854 else if (result & YNegative)
5855 grav = GDK_GRAVITY_SOUTH_WEST;
5857 if ((result & XValue) == 0)
5860 if ((result & YValue) == 0)
5863 if (grav == GDK_GRAVITY_SOUTH_WEST ||
5864 grav == GDK_GRAVITY_SOUTH_EAST)
5865 y = gdk_screen_get_height (window->screen) - h + y;
5867 if (grav == GDK_GRAVITY_SOUTH_EAST ||
5868 grav == GDK_GRAVITY_NORTH_EAST)
5869 x = gdk_screen_get_width (window->screen) - w + x;
5871 /* we don't let you put a window offscreen; maybe some people would
5872 * prefer to be able to, but it's kind of a bogus thing to do.
5881 if ((result & XValue) || (result & YValue))
5883 gtk_window_set_gravity (window, grav);
5884 gtk_window_move (window, x, y);
5888 if (size_set || pos_set)
5890 /* Set USSize, USPosition hints */
5891 GtkWindowGeometryInfo *info;
5893 info = gtk_window_get_geometry_info (window, TRUE);
5896 info->mask |= GDK_HINT_USER_POS;
5898 info->mask |= GDK_HINT_USER_SIZE;
5905 gtk_window_mnemonic_hash_foreach (gpointer key,
5911 GtkWindowKeysForeachFunc func;
5915 GtkWindowMnemonic *mnemonic = value;
5917 if (mnemonic->window == info->window)
5918 (*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
5922 _gtk_window_keys_foreach (GtkWindow *window,
5923 GtkWindowKeysForeachFunc func,
5930 GtkWindowKeysForeachFunc func;
5934 info.window = window;
5936 info.func_data = func_data;
5938 g_hash_table_foreach (mnemonic_hash_table,
5939 gtk_window_mnemonic_hash_foreach,
5942 groups = gtk_accel_groups_from_object (G_OBJECT (window));
5945 GtkAccelGroup *group = groups->data;
5948 for (i = 0; i < group->n_accels; i++)
5950 GtkAccelKey *key = &group->priv_accels[i].key;
5953 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
5956 groups = groups->next;
5961 gtk_window_keys_changed (GtkWindow *window)
5963 gtk_window_free_key_hash (window);
5964 gtk_window_get_key_hash (window);
5967 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
5969 struct _GtkWindowKeyEntry
5973 gboolean is_mnemonic;
5977 add_to_key_hash (GtkWindow *window,
5979 GdkModifierType modifiers,
5980 gboolean is_mnemonic,
5983 GtkKeyHash *key_hash = data;
5985 GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
5987 entry->keyval = keyval;
5988 entry->modifiers = modifiers;
5989 entry->is_mnemonic = is_mnemonic;
5991 /* GtkAccelGroup stores lowercased accelerators. To deal
5992 * with this, if <Shift> was specified, uppercase.
5994 if (modifiers & GDK_SHIFT_MASK)
5996 if (keyval == GDK_Tab)
5997 keyval = GDK_ISO_Left_Tab;
5999 keyval = gdk_keyval_to_upper (keyval);
6002 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
6006 gtk_window_get_key_hash (GtkWindow *window)
6008 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6012 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (window->screen)),
6013 (GDestroyNotify)g_free);
6014 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
6015 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
6021 gtk_window_free_key_hash (GtkWindow *window)
6023 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6026 _gtk_key_hash_free (key_hash);
6027 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
6032 * _gtk_window_activate_key:
6033 * @window: a #GtkWindow
6034 * @event: a #GdkEventKey
6036 * Activates mnemonics and accelerators for this #GtKWindow
6038 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
6041 _gtk_window_activate_key (GtkWindow *window,
6044 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6045 GtkWindowKeyEntry *found_entry = NULL;
6049 gtk_window_keys_changed (window);
6050 key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6055 GSList *entries = _gtk_key_hash_lookup (key_hash,
6056 event->hardware_keycode,
6057 event->state & gtk_accelerator_get_default_mod_mask (),
6061 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
6063 GtkWindowKeyEntry *entry = tmp_list->data;
6064 if (entry->is_mnemonic)
6066 found_entry = entry;
6071 if (!found_entry && entries)
6072 found_entry = entries->data;
6074 g_slist_free (entries);
6079 if (found_entry->is_mnemonic)
6080 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
6082 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);