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;
3209 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3211 gdk_window_withdraw (window->frame);
3213 gdk_window_withdraw (widget->window);
3215 window->configure_request_count = 0;
3216 window->configure_notify_received = FALSE;
3218 /* on unmap, we reset the default positioning of the window,
3219 * so it's placed again, but we don't reset the default
3220 * size of the window, so it's remembered.
3222 window->need_default_position = TRUE;
3224 info = gtk_window_get_geometry_info (window, FALSE);
3227 info->initial_pos_set = FALSE;
3228 info->position_constraints_changed = FALSE;
3233 gtk_window_realize (GtkWidget *widget)
3236 GdkWindow *parent_window;
3237 GdkWindowAttr attributes;
3238 gint attributes_mask;
3240 window = GTK_WINDOW (widget);
3242 /* ensure widget tree is properly size allocated */
3243 if (widget->allocation.x == -1 &&
3244 widget->allocation.y == -1 &&
3245 widget->allocation.width == 1 &&
3246 widget->allocation.height == 1)
3248 GtkRequisition requisition;
3249 GtkAllocation allocation = { 0, 0, 200, 200 };
3251 gtk_widget_size_request (widget, &requisition);
3252 if (requisition.width || requisition.height)
3254 /* non-empty window */
3255 allocation.width = requisition.width;
3256 allocation.height = requisition.height;
3258 gtk_widget_size_allocate (widget, &allocation);
3260 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3262 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3265 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3267 switch (window->type)
3269 case GTK_WINDOW_TOPLEVEL:
3270 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3272 case GTK_WINDOW_POPUP:
3273 attributes.window_type = GDK_WINDOW_TEMP;
3276 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3280 attributes.title = window->title;
3281 attributes.wmclass_name = window->wmclass_name;
3282 attributes.wmclass_class = window->wmclass_class;
3283 attributes.wclass = GDK_INPUT_OUTPUT;
3284 attributes.visual = gtk_widget_get_visual (widget);
3285 attributes.colormap = gtk_widget_get_colormap (widget);
3287 if (window->has_frame)
3289 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3290 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3291 attributes.event_mask = (GDK_EXPOSURE_MASK |
3292 GDK_KEY_PRESS_MASK |
3293 GDK_ENTER_NOTIFY_MASK |
3294 GDK_LEAVE_NOTIFY_MASK |
3295 GDK_FOCUS_CHANGE_MASK |
3296 GDK_STRUCTURE_MASK |
3297 GDK_BUTTON_MOTION_MASK |
3298 GDK_POINTER_MOTION_HINT_MASK |
3299 GDK_BUTTON_PRESS_MASK |
3300 GDK_BUTTON_RELEASE_MASK);
3302 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3304 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
3305 &attributes, attributes_mask);
3307 gdk_window_set_user_data (window->frame, widget);
3309 attributes.window_type = GDK_WINDOW_CHILD;
3310 attributes.x = window->frame_left;
3311 attributes.y = window->frame_top;
3313 attributes_mask = GDK_WA_X | GDK_WA_Y;
3315 parent_window = window->frame;
3319 attributes_mask = 0;
3320 parent_window = gtk_widget_get_root_window (widget);
3323 attributes.width = widget->allocation.width;
3324 attributes.height = widget->allocation.height;
3325 attributes.event_mask = gtk_widget_get_events (widget);
3326 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3327 GDK_KEY_PRESS_MASK |
3328 GDK_KEY_RELEASE_MASK |
3329 GDK_ENTER_NOTIFY_MASK |
3330 GDK_LEAVE_NOTIFY_MASK |
3331 GDK_FOCUS_CHANGE_MASK |
3332 GDK_STRUCTURE_MASK);
3334 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3335 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3336 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3338 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3340 gdk_window_set_user_data (widget->window, window);
3342 widget->style = gtk_style_attach (widget->style, widget->window);
3343 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3345 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3347 /* This is a bad hack to set the window background. */
3348 gtk_window_paint (widget, NULL);
3350 if (window->transient_parent &&
3351 GTK_WIDGET_REALIZED (window->transient_parent))
3352 gdk_window_set_transient_for (widget->window,
3353 GTK_WIDGET (window->transient_parent)->window);
3355 if (window->wm_role)
3356 gdk_window_set_role (widget->window, window->wm_role);
3358 if (!window->decorated)
3359 gdk_window_set_decorations (widget->window, 0);
3361 gdk_window_set_type_hint (widget->window, window->type_hint);
3363 /* transient_for must be set to allow the modal hint */
3364 if (window->transient_parent && window->modal)
3365 gdk_window_set_modal_hint (widget->window, TRUE);
3367 gdk_window_set_modal_hint (widget->window, FALSE);
3370 gtk_window_realize_icon (window);
3374 gtk_window_unrealize (GtkWidget *widget)
3377 GtkWindowGeometryInfo *info;
3379 window = GTK_WINDOW (widget);
3381 /* On unrealize, we reset the size of the window such
3382 * that we will re-apply the default sizing stuff
3383 * next time we show the window.
3385 * Default positioning is reset on unmap, instead of unrealize.
3387 window->need_default_size = TRUE;
3388 info = gtk_window_get_geometry_info (window, FALSE);
3391 info->resize_width = -1;
3392 info->resize_height = -1;
3393 info->last.configure_request.x = 0;
3394 info->last.configure_request.y = 0;
3395 info->last.configure_request.width = -1;
3396 info->last.configure_request.height = -1;
3397 /* be sure we reset geom hints on re-realize */
3398 info->last.flags = 0;
3403 gdk_window_set_user_data (window->frame, NULL);
3404 gdk_window_destroy (window->frame);
3405 window->frame = NULL;
3409 gtk_window_unrealize_icon (window);
3411 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3415 gtk_window_size_request (GtkWidget *widget,
3416 GtkRequisition *requisition)
3421 window = GTK_WINDOW (widget);
3422 bin = GTK_BIN (window);
3424 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3425 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3427 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3429 GtkRequisition child_requisition;
3431 gtk_widget_size_request (bin->child, &child_requisition);
3433 requisition->width += child_requisition.width;
3434 requisition->height += child_requisition.height;
3439 gtk_window_size_allocate (GtkWidget *widget,
3440 GtkAllocation *allocation)
3443 GtkAllocation child_allocation;
3445 window = GTK_WINDOW (widget);
3446 widget->allocation = *allocation;
3448 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3450 child_allocation.x = GTK_CONTAINER (window)->border_width;
3451 child_allocation.y = GTK_CONTAINER (window)->border_width;
3452 child_allocation.width =
3453 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3454 child_allocation.height =
3455 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3457 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3460 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3462 gdk_window_resize (window->frame,
3463 allocation->width + window->frame_left + window->frame_right,
3464 allocation->height + window->frame_top + window->frame_bottom);
3469 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3472 gboolean return_val;
3474 window = GTK_WINDOW (widget);
3476 if (window->frame && (event->any.window == window->frame))
3478 if ((event->type != GDK_KEY_PRESS) &&
3479 (event->type != GDK_KEY_RELEASE) &&
3480 (event->type != GDK_FOCUS_CHANGE))
3482 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
3484 gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
3489 g_object_unref (event->any.window);
3490 event->any.window = g_object_ref (widget->window);
3498 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3500 GdkEventConfigure *configure_event;
3503 switch (event->type)
3506 configure_event = (GdkEventConfigure *)event;
3508 /* Invalidate the decorations */
3511 rect.width = configure_event->width;
3512 rect.height = configure_event->height;
3514 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3516 /* Pass on the (modified) configure event */
3517 configure_event->width -= window->frame_left + window->frame_right;
3518 configure_event->height -= window->frame_top + window->frame_bottom;
3519 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3528 gtk_window_configure_event (GtkWidget *widget,
3529 GdkEventConfigure *event)
3531 GtkWindow *window = GTK_WINDOW (widget);
3532 gboolean expected_reply = window->configure_request_count > 0;
3534 /* window->configure_request_count incremented for each
3535 * configure request, and decremented to a min of 0 for
3536 * each configure notify.
3538 * All it means is that we know we will get at least
3539 * window->configure_request_count more configure notifies.
3540 * We could get more configure notifies than that; some
3541 * of the configure notifies we get may be unrelated to
3542 * the configure requests. But we will get at least
3543 * window->configure_request_count notifies.
3546 if (window->configure_request_count > 0)
3547 window->configure_request_count -= 1;
3549 /* As an optimization, we avoid a resize when possible.
3551 * The only times we can avoid a resize are:
3552 * - we know only the position changed, not the size
3553 * - we know we have made more requests and so will get more
3554 * notifies and can wait to resize when we get them
3557 if (!expected_reply &&
3558 (widget->allocation.width == event->width &&
3559 widget->allocation.height == event->height))
3563 * If we do need to resize, we do that by:
3564 * - filling in widget->allocation with the new size
3565 * - setting configure_notify_received to TRUE
3566 * for use in gtk_window_move_resize()
3567 * - queueing a resize, leading to invocation of
3568 * gtk_window_move_resize() in an idle handler
3572 window->configure_notify_received = TRUE;
3574 widget->allocation.width = event->width;
3575 widget->allocation.height = event->height;
3577 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3582 /* the accel_key and accel_mods fields of the key have to be setup
3583 * upon calling this function. it'll then return whether that key
3584 * is at all used as accelerator, and if so will OR in the
3585 * accel_flags member of the key.
3588 _gtk_window_query_nonaccels (GtkWindow *window,
3590 GdkModifierType accel_mods)
3592 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3594 /* movement keys are considered locked accels */
3597 static const guint bindings[] = {
3598 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
3599 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
3603 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
3604 if (bindings[i] == accel_key)
3608 /* mnemonics are considered locked accels */
3609 if (accel_mods == window->mnemonic_modifier)
3611 GtkWindowMnemonic mkey;
3613 mkey.window = window;
3614 mkey.keyval = accel_key;
3615 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
3623 gtk_window_key_press_event (GtkWidget *widget,
3630 window = GTK_WINDOW (widget);
3634 /* Check for mnemonics and accelerators
3637 handled = _gtk_window_activate_key (window, event);
3641 focus = window->focus_widget;
3643 g_object_ref (focus);
3646 focus && focus != widget &&
3647 gtk_widget_get_toplevel (focus) == widget)
3651 if (GTK_WIDGET_IS_SENSITIVE (focus))
3652 handled = gtk_widget_event (focus, (GdkEvent*) event);
3654 parent = focus->parent;
3656 g_object_ref (parent);
3658 g_object_unref (focus);
3664 g_object_unref (focus);
3667 /* Chain up, invokes binding set */
3668 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
3669 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
3675 gtk_window_key_release_event (GtkWidget *widget,
3681 window = GTK_WINDOW (widget);
3683 if (window->focus_widget &&
3684 window->focus_widget != widget &&
3685 GTK_WIDGET_SENSITIVE (window->focus_widget))
3687 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
3690 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
3691 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
3697 gtk_window_real_activate_default (GtkWindow *window)
3699 gtk_window_activate_default (window);
3703 gtk_window_real_activate_focus (GtkWindow *window)
3705 gtk_window_activate_focus (window);
3709 gtk_window_move_focus (GtkWindow *window,
3710 GtkDirectionType dir)
3712 gtk_widget_child_focus (GTK_WIDGET (window), dir);
3714 if (!GTK_CONTAINER (window)->focus_child)
3715 gtk_window_set_focus (window, NULL);
3719 gtk_window_enter_notify_event (GtkWidget *widget,
3720 GdkEventCrossing *event)
3726 gtk_window_leave_notify_event (GtkWidget *widget,
3727 GdkEventCrossing *event)
3733 do_focus_change (GtkWidget *widget,
3736 GdkEventFocus fevent;
3738 g_object_ref (widget);
3741 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
3743 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
3745 fevent.type = GDK_FOCUS_CHANGE;
3746 fevent.window = widget->window;
3749 gtk_widget_event (widget, (GdkEvent*) &fevent);
3751 g_object_notify (G_OBJECT (widget), "has_focus");
3753 g_object_unref (widget);
3757 gtk_window_focus_in_event (GtkWidget *widget,
3758 GdkEventFocus *event)
3760 GtkWindow *window = GTK_WINDOW (widget);
3762 /* It appears spurious focus in events can occur when
3763 * the window is hidden. So we'll just check to see if
3764 * the window is visible before actually handling the
3767 if (GTK_WIDGET_VISIBLE (widget))
3769 window->has_focus = TRUE;
3771 if (window->focus_widget &&
3772 window->focus_widget != widget &&
3773 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3774 do_focus_change (window->focus_widget, TRUE);
3781 gtk_window_focus_out_event (GtkWidget *widget,
3782 GdkEventFocus *event)
3784 GtkWindow *window = GTK_WINDOW (widget);
3786 window->has_focus = FALSE;
3788 if (window->focus_widget &&
3789 window->focus_widget != widget &&
3790 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
3791 do_focus_change (window->focus_widget, FALSE);
3796 static GdkAtom atom_rcfiles = GDK_NONE;
3799 gtk_window_read_rcfiles (GtkWidget *widget,
3800 GdkEventClient *event)
3802 GList *embedded_windows;
3804 embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
3805 if (embedded_windows)
3810 for (i = 0; i < 5; i++)
3812 sev.data_format = 32;
3813 sev.message_type = atom_rcfiles;
3815 while (embedded_windows)
3817 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
3818 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), (GdkEvent *) &sev, xid);
3819 embedded_windows = embedded_windows->next;
3823 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
3827 gtk_window_client_event (GtkWidget *widget,
3828 GdkEventClient *event)
3831 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
3833 if (event->message_type == atom_rcfiles)
3834 gtk_window_read_rcfiles (widget, event);
3840 gtk_window_check_resize (GtkContainer *container)
3842 GtkWindow *window = GTK_WINDOW (container);
3844 if (GTK_WIDGET_VISIBLE (container))
3845 gtk_window_move_resize (window);
3849 gtk_window_focus (GtkWidget *widget,
3850 GtkDirectionType direction)
3854 GtkContainer *container;
3855 GtkWidget *old_focus_child;
3858 container = GTK_CONTAINER (widget);
3859 window = GTK_WINDOW (widget);
3860 bin = GTK_BIN (widget);
3862 old_focus_child = container->focus_child;
3864 /* We need a special implementation here to deal properly with wrapping
3865 * around in the tab chain without the danger of going into an
3868 if (old_focus_child)
3870 if (gtk_widget_child_focus (old_focus_child, direction))
3874 if (window->focus_widget)
3876 /* Wrapped off the end, clear the focus setting for the toplpevel */
3877 parent = window->focus_widget->parent;
3880 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
3881 parent = GTK_WIDGET (parent)->parent;
3884 gtk_window_set_focus (GTK_WINDOW (container), NULL);
3887 /* Now try to focus the first widget in the window */
3890 if (gtk_widget_child_focus (bin->child, direction))
3898 gtk_window_real_set_focus (GtkWindow *window,
3901 GtkWidget *old_focus = window->focus_widget;
3902 gboolean def_flags = 0;
3906 g_object_ref (old_focus);
3907 g_object_freeze_notify (G_OBJECT (old_focus));
3911 g_object_ref (focus);
3912 g_object_freeze_notify (G_OBJECT (focus));
3915 if (window->default_widget)
3916 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
3918 if (window->focus_widget)
3920 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3921 (window->focus_widget != window->default_widget))
3923 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3925 if (window->default_widget)
3926 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3929 if (window->has_focus)
3930 do_focus_change (window->focus_widget, FALSE);
3933 window->focus_widget = focus;
3935 if (window->focus_widget)
3937 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
3938 (window->focus_widget != window->default_widget))
3940 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
3941 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
3943 if (window->default_widget)
3944 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
3947 if (window->has_focus)
3948 do_focus_change (window->focus_widget, TRUE);
3951 if (window->default_widget &&
3952 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
3953 gtk_widget_queue_draw (window->default_widget);
3957 g_object_thaw_notify (G_OBJECT (old_focus));
3958 g_object_unref (old_focus);
3962 g_object_thaw_notify (G_OBJECT (focus));
3963 g_object_unref (focus);
3967 /*********************************
3968 * Functions related to resizing *
3969 *********************************/
3971 /* This function doesn't constrain to geometry hints */
3973 gtk_window_compute_configure_request_size (GtkWindow *window,
3977 GtkRequisition requisition;
3978 GtkWindowGeometryInfo *info;
3982 * - we've done a size request
3985 widget = GTK_WIDGET (window);
3987 info = gtk_window_get_geometry_info (window, FALSE);
3989 if (window->need_default_size)
3991 gtk_widget_get_child_requisition (widget, &requisition);
3993 /* Default to requisition */
3994 *width = requisition.width;
3995 *height = requisition.height;
3997 /* If window is empty so requests 0, default to random nonzero size */
3998 if (*width == 0 && *height == 0)
4004 /* Override requisition with default size */
4008 gint base_width = 0;
4009 gint base_height = 0;
4011 gint height_inc = 1;
4013 if (info->default_is_geometry &&
4014 (info->default_width > 0 || info->default_height > 0))
4016 GdkGeometry geometry;
4019 gtk_window_compute_hints (window, &geometry, &flags);
4021 if (flags & GDK_HINT_BASE_SIZE)
4023 base_width = geometry.base_width;
4024 base_height = geometry.base_height;
4026 else if (flags & GDK_HINT_MIN_SIZE)
4028 base_width = geometry.min_width;
4029 base_height = geometry.min_height;
4031 if (flags & GDK_HINT_RESIZE_INC)
4033 width_inc = geometry.width_inc;
4034 height_inc = geometry.height_inc;
4038 if (info->default_width > 0)
4039 *width = info->default_width * width_inc + base_width;
4041 if (info->default_height > 0)
4042 *height = info->default_height * height_inc + base_height;
4047 /* Default to keeping current size */
4048 *width = widget->allocation.width;
4049 *height = widget->allocation.height;
4052 /* Override any size with gtk_window_resize() values */
4055 if (info->resize_width > 0)
4056 *width = info->resize_width;
4058 if (info->resize_height > 0)
4059 *height = info->resize_height;
4064 gtk_window_compute_configure_request (GtkWindow *window,
4065 GdkRectangle *request,
4066 GdkGeometry *geometry,
4069 GdkGeometry new_geometry;
4073 GtkWindowPosition pos;
4074 GtkWidget *parent_widget;
4075 GtkWindowGeometryInfo *info;
4078 widget = GTK_WIDGET (window);
4080 gtk_widget_size_request (widget, NULL);
4081 gtk_window_compute_configure_request_size (window, &w, &h);
4083 gtk_window_compute_hints (window, &new_geometry, &new_flags);
4084 gtk_window_constrain_size (window,
4085 &new_geometry, new_flags,
4089 parent_widget = (GtkWidget*) window->transient_parent;
4091 pos = window->position;
4092 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
4093 (parent_widget == NULL ||
4094 !GTK_WIDGET_MAPPED (parent_widget)))
4095 pos = GTK_WIN_POS_NONE;
4097 info = gtk_window_get_geometry_info (window, TRUE);
4099 /* by default, don't change position requested */
4100 x = info->last.configure_request.x;
4101 y = info->last.configure_request.y;
4103 if (window->need_default_position)
4106 /* FIXME this all interrelates with window gravity.
4107 * For most of them I think we want to set GRAVITY_CENTER.
4109 * Not sure how to go about that.
4114 /* here we are only handling CENTER_ALWAYS
4115 * as it relates to default positioning,
4116 * where it's equivalent to simply CENTER
4118 case GTK_WIN_POS_CENTER_ALWAYS:
4119 case GTK_WIN_POS_CENTER:
4121 gint px, py, monitor_num;
4122 GdkRectangle monitor;
4124 gdk_window_get_pointer (gdk_screen_get_root_window (window->screen),
4127 monitor_num = gdk_screen_get_monitor_at_point (window->screen, px, py);
4128 if (monitor_num == -1)
4131 gdk_screen_get_monitor_geometry (window->screen, monitor_num, &monitor);
4133 x = (monitor.width - w) / 2 + monitor.x;
4134 y = (monitor.height - h) / 2 + monitor.y;
4138 case GTK_WIN_POS_CENTER_ON_PARENT:
4142 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
4144 gdk_window_get_origin (parent_widget->window,
4147 x = ox + (parent_widget->allocation.width - w) / 2;
4148 y = oy + (parent_widget->allocation.height - h) / 2;
4152 case GTK_WIN_POS_MOUSE:
4154 gint screen_width = gdk_screen_get_width (window->screen);
4155 gint screen_height = gdk_screen_get_height (window->screen);
4158 gdk_window_get_pointer (NULL, &px, &py, NULL);
4161 x = CLAMP (x, 0, screen_width - w);
4162 y = CLAMP (y, 0, screen_height - h);
4169 } /* if (window->need_default_position) */
4171 if (window->need_default_position &&
4172 info->initial_pos_set)
4174 x = info->initial_x;
4175 y = info->initial_y;
4176 gtk_window_constrain_position (window, w, h, &x, &y);
4182 request->height = h;
4185 *geometry = new_geometry;
4191 gtk_window_constrain_position (GtkWindow *window,
4197 /* See long comments in gtk_window_move_resize()
4198 * on when it's safe to call this function.
4200 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4202 gint center_x, center_y;
4203 gint screen_width = gdk_screen_get_width (window->screen);
4204 gint screen_height = gdk_screen_get_height (window->screen);
4206 center_x = (screen_width - new_width) / 2;
4207 center_y = (screen_height - new_height) / 2;
4215 gtk_window_move_resize (GtkWindow *window)
4219 * First we determine whether any information has changed that would
4220 * cause us to revise our last configure request. If we would send
4221 * a different configure request from last time, then
4222 * configure_request_size_changed = TRUE or
4223 * configure_request_pos_changed = TRUE. configure_request_size_changed
4224 * may be true due to new hints, a gtk_window_resize(), or whatever.
4225 * configure_request_pos_changed may be true due to gtk_window_set_position()
4226 * or gtk_window_move().
4228 * If the configure request has changed, we send off a new one. To
4229 * ensure GTK+ invariants are maintained (resize queue does what it
4230 * should), we go ahead and size_allocate the requested size in this
4233 * If the configure request has not changed, we don't ever resend
4234 * it, because it could mean fighting the user or window manager.
4237 * To prepare the configure request, we come up with a base size/pos:
4238 * - the one from gtk_window_move()/gtk_window_resize()
4239 * - else default_width, default_height if we haven't ever
4241 * - else the size request if we haven't ever been mapped,
4242 * as a substitute default size
4243 * - else the current size of the window, as received from
4244 * configure notifies (i.e. the current allocation)
4246 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4247 * the position request to be centered.
4250 GtkContainer *container;
4251 GtkWindowGeometryInfo *info;
4252 GdkGeometry new_geometry;
4254 GdkRectangle new_request;
4255 gboolean configure_request_size_changed;
4256 gboolean configure_request_pos_changed;
4257 gboolean hints_changed; /* do we need to send these again */
4258 GtkWindowLastGeometryInfo saved_last_info;
4260 widget = GTK_WIDGET (window);
4261 container = GTK_CONTAINER (widget);
4262 info = gtk_window_get_geometry_info (window, TRUE);
4264 configure_request_size_changed = FALSE;
4265 configure_request_pos_changed = FALSE;
4267 gtk_window_compute_configure_request (window, &new_request,
4268 &new_geometry, &new_flags);
4270 /* This check implies the invariant that we never set info->last
4271 * without setting the hints and sending off a configure request.
4273 * If we change info->last without sending the request, we may
4276 if (info->last.configure_request.x != new_request.x ||
4277 info->last.configure_request.y != new_request.y)
4278 configure_request_pos_changed = TRUE;
4280 if ((info->last.configure_request.width != new_request.width ||
4281 info->last.configure_request.height != new_request.height))
4282 configure_request_size_changed = TRUE;
4284 hints_changed = FALSE;
4286 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4287 &new_geometry, new_flags))
4289 hints_changed = TRUE;
4292 /* Position Constraints
4293 * ====================
4295 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4296 * a default. The other POS_ values are used only when the
4297 * window is shown, not after that.
4299 * However, we can't implement a position constraint as
4300 * "anytime the window size changes, center the window"
4301 * because this may well end up fighting the WM or user. In
4302 * fact it gets in an infinite loop with at least one WM.
4304 * Basically, applications are in no way in a position to
4305 * constrain the position of a window, with one exception:
4306 * override redirect windows. (Really the intended purpose
4307 * of CENTER_ALWAYS anyhow, I would think.)
4309 * So the way we implement this "constraint" is to say that when WE
4310 * cause a move or resize, i.e. we make a configure request changing
4311 * window size, we recompute the CENTER_ALWAYS position to reflect
4312 * the new window size, and include it in our request. Also, if we
4313 * just turned on CENTER_ALWAYS we snap to center with a new
4314 * request. Otherwise, if we are just NOTIFIED of a move or resize
4315 * done by someone else e.g. the window manager, we do NOT send a
4316 * new configure request.
4318 * For override redirect windows, this works fine; all window
4319 * sizes are from our configure requests. For managed windows,
4320 * it is at least semi-sane, though who knows what the
4321 * app author is thinking.
4324 /* This condition should be kept in sync with the condition later on
4325 * that determines whether we send a configure request. i.e. we
4326 * should do this position constraining anytime we were going to
4327 * send a configure request anyhow, plus when constraints have
4330 if (configure_request_pos_changed ||
4331 configure_request_size_changed ||
4333 info->position_constraints_changed)
4335 /* We request the constrained position if:
4336 * - we were changing position, and need to clamp
4337 * the change to the constraint
4338 * - we're changing the size anyway
4339 * - set_position() was called to toggle CENTER_ALWAYS on
4342 gtk_window_constrain_position (window,
4348 /* Update whether we need to request a move */
4349 if (info->last.configure_request.x != new_request.x ||
4350 info->last.configure_request.y != new_request.y)
4351 configure_request_pos_changed = TRUE;
4353 configure_request_pos_changed = FALSE;
4357 if (window->type == GTK_WINDOW_TOPLEVEL)
4359 int notify_x, notify_y;
4361 /* this is the position from the last configure notify */
4362 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4364 g_message ("--- %s ---\n"
4365 "last : %d,%d\t%d x %d\n"
4366 "this : %d,%d\t%d x %d\n"
4367 "alloc : %d,%d\t%d x %d\n"
4369 "resize: \t%d x %d\n"
4370 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4371 "configure_notify_received: %d\n"
4372 "configure_request_count: %d\n"
4373 "position_constraints_changed: %d\n",
4374 window->title ? window->title : "(no title)",
4375 info->last.configure_request.x,
4376 info->last.configure_request.y,
4377 info->last.configure_request.width,
4378 info->last.configure_request.height,
4384 widget->allocation.width,
4385 widget->allocation.height,
4386 widget->requisition.width,
4387 widget->requisition.height,
4389 info->resize_height,
4390 configure_request_pos_changed,
4391 configure_request_size_changed,
4393 window->configure_notify_received,
4394 window->configure_request_count,
4395 info->position_constraints_changed);
4399 saved_last_info = info->last;
4400 info->last.geometry = new_geometry;
4401 info->last.flags = new_flags;
4402 info->last.configure_request = new_request;
4404 /* need to set PPosition so the WM will look at our position,
4405 * but we don't want to count PPosition coming and going as a hints
4406 * change for future iterations. So we saved info->last prior to
4410 /* Also, if the initial position was explicitly set, then we always
4411 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4415 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4416 * this is an initial map
4419 if ((configure_request_pos_changed ||
4420 info->initial_pos_set ||
4421 (window->need_default_position &&
4422 window->position != GTK_WIN_POS_NONE)) &&
4423 (new_flags & GDK_HINT_POS) == 0)
4425 new_flags |= GDK_HINT_POS;
4426 hints_changed = TRUE;
4429 /* Set hints if necessary
4432 gdk_window_set_geometry_hints (widget->window,
4436 /* handle resizing/moving and widget tree allocation
4438 if (window->configure_notify_received)
4440 GtkAllocation allocation;
4442 /* If we have received a configure event since
4443 * the last time in this function, we need to
4444 * accept our new size and size_allocate child widgets.
4445 * (see gtk_window_configure_event() for more details).
4447 * 1 or more configure notifies may have been received.
4448 * Also, configure_notify_received will only be TRUE
4449 * if all expected configure notifies have been received
4450 * (one per configure request), as an optimization.
4453 window->configure_notify_received = FALSE;
4455 /* gtk_window_configure_event() filled in widget->allocation */
4456 allocation = widget->allocation;
4457 gtk_widget_size_allocate (widget, &allocation);
4459 /* If the configure request changed, it means that
4461 * 1) coincidentally changed hints or widget properties
4462 * impacting the configure request before getting
4463 * a configure notify, or
4464 * 2) some broken widget is changing its size request
4465 * during size allocation, resulting in
4466 * a false appearance of changed configure request.
4468 * For 1), we could just go ahead and ask for the
4469 * new size right now, but doing that for 2)
4470 * might well be fighting the user (and can even
4471 * trigger a loop). Since we really don't want to
4472 * do that, we requeue a resize in hopes that
4473 * by the time it gets handled, the child has seen
4474 * the light and is willing to go along with the
4475 * new size. (this happens for the zvt widget, since
4476 * the size_allocate() above will have stored the
4477 * requisition corresponding to the new size in the
4480 * This doesn't buy us anything for 1), but it shouldn't
4481 * hurt us too badly, since it is what would have
4482 * happened if we had gotten the configure event before
4483 * the new size had been set.
4486 if (configure_request_size_changed ||
4487 configure_request_pos_changed)
4489 /* Don't change the recorded last info after all, because we
4490 * haven't actually updated to the new info yet - we decided
4491 * to postpone our configure request until later.
4493 info->last = saved_last_info;
4495 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
4498 else if ((configure_request_size_changed || hints_changed) &&
4499 (widget->allocation.width != new_request.width ||
4500 widget->allocation.height != new_request.height))
4503 /* We are in one of the following situations:
4504 * A. configure_request_size_changed
4505 * our requisition has changed and we need a different window size,
4506 * so we request it from the window manager.
4507 * B. !configure_request_size_changed && hints_changed
4508 * the window manager rejects our size, but we have just changed the
4509 * window manager hints, so there's a chance our request will
4510 * be honoured this time, so we try again.
4512 * However, if the new requisition is the same as the current allocation,
4513 * we don't request it again, since we won't get a ConfigureNotify back from
4514 * the window manager unless it decides to change our requisition. If
4515 * we don't get the ConfigureNotify back, the resize queue will never be run.
4518 /* Now send the configure request */
4519 if (configure_request_pos_changed)
4523 gdk_window_move_resize (window->frame,
4524 new_request.x - window->frame_left,
4525 new_request.y - window->frame_top,
4526 new_request.width + window->frame_left + window->frame_right,
4527 new_request.height + window->frame_top + window->frame_bottom);
4528 gdk_window_resize (widget->window,
4529 new_request.width, new_request.height);
4533 gdk_window_move_resize (widget->window,
4534 new_request.x, new_request.y,
4535 new_request.width, new_request.height);
4537 else /* only size changed */
4540 gdk_window_resize (window->frame,
4541 new_request.width + window->frame_left + window->frame_right,
4542 new_request.height + window->frame_top + window->frame_bottom);
4544 gdk_window_resize (widget->window,
4545 new_request.width, new_request.height);
4548 /* Increment the number of have-not-yet-received-notify requests */
4549 window->configure_request_count += 1;
4551 /* We have now sent a request since the last position constraint
4552 * change and definitely don't need a an initial size again (not
4553 * resetting this here can lead to infinite loops for
4554 * GTK_RESIZE_IMMEDIATE containers)
4556 info->position_constraints_changed = FALSE;
4557 info->initial_pos_set = FALSE;
4558 info->resize_width = -1;
4559 info->resize_height = -1;
4561 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
4562 * configure event in response to our resizing request.
4563 * the configure event will cause a new resize with
4564 * ->configure_notify_received=TRUE.
4565 * until then, we want to
4566 * - discard expose events
4567 * - coalesce resizes for our children
4568 * - defer any window resizes until the configure event arrived
4569 * to achieve this, we queue a resize for the window, but remove its
4570 * resizing handler, so resizing will not be handled from the next
4571 * idle handler but when the configure event arrives.
4573 * FIXME: we should also dequeue the pending redraws here, since
4574 * we handle those ourselves upon ->configure_notify_received==TRUE.
4576 if (container->resize_mode == GTK_RESIZE_QUEUE)
4578 gtk_widget_queue_resize (widget);
4579 _gtk_container_dequeue_resize_handler (container);
4584 /* Handle any position changes.
4586 if (configure_request_pos_changed)
4590 gdk_window_move (window->frame,
4591 new_request.x - window->frame_left,
4592 new_request.y - window->frame_top);
4595 gdk_window_move (widget->window,
4596 new_request.x, new_request.y);
4599 /* And run the resize queue.
4601 gtk_container_resize_children (container);
4605 /* Compare two sets of Geometry hints for equality.
4608 gtk_window_compare_hints (GdkGeometry *geometry_a,
4610 GdkGeometry *geometry_b,
4613 if (flags_a != flags_b)
4616 if ((flags_a & GDK_HINT_MIN_SIZE) &&
4617 (geometry_a->min_width != geometry_b->min_width ||
4618 geometry_a->min_height != geometry_b->min_height))
4621 if ((flags_a & GDK_HINT_MAX_SIZE) &&
4622 (geometry_a->max_width != geometry_b->max_width ||
4623 geometry_a->max_height != geometry_b->max_height))
4626 if ((flags_a & GDK_HINT_BASE_SIZE) &&
4627 (geometry_a->base_width != geometry_b->base_width ||
4628 geometry_a->base_height != geometry_b->base_height))
4631 if ((flags_a & GDK_HINT_ASPECT) &&
4632 (geometry_a->min_aspect != geometry_b->min_aspect ||
4633 geometry_a->max_aspect != geometry_b->max_aspect))
4636 if ((flags_a & GDK_HINT_RESIZE_INC) &&
4637 (geometry_a->width_inc != geometry_b->width_inc ||
4638 geometry_a->height_inc != geometry_b->height_inc))
4641 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
4642 geometry_a->win_gravity != geometry_b->win_gravity)
4649 _gtk_window_constrain_size (GtkWindow *window,
4655 GtkWindowGeometryInfo *info;
4657 g_return_if_fail (GTK_IS_WINDOW (window));
4659 info = window->geometry_info;
4662 GdkWindowHints flags = info->last.flags;
4663 GdkGeometry *geometry = &info->last.geometry;
4665 gtk_window_constrain_size (window,
4676 gtk_window_constrain_size (GtkWindow *window,
4677 GdkGeometry *geometry,
4684 gdk_window_constrain_size (geometry, flags, width, height,
4685 new_width, new_height);
4688 /* Compute the set of geometry hints and flags for a window
4689 * based on the application set geometry, and requisiition
4690 * of the window. gtk_widget_size_request() must have been
4694 gtk_window_compute_hints (GtkWindow *window,
4695 GdkGeometry *new_geometry,
4699 gint extra_width = 0;
4700 gint extra_height = 0;
4701 GtkWindowGeometryInfo *geometry_info;
4702 GtkRequisition requisition;
4704 widget = GTK_WIDGET (window);
4706 gtk_widget_get_child_requisition (widget, &requisition);
4707 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
4711 *new_flags = geometry_info->mask;
4712 *new_geometry = geometry_info->geometry;
4719 if (geometry_info && geometry_info->widget)
4721 GtkRequisition child_requisition;
4723 /* FIXME: This really isn't right. It gets the min size wrong and forces
4724 * callers to do horrible hacks like set a huge usize on the child requisition
4725 * to get the base size right. We really want to find the answers to:
4727 * - If the geometry widget was infinitely big, how much extra space
4728 * would be needed for the stuff around it.
4730 * - If the geometry widget was infinitely small, how big would the
4731 * window still have to be.
4733 * Finding these answers would be a bit of a mess here. (Bug #68668)
4735 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
4737 extra_width = widget->requisition.width - child_requisition.width;
4738 extra_height = widget->requisition.height - child_requisition.height;
4741 /* We don't want to set GDK_HINT_POS in here, we just set it
4742 * in gtk_window_move_resize() when we want the position
4746 if (*new_flags & GDK_HINT_BASE_SIZE)
4748 new_geometry->base_width += extra_width;
4749 new_geometry->base_height += extra_height;
4751 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
4752 (*new_flags & GDK_HINT_RESIZE_INC) &&
4753 ((extra_width != 0) || (extra_height != 0)))
4755 *new_flags |= GDK_HINT_BASE_SIZE;
4757 new_geometry->base_width = extra_width;
4758 new_geometry->base_height = extra_height;
4761 if (*new_flags & GDK_HINT_MIN_SIZE)
4763 if (new_geometry->min_width < 0)
4764 new_geometry->min_width = requisition.width;
4766 new_geometry->min_width += extra_width;
4768 if (new_geometry->min_height < 0)
4769 new_geometry->min_height = requisition.height;
4771 new_geometry->min_height += extra_height;
4773 else if (!window->allow_shrink)
4775 *new_flags |= GDK_HINT_MIN_SIZE;
4777 new_geometry->min_width = requisition.width;
4778 new_geometry->min_height = requisition.height;
4781 if (*new_flags & GDK_HINT_MAX_SIZE)
4783 if (new_geometry->max_width < 0)
4784 new_geometry->max_width = requisition.width;
4786 new_geometry->max_width += extra_width;
4788 if (new_geometry->max_height < 0)
4789 new_geometry->max_width = requisition.height;
4791 new_geometry->max_height += extra_height;
4793 else if (!window->allow_grow)
4795 *new_flags |= GDK_HINT_MAX_SIZE;
4797 new_geometry->max_width = requisition.width;
4798 new_geometry->max_height = requisition.height;
4801 *new_flags |= GDK_HINT_WIN_GRAVITY;
4802 new_geometry->win_gravity = window->gravity;
4805 /***********************
4806 * Redrawing functions *
4807 ***********************/
4810 gtk_window_paint (GtkWidget *widget,
4813 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
4814 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
4818 gtk_window_expose (GtkWidget *widget,
4819 GdkEventExpose *event)
4821 if (!GTK_WIDGET_APP_PAINTABLE (widget))
4822 gtk_window_paint (widget, &event->area);
4824 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
4825 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
4831 * gtk_window_set_has_frame:
4832 * @window: a #GtkWindow
4833 * @setting: a boolean
4835 * (Note: this is a special-purpose function for the framebuffer port,
4836 * that causes GTK+ to draw its own window border. For most applications,
4837 * you want gtk_window_set_decorated() instead, which tells the window
4838 * manager whether to draw the window border.)
4840 * If this function is called on a window with setting of %TRUE, before
4841 * it is realized or showed, it will have a "frame" window around
4842 * @window->window, accessible in @window->frame. Using the signal
4843 * frame_event you can recieve all events targeted at the frame.
4845 * This function is used by the linux-fb port to implement managed
4846 * windows, but it could concievably be used by X-programs that
4847 * want to do their own window decorations.
4851 gtk_window_set_has_frame (GtkWindow *window,
4854 g_return_if_fail (GTK_IS_WINDOW (window));
4855 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
4857 window->has_frame = setting != FALSE;
4861 * gtk_window_get_has_frame:
4862 * @window: a #GtkWindow
4864 * Accessor for whether the window has a frame window exterior to
4865 * @window->window. Gets the value set by gtk_window_set_has_frame ().
4867 * Return value: %TRUE if a frame has been added to the window
4868 * via gtk_window_set_has_frame().
4871 gtk_window_get_has_frame (GtkWindow *window)
4873 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4875 return window->has_frame;
4879 * gtk_window_set_frame_dimensions:
4880 * @window: a #GtkWindow that has a frame
4881 * @left: The width of the left border
4882 * @top: The height of the top border
4883 * @right: The width of the right border
4884 * @bottom: The height of the bottom border
4886 * (Note: this is a special-purpose function intended for the framebuffer
4887 * port; see gtk_window_set_has_frame(). It will have no effect on the
4888 * window border drawn by the window manager, which is the normal
4889 * case when using the X Window system.)
4891 * For windows with frames (see gtk_window_set_has_frame()) this function
4892 * can be used to change the size of the frame border.
4895 gtk_window_set_frame_dimensions (GtkWindow *window,
4903 g_return_if_fail (GTK_IS_WINDOW (window));
4905 widget = GTK_WIDGET (window);
4907 if (window->frame_left == left &&
4908 window->frame_top == top &&
4909 window->frame_right == right &&
4910 window->frame_bottom == bottom)
4913 window->frame_left = left;
4914 window->frame_top = top;
4915 window->frame_right = right;
4916 window->frame_bottom = bottom;
4918 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4920 gint width = widget->allocation.width + left + right;
4921 gint height = widget->allocation.height + top + bottom;
4922 gdk_window_resize (window->frame, width, height);
4923 gtk_decorated_window_move_resize_window (window,
4925 widget->allocation.width,
4926 widget->allocation.height);
4931 * gtk_window_present:
4932 * @window: a #GtkWindow
4934 * Presents a window to the user. This may mean raising the window
4935 * in the stacking order, deiconifying it, moving it to the current
4936 * desktop, and/or giving it the keyboard focus, possibly dependent
4937 * on the user's platform, window manager, and preferences.
4939 * If @window is hidden, this function calls gtk_widget_show()
4942 * This function should be used when the user tries to open a window
4943 * that's already open. Say for example the preferences dialog is
4944 * currently open, and the user chooses Preferences from the menu
4945 * a second time; use gtk_window_present() to move the already-open dialog
4946 * where the user can see it.
4950 gtk_window_present (GtkWindow *window)
4954 g_return_if_fail (GTK_IS_WINDOW (window));
4956 widget = GTK_WIDGET (window);
4958 if (GTK_WIDGET_VISIBLE (window))
4960 g_assert (widget->window != NULL);
4962 gdk_window_show (widget->window);
4964 /* note that gdk_window_focus() will also move the window to
4965 * the current desktop, for WM spec compliant window managers.
4967 gdk_window_focus (widget->window,
4968 gtk_get_current_event_time ());
4972 gtk_widget_show (widget);
4977 * gtk_window_iconify:
4978 * @window: a #GtkWindow
4980 * Asks to iconify (i.e. minimize) the specified @window. Note that
4981 * you shouldn't assume the window is definitely iconified afterward,
4982 * because other entities (e.g. the user or <link
4983 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
4984 * again, or there may not be a window manager in which case
4985 * iconification isn't possible, etc. But normally the window will end
4986 * up iconified. Just don't write code that crashes if not.
4988 * It's permitted to call this function before showing a window,
4989 * in which case the window will be iconified before it ever appears
4992 * You can track iconification via the "window_state_event" signal
4997 gtk_window_iconify (GtkWindow *window)
5000 GdkWindow *toplevel;
5002 g_return_if_fail (GTK_IS_WINDOW (window));
5004 widget = GTK_WIDGET (window);
5006 window->iconify_initially = TRUE;
5009 toplevel = window->frame;
5011 toplevel = widget->window;
5013 if (toplevel != NULL)
5014 gdk_window_iconify (toplevel);
5018 * gtk_window_deiconify:
5019 * @window: a #GtkWindow
5021 * Asks to deiconify (i.e. unminimize) the specified @window. Note
5022 * that you shouldn't assume the window is definitely deiconified
5023 * afterward, because other entities (e.g. the user or <link
5024 * linkend="gtk-X11-arch">window manager</link>) could iconify it
5025 * again before your code which assumes deiconification gets to run.
5027 * You can track iconification via the "window_state_event" signal
5031 gtk_window_deiconify (GtkWindow *window)
5034 GdkWindow *toplevel;
5036 g_return_if_fail (GTK_IS_WINDOW (window));
5038 widget = GTK_WIDGET (window);
5040 window->iconify_initially = FALSE;
5043 toplevel = window->frame;
5045 toplevel = widget->window;
5047 if (toplevel != NULL)
5048 gdk_window_deiconify (toplevel);
5053 * @window: a #GtkWindow
5055 * Asks to stick @window, which means that it will appear on all user
5056 * desktops. Note that you shouldn't assume the window is definitely
5057 * stuck afterward, because other entities (e.g. the user or <link
5058 * linkend="gtk-X11-arch">window manager</link>) could unstick it
5059 * again, and some window managers do not support sticking
5060 * windows. But normally the window will end up stuck. Just don't
5061 * write code that crashes if not.
5063 * It's permitted to call this function before showing a window.
5065 * You can track stickiness via the "window_state_event" signal
5070 gtk_window_stick (GtkWindow *window)
5073 GdkWindow *toplevel;
5075 g_return_if_fail (GTK_IS_WINDOW (window));
5077 widget = GTK_WIDGET (window);
5079 window->stick_initially = TRUE;
5082 toplevel = window->frame;
5084 toplevel = widget->window;
5086 if (toplevel != NULL)
5087 gdk_window_stick (toplevel);
5091 * gtk_window_unstick:
5092 * @window: a #GtkWindow
5094 * Asks to unstick @window, which means that it will appear on only
5095 * one of the user's desktops. Note that you shouldn't assume the
5096 * window is definitely unstuck afterward, because other entities
5097 * (e.g. the user or <link linkend="gtk-X11-arch">window
5098 * manager</link>) could stick it again. But normally the window will
5099 * end up stuck. Just don't write code that crashes if not.
5101 * You can track stickiness via the "window_state_event" signal
5106 gtk_window_unstick (GtkWindow *window)
5109 GdkWindow *toplevel;
5111 g_return_if_fail (GTK_IS_WINDOW (window));
5113 widget = GTK_WIDGET (window);
5115 window->stick_initially = FALSE;
5118 toplevel = window->frame;
5120 toplevel = widget->window;
5122 if (toplevel != NULL)
5123 gdk_window_unstick (toplevel);
5127 * gtk_window_maximize:
5128 * @window: a #GtkWindow
5130 * Asks to maximize @window, so that it becomes full-screen. Note that
5131 * you shouldn't assume the window is definitely maximized afterward,
5132 * because other entities (e.g. the user or <link
5133 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
5134 * again, and not all window managers support maximization. But
5135 * normally the window will end up maximized. Just don't write code
5136 * that crashes if not.
5138 * It's permitted to call this function before showing a window,
5139 * in which case the window will be maximized when it appears onscreen
5142 * You can track maximization via the "window_state_event" signal
5147 gtk_window_maximize (GtkWindow *window)
5150 GdkWindow *toplevel;
5152 g_return_if_fail (GTK_IS_WINDOW (window));
5154 widget = GTK_WIDGET (window);
5156 window->maximize_initially = TRUE;
5159 toplevel = window->frame;
5161 toplevel = widget->window;
5163 if (toplevel != NULL)
5164 gdk_window_maximize (toplevel);
5168 * gtk_window_unmaximize:
5169 * @window: a #GtkWindow
5171 * Asks to unmaximize @window. Note that you shouldn't assume the
5172 * window is definitely unmaximized afterward, because other entities
5173 * (e.g. the user or <link linkend="gtk-X11-arch">window
5174 * manager</link>) could maximize it again, and not all window
5175 * managers honor requests to unmaximize. But normally the window will
5176 * end up unmaximized. Just don't write code that crashes if not.
5178 * You can track maximization via the "window_state_event" signal
5183 gtk_window_unmaximize (GtkWindow *window)
5186 GdkWindow *toplevel;
5188 g_return_if_fail (GTK_IS_WINDOW (window));
5190 widget = GTK_WIDGET (window);
5192 window->maximize_initially = FALSE;
5195 toplevel = window->frame;
5197 toplevel = widget->window;
5199 if (toplevel != NULL)
5200 gdk_window_unmaximize (toplevel);
5204 * gtk_window_set_resizable:
5205 * @window: a #GtkWindow
5206 * @resizable: %TRUE if the user can resize this window
5208 * Sets whether the user can resize a window. Windows are user resizable
5212 gtk_window_set_resizable (GtkWindow *window,
5215 g_return_if_fail (GTK_IS_WINDOW (window));
5217 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5221 * gtk_window_get_resizable:
5222 * @window: a #GtkWindow
5224 * Gets the value set by gtk_window_set_resizable().
5226 * Return value: %TRUE if the user can resize the window
5229 gtk_window_get_resizable (GtkWindow *window)
5231 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5233 /* allow_grow is most likely to indicate the semantic concept we
5234 * mean by "resizable" (and will be a reliable indicator if
5235 * set_policy() hasn't been called)
5237 return window->allow_grow;
5241 * gtk_window_set_gravity:
5242 * @window: a #GtkWindow
5243 * @gravity: window gravity
5245 * Window gravity defines the meaning of coordinates passed to
5246 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5249 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5250 * typically "do what you mean."
5254 gtk_window_set_gravity (GtkWindow *window,
5257 g_return_if_fail (GTK_IS_WINDOW (window));
5259 if (gravity != window->gravity)
5261 window->gravity = gravity;
5263 /* gtk_window_move_resize() will adapt gravity
5265 gtk_widget_queue_resize (GTK_WIDGET (window));
5270 * gtk_window_get_gravity:
5271 * @window: a #GtkWindow
5273 * Gets the value set by gtk_window_set_gravity().
5275 * Return value: window gravity
5278 gtk_window_get_gravity (GtkWindow *window)
5280 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5282 return window->gravity;
5286 * gtk_window_begin_resize_drag:
5287 * @window: a #GtkWindow
5288 * @button: mouse button that initiated the drag
5289 * @edge: position of the resize control
5290 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5291 * @root_y: Y position where the user clicked to initiate the drag
5292 * @timestamp: timestamp from the click event that initiated the drag
5294 * Starts resizing a window. This function is used if an application
5295 * has window resizing controls. When GDK can support it, the resize
5296 * will be done using the standard mechanism for the <link
5297 * linkend="gtk-X11-arch">window manager</link> or windowing
5298 * system. Otherwise, GDK will try to emulate window resizing,
5299 * potentially not all that well, depending on the windowing system.
5303 gtk_window_begin_resize_drag (GtkWindow *window,
5311 GdkWindow *toplevel;
5313 g_return_if_fail (GTK_IS_WINDOW (window));
5314 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5316 widget = GTK_WIDGET (window);
5319 toplevel = window->frame;
5321 toplevel = widget->window;
5323 gdk_window_begin_resize_drag (toplevel,
5330 * gtk_window_get_frame_dimensions:
5331 * @window: a #GtkWindow
5332 * @left: location to store the width of the frame at the left, or %NULL
5333 * @top: location to store the height of the frame at the top, or %NULL
5334 * @right: location to store the width of the frame at the returns, or %NULL
5335 * @bottom: location to store the height of the frame at the bottom, or %NULL
5337 * (Note: this is a special-purpose function intended for the
5338 * framebuffer port; see gtk_window_set_has_frame(). It will not
5339 * return the size of the window border drawn by the <link
5340 * linkend="gtk-X11-arch">window manager</link>, which is the normal
5341 * case when using a windowing system. See
5342 * gdk_window_get_frame_extents() to get the standard window border
5345 * Retrieves the dimensions of the frame window for this toplevel.
5346 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5349 gtk_window_get_frame_dimensions (GtkWindow *window,
5355 g_return_if_fail (GTK_IS_WINDOW (window));
5358 *left = window->frame_left;
5360 *top = window->frame_top;
5362 *right = window->frame_right;
5364 *bottom = window->frame_bottom;
5368 * gtk_window_begin_move_drag:
5369 * @window: a #GtkWindow
5370 * @button: mouse button that initiated the drag
5371 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5372 * @root_y: Y position where the user clicked to initiate the drag
5373 * @timestamp: timestamp from the click event that initiated the drag
5375 * Starts moving a window. This function is used if an application has
5376 * window movement grips. When GDK can support it, the window movement
5377 * will be done using the standard mechanism for the <link
5378 * linkend="gtk-X11-arch">window manager</link> or windowing
5379 * system. Otherwise, GDK will try to emulate window movement,
5380 * potentially not all that well, depending on the windowing system.
5384 gtk_window_begin_move_drag (GtkWindow *window,
5391 GdkWindow *toplevel;
5393 g_return_if_fail (GTK_IS_WINDOW (window));
5394 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5396 widget = GTK_WIDGET (window);
5399 toplevel = window->frame;
5401 toplevel = widget->window;
5403 gdk_window_begin_move_drag (toplevel,
5410 * gtk_window_set_screen:
5411 * @window: a #GtkWindow.
5412 * @screen: a #GdkScreen.
5414 * Sets the #GdkScreen where the @window is displayed; if
5415 * the window is already mapped, it will be unmapped, and
5416 * then remapped on the new screen.
5419 gtk_window_set_screen (GtkWindow *window,
5423 gboolean was_mapped;
5425 g_return_if_fail (GTK_IS_WINDOW (window));
5426 g_return_if_fail (GDK_IS_SCREEN (screen));
5428 if (screen == window->screen)
5431 widget = GTK_WIDGET (window);
5433 was_mapped = GTK_WIDGET_MAPPED (widget);
5436 gtk_widget_unmap (widget);
5437 if (GTK_WIDGET_REALIZED (widget))
5438 gtk_widget_unrealize (widget);
5440 gtk_window_free_key_hash (window);
5441 window->screen = screen;
5442 gtk_widget_reset_rc_styles (widget);
5443 g_object_notify (G_OBJECT (window), "screen");
5446 gtk_widget_map (widget);
5450 * gtk_window_get_screen:
5451 * @window: a #GtkWindow.
5453 * Returns the #GdkScreen associated with @window.
5455 * Return value: a #GdkScreen.
5458 gtk_window_get_screen (GtkWindow *window)
5460 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
5462 return window->screen;
5467 gtk_window_group_class_init (GtkWindowGroupClass *klass)
5472 gtk_window_group_get_type (void)
5474 static GtkType window_group_type = 0;
5476 if (!window_group_type)
5478 static const GTypeInfo window_group_info =
5480 sizeof (GtkWindowGroupClass),
5481 NULL, /* base_init */
5482 NULL, /* base_finalize */
5483 (GClassInitFunc) gtk_window_group_class_init,
5484 NULL, /* class_finalize */
5485 NULL, /* class_data */
5486 sizeof (GtkWindowGroup),
5487 16, /* n_preallocs */
5488 (GInstanceInitFunc) NULL,
5491 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
5494 return window_group_type;
5498 * gtk_window_group_new:
5500 * Creates a new #GtkWindowGroup object. Grabs added with
5501 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
5503 * Return value: a new #GtkWindowGroup.
5506 gtk_window_group_new (void)
5508 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
5512 window_group_cleanup_grabs (GtkWindowGroup *group,
5516 GSList *to_remove = NULL;
5518 tmp_list = group->grabs;
5521 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
5522 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
5523 tmp_list = tmp_list->next;
5528 gtk_grab_remove (to_remove->data);
5529 g_object_unref (to_remove->data);
5530 to_remove = g_slist_delete_link (to_remove, to_remove);
5535 * gtk_window_group_add_window:
5536 * @window_group: a #GtkWindowGroup
5537 * @window: the #GtkWindow to add
5539 * Adds a window to a #GtkWindowGroup.
5542 gtk_window_group_add_window (GtkWindowGroup *window_group,
5545 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5546 g_return_if_fail (GTK_IS_WINDOW (window));
5548 if (window->group != window_group)
5550 g_object_ref (window);
5551 g_object_ref (window_group);
5554 gtk_window_group_remove_window (window->group, window);
5556 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
5558 window->group = window_group;
5560 g_object_unref (window);
5565 * gtk_window_group_remove_window:
5566 * @window_group: a #GtkWindowGroup
5567 * @window: the #GtkWindow to remove
5569 * Removes a window from a #GtkWindowGroup.
5572 gtk_window_group_remove_window (GtkWindowGroup *window_group,
5575 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
5576 g_return_if_fail (GTK_IS_WIDGET (window));
5577 g_return_if_fail (window->group == window_group);
5579 g_object_ref (window);
5581 window_group_cleanup_grabs (window_group, window);
5582 window->group = NULL;
5584 g_object_unref (G_OBJECT (window_group));
5585 g_object_unref (window);
5588 /* Return the group for the window or the default group
5591 _gtk_window_get_group (GtkWindow *window)
5593 if (window && window->group)
5594 return window->group;
5597 static GtkWindowGroup *default_group = NULL;
5600 default_group = gtk_window_group_new ();
5602 return default_group;
5608 Derived from XParseGeometry() in XFree86
5610 Copyright 1985, 1986, 1987,1998 The Open Group
5612 All Rights Reserved.
5614 The above copyright notice and this permission notice shall be included
5615 in all copies or substantial portions of the Software.
5617 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5618 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5619 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
5620 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
5621 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
5622 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
5623 OTHER DEALINGS IN THE SOFTWARE.
5625 Except as contained in this notice, the name of The Open Group shall
5626 not be used in advertising or otherwise to promote the sale, use or
5627 other dealings in this Software without prior written authorization
5628 from The Open Group.
5633 * XParseGeometry parses strings of the form
5634 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
5635 * width, height, xoffset, and yoffset are unsigned integers.
5636 * Example: "=80x24+300-49"
5637 * The equal sign is optional.
5638 * It returns a bitmask that indicates which of the four values
5639 * were actually found in the string. For each value found,
5640 * the corresponding argument is updated; for each value
5641 * not found, the corresponding argument is left unchanged.
5644 /* The following code is from Xlib, and is minimally modified, so we
5645 * can track any upstream changes if required. Don't change this
5646 * code. Or if you do, put in a huge comment marking which thing
5651 read_int (gchar *string,
5659 else if (*string == '-')
5665 for (; (*string >= '0') && (*string <= '9'); string++)
5667 result = (result * 10) + (*string - '0');
5679 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
5680 * value (x, y, width, height) was found in the parsed string.
5682 #define NoValue 0x0000
5683 #define XValue 0x0001
5684 #define YValue 0x0002
5685 #define WidthValue 0x0004
5686 #define HeightValue 0x0008
5687 #define AllValues 0x000F
5688 #define XNegative 0x0010
5689 #define YNegative 0x0020
5691 /* Try not to reformat/modify, so we can compare/sync with X sources */
5693 gtk_XParseGeometry (const char *string,
5696 unsigned int *width,
5697 unsigned int *height)
5701 unsigned int tempWidth, tempHeight;
5703 char *nextCharacter;
5705 /* These initializations are just to silence gcc */
5711 if ( (string == NULL) || (*string == '\0')) return(mask);
5713 string++; /* ignore possible '=' at beg of geometry spec */
5715 strind = (char *)string;
5716 if (*strind != '+' && *strind != '-' && *strind != 'x') {
5717 tempWidth = read_int(strind, &nextCharacter);
5718 if (strind == nextCharacter)
5720 strind = nextCharacter;
5724 if (*strind == 'x' || *strind == 'X') {
5726 tempHeight = read_int(strind, &nextCharacter);
5727 if (strind == nextCharacter)
5729 strind = nextCharacter;
5730 mask |= HeightValue;
5733 if ((*strind == '+') || (*strind == '-')) {
5734 if (*strind == '-') {
5736 tempX = -read_int(strind, &nextCharacter);
5737 if (strind == nextCharacter)
5739 strind = nextCharacter;
5745 tempX = read_int(strind, &nextCharacter);
5746 if (strind == nextCharacter)
5748 strind = nextCharacter;
5751 if ((*strind == '+') || (*strind == '-')) {
5752 if (*strind == '-') {
5754 tempY = -read_int(strind, &nextCharacter);
5755 if (strind == nextCharacter)
5757 strind = nextCharacter;
5764 tempY = read_int(strind, &nextCharacter);
5765 if (strind == nextCharacter)
5767 strind = nextCharacter;
5773 /* If strind isn't at the end of the string the it's an invalid
5774 geometry specification. */
5776 if (*strind != '\0') return (0);
5782 if (mask & WidthValue)
5784 if (mask & HeightValue)
5785 *height = tempHeight;
5790 * gtk_window_parse_geometry:
5791 * @window: a #GtkWindow
5792 * @geometry: geometry string
5794 * Parses a standard X Window System geometry string - see the
5795 * manual page for X (type 'man X') for details on this.
5796 * gtk_window_parse_geometry() does work on all GTK+ ports
5797 * including Win32 but is primarily intended for an X environment.
5799 * If either a size or a position can be extracted from the
5800 * geometry string, gtk_window_parse_geometry() returns %TRUE
5801 * and calls gtk_window_set_default_size() and/or gtk_window_move()
5802 * to resize/move the window.
5804 * If gtk_window_parse_geometry() returns %TRUE, it will also
5805 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
5806 * indicating to the window manager that the size/position of
5807 * the window was user-specified. This causes most window
5808 * managers to honor the geometry.
5810 * Return value: %TRUE if string was parsed successfully
5813 gtk_window_parse_geometry (GtkWindow *window,
5814 const gchar *geometry)
5819 gboolean size_set, pos_set;
5821 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5822 g_return_val_if_fail (geometry != NULL, FALSE);
5824 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
5826 if ((result & WidthValue) == 0 ||
5829 if ((result & HeightValue) == 0 ||
5834 if ((result & WidthValue) || (result & HeightValue))
5836 gtk_window_set_default_size_internal (window, TRUE, w, TRUE, h, TRUE);
5840 gtk_window_get_size (window, &w, &h);
5842 grav = GDK_GRAVITY_NORTH_WEST;
5844 if ((result & XNegative) && (result & YNegative))
5845 grav = GDK_GRAVITY_SOUTH_EAST;
5846 else if (result & XNegative)
5847 grav = GDK_GRAVITY_NORTH_EAST;
5848 else if (result & YNegative)
5849 grav = GDK_GRAVITY_SOUTH_WEST;
5851 if ((result & XValue) == 0)
5854 if ((result & YValue) == 0)
5857 if (grav == GDK_GRAVITY_SOUTH_WEST ||
5858 grav == GDK_GRAVITY_SOUTH_EAST)
5859 y = gdk_screen_get_height (window->screen) - h + y;
5861 if (grav == GDK_GRAVITY_SOUTH_EAST ||
5862 grav == GDK_GRAVITY_NORTH_EAST)
5863 x = gdk_screen_get_width (window->screen) - w + x;
5865 /* we don't let you put a window offscreen; maybe some people would
5866 * prefer to be able to, but it's kind of a bogus thing to do.
5875 if ((result & XValue) || (result & YValue))
5877 gtk_window_set_gravity (window, grav);
5878 gtk_window_move (window, x, y);
5882 if (size_set || pos_set)
5884 /* Set USSize, USPosition hints */
5885 GtkWindowGeometryInfo *info;
5887 info = gtk_window_get_geometry_info (window, TRUE);
5890 info->mask |= GDK_HINT_USER_POS;
5892 info->mask |= GDK_HINT_USER_SIZE;
5899 gtk_window_mnemonic_hash_foreach (gpointer key,
5905 GtkWindowKeysForeachFunc func;
5909 GtkWindowMnemonic *mnemonic = value;
5911 if (mnemonic->window == info->window)
5912 (*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
5916 _gtk_window_keys_foreach (GtkWindow *window,
5917 GtkWindowKeysForeachFunc func,
5924 GtkWindowKeysForeachFunc func;
5928 info.window = window;
5930 info.func_data = func_data;
5932 g_hash_table_foreach (mnemonic_hash_table,
5933 gtk_window_mnemonic_hash_foreach,
5936 groups = gtk_accel_groups_from_object (G_OBJECT (window));
5939 GtkAccelGroup *group = groups->data;
5942 for (i = 0; i < group->n_accels; i++)
5944 GtkAccelKey *key = &group->priv_accels[i].key;
5947 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
5950 groups = groups->next;
5955 gtk_window_keys_changed (GtkWindow *window)
5957 gtk_window_free_key_hash (window);
5958 gtk_window_get_key_hash (window);
5961 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
5963 struct _GtkWindowKeyEntry
5967 gboolean is_mnemonic;
5971 add_to_key_hash (GtkWindow *window,
5973 GdkModifierType modifiers,
5974 gboolean is_mnemonic,
5977 GtkKeyHash *key_hash = data;
5979 GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
5981 entry->keyval = keyval;
5982 entry->modifiers = modifiers;
5983 entry->is_mnemonic = is_mnemonic;
5985 /* GtkAccelGroup stores lowercased accelerators. To deal
5986 * with this, if <Shift> was specified, uppercase.
5988 if (modifiers & GDK_SHIFT_MASK)
5990 if (keyval == GDK_Tab)
5991 keyval = GDK_ISO_Left_Tab;
5993 keyval = gdk_keyval_to_upper (keyval);
5996 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
6000 gtk_window_get_key_hash (GtkWindow *window)
6002 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6006 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (window->screen)),
6007 (GDestroyNotify)g_free);
6008 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
6009 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
6015 gtk_window_free_key_hash (GtkWindow *window)
6017 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6020 _gtk_key_hash_free (key_hash);
6021 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
6026 * _gtk_window_activate_key:
6027 * @window: a #GtkWindow
6028 * @event: a #GdkEventKey
6030 * Activates mnemonics and accelerators for this #GtKWindow
6032 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
6035 _gtk_window_activate_key (GtkWindow *window,
6038 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6039 GtkWindowKeyEntry *found_entry = NULL;
6043 gtk_window_keys_changed (window);
6044 key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6049 GSList *entries = _gtk_key_hash_lookup (key_hash,
6050 event->hardware_keycode,
6051 event->state & gtk_accelerator_get_default_mod_mask (),
6055 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
6057 GtkWindowKeyEntry *entry = tmp_list->data;
6058 if (entry->is_mnemonic)
6060 found_entry = entry;
6065 if (!found_entry && entries)
6066 found_entry = entries->data;
6068 g_slist_free (entries);
6073 if (found_entry->is_mnemonic)
6074 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
6076 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);