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 "gtkwindow.h"
35 #include "gtkwindow-decorate.h"
36 #include "gtkbindings.h"
37 #include "gtkkeyhash.h"
39 #include "gtkiconfactory.h"
41 #include "gtkmarshalers.h"
70 PROP_DESTROY_WITH_PARENT,
74 PROP_SKIP_TASKBAR_HINT,
79 /* Readonly properties */
81 PROP_HAS_TOPLEVEL_FOCUS,
89 GdkPixmap *icon_pixmap;
92 guint using_default_icon : 1;
93 guint using_parent_icon : 1;
97 GdkGeometry geometry; /* Last set of geometry hints we set */
99 GdkRectangle configure_request;
100 } GtkWindowLastGeometryInfo;
102 struct _GtkWindowGeometryInfo
104 /* Properties that the app has set on the window
106 GdkGeometry geometry; /* Geometry hints */
108 GtkWidget *widget; /* subwidget to which hints apply */
109 /* from last gtk_window_resize () - if > 0, indicates that
110 * we should resize to this size.
115 /* From last gtk_window_move () prior to mapping -
116 * only used if initial_pos_set
121 /* Default size - used only the FIRST time we map a window,
126 /* whether to use initial_x, initial_y */
127 guint initial_pos_set : 1;
128 /* CENTER_ALWAYS or other position constraint changed since
129 * we sent the last configure request.
131 guint position_constraints_changed : 1;
133 /* if true, default_width, height come from gtk_window_parse_geometry,
134 * and thus should be multiplied by the increments and affect the
135 * geometry widget only
137 guint default_is_geometry : 1;
139 GtkWindowLastGeometryInfo last;
142 typedef struct _GtkWindowMnemonic GtkWindowMnemonic;
144 struct _GtkWindowMnemonic {
151 typedef struct _GtkWindowPrivate GtkWindowPrivate;
153 struct _GtkWindowPrivate
155 guint fullscreen_initially : 1;
156 guint skips_taskbar : 1;
157 guint skips_pager : 1;
160 static void gtk_window_class_init (GtkWindowClass *klass);
161 static void gtk_window_init (GtkWindow *window);
162 static void gtk_window_dispose (GObject *object);
163 static void gtk_window_destroy (GtkObject *object);
164 static void gtk_window_finalize (GObject *object);
165 static void gtk_window_private_finalize (GtkWindowPrivate *priv);
166 static void gtk_window_show (GtkWidget *widget);
167 static void gtk_window_hide (GtkWidget *widget);
168 static void gtk_window_map (GtkWidget *widget);
169 static void gtk_window_unmap (GtkWidget *widget);
170 static void gtk_window_realize (GtkWidget *widget);
171 static void gtk_window_unrealize (GtkWidget *widget);
172 static void gtk_window_size_request (GtkWidget *widget,
173 GtkRequisition *requisition);
174 static void gtk_window_size_allocate (GtkWidget *widget,
175 GtkAllocation *allocation);
176 static gint gtk_window_event (GtkWidget *widget,
178 static gboolean gtk_window_frame_event (GtkWindow *window,
180 static gint gtk_window_configure_event (GtkWidget *widget,
181 GdkEventConfigure *event);
182 static gint gtk_window_key_press_event (GtkWidget *widget,
184 static gint gtk_window_key_release_event (GtkWidget *widget,
186 static gint gtk_window_enter_notify_event (GtkWidget *widget,
187 GdkEventCrossing *event);
188 static gint gtk_window_leave_notify_event (GtkWidget *widget,
189 GdkEventCrossing *event);
190 static gint gtk_window_focus_in_event (GtkWidget *widget,
191 GdkEventFocus *event);
192 static gint gtk_window_focus_out_event (GtkWidget *widget,
193 GdkEventFocus *event);
194 static gint gtk_window_client_event (GtkWidget *widget,
195 GdkEventClient *event);
196 static void gtk_window_check_resize (GtkContainer *container);
197 static gint gtk_window_focus (GtkWidget *widget,
198 GtkDirectionType direction);
199 static void gtk_window_real_set_focus (GtkWindow *window,
202 static void gtk_window_real_activate_default (GtkWindow *window);
203 static void gtk_window_real_activate_focus (GtkWindow *window);
204 static void gtk_window_move_focus (GtkWindow *window,
205 GtkDirectionType dir);
206 static void gtk_window_keys_changed (GtkWindow *window);
207 static void gtk_window_read_rcfiles (GtkWidget *widget,
208 GdkEventClient *event);
209 static void gtk_window_paint (GtkWidget *widget,
211 static gint gtk_window_expose (GtkWidget *widget,
212 GdkEventExpose *event);
213 static void gtk_window_unset_transient_for (GtkWindow *window);
214 static void gtk_window_transient_parent_realized (GtkWidget *parent,
216 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
219 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
221 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
224 static void gtk_window_move_resize (GtkWindow *window);
225 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
227 GdkGeometry *geometry_b,
229 static void gtk_window_constrain_size (GtkWindow *window,
230 GdkGeometry *geometry,
236 static void gtk_window_constrain_position (GtkWindow *window,
241 static void gtk_window_compute_hints (GtkWindow *window,
242 GdkGeometry *new_geometry,
244 static void gtk_window_compute_configure_request (GtkWindow *window,
245 GdkRectangle *request,
246 GdkGeometry *geometry,
249 static void gtk_window_set_default_size_internal (GtkWindow *window,
250 gboolean change_width,
252 gboolean change_height,
254 gboolean is_geometry);
256 static void gtk_window_realize_icon (GtkWindow *window);
257 static void gtk_window_unrealize_icon (GtkWindow *window);
259 static void gtk_window_notify_keys_changed (GtkWindow *window);
260 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
261 static void gtk_window_free_key_hash (GtkWindow *window);
263 static GSList *toplevel_list = NULL;
264 static GHashTable *mnemonic_hash_table = NULL;
265 static GtkBinClass *parent_class = NULL;
266 static guint window_signals[LAST_SIGNAL] = { 0 };
267 static GList *default_icon_list = NULL;
268 static guint default_icon_serial = 0;
269 static gboolean disable_startup_notification = FALSE;
270 static gboolean sent_startup_notification = FALSE;
272 static void gtk_window_set_property (GObject *object,
276 static void gtk_window_get_property (GObject *object,
283 mnemonic_hash (gconstpointer key)
285 const GtkWindowMnemonic *k;
288 k = (GtkWindowMnemonic *)key;
290 h = (gulong) k->window;
291 h ^= k->keyval << 16;
292 h ^= k->keyval >> 16;
298 mnemonic_equal (gconstpointer a, gconstpointer b)
300 const GtkWindowMnemonic *ka;
301 const GtkWindowMnemonic *kb;
303 ka = (GtkWindowMnemonic *)a;
304 kb = (GtkWindowMnemonic *)b;
307 (ka->window == kb->window) &&
308 (ka->keyval == kb->keyval);
312 gtk_window_get_private (GtkWindow *window)
314 GtkWindowPrivate *private;
315 static GQuark private_quark = 0;
318 private_quark = g_quark_from_static_string ("gtk-window-private");
320 private = g_object_get_qdata (G_OBJECT (window), private_quark);
324 private = g_new0 (GtkWindowPrivate, 1);
326 private->fullscreen_initially = FALSE;
327 private->skips_pager = FALSE;
328 private->skips_taskbar = FALSE;
330 g_object_set_qdata_full (G_OBJECT (window), private_quark,
332 (GDestroyNotify) gtk_window_private_finalize);
339 gtk_window_get_type (void)
341 static GType window_type = 0;
345 static const GTypeInfo window_info =
347 sizeof (GtkWindowClass),
348 NULL, /* base_init */
349 NULL, /* base_finalize */
350 (GClassInitFunc) gtk_window_class_init,
351 NULL, /* class_finalize */
352 NULL, /* class_data */
355 (GInstanceInitFunc) gtk_window_init,
358 window_type = g_type_register_static (GTK_TYPE_BIN, "GtkWindow",
366 add_tab_bindings (GtkBindingSet *binding_set,
367 GdkModifierType modifiers,
368 GtkDirectionType direction)
370 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
372 GTK_TYPE_DIRECTION_TYPE, direction);
373 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
375 GTK_TYPE_DIRECTION_TYPE, direction);
379 add_arrow_bindings (GtkBindingSet *binding_set,
381 GtkDirectionType direction)
383 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
385 gtk_binding_entry_add_signal (binding_set, keysym, 0,
387 GTK_TYPE_DIRECTION_TYPE, direction);
388 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
390 GTK_TYPE_DIRECTION_TYPE, direction);
391 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
393 GTK_TYPE_DIRECTION_TYPE, direction);
394 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
396 GTK_TYPE_DIRECTION_TYPE, direction);
401 gtk_window_class_init (GtkWindowClass *klass)
403 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
404 GtkObjectClass *object_class;
405 GtkWidgetClass *widget_class;
406 GtkContainerClass *container_class;
407 GtkBindingSet *binding_set;
409 object_class = (GtkObjectClass*) klass;
410 widget_class = (GtkWidgetClass*) klass;
411 container_class = (GtkContainerClass*) klass;
413 parent_class = g_type_class_peek_parent (klass);
415 mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
417 gobject_class->dispose = gtk_window_dispose;
418 gobject_class->finalize = gtk_window_finalize;
420 gobject_class->set_property = gtk_window_set_property;
421 gobject_class->get_property = gtk_window_get_property;
423 object_class->destroy = gtk_window_destroy;
425 widget_class->show = gtk_window_show;
426 widget_class->hide = gtk_window_hide;
427 widget_class->map = gtk_window_map;
428 widget_class->unmap = gtk_window_unmap;
429 widget_class->realize = gtk_window_realize;
430 widget_class->unrealize = gtk_window_unrealize;
431 widget_class->size_request = gtk_window_size_request;
432 widget_class->size_allocate = gtk_window_size_allocate;
433 widget_class->configure_event = gtk_window_configure_event;
434 widget_class->key_press_event = gtk_window_key_press_event;
435 widget_class->key_release_event = gtk_window_key_release_event;
436 widget_class->enter_notify_event = gtk_window_enter_notify_event;
437 widget_class->leave_notify_event = gtk_window_leave_notify_event;
438 widget_class->focus_in_event = gtk_window_focus_in_event;
439 widget_class->focus_out_event = gtk_window_focus_out_event;
440 widget_class->client_event = gtk_window_client_event;
441 widget_class->focus = gtk_window_focus;
443 widget_class->expose_event = gtk_window_expose;
445 container_class->check_resize = gtk_window_check_resize;
447 klass->set_focus = gtk_window_real_set_focus;
448 klass->frame_event = gtk_window_frame_event;
450 klass->activate_default = gtk_window_real_activate_default;
451 klass->activate_focus = gtk_window_real_activate_focus;
452 klass->move_focus = gtk_window_move_focus;
453 klass->keys_changed = gtk_window_keys_changed;
456 g_object_class_install_property (gobject_class,
458 g_param_spec_enum ("type",
460 _("The type of the window"),
461 GTK_TYPE_WINDOW_TYPE,
463 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
465 g_object_class_install_property (gobject_class,
467 g_param_spec_string ("title",
469 _("The title of the window"),
473 g_object_class_install_property (gobject_class,
475 g_param_spec_string ("role",
477 _("Unique identifier for the window to be used when restoring a session"),
481 g_object_class_install_property (gobject_class,
483 g_param_spec_boolean ("allow_shrink",
485 /* xgettext:no-c-format */
486 _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
490 g_object_class_install_property (gobject_class,
492 g_param_spec_boolean ("allow_grow",
494 _("If TRUE, users can expand the window beyond its minimum size"),
498 g_object_class_install_property (gobject_class,
500 g_param_spec_boolean ("resizable",
502 _("If TRUE, users can resize the window"),
506 g_object_class_install_property (gobject_class,
508 g_param_spec_boolean ("modal",
510 _("If TRUE, the window is modal (other windows are not usable while this one is up)"),
514 g_object_class_install_property (gobject_class,
516 g_param_spec_enum ("window_position",
517 _("Window Position"),
518 _("The initial position of the window"),
519 GTK_TYPE_WINDOW_POSITION,
523 g_object_class_install_property (gobject_class,
525 g_param_spec_int ("default_width",
527 _("The default width of the window, used when initially showing the window"),
533 g_object_class_install_property (gobject_class,
535 g_param_spec_int ("default_height",
537 _("The default height of the window, used when initially showing the window"),
543 g_object_class_install_property (gobject_class,
544 PROP_DESTROY_WITH_PARENT,
545 g_param_spec_boolean ("destroy_with_parent",
546 _("Destroy with Parent"),
547 _("If this window should be destroyed when the parent is destroyed"),
551 g_object_class_install_property (gobject_class,
553 g_param_spec_object ("icon",
555 _("Icon for this window"),
559 g_object_class_install_property (gobject_class,
561 g_param_spec_object ("screen",
563 _("The screen where this window will be displayed"),
567 g_object_class_install_property (gobject_class,
569 g_param_spec_boolean ("is_active",
571 _("Whether the toplevel is the current active window"),
575 g_object_class_install_property (gobject_class,
576 PROP_HAS_TOPLEVEL_FOCUS,
577 g_param_spec_boolean ("has_toplevel_focus",
578 _("Focus in Toplevel"),
579 _("Whether the input focus is within this GtkWindow"),
583 g_object_class_install_property (gobject_class,
585 g_param_spec_enum ("type_hint",
587 _("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
588 GDK_TYPE_WINDOW_TYPE_HINT,
589 GDK_WINDOW_TYPE_HINT_NORMAL,
592 g_object_class_install_property (gobject_class,
593 PROP_SKIP_TASKBAR_HINT,
594 g_param_spec_boolean ("skip_taskbar_hint",
596 _("TRUE if the window should not be in the task bar."),
600 g_object_class_install_property (gobject_class,
601 PROP_SKIP_PAGER_HINT,
602 g_param_spec_boolean ("skip_pager_hint",
604 _("TRUE if the window should not be in the pager."),
609 * GtkWindow:decorated:
611 * Whether the window should be decorated by the window manager.
615 g_object_class_install_property (gobject_class,
617 g_param_spec_boolean ("decorated",
619 _("Whether the window should be decorated by the window manager"),
626 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
627 * more details about window gravity.
631 g_object_class_install_property (gobject_class,
633 g_param_spec_enum ("gravity",
635 _("The window gravity of the window"),
637 GDK_GRAVITY_NORTH_WEST,
640 window_signals[SET_FOCUS] =
641 g_signal_new ("set_focus",
642 G_TYPE_FROM_CLASS (gobject_class),
644 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
646 _gtk_marshal_VOID__OBJECT,
650 window_signals[FRAME_EVENT] =
651 g_signal_new ("frame_event",
652 G_TYPE_FROM_CLASS (gobject_class),
654 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
655 _gtk_boolean_handled_accumulator, NULL,
656 _gtk_marshal_BOOLEAN__BOXED,
660 window_signals[ACTIVATE_FOCUS] =
661 g_signal_new ("activate_focus",
662 G_TYPE_FROM_CLASS (gobject_class),
663 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
664 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
666 _gtk_marshal_VOID__VOID,
670 window_signals[ACTIVATE_DEFAULT] =
671 g_signal_new ("activate_default",
672 G_TYPE_FROM_CLASS (gobject_class),
673 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
674 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
676 _gtk_marshal_VOID__VOID,
680 window_signals[MOVE_FOCUS] =
681 g_signal_new ("move_focus",
682 G_TYPE_FROM_CLASS (gobject_class),
683 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
684 G_STRUCT_OFFSET (GtkWindowClass, move_focus),
686 _gtk_marshal_VOID__ENUM,
689 GTK_TYPE_DIRECTION_TYPE);
691 window_signals[KEYS_CHANGED] =
692 g_signal_new ("keys_changed",
693 G_TYPE_FROM_CLASS (gobject_class),
695 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
697 _gtk_marshal_VOID__VOID,
705 binding_set = gtk_binding_set_by_class (klass);
707 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
708 "activate_focus", 0);
709 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
710 "activate_focus", 0);
712 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
713 "activate_default", 0);
715 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
716 "activate_default", 0);
718 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
719 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
720 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
721 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
723 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
724 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
725 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
726 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
730 gtk_window_init (GtkWindow *window)
732 GdkColormap *colormap;
734 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
735 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
737 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
739 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
741 window->title = NULL;
742 window->wmclass_name = g_strdup (g_get_prgname ());
743 window->wmclass_class = g_strdup (gdk_get_program_class ());
744 window->wm_role = NULL;
745 window->geometry_info = NULL;
746 window->type = GTK_WINDOW_TOPLEVEL;
747 window->focus_widget = NULL;
748 window->default_widget = NULL;
749 window->configure_request_count = 0;
750 window->allow_shrink = FALSE;
751 window->allow_grow = TRUE;
752 window->configure_notify_received = FALSE;
753 window->position = GTK_WIN_POS_NONE;
754 window->need_default_size = TRUE;
755 window->need_default_position = TRUE;
756 window->modal = FALSE;
757 window->frame = NULL;
758 window->has_frame = FALSE;
759 window->frame_left = 0;
760 window->frame_right = 0;
761 window->frame_top = 0;
762 window->frame_bottom = 0;
763 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
764 window->gravity = GDK_GRAVITY_NORTH_WEST;
765 window->decorated = TRUE;
766 window->mnemonic_modifier = GDK_MOD1_MASK;
767 window->screen = gdk_screen_get_default ();
769 colormap = _gtk_widget_peek_colormap ();
771 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
773 g_object_ref (window);
774 gtk_object_sink (GTK_OBJECT (window));
775 window->has_user_ref_count = TRUE;
776 toplevel_list = g_slist_prepend (toplevel_list, window);
778 gtk_decorated_window_init (window);
780 g_signal_connect (window,
782 G_CALLBACK (gtk_window_event),
787 gtk_window_set_property (GObject *object,
794 window = GTK_WINDOW (object);
799 window->type = g_value_get_enum (value);
802 gtk_window_set_title (window, g_value_get_string (value));
805 gtk_window_set_role (window, g_value_get_string (value));
807 case PROP_ALLOW_SHRINK:
808 window->allow_shrink = g_value_get_boolean (value);
809 gtk_widget_queue_resize (GTK_WIDGET (window));
811 case PROP_ALLOW_GROW:
812 window->allow_grow = g_value_get_boolean (value);
813 gtk_widget_queue_resize (GTK_WIDGET (window));
814 g_object_notify (G_OBJECT (window), "resizable");
817 window->allow_grow = g_value_get_boolean (value);
818 gtk_widget_queue_resize (GTK_WIDGET (window));
819 g_object_notify (G_OBJECT (window), "allow_grow");
822 gtk_window_set_modal (window, g_value_get_boolean (value));
825 gtk_window_set_position (window, g_value_get_enum (value));
827 case PROP_DEFAULT_WIDTH:
828 gtk_window_set_default_size_internal (window,
829 TRUE, g_value_get_int (value),
832 case PROP_DEFAULT_HEIGHT:
833 gtk_window_set_default_size_internal (window,
835 TRUE, g_value_get_int (value), FALSE);
837 case PROP_DESTROY_WITH_PARENT:
838 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
841 gtk_window_set_icon (window,
842 g_value_get_object (value));
845 gtk_window_set_screen (window, g_value_get_object (value));
848 gtk_window_set_type_hint (window,
849 g_value_get_enum (value));
851 case PROP_SKIP_TASKBAR_HINT:
852 gtk_window_set_skip_taskbar_hint (window,
853 g_value_get_boolean (value));
855 case PROP_SKIP_PAGER_HINT:
856 gtk_window_set_skip_pager_hint (window,
857 g_value_get_boolean (value));
860 gtk_window_set_decorated (window, g_value_get_boolean (value));
863 gtk_window_set_gravity (window, g_value_get_enum (value));
871 gtk_window_get_property (GObject *object,
878 window = GTK_WINDOW (object);
882 GtkWindowGeometryInfo *info;
884 g_value_set_enum (value, window->type);
887 g_value_set_string (value, window->wm_role);
890 g_value_set_string (value, window->title);
892 case PROP_ALLOW_SHRINK:
893 g_value_set_boolean (value, window->allow_shrink);
895 case PROP_ALLOW_GROW:
896 g_value_set_boolean (value, window->allow_grow);
899 g_value_set_boolean (value, window->allow_grow);
902 g_value_set_boolean (value, window->modal);
905 g_value_set_enum (value, window->position);
907 case PROP_DEFAULT_WIDTH:
908 info = gtk_window_get_geometry_info (window, FALSE);
910 g_value_set_int (value, -1);
912 g_value_set_int (value, info->default_width);
914 case PROP_DEFAULT_HEIGHT:
915 info = gtk_window_get_geometry_info (window, FALSE);
917 g_value_set_int (value, -1);
919 g_value_set_int (value, info->default_height);
921 case PROP_DESTROY_WITH_PARENT:
922 g_value_set_boolean (value, window->destroy_with_parent);
925 g_value_set_object (value, gtk_window_get_icon (window));
928 g_value_set_object (value, window->screen);
931 g_value_set_boolean (value, window->is_active);
933 case PROP_HAS_TOPLEVEL_FOCUS:
934 g_value_set_boolean (value, window->has_toplevel_focus);
937 g_value_set_enum (value,
940 case PROP_SKIP_TASKBAR_HINT:
941 g_value_set_boolean (value,
942 gtk_window_get_skip_taskbar_hint (window));
944 case PROP_SKIP_PAGER_HINT:
945 g_value_set_boolean (value,
946 gtk_window_get_skip_pager_hint (window));
949 g_value_set_boolean (value, gtk_window_get_decorated (window));
952 g_value_set_enum (value, gtk_window_get_gravity (window));
955 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
962 * @type: type of window
964 * Creates a new #GtkWindow, which is a toplevel window that can
965 * contain other widgets. Nearly always, the type of the window should
966 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
967 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
968 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
969 * dialogs, though in some other toolkits dialogs are called "popups".
970 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
971 * On X11, popup windows are not controlled by the <link
972 * linkend="gtk-X11-arch">window manager</link>.
974 * If you simply want an undecorated window (no window borders), use
975 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
977 * Return value: a new #GtkWindow.
980 gtk_window_new (GtkWindowType type)
984 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
986 window = g_object_new (GTK_TYPE_WINDOW, NULL);
990 return GTK_WIDGET (window);
994 * gtk_window_set_title:
995 * @window: a #GtkWindow
996 * @title: title of the window
998 * Sets the title of the #GtkWindow. The title of a window will be
999 * displayed in its title bar; on the X Window System, the title bar
1000 * is rendered by the <link linkend="gtk-X11-arch">window
1001 * manager</link>, so exactly how the title appears to users may vary
1002 * according to a user's exact configuration. The title should help a
1003 * user distinguish this window from other windows they may have
1004 * open. A good title might include the application name and current
1005 * document filename, for example.
1009 gtk_window_set_title (GtkWindow *window,
1012 g_return_if_fail (GTK_IS_WINDOW (window));
1015 g_free (window->title);
1016 window->title = g_strdup (title);
1018 if (GTK_WIDGET_REALIZED (window))
1020 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
1022 gtk_decorated_window_set_title (window, title);
1025 g_object_notify (G_OBJECT (window), "title");
1029 * gtk_window_get_title:
1030 * @window: a #GtkWindow
1032 * Retrieves the title of the window. See gtk_window_set_title().
1034 * Return value: the title of the window, or %NULL if none has
1035 * been set explicitely. The returned string is owned by the widget
1036 * and must not be modified or freed.
1038 G_CONST_RETURN gchar *
1039 gtk_window_get_title (GtkWindow *window)
1041 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1043 return window->title;
1047 * gtk_window_set_wmclass:
1048 * @window: a #GtkWindow
1049 * @wmclass_name: window name hint
1050 * @wmclass_class: window class hint
1052 * Don't use this function. It sets the X Window System "class" and
1053 * "name" hints for a window. According to the ICCCM, you should
1054 * always set these to the same value for all windows in an
1055 * application, and GTK+ sets them to that value by default, so calling
1056 * this function is sort of pointless. However, you may want to call
1057 * gtk_window_set_role() on each window in your application, for the
1058 * benefit of the session manager. Setting the role allows the window
1059 * manager to restore window positions when loading a saved session.
1063 gtk_window_set_wmclass (GtkWindow *window,
1064 const gchar *wmclass_name,
1065 const gchar *wmclass_class)
1067 g_return_if_fail (GTK_IS_WINDOW (window));
1069 g_free (window->wmclass_name);
1070 window->wmclass_name = g_strdup (wmclass_name);
1072 g_free (window->wmclass_class);
1073 window->wmclass_class = g_strdup (wmclass_class);
1075 if (GTK_WIDGET_REALIZED (window))
1076 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1080 * gtk_window_set_role:
1081 * @window: a #GtkWindow
1082 * @role: unique identifier for the window to be used when restoring a session
1084 * This function is only useful on X11, not with other GTK+ targets.
1086 * In combination with the window title, the window role allows a
1087 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1088 * same" window when an application is restarted. So for example you
1089 * might set the "toolbox" role on your app's toolbox window, so that
1090 * when the user restarts their session, the window manager can put
1091 * the toolbox back in the same place.
1093 * If a window already has a unique title, you don't need to set the
1094 * role, since the WM can use the title to identify the window when
1095 * restoring the session.
1099 gtk_window_set_role (GtkWindow *window,
1102 g_return_if_fail (GTK_IS_WINDOW (window));
1104 if (role == window->wm_role)
1107 g_free (window->wm_role);
1108 window->wm_role = g_strdup (role);
1110 if (GTK_WIDGET_REALIZED (window))
1111 gdk_window_set_role (GTK_WIDGET (window)->window, window->wm_role);
1113 g_object_notify (G_OBJECT (window), "role");
1117 * gtk_window_get_role:
1118 * @window: a #GtkWindow
1120 * Returns the role of the window. See gtk_window_set_role() for
1121 * further explanation.
1123 * Return value: the role of the window if set, or %NULL. The
1124 * returned is owned by the widget and must not be modified
1127 G_CONST_RETURN gchar *
1128 gtk_window_get_role (GtkWindow *window)
1130 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1132 return window->wm_role;
1136 * gtk_window_set_focus:
1137 * @window: a #GtkWindow
1138 * @focus: widget to be the new focus widget, or %NULL to unset
1139 * any focus widget for the toplevel window.
1141 * If @focus is not the current focus widget, and is focusable, sets
1142 * it as the focus widget for the window. If @focus is %NULL, unsets
1143 * the focus widget for this window. To set the focus to a particular
1144 * widget in the toplevel, it is usually more convenient to use
1145 * gtk_widget_grab_focus() instead of this function.
1148 gtk_window_set_focus (GtkWindow *window,
1151 g_return_if_fail (GTK_IS_WINDOW (window));
1154 g_return_if_fail (GTK_IS_WIDGET (focus));
1155 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1159 gtk_widget_grab_focus (focus);
1162 /* Clear the existing focus chain, so that when we focus into
1163 * the window again, we start at the beginnning.
1165 GtkWidget *widget = window->focus_widget;
1168 while (widget->parent)
1170 widget = widget->parent;
1171 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1175 _gtk_window_internal_set_focus (window, NULL);
1180 _gtk_window_internal_set_focus (GtkWindow *window,
1183 g_return_if_fail (GTK_IS_WINDOW (window));
1185 if ((window->focus_widget != focus) ||
1186 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1187 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1191 * gtk_window_set_default:
1192 * @window: a #GtkWindow
1193 * @default_widget: widget to be the default, or %NULL to unset the
1194 * default widget for the toplevel.
1196 * The default widget is the widget that's activated when the user
1197 * presses Enter in a dialog (for example). This function sets or
1198 * unsets the default widget for a #GtkWindow about. When setting
1199 * (rather than unsetting) the default widget it's generally easier to
1200 * call gtk_widget_grab_focus() on the widget. Before making a widget
1201 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1202 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1205 gtk_window_set_default (GtkWindow *window,
1206 GtkWidget *default_widget)
1208 g_return_if_fail (GTK_IS_WINDOW (window));
1211 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1213 if (window->default_widget != default_widget)
1215 GtkWidget *old_default_widget = NULL;
1218 g_object_ref (default_widget);
1220 if (window->default_widget)
1222 old_default_widget = window->default_widget;
1224 if (window->focus_widget != window->default_widget ||
1225 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1226 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1227 gtk_widget_queue_draw (window->default_widget);
1230 window->default_widget = default_widget;
1232 if (window->default_widget)
1234 if (window->focus_widget == NULL ||
1235 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1236 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1237 gtk_widget_queue_draw (window->default_widget);
1240 if (old_default_widget)
1241 g_object_notify (G_OBJECT (old_default_widget), "has_default");
1245 g_object_notify (G_OBJECT (default_widget), "has_default");
1246 g_object_unref (default_widget);
1252 gtk_window_set_policy (GtkWindow *window,
1253 gboolean allow_shrink,
1254 gboolean allow_grow,
1255 gboolean auto_shrink)
1257 g_return_if_fail (GTK_IS_WINDOW (window));
1259 window->allow_shrink = (allow_shrink != FALSE);
1260 window->allow_grow = (allow_grow != FALSE);
1262 g_object_freeze_notify (G_OBJECT (window));
1263 g_object_notify (G_OBJECT (window), "allow_shrink");
1264 g_object_notify (G_OBJECT (window), "allow_grow");
1265 g_object_notify (G_OBJECT (window), "resizable");
1266 g_object_thaw_notify (G_OBJECT (window));
1268 gtk_widget_queue_resize (GTK_WIDGET (window));
1272 handle_keys_changed (gpointer data)
1276 GDK_THREADS_ENTER ();
1277 window = GTK_WINDOW (data);
1279 if (window->keys_changed_handler)
1281 g_source_remove (window->keys_changed_handler);
1282 window->keys_changed_handler = 0;
1285 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1286 GDK_THREADS_LEAVE ();
1292 gtk_window_notify_keys_changed (GtkWindow *window)
1294 if (!window->keys_changed_handler)
1295 window->keys_changed_handler = g_idle_add (handle_keys_changed, window);
1299 * gtk_window_add_accel_group:
1300 * @window: window to attach accelerator group to
1301 * @accel_group: a #GtkAccelGroup
1303 * Associate @accel_group with @window, such that calling
1304 * gtk_accel_groups_activate() on @window will activate accelerators
1308 gtk_window_add_accel_group (GtkWindow *window,
1309 GtkAccelGroup *accel_group)
1311 g_return_if_fail (GTK_IS_WINDOW (window));
1312 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1314 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1315 g_signal_connect_object (accel_group, "accel_changed",
1316 G_CALLBACK (gtk_window_notify_keys_changed),
1317 window, G_CONNECT_SWAPPED);
1321 * gtk_window_remove_accel_group:
1322 * @window: a #GtkWindow
1323 * @accel_group: a #GtkAccelGroup
1325 * Reverses the effects of gtk_window_add_accel_group().
1328 gtk_window_remove_accel_group (GtkWindow *window,
1329 GtkAccelGroup *accel_group)
1331 g_return_if_fail (GTK_IS_WINDOW (window));
1332 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1334 g_signal_handlers_disconnect_by_func (accel_group,
1335 gtk_window_notify_keys_changed,
1337 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1341 * gtk_window_add_mnemonic:
1342 * @window: a #GtkWindow
1343 * @keyval: the mnemonic
1344 * @target: the widget that gets activated by the mnemonic
1346 * Adds a mnemonic to this window.
1349 gtk_window_add_mnemonic (GtkWindow *window,
1353 GtkWindowMnemonic key;
1354 GtkWindowMnemonic *mnemonic;
1356 g_return_if_fail (GTK_IS_WINDOW (window));
1357 g_return_if_fail (GTK_IS_WIDGET (target));
1359 key.window = window;
1360 key.keyval = keyval;
1361 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1365 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1366 mnemonic->targets = g_slist_append (mnemonic->targets, target);
1370 mnemonic = g_new (GtkWindowMnemonic, 1);
1372 mnemonic->targets = g_slist_prepend (NULL, target);
1373 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1375 gtk_window_notify_keys_changed (window);
1379 * gtk_window_remove_mnemonic:
1380 * @window: a #GtkWindow
1381 * @keyval: the mnemonic
1382 * @target: the widget that gets activated by the mnemonic
1384 * Removes a mnemonic from this window.
1387 gtk_window_remove_mnemonic (GtkWindow *window,
1391 GtkWindowMnemonic key;
1392 GtkWindowMnemonic *mnemonic;
1394 g_return_if_fail (GTK_IS_WINDOW (window));
1395 g_return_if_fail (GTK_IS_WIDGET (target));
1397 key.window = window;
1398 key.keyval = keyval;
1399 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1401 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1403 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1404 if (mnemonic->targets == NULL)
1406 g_hash_table_remove (mnemonic_hash_table, mnemonic);
1409 gtk_window_notify_keys_changed (window);
1413 * gtk_window_mnemonic_activate:
1414 * @window: a #GtkWindow
1415 * @keyval: the mnemonic
1416 * @modifier: the modifiers
1417 * @returns: %TRUE if the activation is done.
1419 * Activates the targets associated with the mnemonic.
1422 gtk_window_mnemonic_activate (GtkWindow *window,
1424 GdkModifierType modifier)
1426 GtkWindowMnemonic key;
1427 GtkWindowMnemonic *mnemonic;
1429 GtkWidget *widget, *chosen_widget;
1430 gboolean overloaded;
1432 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1434 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1437 key.window = window;
1438 key.keyval = keyval;
1439 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1445 chosen_widget = NULL;
1446 list = mnemonic->targets;
1449 widget = GTK_WIDGET (list->data);
1451 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1452 GTK_WIDGET_MAPPED (widget))
1460 chosen_widget = widget;
1462 list = g_slist_next (list);
1467 /* For round robin we put the activated entry on
1468 * the end of the list after activation
1470 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1471 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1473 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1479 * gtk_window_set_mnemonic_modifier:
1480 * @window: a #GtkWindow
1481 * @modifier: the modifier mask used to activate
1482 * mnemonics on this window.
1484 * Sets the mnemonic modifier for this window.
1487 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1488 GdkModifierType modifier)
1490 g_return_if_fail (GTK_IS_WINDOW (window));
1491 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1493 window->mnemonic_modifier = modifier;
1494 gtk_window_notify_keys_changed (window);
1498 * gtk_window_get_mnemonic_modifier:
1499 * @window: a #GtkWindow
1501 * Returns the mnemonic modifier for this window. See
1502 * gtk_window_set_mnemonic_modifier().
1504 * Return value: the modifier mask used to activate
1505 * mnemonics on this window.
1508 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1510 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1512 return window->mnemonic_modifier;
1516 * gtk_window_set_position:
1517 * @window: a #GtkWindow.
1518 * @position: a position constraint.
1520 * Sets a position constraint for this window. If the old or new
1521 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1522 * the window to be repositioned to satisfy the new constraint.
1525 gtk_window_set_position (GtkWindow *window,
1526 GtkWindowPosition position)
1528 g_return_if_fail (GTK_IS_WINDOW (window));
1530 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1531 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1533 GtkWindowGeometryInfo *info;
1535 info = gtk_window_get_geometry_info (window, TRUE);
1537 /* this flag causes us to re-request the CENTER_ALWAYS
1538 * constraint in gtk_window_move_resize(), see
1539 * comment in that function.
1541 info->position_constraints_changed = TRUE;
1543 gtk_widget_queue_resize (GTK_WIDGET (window));
1546 window->position = position;
1548 g_object_notify (G_OBJECT (window), "window_position");
1552 * gtk_window_activate_focus:
1553 * @window: a #GtkWindow
1555 * Activates the current focused widget within the window.
1557 * Return value: %TRUE if a widget got activated.
1560 gtk_window_activate_focus (GtkWindow *window)
1562 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1564 if (window->focus_widget)
1566 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1567 gtk_widget_activate (window->focus_widget);
1575 * gtk_window_get_focus:
1576 * @window: a #GtkWindow
1578 * Retrieves the current focused widget within the window.
1579 * Note that this is the widget that would have the focus
1580 * if the toplevel window focused; if the toplevel window
1581 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1582 * not be %TRUE for the widget.
1584 * Return value: the currently focused widget, or %NULL if there is none.
1587 gtk_window_get_focus (GtkWindow *window)
1589 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1591 return window->focus_widget;
1595 * gtk_window_activate_default:
1596 * @window: a #GtkWindow
1598 * Activates the default widget for the window, unless the current
1599 * focused widget has been configured to receive the default action
1600 * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
1601 * focused widget is activated.
1603 * Return value: %TRUE if a widget got activated.
1606 gtk_window_activate_default (GtkWindow *window)
1608 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1610 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1611 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1613 gtk_widget_activate (window->default_widget);
1616 else if (window->focus_widget)
1618 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1619 gtk_widget_activate (window->focus_widget);
1627 * gtk_window_set_modal:
1628 * @window: a #GtkWindow
1629 * @modal: whether the window is modal
1631 * Sets a window modal or non-modal. Modal windows prevent interaction
1632 * with other windows in the same application. To keep modal dialogs
1633 * on top of main application windows, use
1634 * gtk_window_set_transient_for() to make the dialog transient for the
1635 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1636 * will then disallow lowering the dialog below the parent.
1641 gtk_window_set_modal (GtkWindow *window,
1644 g_return_if_fail (GTK_IS_WINDOW (window));
1646 modal = modal != FALSE;
1647 if (window->modal == modal)
1650 window->modal = modal;
1652 /* adjust desired modality state */
1653 if (GTK_WIDGET_REALIZED (window))
1655 GtkWidget *widget = GTK_WIDGET (window);
1658 gdk_window_set_modal_hint (widget->window, TRUE);
1660 gdk_window_set_modal_hint (widget->window, FALSE);
1663 if (GTK_WIDGET_VISIBLE (window))
1666 gtk_grab_add (GTK_WIDGET (window));
1668 gtk_grab_remove (GTK_WIDGET (window));
1671 g_object_notify (G_OBJECT (window), "modal");
1675 * gtk_window_get_modal:
1676 * @window: a #GtkWindow
1678 * Returns whether the window is modal. See gtk_window_set_modal().
1680 * Return value: %TRUE if the window is set to be modal and
1681 * establishes a grab when shown
1684 gtk_window_get_modal (GtkWindow *window)
1686 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1688 return window->modal;
1692 * gtk_window_list_toplevels:
1694 * Returns a list of all existing toplevel windows. The widgets
1695 * in the list are not individually referenced. If you want
1696 * to iterate through the list and perform actions involving
1697 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1698 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1699 * then unref all the widgets afterwards.
1701 * Return value: list of toplevel widgets
1704 gtk_window_list_toplevels (void)
1709 for (slist = toplevel_list; slist; slist = slist->next)
1710 list = g_list_prepend (list, slist->data);
1716 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1718 GList *embedded_windows;
1720 g_return_if_fail (GTK_IS_WINDOW (window));
1722 embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1723 if (embedded_windows)
1724 g_object_steal_qdata (G_OBJECT (window),
1725 g_quark_from_static_string ("gtk-embedded"));
1726 embedded_windows = g_list_prepend (embedded_windows,
1727 GUINT_TO_POINTER (xid));
1729 g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
1732 (GDestroyNotify) g_list_free : NULL);
1736 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1738 GList *embedded_windows;
1741 g_return_if_fail (GTK_IS_WINDOW (window));
1743 embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1744 if (embedded_windows)
1745 g_object_steal_qdata (G_OBJECT (window),
1746 g_quark_from_static_string ("gtk-embedded"));
1748 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1751 embedded_windows = g_list_remove_link (embedded_windows, node);
1752 g_list_free_1 (node);
1755 g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
1758 (GDestroyNotify) g_list_free : NULL);
1762 _gtk_window_reposition (GtkWindow *window,
1766 g_return_if_fail (GTK_IS_WINDOW (window));
1768 gtk_window_move (window, x, y);
1772 gtk_window_dispose (GObject *object)
1774 GtkWindow *window = GTK_WINDOW (object);
1776 gtk_window_set_focus (window, NULL);
1777 gtk_window_set_default (window, NULL);
1779 G_OBJECT_CLASS (parent_class)->dispose (object);
1783 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1785 gtk_widget_destroy (GTK_WIDGET (child));
1789 connect_parent_destroyed (GtkWindow *window)
1791 if (window->transient_parent)
1793 g_signal_connect (window->transient_parent,
1795 G_CALLBACK (parent_destroyed_callback),
1801 disconnect_parent_destroyed (GtkWindow *window)
1803 if (window->transient_parent)
1805 g_signal_handlers_disconnect_by_func (window->transient_parent,
1806 parent_destroyed_callback,
1812 gtk_window_transient_parent_realized (GtkWidget *parent,
1815 if (GTK_WIDGET_REALIZED (window))
1816 gdk_window_set_transient_for (window->window, parent->window);
1820 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1823 if (GTK_WIDGET_REALIZED (window))
1824 gdk_property_delete (window->window,
1825 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1829 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
1833 gtk_window_set_screen (window, parent->screen);
1837 gtk_window_unset_transient_for (GtkWindow *window)
1839 if (window->transient_parent)
1841 g_signal_handlers_disconnect_by_func (window->transient_parent,
1842 gtk_window_transient_parent_realized,
1844 g_signal_handlers_disconnect_by_func (window->transient_parent,
1845 gtk_window_transient_parent_unrealized,
1847 g_signal_handlers_disconnect_by_func (window->transient_parent,
1848 gtk_window_transient_parent_screen_changed,
1850 g_signal_handlers_disconnect_by_func (window->transient_parent,
1851 gtk_widget_destroyed,
1852 &window->transient_parent);
1854 if (window->destroy_with_parent)
1855 disconnect_parent_destroyed (window);
1857 window->transient_parent = NULL;
1862 * gtk_window_set_transient_for:
1863 * @window: a #GtkWindow
1864 * @parent: parent window
1866 * Dialog windows should be set transient for the main application
1867 * window they were spawned from. This allows <link
1868 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1869 * dialog on top of the main window, or center the dialog over the
1870 * main window. gtk_dialog_new_with_buttons() and other convenience
1871 * functions in GTK+ will sometimes call
1872 * gtk_window_set_transient_for() on your behalf.
1874 * On Windows, this function will and put the child window
1875 * on top of the parent, much as the window manager would have
1880 gtk_window_set_transient_for (GtkWindow *window,
1883 g_return_if_fail (GTK_IS_WINDOW (window));
1884 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1885 g_return_if_fail (window != parent);
1888 if (window->transient_parent)
1890 if (GTK_WIDGET_REALIZED (window) &&
1891 GTK_WIDGET_REALIZED (window->transient_parent) &&
1892 (!parent || !GTK_WIDGET_REALIZED (parent)))
1893 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1894 GTK_WIDGET (window));
1896 gtk_window_unset_transient_for (window);
1899 window->transient_parent = parent;
1903 g_signal_connect (parent, "destroy",
1904 G_CALLBACK (gtk_widget_destroyed),
1905 &window->transient_parent);
1906 g_signal_connect (parent, "realize",
1907 G_CALLBACK (gtk_window_transient_parent_realized),
1909 g_signal_connect (parent, "unrealize",
1910 G_CALLBACK (gtk_window_transient_parent_unrealized),
1912 g_signal_connect (parent, "notify::screen",
1913 G_CALLBACK (gtk_window_transient_parent_screen_changed),
1916 gtk_window_set_screen (window, parent->screen);
1918 if (window->destroy_with_parent)
1919 connect_parent_destroyed (window);
1921 if (GTK_WIDGET_REALIZED (window) &&
1922 GTK_WIDGET_REALIZED (parent))
1923 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1924 GTK_WIDGET (window));
1929 * gtk_window_get_transient_for:
1930 * @window: a #GtkWindow
1932 * Fetches the transient parent for this window. See
1933 * gtk_window_set_transient_for().
1935 * Return value: the transient parent for this window, or %NULL
1936 * if no transient parent has been set.
1939 gtk_window_get_transient_for (GtkWindow *window)
1941 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1943 return window->transient_parent;
1947 * gtk_window_set_type_hint:
1948 * @window: a #GtkWindow
1949 * @hint: the window type
1951 * By setting the type hint for the window, you allow the window
1952 * manager to decorate and handle the window in a way which is
1953 * suitable to the function of the window in your application.
1955 * This function should be called before the window becomes visible.
1957 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1958 * will sometimes call gtk_window_set_type_hint() on your behalf.
1962 gtk_window_set_type_hint (GtkWindow *window,
1963 GdkWindowTypeHint hint)
1965 g_return_if_fail (GTK_IS_WINDOW (window));
1966 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1967 window->type_hint = hint;
1971 * gtk_window_get_type_hint:
1972 * @window: a #GtkWindow
1974 * Gets the type hint for this window. See gtk_window_set_type_hint().
1976 * Return value: the type hint for @window.
1979 gtk_window_get_type_hint (GtkWindow *window)
1981 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1983 return window->type_hint;
1987 * gtk_window_set_skip_taskbar_hint:
1988 * @window: a #GtkWindow
1989 * @setting: %TRUE to keep this window from appearing in the task bar
1991 * Windows may set a hint asking the desktop environment not to display
1992 * the window in the task bar. This function toggles this hint.
1997 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2000 GtkWindowPrivate *priv;
2002 g_return_if_fail (GTK_IS_WINDOW (window));
2004 priv = gtk_window_get_private (window);
2006 setting = setting != FALSE;
2008 if (priv->skips_taskbar != setting)
2010 priv->skips_taskbar = setting;
2011 if (GTK_WIDGET_REALIZED (window))
2012 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
2013 priv->skips_taskbar);
2014 g_object_notify (G_OBJECT (window), "skip_taskbar_hint");
2019 * gtk_window_get_skip_taskbar_hint:
2020 * @window: a #GtkWindow
2022 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2024 * Return value: %TRUE if window shouldn't be in taskbar
2029 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2031 GtkWindowPrivate *priv;
2033 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2035 priv = gtk_window_get_private (window);
2037 return priv->skips_taskbar;
2041 * gtk_window_set_skip_pager_hint:
2042 * @window: a #GtkWindow
2043 * @setting: %TRUE to keep this window from appearing in the pager
2045 * Windows may set a hint asking the desktop environment not to display
2046 * the window in the pager. This function toggles this hint.
2047 * (A "pager" is any desktop navigation tool such as a workspace
2048 * switcher that displays a thumbnail representation of the windows
2054 gtk_window_set_skip_pager_hint (GtkWindow *window,
2057 GtkWindowPrivate *priv;
2059 g_return_if_fail (GTK_IS_WINDOW (window));
2061 priv = gtk_window_get_private (window);
2063 setting = setting != FALSE;
2065 if (priv->skips_pager != setting)
2067 priv->skips_pager = setting;
2068 if (GTK_WIDGET_REALIZED (window))
2069 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2071 g_object_notify (G_OBJECT (window), "skip_pager_hint");
2076 * gtk_window_get_skip_pager_hint:
2077 * @window: a #GtkWindow
2079 * Gets the value set by gtk_window_set_skip_pager_hint().
2081 * Return value: %TRUE if window shouldn't be in pager
2086 gtk_window_get_skip_pager_hint (GtkWindow *window)
2088 GtkWindowPrivate *priv;
2090 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2092 priv = gtk_window_get_private (window);
2094 return priv->skips_pager;
2098 * gtk_window_set_destroy_with_parent:
2099 * @window: a #GtkWindow
2100 * @setting: whether to destroy @window with its transient parent
2102 * If @setting is %TRUE, then destroying the transient parent of @window
2103 * will also destroy @window itself. This is useful for dialogs that
2104 * shouldn't persist beyond the lifetime of the main window they're
2105 * associated with, for example.
2108 gtk_window_set_destroy_with_parent (GtkWindow *window,
2111 g_return_if_fail (GTK_IS_WINDOW (window));
2113 if (window->destroy_with_parent == (setting != FALSE))
2116 if (window->destroy_with_parent)
2118 disconnect_parent_destroyed (window);
2122 connect_parent_destroyed (window);
2125 window->destroy_with_parent = setting;
2127 g_object_notify (G_OBJECT (window), "destroy_with_parent");
2131 * gtk_window_get_destroy_with_parent:
2132 * @window: a #GtkWindow
2134 * Returns whether the window will be destroyed with its transient parent. See
2135 * gtk_window_set_destroy_with_parent ().
2137 * Return value: %TRUE if the window will be destroyed with its transient parent.
2140 gtk_window_get_destroy_with_parent (GtkWindow *window)
2142 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2144 return window->destroy_with_parent;
2147 static GtkWindowGeometryInfo*
2148 gtk_window_get_geometry_info (GtkWindow *window,
2151 GtkWindowGeometryInfo *info;
2153 info = window->geometry_info;
2154 if (!info && create)
2156 info = g_new0 (GtkWindowGeometryInfo, 1);
2158 info->default_width = -1;
2159 info->default_height = -1;
2160 info->resize_width = -1;
2161 info->resize_height = -1;
2162 info->initial_x = 0;
2163 info->initial_y = 0;
2164 info->initial_pos_set = FALSE;
2165 info->default_is_geometry = FALSE;
2166 info->position_constraints_changed = FALSE;
2167 info->last.configure_request.x = 0;
2168 info->last.configure_request.y = 0;
2169 info->last.configure_request.width = -1;
2170 info->last.configure_request.height = -1;
2171 info->widget = NULL;
2173 window->geometry_info = info;
2180 * gtk_window_set_geometry_hints:
2181 * @window: a #GtkWindow
2182 * @geometry_widget: widget the geometry hints will be applied to
2183 * @geometry: struct containing geometry information
2184 * @geom_mask: mask indicating which struct fields should be paid attention to
2186 * This function sets up hints about how a window can be resized by
2187 * the user. You can set a minimum and maximum size; allowed resize
2188 * increments (e.g. for xterm, you can only resize by the size of a
2189 * character); aspect ratios; and more. See the #GdkGeometry struct.
2193 gtk_window_set_geometry_hints (GtkWindow *window,
2194 GtkWidget *geometry_widget,
2195 GdkGeometry *geometry,
2196 GdkWindowHints geom_mask)
2198 GtkWindowGeometryInfo *info;
2200 g_return_if_fail (GTK_IS_WINDOW (window));
2201 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2203 info = gtk_window_get_geometry_info (window, TRUE);
2206 g_signal_handlers_disconnect_by_func (info->widget,
2207 gtk_widget_destroyed,
2210 info->widget = geometry_widget;
2212 g_signal_connect (geometry_widget, "destroy",
2213 G_CALLBACK (gtk_widget_destroyed),
2217 info->geometry = *geometry;
2219 /* We store gravity in window->gravity not in the hints. */
2220 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2222 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2224 gtk_window_set_gravity (window, geometry->win_gravity);
2227 gtk_widget_queue_resize (GTK_WIDGET (window));
2231 * gtk_window_set_decorated:
2232 * @window: a #GtkWindow
2233 * @setting: %TRUE to decorate the window
2235 * By default, windows are decorated with a title bar, resize
2236 * controls, etc. Some <link linkend="gtk-X11-arch">window
2237 * managers</link> allow GTK+ to disable these decorations, creating a
2238 * borderless window. If you set the decorated property to %FALSE
2239 * using this function, GTK+ will do its best to convince the window
2240 * manager not to decorate the window. Depending on the system, this
2241 * function may not have any effect when called on a window that is
2242 * already visible, so you should call it before calling gtk_window_show().
2244 * On Windows, this function always works, since there's no window manager
2249 gtk_window_set_decorated (GtkWindow *window,
2252 g_return_if_fail (GTK_IS_WINDOW (window));
2254 setting = setting != FALSE;
2256 if (setting == window->decorated)
2259 window->decorated = setting;
2261 if (GTK_WIDGET (window)->window)
2263 if (window->decorated)
2264 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2267 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2271 g_object_notify (G_OBJECT (window), "decorated");
2275 * gtk_window_get_decorated:
2276 * @window: a #GtkWindow
2278 * Returns whether the window has been set to have decorations
2279 * such as a title bar via gtk_window_set_decorated().
2281 * Return value: %TRUE if the window has been set to have decorations
2284 gtk_window_get_decorated (GtkWindow *window)
2286 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2288 return window->decorated;
2291 static GtkWindowIconInfo*
2292 get_icon_info (GtkWindow *window)
2294 return g_object_get_data (G_OBJECT (window),
2295 "gtk-window-icon-info");
2298 static GtkWindowIconInfo*
2299 ensure_icon_info (GtkWindow *window)
2301 GtkWindowIconInfo *info;
2303 info = get_icon_info (window);
2307 info = g_new0 (GtkWindowIconInfo, 1);
2308 g_object_set_data_full (G_OBJECT (window),
2309 "gtk-window-icon-info",
2324 get_screen_icon_info (GdkScreen *screen)
2326 ScreenIconInfo *info = g_object_get_data (G_OBJECT (screen),
2327 "gtk-window-default-icon-pixmap");
2330 info = g_new0 (ScreenIconInfo, 1);
2331 g_object_set_data (G_OBJECT (screen), "gtk-window-default-icon-pixmap", info);
2334 if (info->serial != default_icon_serial)
2338 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2339 info->pixmap = NULL;
2344 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2348 info->serial = default_icon_serial;
2355 get_pixmap_and_mask (GdkWindow *window,
2356 GtkWindowIconInfo *parent_info,
2357 gboolean is_default_list,
2359 GdkPixmap **pmap_return,
2360 GdkBitmap **mask_return)
2362 GdkScreen *screen = gdk_drawable_get_screen (window);
2363 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2364 GdkPixbuf *best_icon;
2368 *pmap_return = NULL;
2369 *mask_return = NULL;
2371 if (is_default_list &&
2372 default_icon_info->pixmap != NULL)
2374 /* Use shared icon pixmap for all windows on this screen.
2376 if (default_icon_info->pixmap)
2377 g_object_ref (default_icon_info->pixmap);
2378 if (default_icon_info->mask)
2379 g_object_ref (default_icon_info->mask);
2381 *pmap_return = default_icon_info->pixmap;
2382 *mask_return = default_icon_info->mask;
2384 else if (parent_info && parent_info->icon_pixmap)
2386 if (parent_info->icon_pixmap)
2387 g_object_ref (parent_info->icon_pixmap);
2388 if (parent_info->icon_mask)
2389 g_object_ref (parent_info->icon_mask);
2391 *pmap_return = parent_info->icon_pixmap;
2392 *mask_return = parent_info->icon_mask;
2396 #define IDEAL_SIZE 48
2398 best_size = G_MAXINT;
2400 tmp_list = icon_list;
2401 while (tmp_list != NULL)
2403 GdkPixbuf *pixbuf = tmp_list->data;
2406 /* average width and height - if someone passes in a rectangular
2407 * icon they deserve what they get.
2409 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2412 if (best_icon == NULL)
2419 /* icon is better if it's 32 pixels or larger, and closer to
2420 * the ideal size than the current best.
2423 (ABS (best_size - IDEAL_SIZE) <
2424 ABS (this - IDEAL_SIZE)))
2431 tmp_list = tmp_list->next;
2435 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2436 gdk_screen_get_system_colormap (screen),
2441 /* Save pmap/mask for others to use if appropriate */
2444 parent_info->icon_pixmap = *pmap_return;
2445 parent_info->icon_mask = *mask_return;
2447 if (parent_info->icon_pixmap)
2448 g_object_ref (parent_info->icon_pixmap);
2449 if (parent_info->icon_mask)
2450 g_object_ref (parent_info->icon_mask);
2452 else if (is_default_list)
2454 default_icon_info->pixmap = *pmap_return;
2455 default_icon_info->mask = *mask_return;
2457 if (default_icon_info->pixmap)
2458 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2459 (gpointer*)&default_icon_info->pixmap);
2460 if (default_icon_info->mask)
2461 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2462 (gpointer*)&default_icon_info->mask);
2468 gtk_window_realize_icon (GtkWindow *window)
2471 GtkWindowIconInfo *info;
2474 widget = GTK_WIDGET (window);
2476 g_return_if_fail (widget->window != NULL);
2478 /* no point setting an icon on override-redirect */
2479 if (window->type == GTK_WINDOW_POPUP)
2484 info = ensure_icon_info (window);
2489 g_return_if_fail (info->icon_pixmap == NULL);
2490 g_return_if_fail (info->icon_mask == NULL);
2492 info->using_default_icon = FALSE;
2493 info->using_parent_icon = FALSE;
2495 icon_list = info->icon_list;
2497 /* Inherit from transient parent */
2498 if (icon_list == NULL && window->transient_parent)
2500 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2502 info->using_parent_icon = TRUE;
2505 /* Inherit from default */
2506 if (icon_list == NULL)
2508 icon_list = default_icon_list;
2510 info->using_default_icon = TRUE;
2513 gdk_window_set_icon_list (widget->window, icon_list);
2515 get_pixmap_and_mask (widget->window,
2516 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2517 info->using_default_icon,
2522 /* This is a slight ICCCM violation since it's a color pixmap not
2523 * a bitmap, but everyone does it.
2525 gdk_window_set_icon (widget->window,
2530 info->realized = TRUE;
2534 gtk_window_unrealize_icon (GtkWindow *window)
2536 GtkWindowIconInfo *info;
2539 widget = GTK_WIDGET (window);
2541 info = get_icon_info (window);
2546 if (info->icon_pixmap)
2547 g_object_unref (info->icon_pixmap);
2549 if (info->icon_mask)
2550 g_object_unref (info->icon_mask);
2552 info->icon_pixmap = NULL;
2553 info->icon_mask = NULL;
2555 /* We don't clear the properties on the window, just figure the
2556 * window is going away.
2559 info->realized = FALSE;
2563 * gtk_window_set_icon_list:
2564 * @window: a #GtkWindow
2565 * @list: list of #GdkPixbuf
2567 * Sets up the icon representing a #GtkWindow. The icon is used when
2568 * the window is minimized (also known as iconified). Some window
2569 * managers or desktop environments may also place it in the window
2570 * frame, or display it in other contexts.
2572 * gtk_window_set_icon_list() allows you to pass in the same icon in
2573 * several hand-drawn sizes. The list should contain the natural sizes
2574 * your icon is available in; that is, don't scale the image before
2575 * passing it to GTK+. Scaling is postponed until the last minute,
2576 * when the desired final size is known, to allow best quality.
2578 * By passing several sizes, you may improve the final image quality
2579 * of the icon, by reducing or eliminating automatic image scaling.
2581 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2582 * larger images (64x64, 128x128) if you have them.
2584 * See also gtk_window_set_default_icon_list() to set the icon
2585 * for all windows in your application in one go.
2587 * Note that transient windows (those who have been set transient for another
2588 * window using gtk_window_set_transient_for()) will inherit their
2589 * icon from their transient parent. So there's no need to explicitly
2590 * set the icon on transient windows.
2593 gtk_window_set_icon_list (GtkWindow *window,
2596 GtkWindowIconInfo *info;
2598 g_return_if_fail (GTK_IS_WINDOW (window));
2600 info = ensure_icon_info (window);
2602 if (info->icon_list == list) /* check for NULL mostly */
2605 g_list_foreach (info->icon_list,
2606 (GFunc) g_object_unref, NULL);
2608 g_list_free (info->icon_list);
2610 info->icon_list = g_list_copy (list);
2611 g_list_foreach (info->icon_list,
2612 (GFunc) g_object_ref, NULL);
2614 g_object_notify (G_OBJECT (window), "icon");
2616 gtk_window_unrealize_icon (window);
2618 if (GTK_WIDGET_REALIZED (window))
2619 gtk_window_realize_icon (window);
2621 /* We could try to update our transient children, but I don't think
2622 * it's really worth it. If we did it, the best way would probably
2623 * be to have children connect to notify::icon_list
2628 * gtk_window_get_icon_list:
2629 * @window: a #GtkWindow
2631 * Retrieves the list of icons set by gtk_window_set_icon_list().
2632 * The list is copied, but the reference count on each
2633 * member won't be incremented.
2635 * Return value: copy of window's icon list
2638 gtk_window_get_icon_list (GtkWindow *window)
2640 GtkWindowIconInfo *info;
2642 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2644 info = get_icon_info (window);
2647 return g_list_copy (info->icon_list);
2653 * gtk_window_set_icon:
2654 * @window: a #GtkWindow
2655 * @icon: icon image, or %NULL
2657 * Sets up the icon representing a #GtkWindow. This icon is used when
2658 * the window is minimized (also known as iconified). Some window
2659 * managers or desktop environments may also place it in the window
2660 * frame, or display it in other contexts.
2662 * The icon should be provided in whatever size it was naturally
2663 * drawn; that is, don't scale the image before passing it to
2664 * GTK+. Scaling is postponed until the last minute, when the desired
2665 * final size is known, to allow best quality.
2667 * If you have your icon hand-drawn in multiple sizes, use
2668 * gtk_window_set_icon_list(). Then the best size will be used.
2670 * This function is equivalent to calling gtk_window_set_icon_list()
2671 * with a 1-element list.
2673 * See also gtk_window_set_default_icon_list() to set the icon
2674 * for all windows in your application in one go.
2677 gtk_window_set_icon (GtkWindow *window,
2682 g_return_if_fail (GTK_IS_WINDOW (window));
2683 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2688 list = g_list_append (list, icon);
2690 gtk_window_set_icon_list (window, list);
2695 * gtk_window_get_icon:
2696 * @window: a #GtkWindow
2698 * Gets the value set by gtk_window_set_icon() (or if you've
2699 * called gtk_window_set_icon_list(), gets the first icon in
2702 * Return value: icon for window
2705 gtk_window_get_icon (GtkWindow *window)
2707 GtkWindowIconInfo *info;
2709 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2711 info = get_icon_info (window);
2712 if (info && info->icon_list)
2713 return GDK_PIXBUF (info->icon_list->data);
2718 /* Load pixbuf, printing warning on failure if error == NULL
2721 load_pixbuf_verbosely (const char *filename,
2724 GError *local_err = NULL;
2727 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
2735 g_warning ("Error loading icon from file '%s':\n\t%s",
2736 filename, local_err->message);
2737 g_error_free (local_err);
2745 * gtk_window_set_icon_from_file:
2746 * @window: a #GtkWindow
2747 * @filename: location of icon file
2748 * @err: location to store error, or %NULL.
2750 * Sets the icon for @window.
2751 * Warns on failure if @err is %NULL.
2753 * This function is equivalent to calling gtk_window_set_icon()
2754 * with a pixbuf created by loading the image from @filename.
2756 * Returns: %TRUE if setting the icon succeeded.
2761 gtk_window_set_icon_from_file (GtkWindow *window,
2762 const gchar *filename,
2765 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2769 gtk_window_set_icon (window, pixbuf);
2770 g_object_unref (pixbuf);
2779 * gtk_window_set_default_icon_list:
2780 * @list: a list of #GdkPixbuf
2782 * Sets an icon list to be used as fallback for windows that haven't
2783 * had gtk_window_set_icon_list() called on them to set up a
2784 * window-specific icon list. This function allows you to set up the
2785 * icon for all windows in your app at once.
2787 * See gtk_window_set_icon_list() for more details.
2791 gtk_window_set_default_icon_list (GList *list)
2795 if (list == default_icon_list)
2798 /* Update serial so we don't used cached pixmaps/masks
2800 default_icon_serial++;
2802 g_list_foreach (default_icon_list,
2803 (GFunc) g_object_unref, NULL);
2805 g_list_free (default_icon_list);
2807 default_icon_list = g_list_copy (list);
2808 g_list_foreach (default_icon_list,
2809 (GFunc) g_object_ref, NULL);
2811 /* Update all toplevels */
2812 toplevels = gtk_window_list_toplevels ();
2813 tmp_list = toplevels;
2814 while (tmp_list != NULL)
2816 GtkWindowIconInfo *info;
2817 GtkWindow *w = tmp_list->data;
2819 info = get_icon_info (w);
2820 if (info && info->using_default_icon)
2822 gtk_window_unrealize_icon (w);
2823 if (GTK_WIDGET_REALIZED (w))
2824 gtk_window_realize_icon (w);
2827 tmp_list = tmp_list->next;
2829 g_list_free (toplevels);
2833 * gtk_window_set_default_icon:
2836 * Sets an icon to be used as fallback for windows that haven't
2837 * had gtk_window_set_icon() called on them from a pixbuf.
2842 gtk_window_set_default_icon (GdkPixbuf *icon)
2846 g_return_if_fail (GDK_IS_PIXBUF (icon));
2848 list = g_list_prepend (NULL, icon);
2849 gtk_window_set_default_icon_list (list);
2854 * gtk_window_set_default_icon_from_file:
2855 * @filename: location of icon file
2856 * @err: location to store error, or %NULL.
2858 * Sets an icon to be used as fallback for windows that haven't
2859 * had gtk_window_set_icon_list() called on them from a file
2860 * on disk. Warns on failure if @err is %NULL.
2862 * Returns: %TRUE if setting the icon succeeded.
2867 gtk_window_set_default_icon_from_file (const gchar *filename,
2870 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2874 gtk_window_set_default_icon (pixbuf);
2875 g_object_unref (pixbuf);
2884 * gtk_window_get_default_icon_list:
2886 * Gets the value set by gtk_window_set_default_icon_list().
2887 * The list is a copy and should be freed with g_list_free(),
2888 * but the pixbufs in the list have not had their reference count
2891 * Return value: copy of default icon list
2894 gtk_window_get_default_icon_list (void)
2896 return g_list_copy (default_icon_list);
2900 gtk_window_set_default_size_internal (GtkWindow *window,
2901 gboolean change_width,
2903 gboolean change_height,
2905 gboolean is_geometry)
2907 GtkWindowGeometryInfo *info;
2909 g_return_if_fail (change_width == FALSE || width >= -1);
2910 g_return_if_fail (change_height == FALSE || height >= -1);
2912 info = gtk_window_get_geometry_info (window, TRUE);
2914 g_object_freeze_notify (G_OBJECT (window));
2916 info->default_is_geometry = is_geometry != FALSE;
2926 info->default_width = width;
2928 g_object_notify (G_OBJECT (window), "default_width");
2939 info->default_height = height;
2941 g_object_notify (G_OBJECT (window), "default_height");
2944 g_object_thaw_notify (G_OBJECT (window));
2946 gtk_widget_queue_resize (GTK_WIDGET (window));
2950 * gtk_window_set_default_size:
2951 * @window: a #GtkWindow
2952 * @width: width in pixels, or -1 to unset the default width
2953 * @height: height in pixels, or -1 to unset the default height
2955 * Sets the default size of a window. If the window's "natural" size
2956 * (its size request) is larger than the default, the default will be
2957 * ignored. More generally, if the default size does not obey the
2958 * geometry hints for the window (gtk_window_set_geometry_hints() can
2959 * be used to set these explicitly), the default size will be clamped
2960 * to the nearest permitted size.
2962 * Unlike gtk_widget_set_size_request(), which sets a size request for
2963 * a widget and thus would keep users from shrinking the window, this
2964 * function only sets the initial size, just as if the user had
2965 * resized the window themselves. Users can still shrink the window
2966 * again as they normally would. Setting a default size of -1 means to
2967 * use the "natural" default size (the size request of the window).
2969 * For more control over a window's initial size and how resizing works,
2970 * investigate gtk_window_set_geometry_hints().
2972 * For some uses, gtk_window_resize() is a more appropriate function.
2973 * gtk_window_resize() changes the current size of the window, rather
2974 * than the size to be used on initial display. gtk_window_resize() always
2975 * affects the window itself, not the geometry widget.
2977 * The default size of a window only affects the first time a window is
2978 * shown; if a window is hidden and re-shown, it will remember the size
2979 * it had prior to hiding, rather than using the default size.
2981 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2982 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2985 gtk_window_set_default_size (GtkWindow *window,
2989 g_return_if_fail (GTK_IS_WINDOW (window));
2990 g_return_if_fail (width >= -1);
2991 g_return_if_fail (height >= -1);
2993 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
2997 * gtk_window_get_default_size:
2998 * @window: a #GtkWindow
2999 * @width: location to store the default width, or %NULL
3000 * @height: location to store the default height, or %NULL
3002 * Gets the default size of the window. A value of -1 for the width or
3003 * height indicates that a default size has not been explicitly set
3004 * for that dimension, so the "natural" size of the window will be
3009 gtk_window_get_default_size (GtkWindow *window,
3013 GtkWindowGeometryInfo *info;
3015 g_return_if_fail (GTK_IS_WINDOW (window));
3017 info = gtk_window_get_geometry_info (window, FALSE);
3020 *width = info ? info->default_width : -1;
3023 *height = info ? info->default_height : -1;
3027 * gtk_window_resize:
3028 * @window: a #GtkWindow
3029 * @width: width in pixels to resize the window to
3030 * @height: height in pixels to resize the window to
3032 * Resizes the window as if the user had done so, obeying geometry
3033 * constraints. The default geometry constraint is that windows may
3034 * not be smaller than their size request; to override this
3035 * constraint, call gtk_widget_set_size_request() to set the window's
3036 * request to a smaller value.
3038 * If gtk_window_resize() is called before showing a window for the
3039 * first time, it overrides any default size set with
3040 * gtk_window_set_default_size().
3042 * Windows may not be resized smaller than 1 by 1 pixels.
3046 gtk_window_resize (GtkWindow *window,
3050 GtkWindowGeometryInfo *info;
3052 g_return_if_fail (GTK_IS_WINDOW (window));
3053 g_return_if_fail (width > 0);
3054 g_return_if_fail (height > 0);
3056 info = gtk_window_get_geometry_info (window, TRUE);
3058 info->resize_width = width;
3059 info->resize_height = height;
3061 gtk_widget_queue_resize (GTK_WIDGET (window));
3065 * gtk_window_get_size:
3066 * @window: a #GtkWindow
3067 * @width: return location for width, or %NULL
3068 * @height: return location for height, or %NULL
3070 * Obtains the current size of @window. If @window is not onscreen,
3071 * it returns the size GTK+ will suggest to the <link
3072 * linkend="gtk-X11-arch">window manager</link> for the initial window
3073 * size (but this is not reliably the same as the size the window
3074 * manager will actually select). The size obtained by
3075 * gtk_window_get_size() is the last size received in a
3076 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
3077 * rather than querying the X server for the size. As a result, if you
3078 * call gtk_window_resize() then immediately call
3079 * gtk_window_get_size(), the size won't have taken effect yet. After
3080 * the window manager processes the resize request, GTK+ receives
3081 * notification that the size has changed via a configure event, and
3082 * the size of the window gets updated.
3084 * Note 1: Nearly any use of this function creates a race condition,
3085 * because the size of the window may change between the time that you
3086 * get the size and the time that you perform some action assuming
3087 * that size is the current size. To avoid race conditions, connect to
3088 * "configure_event" on the window and adjust your size-dependent
3089 * state to match the size delivered in the #GdkEventConfigure.
3091 * Note 2: The returned size does <emphasis>not</emphasis> include the
3092 * size of the window manager decorations (aka the window frame or
3093 * border). Those are not drawn by GTK+ and GTK+ has no reliable
3094 * method of determining their size.
3096 * Note 3: If you are getting a window size in order to position
3097 * the window onscreen, there may be a better way. The preferred
3098 * way is to simply set the window's semantic type with
3099 * gtk_window_set_type_hint(), which allows the window manager to
3100 * e.g. center dialogs. Also, if you set the transient parent of
3101 * dialogs with gtk_window_set_transient_for() window managers
3102 * will often center the dialog over its parent window. It's
3103 * much preferred to let the window manager handle these
3104 * things rather than doing it yourself, because all apps will
3105 * behave consistently and according to user prefs if the window
3106 * manager handles it. Also, the window manager can take the size
3107 * of the window decorations/border into account, while your
3108 * application cannot.
3110 * In any case, if you insist on application-specified window
3111 * positioning, there's <emphasis>still</emphasis> a better way than
3112 * doing it yourself - gtk_window_set_position() will frequently
3113 * handle the details for you.
3117 gtk_window_get_size (GtkWindow *window,
3124 g_return_if_fail (GTK_IS_WINDOW (window));
3126 widget = GTK_WIDGET (window);
3128 if (width == NULL && height == NULL)
3131 if (GTK_WIDGET_MAPPED (window))
3133 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3138 GdkRectangle configure_request;
3140 gtk_window_compute_configure_request (window,
3144 w = configure_request.width;
3145 h = configure_request.height;
3156 * @window: a #GtkWindow
3157 * @x: X coordinate to move window to
3158 * @y: Y coordinate to move window to
3160 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3161 * @window to the given position. Window managers are free to ignore
3162 * this; most window managers ignore requests for initial window
3163 * positions (instead using a user-defined placement algorithm) and
3164 * honor requests after the window has already been shown.
3166 * Note: the position is the position of the gravity-determined
3167 * reference point for the window. The gravity determines two things:
3168 * first, the location of the reference point in root window
3169 * coordinates; and second, which point on the window is positioned at
3170 * the reference point.
3172 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3173 * point is simply the @x, @y supplied to gtk_window_move(). The
3174 * top-left corner of the window decorations (aka window frame or
3175 * border) will be placed at @x, @y. Therefore, to position a window
3176 * at the top left of the screen, you want to use the default gravity
3177 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3179 * To position a window at the bottom right corner of the screen, you
3180 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3181 * point is at @x + the window width and @y + the window height, and
3182 * the bottom-right corner of the window border will be placed at that
3183 * reference point. So, to place a window in the bottom right corner
3184 * you would first set gravity to south east, then write:
3185 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3186 * gdk_screen_height () - window_height)</literal>.
3188 * The Extended Window Manager Hints specification at <ulink
3189 * url="http://www.freedesktop.org/standards/wm-spec.html">
3190 * http://www.freedesktop.org/standards/wm-spec.html</ulink> has a
3191 * nice table of gravities in the "implementation notes" section.
3193 * The gtk_window_get_position() documentation may also be relevant.
3197 gtk_window_move (GtkWindow *window,
3201 GtkWindowGeometryInfo *info;
3204 g_return_if_fail (GTK_IS_WINDOW (window));
3206 widget = GTK_WIDGET (window);
3208 info = gtk_window_get_geometry_info (window, TRUE);
3210 if (GTK_WIDGET_MAPPED (window))
3212 /* we have now sent a request with this position
3213 * with currently-active constraints, so toggle flag.
3215 info->position_constraints_changed = FALSE;
3217 /* we only constrain if mapped - if not mapped,
3218 * then gtk_window_compute_configure_request()
3219 * will apply the constraints later, and we
3220 * don't want to lose information about
3221 * what position the user set before then.
3222 * i.e. if you do a move() then turn off POS_CENTER
3223 * then show the window, your move() will work.
3225 gtk_window_constrain_position (window,
3226 widget->allocation.width,
3227 widget->allocation.height,
3230 /* Note that this request doesn't go through our standard request
3231 * framework, e.g. doesn't increment configure_request_count,
3232 * doesn't set info->last, etc.; that's because
3233 * we don't save the info needed to arrive at this same request
3236 * To gtk_window_move_resize(), this will end up looking exactly
3237 * the same as the position being changed by the window
3241 /* FIXME are we handling gravity properly for framed windows? */
3243 gdk_window_move (window->frame,
3244 x - window->frame_left,
3245 y - window->frame_top);
3247 gdk_window_move (GTK_WIDGET (window)->window,
3252 /* Save this position to apply on mapping */
3253 info->initial_x = x;
3254 info->initial_y = y;
3255 info->initial_pos_set = TRUE;
3260 * gtk_window_get_position:
3261 * @window: a #GtkWindow
3262 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3263 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3265 * This function returns the position you need to pass to
3266 * gtk_window_move() to keep @window in its current position. This
3267 * means that the meaning of the returned value varies with window
3268 * gravity. See gtk_window_move() for more details.
3270 * If you haven't changed the window gravity, its gravity will be
3271 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3272 * gets the position of the top-left corner of the window manager
3273 * frame for the window. gtk_window_move() sets the position of this
3274 * same top-left corner.
3276 * gtk_window_get_position() is not 100% reliable because the X Window System
3277 * does not specify a way to obtain the geometry of the
3278 * decorations placed on a window by the window manager.
3279 * Thus GTK+ is using a "best guess" that works with most
3282 * Moreover, nearly all window managers are historically broken with
3283 * respect to their handling of window gravity. So moving a window to
3284 * its current position as returned by gtk_window_get_position() tends
3285 * to result in moving the window slightly. Window managers are
3286 * slowly getting better over time.
3288 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3289 * frame is not relevant, and thus gtk_window_get_position() will
3290 * always produce accurate results. However you can't use static
3291 * gravity to do things like place a window in a corner of the screen,
3292 * because static gravity ignores the window manager decorations.
3294 * If you are saving and restoring your application's window
3295 * positions, you should know that it's impossible for applications to
3296 * do this without getting it somewhat wrong because applications do
3297 * not have sufficient knowledge of window manager state. The Correct
3298 * Mechanism is to support the session management protocol (see the
3299 * "GnomeClient" object in the GNOME libraries for example) and allow
3300 * the window manager to save your window sizes and positions.
3305 gtk_window_get_position (GtkWindow *window,
3311 g_return_if_fail (GTK_IS_WINDOW (window));
3313 widget = GTK_WIDGET (window);
3315 if (window->gravity == GDK_GRAVITY_STATIC)
3317 if (GTK_WIDGET_MAPPED (widget))
3319 /* This does a server round-trip, which is sort of wrong;
3320 * but a server round-trip is inevitable for
3321 * gdk_window_get_frame_extents() in the usual
3322 * NorthWestGravity case below, so not sure what else to
3323 * do. We should likely be consistent about whether we get
3324 * the client-side info or the server-side info.
3326 gdk_window_get_origin (widget->window, root_x, root_y);
3330 GdkRectangle configure_request;
3332 gtk_window_compute_configure_request (window,
3336 *root_x = configure_request.x;
3337 *root_y = configure_request.y;
3342 GdkRectangle frame_extents;
3347 if (GTK_WIDGET_MAPPED (widget))
3350 gdk_window_get_frame_extents (window->frame, &frame_extents);
3352 gdk_window_get_frame_extents (widget->window, &frame_extents);
3353 x = frame_extents.x;
3354 y = frame_extents.y;
3355 gtk_window_get_size (window, &w, &h);
3359 /* We just say the frame has 0 size on all sides.
3360 * Not sure what else to do.
3362 gtk_window_compute_configure_request (window,
3365 x = frame_extents.x;
3366 y = frame_extents.y;
3367 w = frame_extents.width;
3368 h = frame_extents.height;
3371 switch (window->gravity)
3373 case GDK_GRAVITY_NORTH:
3374 case GDK_GRAVITY_CENTER:
3375 case GDK_GRAVITY_SOUTH:
3376 /* Find center of frame. */
3377 x += frame_extents.width / 2;
3378 /* Center client window on that point. */
3382 case GDK_GRAVITY_SOUTH_EAST:
3383 case GDK_GRAVITY_EAST:
3384 case GDK_GRAVITY_NORTH_EAST:
3385 /* Find right edge of frame */
3386 x += frame_extents.width;
3387 /* Align left edge of client at that point. */
3394 switch (window->gravity)
3396 case GDK_GRAVITY_WEST:
3397 case GDK_GRAVITY_CENTER:
3398 case GDK_GRAVITY_EAST:
3399 /* Find center of frame. */
3400 y += frame_extents.height / 2;
3401 /* Center client window there. */
3404 case GDK_GRAVITY_SOUTH_WEST:
3405 case GDK_GRAVITY_SOUTH:
3406 case GDK_GRAVITY_SOUTH_EAST:
3407 /* Find south edge of frame */
3408 y += frame_extents.height;
3409 /* Place bottom edge of client there */
3424 * gtk_window_reshow_with_initial_size:
3425 * @window: a #GtkWindow
3427 * Hides @window, then reshows it, resetting the
3428 * default size and position of the window. Used
3429 * by GUI builders only.
3432 gtk_window_reshow_with_initial_size (GtkWindow *window)
3436 g_return_if_fail (GTK_IS_WINDOW (window));
3438 widget = GTK_WIDGET (window);
3440 gtk_widget_hide (widget);
3441 gtk_widget_unrealize (widget);
3442 gtk_widget_show (widget);
3446 gtk_window_destroy (GtkObject *object)
3448 GtkWindow *window = GTK_WINDOW (object);
3450 if (window->transient_parent)
3451 gtk_window_set_transient_for (window, NULL);
3453 /* frees the icons */
3454 gtk_window_set_icon_list (window, NULL);
3456 if (window->has_user_ref_count)
3458 window->has_user_ref_count = FALSE;
3459 g_object_unref (window);
3463 gtk_window_group_remove_window (window->group, window);
3465 gtk_window_free_key_hash (window);
3467 GTK_OBJECT_CLASS (parent_class)->destroy (object);
3471 gtk_window_mnemonic_hash_remove (gpointer key,
3475 GtkWindowMnemonic *mnemonic = key;
3476 GtkWindow *window = user;
3478 if (mnemonic->window == window)
3480 if (mnemonic->targets)
3482 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
3484 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
3485 name, mnemonic->targets->data);
3488 g_slist_free (mnemonic->targets);
3497 gtk_window_private_finalize (GtkWindowPrivate *priv)
3504 gtk_window_finalize (GObject *object)
3506 GtkWindow *window = GTK_WINDOW (object);
3508 toplevel_list = g_slist_remove (toplevel_list, window);
3510 g_free (window->title);
3511 g_free (window->wmclass_name);
3512 g_free (window->wmclass_class);
3513 g_free (window->wm_role);
3515 g_hash_table_foreach_remove (mnemonic_hash_table,
3516 gtk_window_mnemonic_hash_remove,
3518 if (window->geometry_info)
3520 if (window->geometry_info->widget)
3521 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3522 gtk_widget_destroyed,
3523 &window->geometry_info->widget);
3524 g_free (window->geometry_info);
3527 if (window->keys_changed_handler)
3529 g_source_remove (window->keys_changed_handler);
3530 window->keys_changed_handler = 0;
3533 G_OBJECT_CLASS (parent_class)->finalize (object);
3537 gtk_window_show (GtkWidget *widget)
3539 GtkWindow *window = GTK_WINDOW (widget);
3540 GtkContainer *container = GTK_CONTAINER (window);
3541 gboolean need_resize;
3543 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3545 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3546 container->need_resize = FALSE;
3550 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3551 GtkAllocation allocation = { 0, 0 };
3552 GdkRectangle configure_request;
3553 GdkGeometry new_geometry;
3555 gboolean was_realized;
3557 /* We are going to go ahead and perform this configure request
3558 * and then emulate a configure notify by going ahead and
3559 * doing a size allocate. Sort of a synchronous
3560 * mini-copy of gtk_window_move_resize() here.
3562 gtk_window_compute_configure_request (window,
3567 /* We update this because we are going to go ahead
3568 * and gdk_window_resize() below, rather than
3571 info->last.configure_request.width = configure_request.width;
3572 info->last.configure_request.height = configure_request.height;
3574 /* and allocate the window - this is normally done
3575 * in move_resize in response to configure notify
3577 allocation.width = configure_request.width;
3578 allocation.height = configure_request.height;
3579 gtk_widget_size_allocate (widget, &allocation);
3581 /* Then we guarantee we have a realize */
3582 was_realized = FALSE;
3583 if (!GTK_WIDGET_REALIZED (widget))
3585 gtk_widget_realize (widget);
3586 was_realized = TRUE;
3589 /* Must be done after the windows are realized,
3590 * so that the decorations can be read
3592 gtk_decorated_window_calculate_frame_size (window);
3594 /* We only send configure request if we didn't just finish
3595 * creating the window; if we just created the window
3596 * then we created it with widget->allocation anyhow.
3599 gdk_window_resize (widget->window,
3600 configure_request.width,
3601 configure_request.height);
3604 gtk_container_check_resize (container);
3606 gtk_widget_map (widget);
3608 /* Try to make sure that we have some focused widget
3610 #ifdef GDK_WINDOWING_X11
3611 if (!window->focus_widget && !GTK_IS_PLUG (window))
3613 if (!window->focus_widget)
3615 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
3618 gtk_grab_add (widget);
3622 gtk_window_hide (GtkWidget *widget)
3624 GtkWindow *window = GTK_WINDOW (widget);
3626 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3627 gtk_widget_unmap (widget);
3630 gtk_grab_remove (widget);
3634 gtk_window_map (GtkWidget *widget)
3636 GtkWindow *window = GTK_WINDOW (widget);
3637 GdkWindow *toplevel;
3638 GtkWindowPrivate *priv;
3640 priv = gtk_window_get_private (window);
3642 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3644 if (window->bin.child &&
3645 GTK_WIDGET_VISIBLE (window->bin.child) &&
3646 !GTK_WIDGET_MAPPED (window->bin.child))
3647 gtk_widget_map (window->bin.child);
3650 toplevel = window->frame;
3652 toplevel = widget->window;
3654 if (window->maximize_initially)
3655 gdk_window_maximize (toplevel);
3657 gdk_window_unmaximize (toplevel);
3659 if (window->stick_initially)
3660 gdk_window_stick (toplevel);
3662 gdk_window_unstick (toplevel);
3664 if (window->iconify_initially)
3665 gdk_window_iconify (toplevel);
3667 gdk_window_deiconify (toplevel);
3669 if (priv->fullscreen_initially)
3670 gdk_window_fullscreen (toplevel);
3672 gdk_window_unfullscreen (toplevel);
3674 gdk_window_set_keep_above (toplevel, window->above_initially);
3676 gdk_window_set_keep_below (toplevel, window->below_initially);
3678 /* No longer use the default settings */
3679 window->need_default_size = FALSE;
3680 window->need_default_position = FALSE;
3682 gdk_window_show (widget->window);
3685 gdk_window_show (window->frame);
3687 if (!disable_startup_notification &&
3688 !sent_startup_notification)
3690 sent_startup_notification = TRUE;
3691 gdk_notify_startup_complete ();
3696 gtk_window_unmap (GtkWidget *widget)
3698 GtkWindow *window = GTK_WINDOW (widget);
3699 GtkWindowGeometryInfo *info;
3700 GdkWindowState state;
3702 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3704 gdk_window_withdraw (window->frame);
3706 gdk_window_withdraw (widget->window);
3708 window->configure_request_count = 0;
3709 window->configure_notify_received = FALSE;
3711 /* on unmap, we reset the default positioning of the window,
3712 * so it's placed again, but we don't reset the default
3713 * size of the window, so it's remembered.
3715 window->need_default_position = TRUE;
3717 info = gtk_window_get_geometry_info (window, FALSE);
3720 info->initial_pos_set = FALSE;
3721 info->position_constraints_changed = FALSE;
3724 state = gdk_window_get_state (widget->window);
3725 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
3726 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
3727 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
3728 window->above_initially = state & GDK_WINDOW_STATE_ABOVE;
3729 window->below_initially = state & GDK_WINDOW_STATE_BELOW;
3733 gtk_window_realize (GtkWidget *widget)
3736 GdkWindow *parent_window;
3737 GdkWindowAttr attributes;
3738 gint attributes_mask;
3740 window = GTK_WINDOW (widget);
3742 /* ensure widget tree is properly size allocated */
3743 if (widget->allocation.x == -1 &&
3744 widget->allocation.y == -1 &&
3745 widget->allocation.width == 1 &&
3746 widget->allocation.height == 1)
3748 GtkRequisition requisition;
3749 GtkAllocation allocation = { 0, 0, 200, 200 };
3751 gtk_widget_size_request (widget, &requisition);
3752 if (requisition.width || requisition.height)
3754 /* non-empty window */
3755 allocation.width = requisition.width;
3756 allocation.height = requisition.height;
3758 gtk_widget_size_allocate (widget, &allocation);
3760 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3762 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3765 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3767 switch (window->type)
3769 case GTK_WINDOW_TOPLEVEL:
3770 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3772 case GTK_WINDOW_POPUP:
3773 attributes.window_type = GDK_WINDOW_TEMP;
3776 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3780 attributes.title = window->title;
3781 attributes.wmclass_name = window->wmclass_name;
3782 attributes.wmclass_class = window->wmclass_class;
3783 attributes.wclass = GDK_INPUT_OUTPUT;
3784 attributes.visual = gtk_widget_get_visual (widget);
3785 attributes.colormap = gtk_widget_get_colormap (widget);
3787 if (window->has_frame)
3789 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3790 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3791 attributes.event_mask = (GDK_EXPOSURE_MASK |
3792 GDK_KEY_PRESS_MASK |
3793 GDK_ENTER_NOTIFY_MASK |
3794 GDK_LEAVE_NOTIFY_MASK |
3795 GDK_FOCUS_CHANGE_MASK |
3796 GDK_STRUCTURE_MASK |
3797 GDK_BUTTON_MOTION_MASK |
3798 GDK_POINTER_MOTION_HINT_MASK |
3799 GDK_BUTTON_PRESS_MASK |
3800 GDK_BUTTON_RELEASE_MASK);
3802 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3804 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
3805 &attributes, attributes_mask);
3807 gdk_window_set_user_data (window->frame, widget);
3809 attributes.window_type = GDK_WINDOW_CHILD;
3810 attributes.x = window->frame_left;
3811 attributes.y = window->frame_top;
3813 attributes_mask = GDK_WA_X | GDK_WA_Y;
3815 parent_window = window->frame;
3819 attributes_mask = 0;
3820 parent_window = gtk_widget_get_root_window (widget);
3823 attributes.width = widget->allocation.width;
3824 attributes.height = widget->allocation.height;
3825 attributes.event_mask = gtk_widget_get_events (widget);
3826 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3827 GDK_KEY_PRESS_MASK |
3828 GDK_KEY_RELEASE_MASK |
3829 GDK_ENTER_NOTIFY_MASK |
3830 GDK_LEAVE_NOTIFY_MASK |
3831 GDK_FOCUS_CHANGE_MASK |
3832 GDK_STRUCTURE_MASK);
3834 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3835 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3836 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3838 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3840 gdk_window_set_user_data (widget->window, window);
3842 widget->style = gtk_style_attach (widget->style, widget->window);
3843 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3845 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3847 /* This is a bad hack to set the window background. */
3848 gtk_window_paint (widget, NULL);
3850 if (window->transient_parent &&
3851 GTK_WIDGET_REALIZED (window->transient_parent))
3852 gdk_window_set_transient_for (widget->window,
3853 GTK_WIDGET (window->transient_parent)->window);
3855 if (window->wm_role)
3856 gdk_window_set_role (widget->window, window->wm_role);
3858 if (!window->decorated)
3859 gdk_window_set_decorations (widget->window, 0);
3861 gdk_window_set_type_hint (widget->window, window->type_hint);
3863 if (gtk_window_get_skip_pager_hint (window))
3865 g_print ("setting skip pager when realizing\n");
3866 gdk_window_set_skip_pager_hint (widget->window, TRUE);
3869 if (gtk_window_get_skip_taskbar_hint (window))
3870 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
3873 gdk_window_set_modal_hint (widget->window, TRUE);
3875 gdk_window_set_modal_hint (widget->window, FALSE);
3878 gtk_window_realize_icon (window);
3882 gtk_window_unrealize (GtkWidget *widget)
3885 GtkWindowGeometryInfo *info;
3887 window = GTK_WINDOW (widget);
3889 /* On unrealize, we reset the size of the window such
3890 * that we will re-apply the default sizing stuff
3891 * next time we show the window.
3893 * Default positioning is reset on unmap, instead of unrealize.
3895 window->need_default_size = TRUE;
3896 info = gtk_window_get_geometry_info (window, FALSE);
3899 info->resize_width = -1;
3900 info->resize_height = -1;
3901 info->last.configure_request.x = 0;
3902 info->last.configure_request.y = 0;
3903 info->last.configure_request.width = -1;
3904 info->last.configure_request.height = -1;
3905 /* be sure we reset geom hints on re-realize */
3906 info->last.flags = 0;
3911 gdk_window_set_user_data (window->frame, NULL);
3912 gdk_window_destroy (window->frame);
3913 window->frame = NULL;
3917 gtk_window_unrealize_icon (window);
3919 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3923 gtk_window_size_request (GtkWidget *widget,
3924 GtkRequisition *requisition)
3929 window = GTK_WINDOW (widget);
3930 bin = GTK_BIN (window);
3932 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3933 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3935 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3937 GtkRequisition child_requisition;
3939 gtk_widget_size_request (bin->child, &child_requisition);
3941 requisition->width += child_requisition.width;
3942 requisition->height += child_requisition.height;
3947 gtk_window_size_allocate (GtkWidget *widget,
3948 GtkAllocation *allocation)
3951 GtkAllocation child_allocation;
3953 window = GTK_WINDOW (widget);
3954 widget->allocation = *allocation;
3956 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3958 child_allocation.x = GTK_CONTAINER (window)->border_width;
3959 child_allocation.y = GTK_CONTAINER (window)->border_width;
3960 child_allocation.width =
3961 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3962 child_allocation.height =
3963 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3965 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3968 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3970 gdk_window_resize (window->frame,
3971 allocation->width + window->frame_left + window->frame_right,
3972 allocation->height + window->frame_top + window->frame_bottom);
3977 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3980 gboolean return_val;
3982 window = GTK_WINDOW (widget);
3984 if (window->frame && (event->any.window == window->frame))
3986 if ((event->type != GDK_KEY_PRESS) &&
3987 (event->type != GDK_KEY_RELEASE) &&
3988 (event->type != GDK_FOCUS_CHANGE))
3990 g_signal_stop_emission_by_name (widget, "event");
3992 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
3997 g_object_unref (event->any.window);
3998 event->any.window = g_object_ref (widget->window);
4006 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
4008 GdkEventConfigure *configure_event;
4011 switch (event->type)
4014 configure_event = (GdkEventConfigure *)event;
4016 /* Invalidate the decorations */
4019 rect.width = configure_event->width;
4020 rect.height = configure_event->height;
4022 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
4024 /* Pass on the (modified) configure event */
4025 configure_event->width -= window->frame_left + window->frame_right;
4026 configure_event->height -= window->frame_top + window->frame_bottom;
4027 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
4036 gtk_window_configure_event (GtkWidget *widget,
4037 GdkEventConfigure *event)
4039 GtkWindow *window = GTK_WINDOW (widget);
4040 gboolean expected_reply = window->configure_request_count > 0;
4042 /* window->configure_request_count incremented for each
4043 * configure request, and decremented to a min of 0 for
4044 * each configure notify.
4046 * All it means is that we know we will get at least
4047 * window->configure_request_count more configure notifies.
4048 * We could get more configure notifies than that; some
4049 * of the configure notifies we get may be unrelated to
4050 * the configure requests. But we will get at least
4051 * window->configure_request_count notifies.
4054 if (window->configure_request_count > 0)
4055 window->configure_request_count -= 1;
4057 /* As an optimization, we avoid a resize when possible.
4059 * The only times we can avoid a resize are:
4060 * - we know only the position changed, not the size
4061 * - we know we have made more requests and so will get more
4062 * notifies and can wait to resize when we get them
4065 if (!expected_reply &&
4066 (widget->allocation.width == event->width &&
4067 widget->allocation.height == event->height))
4071 * If we do need to resize, we do that by:
4072 * - filling in widget->allocation with the new size
4073 * - setting configure_notify_received to TRUE
4074 * for use in gtk_window_move_resize()
4075 * - queueing a resize, leading to invocation of
4076 * gtk_window_move_resize() in an idle handler
4080 window->configure_notify_received = TRUE;
4082 widget->allocation.width = event->width;
4083 widget->allocation.height = event->height;
4085 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4090 /* the accel_key and accel_mods fields of the key have to be setup
4091 * upon calling this function. it'll then return whether that key
4092 * is at all used as accelerator, and if so will OR in the
4093 * accel_flags member of the key.
4096 _gtk_window_query_nonaccels (GtkWindow *window,
4098 GdkModifierType accel_mods)
4100 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4102 /* movement keys are considered locked accels */
4105 static const guint bindings[] = {
4106 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
4107 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
4111 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
4112 if (bindings[i] == accel_key)
4116 /* mnemonics are considered locked accels */
4117 if (accel_mods == window->mnemonic_modifier)
4119 GtkWindowMnemonic mkey;
4121 mkey.window = window;
4122 mkey.keyval = accel_key;
4123 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
4131 gtk_window_key_press_event (GtkWidget *widget,
4138 window = GTK_WINDOW (widget);
4142 /* Check for mnemonics and accelerators
4145 handled = _gtk_window_activate_key (window, event);
4149 focus = window->focus_widget;
4151 g_object_ref (focus);
4154 focus && focus != widget &&
4155 gtk_widget_get_toplevel (focus) == widget)
4159 if (GTK_WIDGET_IS_SENSITIVE (focus))
4160 handled = gtk_widget_event (focus, (GdkEvent*) event);
4162 parent = focus->parent;
4164 g_object_ref (parent);
4166 g_object_unref (focus);
4172 g_object_unref (focus);
4175 /* Chain up, invokes binding set */
4176 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
4177 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4183 gtk_window_key_release_event (GtkWidget *widget,
4189 window = GTK_WINDOW (widget);
4191 if (window->focus_widget &&
4192 window->focus_widget != widget &&
4193 GTK_WIDGET_SENSITIVE (window->focus_widget))
4195 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
4198 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
4199 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
4205 gtk_window_real_activate_default (GtkWindow *window)
4207 gtk_window_activate_default (window);
4211 gtk_window_real_activate_focus (GtkWindow *window)
4213 gtk_window_activate_focus (window);
4217 gtk_window_move_focus (GtkWindow *window,
4218 GtkDirectionType dir)
4220 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4222 if (!GTK_CONTAINER (window)->focus_child)
4223 gtk_window_set_focus (window, NULL);
4227 gtk_window_enter_notify_event (GtkWidget *widget,
4228 GdkEventCrossing *event)
4234 gtk_window_leave_notify_event (GtkWidget *widget,
4235 GdkEventCrossing *event)
4241 do_focus_change (GtkWidget *widget,
4244 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4246 g_object_ref (widget);
4249 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4251 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4253 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4254 fevent->focus_change.window = widget->window;
4256 g_object_ref (widget->window);
4257 fevent->focus_change.in = in;
4259 gtk_widget_event (widget, fevent);
4261 g_object_notify (G_OBJECT (widget), "has_focus");
4263 g_object_unref (widget);
4264 gdk_event_free (fevent);
4268 gtk_window_focus_in_event (GtkWidget *widget,
4269 GdkEventFocus *event)
4271 GtkWindow *window = GTK_WINDOW (widget);
4273 /* It appears spurious focus in events can occur when
4274 * the window is hidden. So we'll just check to see if
4275 * the window is visible before actually handling the
4278 if (GTK_WIDGET_VISIBLE (widget))
4280 _gtk_window_set_has_toplevel_focus (window, TRUE);
4281 _gtk_window_set_is_active (window, TRUE);
4288 gtk_window_focus_out_event (GtkWidget *widget,
4289 GdkEventFocus *event)
4291 GtkWindow *window = GTK_WINDOW (widget);
4293 _gtk_window_set_has_toplevel_focus (window, FALSE);
4294 _gtk_window_set_is_active (window, FALSE);
4299 static GdkAtom atom_rcfiles = GDK_NONE;
4302 gtk_window_read_rcfiles (GtkWidget *widget,
4303 GdkEventClient *event)
4305 GList *embedded_windows;
4307 embedded_windows = g_object_get_data (G_OBJECT (widget), "gtk-embedded");
4308 if (embedded_windows)
4310 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4313 for (i = 0; i < 5; i++)
4314 send_event->client.data.l[i] = 0;
4315 send_event->client.data_format = 32;
4316 send_event->client.message_type = atom_rcfiles;
4318 while (embedded_windows)
4320 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4321 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4322 embedded_windows = embedded_windows->next;
4325 gdk_event_free (send_event);
4328 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4332 gtk_window_client_event (GtkWidget *widget,
4333 GdkEventClient *event)
4336 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
4338 if (event->message_type == atom_rcfiles)
4339 gtk_window_read_rcfiles (widget, event);
4345 gtk_window_check_resize (GtkContainer *container)
4347 GtkWindow *window = GTK_WINDOW (container);
4349 if (GTK_WIDGET_VISIBLE (container))
4350 gtk_window_move_resize (window);
4354 gtk_window_focus (GtkWidget *widget,
4355 GtkDirectionType direction)
4359 GtkContainer *container;
4360 GtkWidget *old_focus_child;
4363 container = GTK_CONTAINER (widget);
4364 window = GTK_WINDOW (widget);
4365 bin = GTK_BIN (widget);
4367 old_focus_child = container->focus_child;
4369 /* We need a special implementation here to deal properly with wrapping
4370 * around in the tab chain without the danger of going into an
4373 if (old_focus_child)
4375 if (gtk_widget_child_focus (old_focus_child, direction))
4379 if (window->focus_widget)
4381 if (direction == GTK_DIR_LEFT ||
4382 direction == GTK_DIR_RIGHT ||
4383 direction == GTK_DIR_UP ||
4384 direction == GTK_DIR_DOWN)
4389 /* Wrapped off the end, clear the focus setting for the toplpevel */
4390 parent = window->focus_widget->parent;
4393 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4394 parent = GTK_WIDGET (parent)->parent;
4397 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4400 /* Now try to focus the first widget in the window */
4403 if (gtk_widget_child_focus (bin->child, direction))
4411 gtk_window_real_set_focus (GtkWindow *window,
4414 GtkWidget *old_focus = window->focus_widget;
4415 gboolean def_flags = 0;
4419 g_object_ref (old_focus);
4420 g_object_freeze_notify (G_OBJECT (old_focus));
4424 g_object_ref (focus);
4425 g_object_freeze_notify (G_OBJECT (focus));
4428 if (window->default_widget)
4429 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4431 if (window->focus_widget)
4433 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4434 (window->focus_widget != window->default_widget))
4436 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4438 if (window->default_widget)
4439 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4442 window->focus_widget = NULL;
4444 if (window->has_focus)
4445 do_focus_change (old_focus, FALSE);
4447 g_object_notify (G_OBJECT (old_focus), "is_focus");
4450 /* The above notifications may have set a new focus widget,
4451 * if so, we don't want to override it.
4453 if (focus && !window->focus_widget)
4455 window->focus_widget = focus;
4457 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4458 (window->focus_widget != window->default_widget))
4460 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4461 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4463 if (window->default_widget)
4464 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4467 if (window->has_focus)
4468 do_focus_change (window->focus_widget, TRUE);
4470 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4473 /* If the default widget changed, a redraw will have been queued
4474 * on the old and new default widgets by gtk_window_set_default(), so
4475 * we only have to worry about the case where it didn't change.
4476 * We'll sometimes queue a draw twice on the new widget but that
4479 if (window->default_widget &&
4480 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
4481 gtk_widget_queue_draw (window->default_widget);
4485 g_object_thaw_notify (G_OBJECT (old_focus));
4486 g_object_unref (old_focus);
4490 g_object_thaw_notify (G_OBJECT (focus));
4491 g_object_unref (focus);
4496 * _gtk_window_unset_focus_and_default:
4497 * @window: a #GtkWindow
4498 * @widget: a widget inside of @window
4500 * Checks whether the focus and default widgets of @window are
4501 * @widget or a descendent of @widget, and if so, unset them.
4504 _gtk_window_unset_focus_and_default (GtkWindow *window,
4510 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
4512 child = window->focus_widget;
4514 while (child && child != widget)
4515 child = child->parent;
4517 if (child == widget)
4518 gtk_window_set_focus (GTK_WINDOW (window), NULL);
4521 child = window->default_widget;
4523 while (child && child != widget)
4524 child = child->parent;
4526 if (child == widget)
4527 gtk_window_set_default (window, NULL);
4530 /*********************************
4531 * Functions related to resizing *
4532 *********************************/
4534 /* This function doesn't constrain to geometry hints */
4536 gtk_window_compute_configure_request_size (GtkWindow *window,
4540 GtkRequisition requisition;
4541 GtkWindowGeometryInfo *info;
4545 * - we've done a size request
4548 widget = GTK_WIDGET (window);
4550 info = gtk_window_get_geometry_info (window, FALSE);
4552 if (window->need_default_size)
4554 gtk_widget_get_child_requisition (widget, &requisition);
4556 /* Default to requisition */
4557 *width = requisition.width;
4558 *height = requisition.height;
4560 /* If window is empty so requests 0, default to random nonzero size */
4561 if (*width == 0 && *height == 0)
4567 /* Override requisition with default size */
4571 gint base_width = 0;
4572 gint base_height = 0;
4574 gint height_inc = 1;
4576 if (info->default_is_geometry &&
4577 (info->default_width > 0 || info->default_height > 0))
4579 GdkGeometry geometry;
4582 gtk_window_compute_hints (window, &geometry, &flags);
4584 if (flags & GDK_HINT_BASE_SIZE)
4586 base_width = geometry.base_width;
4587 base_height = geometry.base_height;
4589 else if (flags & GDK_HINT_MIN_SIZE)
4591 base_width = geometry.min_width;
4592 base_height = geometry.min_height;
4594 if (flags & GDK_HINT_RESIZE_INC)
4596 width_inc = geometry.width_inc;
4597 height_inc = geometry.height_inc;
4601 if (info->default_width > 0)
4602 *width = info->default_width * width_inc + base_width;
4604 if (info->default_height > 0)
4605 *height = info->default_height * height_inc + base_height;
4610 /* Default to keeping current size */
4611 *width = widget->allocation.width;
4612 *height = widget->allocation.height;
4615 /* Override any size with gtk_window_resize() values */
4618 if (info->resize_width > 0)
4619 *width = info->resize_width;
4621 if (info->resize_height > 0)
4622 *height = info->resize_height;
4626 static GtkWindowPosition
4627 get_effective_position (GtkWindow *window)
4629 GtkWindowPosition pos = window->position;
4630 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
4631 (window->transient_parent == NULL ||
4632 !GTK_WIDGET_MAPPED (window->transient_parent)))
4633 pos = GTK_WIN_POS_NONE;
4639 get_center_monitor_of_window (GtkWindow *window)
4641 /* We could try to sort out the relative positions of the monitors and
4642 * stuff, or we could just be losers and assume you have a row
4643 * or column of monitors.
4645 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
4649 get_monitor_containing_pointer (GtkWindow *window)
4653 GdkScreen *window_screen;
4654 GdkScreen *pointer_screen;
4656 window_screen = gtk_window_check_screen (window);
4657 gdk_display_get_pointer (gdk_screen_get_display (window_screen),
4661 if (pointer_screen == window_screen)
4662 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
4670 center_window_on_monitor (GtkWindow *window,
4676 GdkRectangle monitor;
4679 monitor_num = get_monitor_containing_pointer (window);
4681 if (monitor_num == -1)
4682 monitor_num = get_center_monitor_of_window (window);
4684 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
4685 monitor_num, &monitor);
4687 *x = (monitor.width - w) / 2 + monitor.x;
4688 *y = (monitor.height - h) / 2 + monitor.y;
4690 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
4691 * and WM decorations.
4700 clamp_window_to_rectangle (gint *x,
4704 const GdkRectangle *rect)
4706 gint outside_w, outside_h;
4708 outside_w = (*x + w) - (rect->x + rect->width);
4712 outside_h = (*y + h) - (rect->y + rect->height);
4716 /* if larger than the screen, center on the screen. */
4718 *x += (rect->x - *x) / 2;
4720 *y += (rect->y - *y) / 2;
4725 gtk_window_compute_configure_request (GtkWindow *window,
4726 GdkRectangle *request,
4727 GdkGeometry *geometry,
4730 GdkGeometry new_geometry;
4734 GtkWindowPosition pos;
4735 GtkWidget *parent_widget;
4736 GtkWindowGeometryInfo *info;
4740 widget = GTK_WIDGET (window);
4742 screen = gtk_window_check_screen (window);
4744 gtk_widget_size_request (widget, NULL);
4745 gtk_window_compute_configure_request_size (window, &w, &h);
4747 gtk_window_compute_hints (window, &new_geometry, &new_flags);
4748 gtk_window_constrain_size (window,
4749 &new_geometry, new_flags,
4753 parent_widget = (GtkWidget*) window->transient_parent;
4755 pos = get_effective_position (window);
4756 info = gtk_window_get_geometry_info (window, TRUE);
4758 /* by default, don't change position requested */
4759 x = info->last.configure_request.x;
4760 y = info->last.configure_request.y;
4762 if (window->need_default_position)
4765 /* FIXME this all interrelates with window gravity.
4766 * For most of them I think we want to set GRAVITY_CENTER.
4768 * Not sure how to go about that.
4773 /* here we are only handling CENTER_ALWAYS
4774 * as it relates to default positioning,
4775 * where it's equivalent to simply CENTER
4777 case GTK_WIN_POS_CENTER_ALWAYS:
4778 case GTK_WIN_POS_CENTER:
4779 center_window_on_monitor (window, w, h, &x, &y);
4782 case GTK_WIN_POS_CENTER_ON_PARENT:
4785 GdkRectangle monitor;
4788 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
4790 if (parent_widget->window != NULL)
4791 monitor_num = gdk_screen_get_monitor_at_window (screen,
4792 parent_widget->window);
4796 gdk_window_get_origin (parent_widget->window,
4799 x = ox + (parent_widget->allocation.width - w) / 2;
4800 y = oy + (parent_widget->allocation.height - h) / 2;
4802 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4803 * WM decorations. If parent wasn't on a monitor, just
4806 if (monitor_num >= 0)
4808 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
4809 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4814 case GTK_WIN_POS_MOUSE:
4816 gint screen_width = gdk_screen_get_width (screen);
4817 gint screen_height = gdk_screen_get_height (screen);
4819 GdkRectangle monitor;
4820 GdkScreen *pointer_screen;
4823 gdk_display_get_pointer (gdk_screen_get_display (screen),
4827 if (pointer_screen == screen)
4828 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
4834 x = CLAMP (x, 0, screen_width - w);
4835 y = CLAMP (y, 0, screen_height - h);
4837 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4838 * WM decorations. Don't try to figure out what's going
4839 * on if the mouse wasn't inside a monitor.
4841 if (monitor_num >= 0)
4843 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
4844 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4852 } /* if (window->need_default_position) */
4854 if (window->need_default_position &&
4855 info->initial_pos_set)
4857 x = info->initial_x;
4858 y = info->initial_y;
4859 gtk_window_constrain_position (window, w, h, &x, &y);
4865 request->height = h;
4868 *geometry = new_geometry;
4874 gtk_window_constrain_position (GtkWindow *window,
4880 /* See long comments in gtk_window_move_resize()
4881 * on when it's safe to call this function.
4883 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4885 gint center_x, center_y;
4887 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
4895 gtk_window_move_resize (GtkWindow *window)
4899 * First we determine whether any information has changed that would
4900 * cause us to revise our last configure request. If we would send
4901 * a different configure request from last time, then
4902 * configure_request_size_changed = TRUE or
4903 * configure_request_pos_changed = TRUE. configure_request_size_changed
4904 * may be true due to new hints, a gtk_window_resize(), or whatever.
4905 * configure_request_pos_changed may be true due to gtk_window_set_position()
4906 * or gtk_window_move().
4908 * If the configure request has changed, we send off a new one. To
4909 * ensure GTK+ invariants are maintained (resize queue does what it
4910 * should), we go ahead and size_allocate the requested size in this
4913 * If the configure request has not changed, we don't ever resend
4914 * it, because it could mean fighting the user or window manager.
4917 * To prepare the configure request, we come up with a base size/pos:
4918 * - the one from gtk_window_move()/gtk_window_resize()
4919 * - else default_width, default_height if we haven't ever
4921 * - else the size request if we haven't ever been mapped,
4922 * as a substitute default size
4923 * - else the current size of the window, as received from
4924 * configure notifies (i.e. the current allocation)
4926 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4927 * the position request to be centered.
4930 GtkContainer *container;
4931 GtkWindowGeometryInfo *info;
4932 GdkGeometry new_geometry;
4934 GdkRectangle new_request;
4935 gboolean configure_request_size_changed;
4936 gboolean configure_request_pos_changed;
4937 gboolean hints_changed; /* do we need to send these again */
4938 GtkWindowLastGeometryInfo saved_last_info;
4940 widget = GTK_WIDGET (window);
4941 container = GTK_CONTAINER (widget);
4942 info = gtk_window_get_geometry_info (window, TRUE);
4944 configure_request_size_changed = FALSE;
4945 configure_request_pos_changed = FALSE;
4947 gtk_window_compute_configure_request (window, &new_request,
4948 &new_geometry, &new_flags);
4950 /* This check implies the invariant that we never set info->last
4951 * without setting the hints and sending off a configure request.
4953 * If we change info->last without sending the request, we may
4956 if (info->last.configure_request.x != new_request.x ||
4957 info->last.configure_request.y != new_request.y)
4958 configure_request_pos_changed = TRUE;
4960 if ((info->last.configure_request.width != new_request.width ||
4961 info->last.configure_request.height != new_request.height))
4962 configure_request_size_changed = TRUE;
4964 hints_changed = FALSE;
4966 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4967 &new_geometry, new_flags))
4969 hints_changed = TRUE;
4972 /* Position Constraints
4973 * ====================
4975 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4976 * a default. The other POS_ values are used only when the
4977 * window is shown, not after that.
4979 * However, we can't implement a position constraint as
4980 * "anytime the window size changes, center the window"
4981 * because this may well end up fighting the WM or user. In
4982 * fact it gets in an infinite loop with at least one WM.
4984 * Basically, applications are in no way in a position to
4985 * constrain the position of a window, with one exception:
4986 * override redirect windows. (Really the intended purpose
4987 * of CENTER_ALWAYS anyhow, I would think.)
4989 * So the way we implement this "constraint" is to say that when WE
4990 * cause a move or resize, i.e. we make a configure request changing
4991 * window size, we recompute the CENTER_ALWAYS position to reflect
4992 * the new window size, and include it in our request. Also, if we
4993 * just turned on CENTER_ALWAYS we snap to center with a new
4994 * request. Otherwise, if we are just NOTIFIED of a move or resize
4995 * done by someone else e.g. the window manager, we do NOT send a
4996 * new configure request.
4998 * For override redirect windows, this works fine; all window
4999 * sizes are from our configure requests. For managed windows,
5000 * it is at least semi-sane, though who knows what the
5001 * app author is thinking.
5004 /* This condition should be kept in sync with the condition later on
5005 * that determines whether we send a configure request. i.e. we
5006 * should do this position constraining anytime we were going to
5007 * send a configure request anyhow, plus when constraints have
5010 if (configure_request_pos_changed ||
5011 configure_request_size_changed ||
5013 info->position_constraints_changed)
5015 /* We request the constrained position if:
5016 * - we were changing position, and need to clamp
5017 * the change to the constraint
5018 * - we're changing the size anyway
5019 * - set_position() was called to toggle CENTER_ALWAYS on
5022 gtk_window_constrain_position (window,
5028 /* Update whether we need to request a move */
5029 if (info->last.configure_request.x != new_request.x ||
5030 info->last.configure_request.y != new_request.y)
5031 configure_request_pos_changed = TRUE;
5033 configure_request_pos_changed = FALSE;
5037 if (window->type == GTK_WINDOW_TOPLEVEL)
5039 int notify_x, notify_y;
5041 /* this is the position from the last configure notify */
5042 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
5044 g_message ("--- %s ---\n"
5045 "last : %d,%d\t%d x %d\n"
5046 "this : %d,%d\t%d x %d\n"
5047 "alloc : %d,%d\t%d x %d\n"
5049 "resize: \t%d x %d\n"
5050 "size_changed: %d pos_changed: %d hints_changed: %d\n"
5051 "configure_notify_received: %d\n"
5052 "configure_request_count: %d\n"
5053 "position_constraints_changed: %d\n",
5054 window->title ? window->title : "(no title)",
5055 info->last.configure_request.x,
5056 info->last.configure_request.y,
5057 info->last.configure_request.width,
5058 info->last.configure_request.height,
5064 widget->allocation.width,
5065 widget->allocation.height,
5066 widget->requisition.width,
5067 widget->requisition.height,
5069 info->resize_height,
5070 configure_request_pos_changed,
5071 configure_request_size_changed,
5073 window->configure_notify_received,
5074 window->configure_request_count,
5075 info->position_constraints_changed);
5079 saved_last_info = info->last;
5080 info->last.geometry = new_geometry;
5081 info->last.flags = new_flags;
5082 info->last.configure_request = new_request;
5084 /* need to set PPosition so the WM will look at our position,
5085 * but we don't want to count PPosition coming and going as a hints
5086 * change for future iterations. So we saved info->last prior to
5090 /* Also, if the initial position was explicitly set, then we always
5091 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
5095 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
5096 * this is an initial map
5099 if ((configure_request_pos_changed ||
5100 info->initial_pos_set ||
5101 (window->need_default_position &&
5102 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
5103 (new_flags & GDK_HINT_POS) == 0)
5105 new_flags |= GDK_HINT_POS;
5106 hints_changed = TRUE;
5109 /* Set hints if necessary
5112 gdk_window_set_geometry_hints (widget->window,
5116 /* handle resizing/moving and widget tree allocation
5118 if (window->configure_notify_received)
5120 GtkAllocation allocation;
5122 /* If we have received a configure event since
5123 * the last time in this function, we need to
5124 * accept our new size and size_allocate child widgets.
5125 * (see gtk_window_configure_event() for more details).
5127 * 1 or more configure notifies may have been received.
5128 * Also, configure_notify_received will only be TRUE
5129 * if all expected configure notifies have been received
5130 * (one per configure request), as an optimization.
5133 window->configure_notify_received = FALSE;
5135 /* gtk_window_configure_event() filled in widget->allocation */
5136 allocation = widget->allocation;
5137 gtk_widget_size_allocate (widget, &allocation);
5139 /* If the configure request changed, it means that
5141 * 1) coincidentally changed hints or widget properties
5142 * impacting the configure request before getting
5143 * a configure notify, or
5144 * 2) some broken widget is changing its size request
5145 * during size allocation, resulting in
5146 * a false appearance of changed configure request.
5148 * For 1), we could just go ahead and ask for the
5149 * new size right now, but doing that for 2)
5150 * might well be fighting the user (and can even
5151 * trigger a loop). Since we really don't want to
5152 * do that, we requeue a resize in hopes that
5153 * by the time it gets handled, the child has seen
5154 * the light and is willing to go along with the
5155 * new size. (this happens for the zvt widget, since
5156 * the size_allocate() above will have stored the
5157 * requisition corresponding to the new size in the
5160 * This doesn't buy us anything for 1), but it shouldn't
5161 * hurt us too badly, since it is what would have
5162 * happened if we had gotten the configure event before
5163 * the new size had been set.
5166 if (configure_request_size_changed ||
5167 configure_request_pos_changed)
5169 /* Don't change the recorded last info after all, because we
5170 * haven't actually updated to the new info yet - we decided
5171 * to postpone our configure request until later.
5173 info->last = saved_last_info;
5175 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
5178 return; /* Bail out, we didn't really process the move/resize */
5180 else if ((configure_request_size_changed || hints_changed) &&
5181 (widget->allocation.width != new_request.width ||
5182 widget->allocation.height != new_request.height))
5185 /* We are in one of the following situations:
5186 * A. configure_request_size_changed
5187 * our requisition has changed and we need a different window size,
5188 * so we request it from the window manager.
5189 * B. !configure_request_size_changed && hints_changed
5190 * the window manager rejects our size, but we have just changed the
5191 * window manager hints, so there's a chance our request will
5192 * be honoured this time, so we try again.
5194 * However, if the new requisition is the same as the current allocation,
5195 * we don't request it again, since we won't get a ConfigureNotify back from
5196 * the window manager unless it decides to change our requisition. If
5197 * we don't get the ConfigureNotify back, the resize queue will never be run.
5200 /* Now send the configure request */
5201 if (configure_request_pos_changed)
5205 gdk_window_move_resize (window->frame,
5206 new_request.x - window->frame_left,
5207 new_request.y - window->frame_top,
5208 new_request.width + window->frame_left + window->frame_right,
5209 new_request.height + window->frame_top + window->frame_bottom);
5210 gdk_window_resize (widget->window,
5211 new_request.width, new_request.height);
5214 gdk_window_move_resize (widget->window,
5215 new_request.x, new_request.y,
5216 new_request.width, new_request.height);
5218 else /* only size changed */
5221 gdk_window_resize (window->frame,
5222 new_request.width + window->frame_left + window->frame_right,
5223 new_request.height + window->frame_top + window->frame_bottom);
5224 gdk_window_resize (widget->window,
5225 new_request.width, new_request.height);
5228 /* Increment the number of have-not-yet-received-notify requests */
5229 window->configure_request_count += 1;
5231 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5232 * configure event in response to our resizing request.
5233 * the configure event will cause a new resize with
5234 * ->configure_notify_received=TRUE.
5235 * until then, we want to
5236 * - discard expose events
5237 * - coalesce resizes for our children
5238 * - defer any window resizes until the configure event arrived
5239 * to achieve this, we queue a resize for the window, but remove its
5240 * resizing handler, so resizing will not be handled from the next
5241 * idle handler but when the configure event arrives.
5243 * FIXME: we should also dequeue the pending redraws here, since
5244 * we handle those ourselves upon ->configure_notify_received==TRUE.
5246 if (container->resize_mode == GTK_RESIZE_QUEUE)
5248 gtk_widget_queue_resize (widget);
5249 _gtk_container_dequeue_resize_handler (container);
5254 /* Handle any position changes.
5256 if (configure_request_pos_changed)
5260 gdk_window_move (window->frame,
5261 new_request.x - window->frame_left,
5262 new_request.y - window->frame_top);
5265 gdk_window_move (widget->window,
5266 new_request.x, new_request.y);
5269 /* And run the resize queue.
5271 gtk_container_resize_children (container);
5274 /* We have now processed a move/resize since the last position
5275 * constraint change, setting of the initial position, or resize.
5276 * (Not resetting these flags here can lead to infinite loops for
5277 * GTK_RESIZE_IMMEDIATE containers)
5279 info->position_constraints_changed = FALSE;
5280 info->initial_pos_set = FALSE;
5281 info->resize_width = -1;
5282 info->resize_height = -1;
5285 /* Compare two sets of Geometry hints for equality.
5288 gtk_window_compare_hints (GdkGeometry *geometry_a,
5290 GdkGeometry *geometry_b,
5293 if (flags_a != flags_b)
5296 if ((flags_a & GDK_HINT_MIN_SIZE) &&
5297 (geometry_a->min_width != geometry_b->min_width ||
5298 geometry_a->min_height != geometry_b->min_height))
5301 if ((flags_a & GDK_HINT_MAX_SIZE) &&
5302 (geometry_a->max_width != geometry_b->max_width ||
5303 geometry_a->max_height != geometry_b->max_height))
5306 if ((flags_a & GDK_HINT_BASE_SIZE) &&
5307 (geometry_a->base_width != geometry_b->base_width ||
5308 geometry_a->base_height != geometry_b->base_height))
5311 if ((flags_a & GDK_HINT_ASPECT) &&
5312 (geometry_a->min_aspect != geometry_b->min_aspect ||
5313 geometry_a->max_aspect != geometry_b->max_aspect))
5316 if ((flags_a & GDK_HINT_RESIZE_INC) &&
5317 (geometry_a->width_inc != geometry_b->width_inc ||
5318 geometry_a->height_inc != geometry_b->height_inc))
5321 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5322 geometry_a->win_gravity != geometry_b->win_gravity)
5329 _gtk_window_constrain_size (GtkWindow *window,
5335 GtkWindowGeometryInfo *info;
5337 g_return_if_fail (GTK_IS_WINDOW (window));
5339 info = window->geometry_info;
5342 GdkWindowHints flags = info->last.flags;
5343 GdkGeometry *geometry = &info->last.geometry;
5345 gtk_window_constrain_size (window,
5356 gtk_window_constrain_size (GtkWindow *window,
5357 GdkGeometry *geometry,
5364 gdk_window_constrain_size (geometry, flags, width, height,
5365 new_width, new_height);
5368 /* Compute the set of geometry hints and flags for a window
5369 * based on the application set geometry, and requisiition
5370 * of the window. gtk_widget_size_request() must have been
5374 gtk_window_compute_hints (GtkWindow *window,
5375 GdkGeometry *new_geometry,
5379 gint extra_width = 0;
5380 gint extra_height = 0;
5381 GtkWindowGeometryInfo *geometry_info;
5382 GtkRequisition requisition;
5384 widget = GTK_WIDGET (window);
5386 gtk_widget_get_child_requisition (widget, &requisition);
5387 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5391 *new_flags = geometry_info->mask;
5392 *new_geometry = geometry_info->geometry;
5399 if (geometry_info && geometry_info->widget)
5401 GtkRequisition child_requisition;
5403 /* FIXME: This really isn't right. It gets the min size wrong and forces
5404 * callers to do horrible hacks like set a huge usize on the child requisition
5405 * to get the base size right. We really want to find the answers to:
5407 * - If the geometry widget was infinitely big, how much extra space
5408 * would be needed for the stuff around it.
5410 * - If the geometry widget was infinitely small, how big would the
5411 * window still have to be.
5413 * Finding these answers would be a bit of a mess here. (Bug #68668)
5415 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5417 extra_width = widget->requisition.width - child_requisition.width;
5418 extra_height = widget->requisition.height - child_requisition.height;
5421 /* We don't want to set GDK_HINT_POS in here, we just set it
5422 * in gtk_window_move_resize() when we want the position
5426 if (*new_flags & GDK_HINT_BASE_SIZE)
5428 new_geometry->base_width += extra_width;
5429 new_geometry->base_height += extra_height;
5431 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5432 (*new_flags & GDK_HINT_RESIZE_INC) &&
5433 ((extra_width != 0) || (extra_height != 0)))
5435 *new_flags |= GDK_HINT_BASE_SIZE;
5437 new_geometry->base_width = extra_width;
5438 new_geometry->base_height = extra_height;
5441 if (*new_flags & GDK_HINT_MIN_SIZE)
5443 if (new_geometry->min_width < 0)
5444 new_geometry->min_width = requisition.width;
5446 new_geometry->min_width += extra_width;
5448 if (new_geometry->min_height < 0)
5449 new_geometry->min_height = requisition.height;
5451 new_geometry->min_height += extra_height;
5453 else if (!window->allow_shrink)
5455 *new_flags |= GDK_HINT_MIN_SIZE;
5457 new_geometry->min_width = requisition.width;
5458 new_geometry->min_height = requisition.height;
5461 if (*new_flags & GDK_HINT_MAX_SIZE)
5463 if (new_geometry->max_width < 0)
5464 new_geometry->max_width = requisition.width;
5466 new_geometry->max_width += extra_width;
5468 if (new_geometry->max_height < 0)
5469 new_geometry->max_height = requisition.height;
5471 new_geometry->max_height += extra_height;
5473 else if (!window->allow_grow)
5475 *new_flags |= GDK_HINT_MAX_SIZE;
5477 new_geometry->max_width = requisition.width;
5478 new_geometry->max_height = requisition.height;
5481 *new_flags |= GDK_HINT_WIN_GRAVITY;
5482 new_geometry->win_gravity = window->gravity;
5485 /***********************
5486 * Redrawing functions *
5487 ***********************/
5490 gtk_window_paint (GtkWidget *widget,
5493 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
5494 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
5498 gtk_window_expose (GtkWidget *widget,
5499 GdkEventExpose *event)
5501 if (!GTK_WIDGET_APP_PAINTABLE (widget))
5502 gtk_window_paint (widget, &event->area);
5504 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
5505 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
5511 * gtk_window_set_has_frame:
5512 * @window: a #GtkWindow
5513 * @setting: a boolean
5515 * (Note: this is a special-purpose function for the framebuffer port,
5516 * that causes GTK+ to draw its own window border. For most applications,
5517 * you want gtk_window_set_decorated() instead, which tells the window
5518 * manager whether to draw the window border.)
5520 * If this function is called on a window with setting of %TRUE, before
5521 * it is realized or showed, it will have a "frame" window around
5522 * @window->window, accessible in @window->frame. Using the signal
5523 * frame_event you can receive all events targeted at the frame.
5525 * This function is used by the linux-fb port to implement managed
5526 * windows, but it could concievably be used by X-programs that
5527 * want to do their own window decorations.
5531 gtk_window_set_has_frame (GtkWindow *window,
5534 g_return_if_fail (GTK_IS_WINDOW (window));
5535 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
5537 window->has_frame = setting != FALSE;
5541 * gtk_window_get_has_frame:
5542 * @window: a #GtkWindow
5544 * Accessor for whether the window has a frame window exterior to
5545 * @window->window. Gets the value set by gtk_window_set_has_frame ().
5547 * Return value: %TRUE if a frame has been added to the window
5548 * via gtk_window_set_has_frame().
5551 gtk_window_get_has_frame (GtkWindow *window)
5553 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5555 return window->has_frame;
5559 * gtk_window_set_frame_dimensions:
5560 * @window: a #GtkWindow that has a frame
5561 * @left: The width of the left border
5562 * @top: The height of the top border
5563 * @right: The width of the right border
5564 * @bottom: The height of the bottom border
5566 * (Note: this is a special-purpose function intended for the framebuffer
5567 * port; see gtk_window_set_has_frame(). It will have no effect on the
5568 * window border drawn by the window manager, which is the normal
5569 * case when using the X Window system.)
5571 * For windows with frames (see gtk_window_set_has_frame()) this function
5572 * can be used to change the size of the frame border.
5575 gtk_window_set_frame_dimensions (GtkWindow *window,
5583 g_return_if_fail (GTK_IS_WINDOW (window));
5585 widget = GTK_WIDGET (window);
5587 if (window->frame_left == left &&
5588 window->frame_top == top &&
5589 window->frame_right == right &&
5590 window->frame_bottom == bottom)
5593 window->frame_left = left;
5594 window->frame_top = top;
5595 window->frame_right = right;
5596 window->frame_bottom = bottom;
5598 if (GTK_WIDGET_REALIZED (widget) && window->frame)
5600 gint width = widget->allocation.width + left + right;
5601 gint height = widget->allocation.height + top + bottom;
5602 gdk_window_resize (window->frame, width, height);
5603 gtk_decorated_window_move_resize_window (window,
5605 widget->allocation.width,
5606 widget->allocation.height);
5611 * gtk_window_present:
5612 * @window: a #GtkWindow
5614 * Presents a window to the user. This may mean raising the window
5615 * in the stacking order, deiconifying it, moving it to the current
5616 * desktop, and/or giving it the keyboard focus, possibly dependent
5617 * on the user's platform, window manager, and preferences.
5619 * If @window is hidden, this function calls gtk_widget_show()
5622 * This function should be used when the user tries to open a window
5623 * that's already open. Say for example the preferences dialog is
5624 * currently open, and the user chooses Preferences from the menu
5625 * a second time; use gtk_window_present() to move the already-open dialog
5626 * where the user can see it.
5630 gtk_window_present (GtkWindow *window)
5634 g_return_if_fail (GTK_IS_WINDOW (window));
5636 widget = GTK_WIDGET (window);
5638 if (GTK_WIDGET_VISIBLE (window))
5640 g_assert (widget->window != NULL);
5642 gdk_window_show (widget->window);
5644 /* note that gdk_window_focus() will also move the window to
5645 * the current desktop, for WM spec compliant window managers.
5647 gdk_window_focus (widget->window,
5648 gtk_get_current_event_time ());
5652 gtk_widget_show (widget);
5657 * gtk_window_iconify:
5658 * @window: a #GtkWindow
5660 * Asks to iconify (i.e. minimize) the specified @window. Note that
5661 * you shouldn't assume the window is definitely iconified afterward,
5662 * because other entities (e.g. the user or <link
5663 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
5664 * again, or there may not be a window manager in which case
5665 * iconification isn't possible, etc. But normally the window will end
5666 * up iconified. Just don't write code that crashes if not.
5668 * It's permitted to call this function before showing a window,
5669 * in which case the window will be iconified before it ever appears
5672 * You can track iconification via the "window_state_event" signal
5677 gtk_window_iconify (GtkWindow *window)
5680 GdkWindow *toplevel;
5682 g_return_if_fail (GTK_IS_WINDOW (window));
5684 widget = GTK_WIDGET (window);
5686 window->iconify_initially = TRUE;
5689 toplevel = window->frame;
5691 toplevel = widget->window;
5693 if (toplevel != NULL)
5694 gdk_window_iconify (toplevel);
5698 * gtk_window_deiconify:
5699 * @window: a #GtkWindow
5701 * Asks to deiconify (i.e. unminimize) the specified @window. Note
5702 * that you shouldn't assume the window is definitely deiconified
5703 * afterward, because other entities (e.g. the user or <link
5704 * linkend="gtk-X11-arch">window manager</link>) could iconify it
5705 * again before your code which assumes deiconification gets to run.
5707 * You can track iconification via the "window_state_event" signal
5711 gtk_window_deiconify (GtkWindow *window)
5714 GdkWindow *toplevel;
5716 g_return_if_fail (GTK_IS_WINDOW (window));
5718 widget = GTK_WIDGET (window);
5720 window->iconify_initially = FALSE;
5723 toplevel = window->frame;
5725 toplevel = widget->window;
5727 if (toplevel != NULL)
5728 gdk_window_deiconify (toplevel);
5733 * @window: a #GtkWindow
5735 * Asks to stick @window, which means that it will appear on all user
5736 * desktops. Note that you shouldn't assume the window is definitely
5737 * stuck afterward, because other entities (e.g. the user or <link
5738 * linkend="gtk-X11-arch">window manager</link>) could unstick it
5739 * again, and some window managers do not support sticking
5740 * windows. But normally the window will end up stuck. Just don't
5741 * write code that crashes if not.
5743 * It's permitted to call this function before showing a window.
5745 * You can track stickiness via the "window_state_event" signal
5750 gtk_window_stick (GtkWindow *window)
5753 GdkWindow *toplevel;
5755 g_return_if_fail (GTK_IS_WINDOW (window));
5757 widget = GTK_WIDGET (window);
5759 window->stick_initially = TRUE;
5762 toplevel = window->frame;
5764 toplevel = widget->window;
5766 if (toplevel != NULL)
5767 gdk_window_stick (toplevel);
5771 * gtk_window_unstick:
5772 * @window: a #GtkWindow
5774 * Asks to unstick @window, which means that it will appear on only
5775 * one of the user's desktops. Note that you shouldn't assume the
5776 * window is definitely unstuck afterward, because other entities
5777 * (e.g. the user or <link linkend="gtk-X11-arch">window
5778 * manager</link>) could stick it again. But normally the window will
5779 * end up stuck. Just don't write code that crashes if not.
5781 * You can track stickiness via the "window_state_event" signal
5786 gtk_window_unstick (GtkWindow *window)
5789 GdkWindow *toplevel;
5791 g_return_if_fail (GTK_IS_WINDOW (window));
5793 widget = GTK_WIDGET (window);
5795 window->stick_initially = FALSE;
5798 toplevel = window->frame;
5800 toplevel = widget->window;
5802 if (toplevel != NULL)
5803 gdk_window_unstick (toplevel);
5807 * gtk_window_maximize:
5808 * @window: a #GtkWindow
5810 * Asks to maximize @window, so that it becomes full-screen. Note that
5811 * you shouldn't assume the window is definitely maximized afterward,
5812 * because other entities (e.g. the user or <link
5813 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
5814 * again, and not all window managers support maximization. But
5815 * normally the window will end up maximized. Just don't write code
5816 * that crashes if not.
5818 * It's permitted to call this function before showing a window,
5819 * in which case the window will be maximized when it appears onscreen
5822 * You can track maximization via the "window_state_event" signal
5827 gtk_window_maximize (GtkWindow *window)
5830 GdkWindow *toplevel;
5832 g_return_if_fail (GTK_IS_WINDOW (window));
5834 widget = GTK_WIDGET (window);
5836 window->maximize_initially = TRUE;
5839 toplevel = window->frame;
5841 toplevel = widget->window;
5843 if (toplevel != NULL)
5844 gdk_window_maximize (toplevel);
5848 * gtk_window_unmaximize:
5849 * @window: a #GtkWindow
5851 * Asks to unmaximize @window. Note that you shouldn't assume the
5852 * window is definitely unmaximized afterward, because other entities
5853 * (e.g. the user or <link linkend="gtk-X11-arch">window
5854 * manager</link>) could maximize it again, and not all window
5855 * managers honor requests to unmaximize. But normally the window will
5856 * end up unmaximized. Just don't write code that crashes if not.
5858 * You can track maximization via the "window_state_event" signal
5863 gtk_window_unmaximize (GtkWindow *window)
5866 GdkWindow *toplevel;
5868 g_return_if_fail (GTK_IS_WINDOW (window));
5870 widget = GTK_WIDGET (window);
5872 window->maximize_initially = FALSE;
5875 toplevel = window->frame;
5877 toplevel = widget->window;
5879 if (toplevel != NULL)
5880 gdk_window_unmaximize (toplevel);
5884 * gtk_window_fullscreen:
5885 * @window: a #GtkWindow
5887 * Asks to place @window in the fullscreen state. Note that you
5888 * shouldn't assume the window is definitely full screen afterward,
5889 * because other entities (e.g. the user or <link
5890 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
5891 * again, and not all window managers honor requests to fullscreen
5892 * windows. But normally the window will end up fullscreen. Just
5893 * don't write code that crashes if not.
5895 * You can track the fullscreen state via the "window_state_event" signal
5901 gtk_window_fullscreen (GtkWindow *window)
5904 GdkWindow *toplevel;
5905 GtkWindowPrivate *priv;
5907 g_return_if_fail (GTK_IS_WINDOW (window));
5909 widget = GTK_WIDGET (window);
5910 priv = gtk_window_get_private (window);
5912 priv->fullscreen_initially = TRUE;
5915 toplevel = window->frame;
5917 toplevel = widget->window;
5919 if (toplevel != NULL)
5920 gdk_window_fullscreen (toplevel);
5924 * gtk_window_unfullscreen:
5925 * @window: a #GtkWindow
5927 * Asks to toggle off the fullscreen state for @window. Note that you
5928 * shouldn't assume the window is definitely not full screen
5929 * afterward, because other entities (e.g. the user or <link
5930 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
5931 * again, and not all window managers honor requests to unfullscreen
5932 * windows. But normally the window will end up restored to its normal
5933 * state. Just don't write code that crashes if not.
5935 * You can track the fullscreen state via the "window_state_event" signal
5941 gtk_window_unfullscreen (GtkWindow *window)
5944 GdkWindow *toplevel;
5945 GtkWindowPrivate *priv;
5947 g_return_if_fail (GTK_IS_WINDOW (window));
5949 widget = GTK_WIDGET (window);
5950 priv = gtk_window_get_private (window);
5952 priv->fullscreen_initially = FALSE;
5955 toplevel = window->frame;
5957 toplevel = widget->window;
5959 if (toplevel != NULL)
5960 gdk_window_unfullscreen (toplevel);
5964 * gtk_window_set_keep_above:
5965 * @window: a #GtkWindow
5966 * @setting: whether to keep @window above other windows
5968 * Asks to keep @window above, so that it stays on top. Note that
5969 * you shouldn't assume the window is definitely above afterward,
5970 * because other entities (e.g. the user or <link
5971 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
5972 * and not all window managers support keeping windows above. But
5973 * normally the window will end kept above. Just don't write code
5974 * that crashes if not.
5976 * It's permitted to call this function before showing a window,
5977 * in which case the window will be kept above when it appears onscreen
5980 * You can track the above state via the "window_state_event" signal
5983 * Note that, according to the <ulink
5984 * url="http://www.freedesktop.org/standards/wm-spec.html">Extended Window Manager Hints</ulink>
5985 * specification, the above state is mainly meant for user preferences and should not be used
5986 * by applications e.g. for drawing attention to their dialogs.
5991 gtk_window_set_keep_above (GtkWindow *window, gboolean setting)
5994 GdkWindow *toplevel;
5996 g_return_if_fail (GTK_IS_WINDOW (window));
5998 widget = GTK_WIDGET (window);
6000 window->above_initially = setting;
6002 window->below_initially = FALSE;
6005 toplevel = window->frame;
6007 toplevel = widget->window;
6009 if (toplevel != NULL)
6010 gdk_window_set_keep_above (toplevel, setting);
6014 * gtk_window_set_keep_below:
6015 * @window: a #GtkWindow
6016 * @setting: whether to keep @window below other windows
6018 * Asks to keep @window below, so that it stays in bottom. Note that
6019 * you shouldn't assume the window is definitely below afterward,
6020 * because other entities (e.g. the user or <link
6021 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
6022 * and not all window managers support putting windows below. But
6023 * normally the window will be kept below. Just don't write code
6024 * that crashes if not.
6026 * It's permitted to call this function before showing a window,
6027 * in which case the window will be kept below when it appears onscreen
6030 * You can track the below state via the "window_state_event" signal
6033 * Note that, according to the <ulink
6034 * url="http://www.freedesktop.org/standards/wm-spec.html">Extended Window Manager Hints</ulink>
6035 * specification, the above state is mainly meant for user preferences and should not be used
6036 * by applications e.g. for drawing attention to their dialogs.
6041 gtk_window_set_keep_below (GtkWindow *window, gboolean setting)
6044 GdkWindow *toplevel;
6046 g_return_if_fail (GTK_IS_WINDOW (window));
6048 widget = GTK_WIDGET (window);
6050 window->below_initially = setting;
6052 window->above_initially = FALSE;
6055 toplevel = window->frame;
6057 toplevel = widget->window;
6059 if (toplevel != NULL)
6060 gdk_window_set_keep_below (toplevel, setting);
6064 * gtk_window_set_resizable:
6065 * @window: a #GtkWindow
6066 * @resizable: %TRUE if the user can resize this window
6068 * Sets whether the user can resize a window. Windows are user resizable
6072 gtk_window_set_resizable (GtkWindow *window,
6075 g_return_if_fail (GTK_IS_WINDOW (window));
6077 gtk_window_set_policy (window, FALSE, resizable, FALSE);
6081 * gtk_window_get_resizable:
6082 * @window: a #GtkWindow
6084 * Gets the value set by gtk_window_set_resizable().
6086 * Return value: %TRUE if the user can resize the window
6089 gtk_window_get_resizable (GtkWindow *window)
6091 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6093 /* allow_grow is most likely to indicate the semantic concept we
6094 * mean by "resizable" (and will be a reliable indicator if
6095 * set_policy() hasn't been called)
6097 return window->allow_grow;
6101 * gtk_window_set_gravity:
6102 * @window: a #GtkWindow
6103 * @gravity: window gravity
6105 * Window gravity defines the meaning of coordinates passed to
6106 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
6109 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
6110 * typically "do what you mean."
6114 gtk_window_set_gravity (GtkWindow *window,
6117 g_return_if_fail (GTK_IS_WINDOW (window));
6119 if (gravity != window->gravity)
6121 window->gravity = gravity;
6123 /* gtk_window_move_resize() will adapt gravity
6125 gtk_widget_queue_resize (GTK_WIDGET (window));
6127 g_object_notify (G_OBJECT (window), "gravity");
6132 * gtk_window_get_gravity:
6133 * @window: a #GtkWindow
6135 * Gets the value set by gtk_window_set_gravity().
6137 * Return value: window gravity
6140 gtk_window_get_gravity (GtkWindow *window)
6142 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
6144 return window->gravity;
6148 * gtk_window_begin_resize_drag:
6149 * @window: a #GtkWindow
6150 * @button: mouse button that initiated the drag
6151 * @edge: position of the resize control
6152 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6153 * @root_y: Y position where the user clicked to initiate the drag
6154 * @timestamp: timestamp from the click event that initiated the drag
6156 * Starts resizing a window. This function is used if an application
6157 * has window resizing controls. When GDK can support it, the resize
6158 * will be done using the standard mechanism for the <link
6159 * linkend="gtk-X11-arch">window manager</link> or windowing
6160 * system. Otherwise, GDK will try to emulate window resizing,
6161 * potentially not all that well, depending on the windowing system.
6165 gtk_window_begin_resize_drag (GtkWindow *window,
6173 GdkWindow *toplevel;
6175 g_return_if_fail (GTK_IS_WINDOW (window));
6176 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6178 widget = GTK_WIDGET (window);
6181 toplevel = window->frame;
6183 toplevel = widget->window;
6185 gdk_window_begin_resize_drag (toplevel,
6192 * gtk_window_get_frame_dimensions:
6193 * @window: a #GtkWindow
6194 * @left: location to store the width of the frame at the left, or %NULL
6195 * @top: location to store the height of the frame at the top, or %NULL
6196 * @right: location to store the width of the frame at the returns, or %NULL
6197 * @bottom: location to store the height of the frame at the bottom, or %NULL
6199 * (Note: this is a special-purpose function intended for the
6200 * framebuffer port; see gtk_window_set_has_frame(). It will not
6201 * return the size of the window border drawn by the <link
6202 * linkend="gtk-X11-arch">window manager</link>, which is the normal
6203 * case when using a windowing system. See
6204 * gdk_window_get_frame_extents() to get the standard window border
6207 * Retrieves the dimensions of the frame window for this toplevel.
6208 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
6211 gtk_window_get_frame_dimensions (GtkWindow *window,
6217 g_return_if_fail (GTK_IS_WINDOW (window));
6220 *left = window->frame_left;
6222 *top = window->frame_top;
6224 *right = window->frame_right;
6226 *bottom = window->frame_bottom;
6230 * gtk_window_begin_move_drag:
6231 * @window: a #GtkWindow
6232 * @button: mouse button that initiated the drag
6233 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6234 * @root_y: Y position where the user clicked to initiate the drag
6235 * @timestamp: timestamp from the click event that initiated the drag
6237 * Starts moving a window. This function is used if an application has
6238 * window movement grips. When GDK can support it, the window movement
6239 * will be done using the standard mechanism for the <link
6240 * linkend="gtk-X11-arch">window manager</link> or windowing
6241 * system. Otherwise, GDK will try to emulate window movement,
6242 * potentially not all that well, depending on the windowing system.
6246 gtk_window_begin_move_drag (GtkWindow *window,
6253 GdkWindow *toplevel;
6255 g_return_if_fail (GTK_IS_WINDOW (window));
6256 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6258 widget = GTK_WIDGET (window);
6261 toplevel = window->frame;
6263 toplevel = widget->window;
6265 gdk_window_begin_move_drag (toplevel,
6272 * gtk_window_set_screen:
6273 * @window: a #GtkWindow.
6274 * @screen: a #GdkScreen.
6276 * Sets the #GdkScreen where the @window is displayed; if
6277 * the window is already mapped, it will be unmapped, and
6278 * then remapped on the new screen.
6283 gtk_window_set_screen (GtkWindow *window,
6287 GdkScreen *previous_screen;
6288 gboolean was_mapped;
6290 g_return_if_fail (GTK_IS_WINDOW (window));
6291 g_return_if_fail (GDK_IS_SCREEN (screen));
6293 if (screen == window->screen)
6296 widget = GTK_WIDGET (window);
6298 previous_screen = window->screen;
6299 was_mapped = GTK_WIDGET_MAPPED (widget);
6302 gtk_widget_unmap (widget);
6303 if (GTK_WIDGET_REALIZED (widget))
6304 gtk_widget_unrealize (widget);
6306 gtk_window_free_key_hash (window);
6307 window->screen = screen;
6308 gtk_widget_reset_rc_styles (widget);
6309 if (screen != previous_screen)
6310 _gtk_widget_propagate_screen_changed (widget, previous_screen);
6311 g_object_notify (G_OBJECT (window), "screen");
6314 gtk_widget_map (widget);
6318 gtk_window_check_screen (GtkWindow *window)
6321 return window->screen;
6324 g_warning ("Screen for GtkWindow not set; you must always set\n"
6325 "a screen for a GtkWindow before using the window");
6331 * gtk_window_get_screen:
6332 * @window: a #GtkWindow.
6334 * Returns the #GdkScreen associated with @window.
6336 * Return value: a #GdkScreen.
6341 gtk_window_get_screen (GtkWindow *window)
6343 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6345 return window->screen;
6349 * gtk_window_is_active:
6350 * @window: a #GtkWindow
6352 * Returns whether the window is part of the current active toplevel.
6353 * (That is, the toplevel window receiving keystrokes.)
6354 * The return value is %TRUE if the window is active toplevel
6355 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
6356 * You might use this function if you wanted to draw a widget
6357 * differently in an active window from a widget in an inactive window.
6358 * See gtk_window_has_toplevel_focus()
6360 * Return value: %TRUE if the window part of the current active window.
6365 gtk_window_is_active (GtkWindow *window)
6367 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6369 return window->is_active;
6373 * gtk_window_has_toplevel_focus:
6374 * @window: a #GtkWindow
6376 * Returns whether the input focus is within this GtkWindow.
6377 * For real toplevel windows, this is identical to gtk_window_is_active(),
6378 * but for embedded windows, like #GtkPlug, the results will differ.
6380 * Return value: %TRUE if the the input focus is within this GtkWindow
6385 gtk_window_has_toplevel_focus (GtkWindow *window)
6387 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6389 return window->has_toplevel_focus;
6393 gtk_window_group_class_init (GtkWindowGroupClass *klass)
6398 gtk_window_group_get_type (void)
6400 static GType window_group_type = 0;
6402 if (!window_group_type)
6404 static const GTypeInfo window_group_info =
6406 sizeof (GtkWindowGroupClass),
6407 NULL, /* base_init */
6408 NULL, /* base_finalize */
6409 (GClassInitFunc) gtk_window_group_class_init,
6410 NULL, /* class_finalize */
6411 NULL, /* class_data */
6412 sizeof (GtkWindowGroup),
6413 16, /* n_preallocs */
6414 (GInstanceInitFunc) NULL,
6417 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
6420 return window_group_type;
6424 * gtk_window_group_new:
6426 * Creates a new #GtkWindowGroup object. Grabs added with
6427 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
6429 * Return value: a new #GtkWindowGroup.
6432 gtk_window_group_new (void)
6434 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
6438 window_group_cleanup_grabs (GtkWindowGroup *group,
6442 GSList *to_remove = NULL;
6444 tmp_list = group->grabs;
6447 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
6448 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
6449 tmp_list = tmp_list->next;
6454 gtk_grab_remove (to_remove->data);
6455 g_object_unref (to_remove->data);
6456 to_remove = g_slist_delete_link (to_remove, to_remove);
6461 * gtk_window_group_add_window:
6462 * @window_group: a #GtkWindowGroup
6463 * @window: the #GtkWindow to add
6465 * Adds a window to a #GtkWindowGroup.
6468 gtk_window_group_add_window (GtkWindowGroup *window_group,
6471 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6472 g_return_if_fail (GTK_IS_WINDOW (window));
6474 if (window->group != window_group)
6476 g_object_ref (window);
6477 g_object_ref (window_group);
6480 gtk_window_group_remove_window (window->group, window);
6482 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
6484 window->group = window_group;
6486 g_object_unref (window);
6491 * gtk_window_group_remove_window:
6492 * @window_group: a #GtkWindowGroup
6493 * @window: the #GtkWindow to remove
6495 * Removes a window from a #GtkWindowGroup.
6498 gtk_window_group_remove_window (GtkWindowGroup *window_group,
6501 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6502 g_return_if_fail (GTK_IS_WIDGET (window));
6503 g_return_if_fail (window->group == window_group);
6505 g_object_ref (window);
6507 window_group_cleanup_grabs (window_group, window);
6508 window->group = NULL;
6510 g_object_unref (window_group);
6511 g_object_unref (window);
6514 /* Return the group for the window or the default group
6517 _gtk_window_get_group (GtkWindow *window)
6519 if (window && window->group)
6520 return window->group;
6523 static GtkWindowGroup *default_group = NULL;
6526 default_group = gtk_window_group_new ();
6528 return default_group;
6534 Derived from XParseGeometry() in XFree86
6536 Copyright 1985, 1986, 1987,1998 The Open Group
6538 All Rights Reserved.
6540 The above copyright notice and this permission notice shall be included
6541 in all copies or substantial portions of the Software.
6543 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
6544 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6545 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6546 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
6547 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
6548 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
6549 OTHER DEALINGS IN THE SOFTWARE.
6551 Except as contained in this notice, the name of The Open Group shall
6552 not be used in advertising or otherwise to promote the sale, use or
6553 other dealings in this Software without prior written authorization
6554 from The Open Group.
6559 * XParseGeometry parses strings of the form
6560 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
6561 * width, height, xoffset, and yoffset are unsigned integers.
6562 * Example: "=80x24+300-49"
6563 * The equal sign is optional.
6564 * It returns a bitmask that indicates which of the four values
6565 * were actually found in the string. For each value found,
6566 * the corresponding argument is updated; for each value
6567 * not found, the corresponding argument is left unchanged.
6570 /* The following code is from Xlib, and is minimally modified, so we
6571 * can track any upstream changes if required. Don't change this
6572 * code. Or if you do, put in a huge comment marking which thing
6577 read_int (gchar *string,
6585 else if (*string == '-')
6591 for (; (*string >= '0') && (*string <= '9'); string++)
6593 result = (result * 10) + (*string - '0');
6605 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
6606 * value (x, y, width, height) was found in the parsed string.
6608 #define NoValue 0x0000
6609 #define XValue 0x0001
6610 #define YValue 0x0002
6611 #define WidthValue 0x0004
6612 #define HeightValue 0x0008
6613 #define AllValues 0x000F
6614 #define XNegative 0x0010
6615 #define YNegative 0x0020
6617 /* Try not to reformat/modify, so we can compare/sync with X sources */
6619 gtk_XParseGeometry (const char *string,
6622 unsigned int *width,
6623 unsigned int *height)
6627 unsigned int tempWidth, tempHeight;
6629 char *nextCharacter;
6631 /* These initializations are just to silence gcc */
6637 if ( (string == NULL) || (*string == '\0')) return(mask);
6639 string++; /* ignore possible '=' at beg of geometry spec */
6641 strind = (char *)string;
6642 if (*strind != '+' && *strind != '-' && *strind != 'x') {
6643 tempWidth = read_int(strind, &nextCharacter);
6644 if (strind == nextCharacter)
6646 strind = nextCharacter;
6650 if (*strind == 'x' || *strind == 'X') {
6652 tempHeight = read_int(strind, &nextCharacter);
6653 if (strind == nextCharacter)
6655 strind = nextCharacter;
6656 mask |= HeightValue;
6659 if ((*strind == '+') || (*strind == '-')) {
6660 if (*strind == '-') {
6662 tempX = -read_int(strind, &nextCharacter);
6663 if (strind == nextCharacter)
6665 strind = nextCharacter;
6671 tempX = read_int(strind, &nextCharacter);
6672 if (strind == nextCharacter)
6674 strind = nextCharacter;
6677 if ((*strind == '+') || (*strind == '-')) {
6678 if (*strind == '-') {
6680 tempY = -read_int(strind, &nextCharacter);
6681 if (strind == nextCharacter)
6683 strind = nextCharacter;
6690 tempY = read_int(strind, &nextCharacter);
6691 if (strind == nextCharacter)
6693 strind = nextCharacter;
6699 /* If strind isn't at the end of the string the it's an invalid
6700 geometry specification. */
6702 if (*strind != '\0') return (0);
6708 if (mask & WidthValue)
6710 if (mask & HeightValue)
6711 *height = tempHeight;
6716 * gtk_window_parse_geometry:
6717 * @window: a #GtkWindow
6718 * @geometry: geometry string
6720 * Parses a standard X Window System geometry string - see the
6721 * manual page for X (type 'man X') for details on this.
6722 * gtk_window_parse_geometry() does work on all GTK+ ports
6723 * including Win32 but is primarily intended for an X environment.
6725 * If either a size or a position can be extracted from the
6726 * geometry string, gtk_window_parse_geometry() returns %TRUE
6727 * and calls gtk_window_set_default_size() and/or gtk_window_move()
6728 * to resize/move the window.
6730 * If gtk_window_parse_geometry() returns %TRUE, it will also
6731 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
6732 * indicating to the window manager that the size/position of
6733 * the window was user-specified. This causes most window
6734 * managers to honor the geometry.
6736 * Note that for gtk_window_parse_geometry() to work as expected, it has
6737 * to be called when the window has its "final" size, i.e. after calling
6738 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
6741 * <informalexample><programlisting>
6743 * main (int argc, char *argv[])
6745 * GtkWidget *window, vbox;
6746 * GdkGeometry size_hints;
6748 * gtk_init (&argc, &argv);
6750 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6751 * vbox = gtk_vbox_new (FALSE, 0);
6753 * gtk_container_add (GTK_CONTAINER (window), vbox);
6754 * fill_with_content (vbox);
6755 * gtk_widget_show_all (vbox);
6758 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
6761 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
6764 * GDK_HINT_MIN_SIZE |
6765 * GDK_HINT_BASE_SIZE |
6766 * GDK_HINT_RESIZE_INC);
6770 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
6771 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
6774 * gtk_widget_show_all (window);
6779 * </programlisting></informalexample>
6781 * Return value: %TRUE if string was parsed successfully
6784 gtk_window_parse_geometry (GtkWindow *window,
6785 const gchar *geometry)
6790 gboolean size_set, pos_set;
6793 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6794 g_return_val_if_fail (geometry != NULL, FALSE);
6796 screen = gtk_window_check_screen (window);
6798 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
6800 if ((result & WidthValue) == 0 ||
6803 if ((result & HeightValue) == 0 ||
6808 if ((result & WidthValue) || (result & HeightValue))
6810 gtk_window_set_default_size_internal (window, TRUE, w, TRUE, h, TRUE);
6814 gtk_window_get_size (window, &w, &h);
6816 grav = GDK_GRAVITY_NORTH_WEST;
6818 if ((result & XNegative) && (result & YNegative))
6819 grav = GDK_GRAVITY_SOUTH_EAST;
6820 else if (result & XNegative)
6821 grav = GDK_GRAVITY_NORTH_EAST;
6822 else if (result & YNegative)
6823 grav = GDK_GRAVITY_SOUTH_WEST;
6825 if ((result & XValue) == 0)
6828 if ((result & YValue) == 0)
6831 if (grav == GDK_GRAVITY_SOUTH_WEST ||
6832 grav == GDK_GRAVITY_SOUTH_EAST)
6833 y = gdk_screen_get_height (screen) - h + y;
6835 if (grav == GDK_GRAVITY_SOUTH_EAST ||
6836 grav == GDK_GRAVITY_NORTH_EAST)
6837 x = gdk_screen_get_width (screen) - w + x;
6839 /* we don't let you put a window offscreen; maybe some people would
6840 * prefer to be able to, but it's kind of a bogus thing to do.
6849 if ((result & XValue) || (result & YValue))
6851 gtk_window_set_gravity (window, grav);
6852 gtk_window_move (window, x, y);
6856 if (size_set || pos_set)
6858 /* Set USSize, USPosition hints */
6859 GtkWindowGeometryInfo *info;
6861 info = gtk_window_get_geometry_info (window, TRUE);
6864 info->mask |= GDK_HINT_USER_POS;
6866 info->mask |= GDK_HINT_USER_SIZE;
6873 gtk_window_mnemonic_hash_foreach (gpointer key,
6879 GtkWindowKeysForeachFunc func;
6883 GtkWindowMnemonic *mnemonic = value;
6885 if (mnemonic->window == info->window)
6886 (*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
6890 _gtk_window_keys_foreach (GtkWindow *window,
6891 GtkWindowKeysForeachFunc func,
6898 GtkWindowKeysForeachFunc func;
6902 info.window = window;
6904 info.func_data = func_data;
6906 g_hash_table_foreach (mnemonic_hash_table,
6907 gtk_window_mnemonic_hash_foreach,
6910 groups = gtk_accel_groups_from_object (G_OBJECT (window));
6913 GtkAccelGroup *group = groups->data;
6916 for (i = 0; i < group->n_accels; i++)
6918 GtkAccelKey *key = &group->priv_accels[i].key;
6921 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
6924 groups = groups->next;
6929 gtk_window_keys_changed (GtkWindow *window)
6931 gtk_window_free_key_hash (window);
6932 gtk_window_get_key_hash (window);
6935 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
6937 struct _GtkWindowKeyEntry
6941 gboolean is_mnemonic;
6945 add_to_key_hash (GtkWindow *window,
6947 GdkModifierType modifiers,
6948 gboolean is_mnemonic,
6951 GtkKeyHash *key_hash = data;
6953 GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
6955 entry->keyval = keyval;
6956 entry->modifiers = modifiers;
6957 entry->is_mnemonic = is_mnemonic;
6959 /* GtkAccelGroup stores lowercased accelerators. To deal
6960 * with this, if <Shift> was specified, uppercase.
6962 if (modifiers & GDK_SHIFT_MASK)
6964 if (keyval == GDK_Tab)
6965 keyval = GDK_ISO_Left_Tab;
6967 keyval = gdk_keyval_to_upper (keyval);
6970 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
6974 gtk_window_get_key_hash (GtkWindow *window)
6976 GdkScreen *screen = gtk_window_check_screen (window);
6977 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6982 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
6983 (GDestroyNotify)g_free);
6984 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
6985 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
6991 gtk_window_free_key_hash (GtkWindow *window)
6993 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6996 _gtk_key_hash_free (key_hash);
6997 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
7002 * _gtk_window_activate_key:
7003 * @window: a #GtkWindow
7004 * @event: a #GdkEventKey
7006 * Activates mnemonics and accelerators for this #GtKWindow
7008 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
7011 _gtk_window_activate_key (GtkWindow *window,
7014 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
7015 GtkWindowKeyEntry *found_entry = NULL;
7019 gtk_window_keys_changed (window);
7020 key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
7025 GSList *entries = _gtk_key_hash_lookup (key_hash,
7026 event->hardware_keycode,
7028 gtk_accelerator_get_default_mod_mask (),
7032 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
7034 GtkWindowKeyEntry *entry = tmp_list->data;
7035 if (entry->is_mnemonic)
7037 found_entry = entry;
7042 if (!found_entry && entries)
7043 found_entry = entries->data;
7045 g_slist_free (entries);
7050 if (found_entry->is_mnemonic)
7051 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
7053 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
7060 window_update_has_focus (GtkWindow *window)
7062 GtkWidget *widget = GTK_WIDGET (window);
7063 gboolean has_focus = window->has_toplevel_focus && window->is_active;
7065 if (has_focus != window->has_focus)
7067 window->has_focus = has_focus;
7071 if (window->focus_widget &&
7072 window->focus_widget != widget &&
7073 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7074 do_focus_change (window->focus_widget, TRUE);
7078 if (window->focus_widget &&
7079 window->focus_widget != widget &&
7080 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7081 do_focus_change (window->focus_widget, FALSE);
7087 * _gtk_window_set_is_active:
7088 * @window: a #GtkWindow
7089 * @is_active: %TRUE if the window is in the currently active toplevel
7091 * Internal function that sets whether the #GtkWindow is part
7092 * of the currently active toplevel window (taking into account inter-process
7096 _gtk_window_set_is_active (GtkWindow *window,
7099 g_return_if_fail (GTK_IS_WINDOW (window));
7101 is_active = is_active != FALSE;
7103 if (is_active != window->is_active)
7105 window->is_active = is_active;
7106 window_update_has_focus (window);
7108 g_object_notify (G_OBJECT (window), "is_active");
7113 * _gtk_window_set_has_toplevel_focus:
7114 * @window: a #GtkWindow
7115 * @has_toplevel_focus: %TRUE if the in
7117 * Internal function that sets whether the keyboard focus for the
7118 * toplevel window (taking into account inter-process embedding.)
7121 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
7122 gboolean has_toplevel_focus)
7124 g_return_if_fail (GTK_IS_WINDOW (window));
7126 has_toplevel_focus = has_toplevel_focus != FALSE;
7128 if (has_toplevel_focus != window->has_toplevel_focus)
7130 window->has_toplevel_focus = has_toplevel_focus;
7131 window_update_has_focus (window);
7133 g_object_notify (G_OBJECT (window), "has_toplevel_focus");
7138 * gtk_window_set_auto_startup_notification:
7139 * @setting: %TRUE to automatically do startup notification
7141 * By default, after showing the first #GtkWindow for each #GdkScreen,
7142 * GTK+ calls gdk_screen_notify_startup_complete(). Call this
7143 * function to disable the automatic startup notification. You might
7144 * do this if your first window is a splash screen, and you want to
7145 * delay notification until after your real main window has been
7146 * shown, for example.
7148 * In that example, you would disable startup notification
7149 * temporarily, show your splash screen, then re-enable it so that
7150 * showing the main window would automatically result in notification.
7155 gtk_window_set_auto_startup_notification (gboolean setting)
7157 disable_startup_notification = !setting;