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"
69 PROP_DESTROY_WITH_PARENT,
73 PROP_SKIP_TASKBAR_HINT,
76 /* Readonly properties */
78 PROP_HAS_TOPLEVEL_FOCUS,
86 GdkPixmap *icon_pixmap;
89 guint using_default_icon : 1;
90 guint using_parent_icon : 1;
94 GdkGeometry geometry; /* Last set of geometry hints we set */
96 GdkRectangle configure_request;
97 } GtkWindowLastGeometryInfo;
99 struct _GtkWindowGeometryInfo
101 /* Properties that the app has set on the window
103 GdkGeometry geometry; /* Geometry hints */
105 GtkWidget *widget; /* subwidget to which hints apply */
106 /* from last gtk_window_resize () - if > 0, indicates that
107 * we should resize to this size.
112 /* From last gtk_window_move () prior to mapping -
113 * only used if initial_pos_set
118 /* Default size - used only the FIRST time we map a window,
123 /* whether to use initial_x, initial_y */
124 guint initial_pos_set : 1;
125 /* CENTER_ALWAYS or other position constraint changed since
126 * we sent the last configure request.
128 guint position_constraints_changed : 1;
130 /* if true, default_width, height come from gtk_window_parse_geometry,
131 * and thus should be multiplied by the increments and affect the
132 * geometry widget only
134 guint default_is_geometry : 1;
136 GtkWindowLastGeometryInfo last;
139 typedef struct _GtkWindowMnemonic GtkWindowMnemonic;
141 struct _GtkWindowMnemonic {
148 typedef struct _GtkWindowPrivate GtkWindowPrivate;
150 struct _GtkWindowPrivate
152 guint fullscreen_initially : 1;
153 guint skips_taskbar : 1;
154 guint skips_pager : 1;
157 static void gtk_window_class_init (GtkWindowClass *klass);
158 static void gtk_window_init (GtkWindow *window);
159 static void gtk_window_dispose (GObject *object);
160 static void gtk_window_destroy (GtkObject *object);
161 static void gtk_window_finalize (GObject *object);
162 static void gtk_window_private_finalize (GtkWindowPrivate *priv);
163 static void gtk_window_show (GtkWidget *widget);
164 static void gtk_window_hide (GtkWidget *widget);
165 static void gtk_window_map (GtkWidget *widget);
166 static void gtk_window_unmap (GtkWidget *widget);
167 static void gtk_window_realize (GtkWidget *widget);
168 static void gtk_window_unrealize (GtkWidget *widget);
169 static void gtk_window_size_request (GtkWidget *widget,
170 GtkRequisition *requisition);
171 static void gtk_window_size_allocate (GtkWidget *widget,
172 GtkAllocation *allocation);
173 static gint gtk_window_event (GtkWidget *widget,
175 static gboolean gtk_window_frame_event (GtkWindow *window,
177 static gint gtk_window_configure_event (GtkWidget *widget,
178 GdkEventConfigure *event);
179 static gint gtk_window_key_press_event (GtkWidget *widget,
181 static gint gtk_window_key_release_event (GtkWidget *widget,
183 static gint gtk_window_enter_notify_event (GtkWidget *widget,
184 GdkEventCrossing *event);
185 static gint gtk_window_leave_notify_event (GtkWidget *widget,
186 GdkEventCrossing *event);
187 static gint gtk_window_focus_in_event (GtkWidget *widget,
188 GdkEventFocus *event);
189 static gint gtk_window_focus_out_event (GtkWidget *widget,
190 GdkEventFocus *event);
191 static gint gtk_window_client_event (GtkWidget *widget,
192 GdkEventClient *event);
193 static void gtk_window_check_resize (GtkContainer *container);
194 static gint gtk_window_focus (GtkWidget *widget,
195 GtkDirectionType direction);
196 static void gtk_window_real_set_focus (GtkWindow *window,
199 static void gtk_window_real_activate_default (GtkWindow *window);
200 static void gtk_window_real_activate_focus (GtkWindow *window);
201 static void gtk_window_move_focus (GtkWindow *window,
202 GtkDirectionType dir);
203 static void gtk_window_keys_changed (GtkWindow *window);
204 static void gtk_window_read_rcfiles (GtkWidget *widget,
205 GdkEventClient *event);
206 static void gtk_window_paint (GtkWidget *widget,
208 static gint gtk_window_expose (GtkWidget *widget,
209 GdkEventExpose *event);
210 static void gtk_window_unset_transient_for (GtkWindow *window);
211 static void gtk_window_transient_parent_realized (GtkWidget *parent,
213 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
216 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
218 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
221 static void gtk_window_move_resize (GtkWindow *window);
222 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
224 GdkGeometry *geometry_b,
226 static void gtk_window_constrain_size (GtkWindow *window,
227 GdkGeometry *geometry,
233 static void gtk_window_constrain_position (GtkWindow *window,
238 static void gtk_window_compute_hints (GtkWindow *window,
239 GdkGeometry *new_geometry,
241 static void gtk_window_compute_configure_request (GtkWindow *window,
242 GdkRectangle *request,
243 GdkGeometry *geometry,
246 static void gtk_window_set_default_size_internal (GtkWindow *window,
247 gboolean change_width,
249 gboolean change_height,
251 gboolean is_geometry);
253 static void gtk_window_realize_icon (GtkWindow *window);
254 static void gtk_window_unrealize_icon (GtkWindow *window);
256 static void gtk_window_notify_keys_changed (GtkWindow *window);
257 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
258 static void gtk_window_free_key_hash (GtkWindow *window);
260 static GSList *toplevel_list = NULL;
261 static GHashTable *mnemonic_hash_table = NULL;
262 static GtkBinClass *parent_class = NULL;
263 static guint window_signals[LAST_SIGNAL] = { 0 };
264 static GList *default_icon_list = NULL;
265 static guint default_icon_serial = 0;
266 static gboolean disable_startup_notification = FALSE;
267 static gboolean sent_startup_notification = FALSE;
269 static void gtk_window_set_property (GObject *object,
273 static void gtk_window_get_property (GObject *object,
280 mnemonic_hash (gconstpointer key)
282 const GtkWindowMnemonic *k;
285 k = (GtkWindowMnemonic *)key;
287 h = (gulong) k->window;
288 h ^= k->keyval << 16;
289 h ^= k->keyval >> 16;
295 mnemonic_equal (gconstpointer a, gconstpointer b)
297 const GtkWindowMnemonic *ka;
298 const GtkWindowMnemonic *kb;
300 ka = (GtkWindowMnemonic *)a;
301 kb = (GtkWindowMnemonic *)b;
304 (ka->window == kb->window) &&
305 (ka->keyval == kb->keyval);
309 gtk_window_get_private (GtkWindow *window)
311 GtkWindowPrivate *private;
312 static GQuark private_quark = 0;
315 private_quark = g_quark_from_static_string ("gtk-window-private");
317 private = g_object_get_qdata (G_OBJECT (window), private_quark);
321 private = g_new0 (GtkWindowPrivate, 1);
323 private->fullscreen_initially = FALSE;
324 private->skips_pager = FALSE;
325 private->skips_taskbar = FALSE;
327 g_object_set_qdata_full (G_OBJECT (window), private_quark,
329 (GDestroyNotify) gtk_window_private_finalize);
336 gtk_window_get_type (void)
338 static GType window_type = 0;
342 static const GTypeInfo window_info =
344 sizeof (GtkWindowClass),
345 NULL, /* base_init */
346 NULL, /* base_finalize */
347 (GClassInitFunc) gtk_window_class_init,
348 NULL, /* class_finalize */
349 NULL, /* class_data */
352 (GInstanceInitFunc) gtk_window_init,
355 window_type = g_type_register_static (GTK_TYPE_BIN, "GtkWindow",
363 add_tab_bindings (GtkBindingSet *binding_set,
364 GdkModifierType modifiers,
365 GtkDirectionType direction)
367 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
369 GTK_TYPE_DIRECTION_TYPE, direction);
370 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
372 GTK_TYPE_DIRECTION_TYPE, direction);
376 add_arrow_bindings (GtkBindingSet *binding_set,
378 GtkDirectionType direction)
380 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
382 gtk_binding_entry_add_signal (binding_set, keysym, 0,
384 GTK_TYPE_DIRECTION_TYPE, direction);
385 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
387 GTK_TYPE_DIRECTION_TYPE, direction);
388 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
390 GTK_TYPE_DIRECTION_TYPE, direction);
391 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
393 GTK_TYPE_DIRECTION_TYPE, direction);
398 gtk_window_class_init (GtkWindowClass *klass)
400 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
401 GtkObjectClass *object_class;
402 GtkWidgetClass *widget_class;
403 GtkContainerClass *container_class;
404 GtkBindingSet *binding_set;
406 object_class = (GtkObjectClass*) klass;
407 widget_class = (GtkWidgetClass*) klass;
408 container_class = (GtkContainerClass*) klass;
410 parent_class = g_type_class_peek_parent (klass);
412 mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
414 gobject_class->dispose = gtk_window_dispose;
415 gobject_class->finalize = gtk_window_finalize;
417 gobject_class->set_property = gtk_window_set_property;
418 gobject_class->get_property = gtk_window_get_property;
420 object_class->destroy = gtk_window_destroy;
422 widget_class->show = gtk_window_show;
423 widget_class->hide = gtk_window_hide;
424 widget_class->map = gtk_window_map;
425 widget_class->unmap = gtk_window_unmap;
426 widget_class->realize = gtk_window_realize;
427 widget_class->unrealize = gtk_window_unrealize;
428 widget_class->size_request = gtk_window_size_request;
429 widget_class->size_allocate = gtk_window_size_allocate;
430 widget_class->configure_event = gtk_window_configure_event;
431 widget_class->key_press_event = gtk_window_key_press_event;
432 widget_class->key_release_event = gtk_window_key_release_event;
433 widget_class->enter_notify_event = gtk_window_enter_notify_event;
434 widget_class->leave_notify_event = gtk_window_leave_notify_event;
435 widget_class->focus_in_event = gtk_window_focus_in_event;
436 widget_class->focus_out_event = gtk_window_focus_out_event;
437 widget_class->client_event = gtk_window_client_event;
438 widget_class->focus = gtk_window_focus;
440 widget_class->expose_event = gtk_window_expose;
442 container_class->check_resize = gtk_window_check_resize;
444 klass->set_focus = gtk_window_real_set_focus;
445 klass->frame_event = gtk_window_frame_event;
447 klass->activate_default = gtk_window_real_activate_default;
448 klass->activate_focus = gtk_window_real_activate_focus;
449 klass->move_focus = gtk_window_move_focus;
450 klass->keys_changed = gtk_window_keys_changed;
453 g_object_class_install_property (gobject_class,
455 g_param_spec_enum ("type",
457 _("The type of the window"),
458 GTK_TYPE_WINDOW_TYPE,
460 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
463 g_object_class_install_property (gobject_class,
465 g_param_spec_string ("title",
467 _("The title of the window"),
471 g_object_class_install_property (gobject_class,
473 g_param_spec_boolean ("allow_shrink",
475 /* xgettext:no-c-format */
476 _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
480 g_object_class_install_property (gobject_class,
482 g_param_spec_boolean ("allow_grow",
484 _("If TRUE, users can expand the window beyond its minimum size"),
488 g_object_class_install_property (gobject_class,
490 g_param_spec_boolean ("resizable",
492 _("If TRUE, users can resize the window"),
496 g_object_class_install_property (gobject_class,
498 g_param_spec_boolean ("modal",
500 _("If TRUE, the window is modal (other windows are not usable while this one is up)"),
504 g_object_class_install_property (gobject_class,
506 g_param_spec_enum ("window_position",
507 _("Window Position"),
508 _("The initial position of the window"),
509 GTK_TYPE_WINDOW_POSITION,
513 g_object_class_install_property (gobject_class,
515 g_param_spec_int ("default_width",
517 _("The default width of the window, used when initially showing the window"),
523 g_object_class_install_property (gobject_class,
525 g_param_spec_int ("default_height",
527 _("The default height of the window, used when initially showing the window"),
533 g_object_class_install_property (gobject_class,
534 PROP_DESTROY_WITH_PARENT,
535 g_param_spec_boolean ("destroy_with_parent",
536 _("Destroy with Parent"),
537 _("If this window should be destroyed when the parent is destroyed"),
541 g_object_class_install_property (gobject_class,
543 g_param_spec_object ("icon",
545 _("Icon for this window"),
549 g_object_class_install_property (gobject_class,
551 g_param_spec_object ("screen",
553 _("The screen where this window will be displayed"),
557 g_object_class_install_property (gobject_class,
559 g_param_spec_boolean ("is_active",
561 _("Whether the toplevel is the current active window"),
565 g_object_class_install_property (gobject_class,
566 PROP_HAS_TOPLEVEL_FOCUS,
567 g_param_spec_boolean ("has_toplevel_focus",
568 _("Focus in Toplevel"),
569 _("Whether the input focus is within this GtkWindow"),
573 g_object_class_install_property (gobject_class,
575 g_param_spec_enum ("type_hint",
577 _("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
578 GDK_TYPE_WINDOW_TYPE_HINT,
579 GDK_WINDOW_TYPE_HINT_NORMAL,
582 g_object_class_install_property (gobject_class,
583 PROP_SKIP_TASKBAR_HINT,
584 g_param_spec_boolean ("skip_taskbar_hint",
586 _("TRUE if the window should not be in the task bar."),
590 g_object_class_install_property (gobject_class,
591 PROP_SKIP_PAGER_HINT,
592 g_param_spec_boolean ("skip_pager_hint",
594 _("TRUE if the window should not be in the pager."),
598 window_signals[SET_FOCUS] =
599 g_signal_new ("set_focus",
600 G_TYPE_FROM_CLASS (gobject_class),
602 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
604 _gtk_marshal_VOID__OBJECT,
608 window_signals[FRAME_EVENT] =
609 g_signal_new ("frame_event",
610 G_TYPE_FROM_CLASS (gobject_class),
612 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
613 _gtk_boolean_handled_accumulator, NULL,
614 _gtk_marshal_BOOLEAN__BOXED,
618 window_signals[ACTIVATE_FOCUS] =
619 g_signal_new ("activate_focus",
620 G_TYPE_FROM_CLASS (gobject_class),
621 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
622 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
624 _gtk_marshal_VOID__VOID,
628 window_signals[ACTIVATE_DEFAULT] =
629 g_signal_new ("activate_default",
630 G_TYPE_FROM_CLASS (gobject_class),
631 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
632 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
634 _gtk_marshal_VOID__VOID,
638 window_signals[MOVE_FOCUS] =
639 g_signal_new ("move_focus",
640 G_TYPE_FROM_CLASS (gobject_class),
641 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
642 G_STRUCT_OFFSET (GtkWindowClass, move_focus),
644 _gtk_marshal_VOID__ENUM,
647 GTK_TYPE_DIRECTION_TYPE);
649 window_signals[KEYS_CHANGED] =
650 g_signal_new ("keys_changed",
651 G_TYPE_FROM_CLASS (gobject_class),
653 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
655 _gtk_marshal_VOID__VOID,
663 binding_set = gtk_binding_set_by_class (klass);
665 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
666 "activate_focus", 0);
667 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
668 "activate_focus", 0);
670 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
671 "activate_default", 0);
673 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
674 "activate_default", 0);
676 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
677 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
678 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
679 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
681 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
682 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
683 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
684 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
688 gtk_window_init (GtkWindow *window)
690 GdkColormap *colormap;
692 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
693 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
695 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
697 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
699 window->title = NULL;
700 window->wmclass_name = g_strdup (g_get_prgname ());
701 window->wmclass_class = g_strdup (gdk_get_program_class ());
702 window->wm_role = NULL;
703 window->geometry_info = NULL;
704 window->type = GTK_WINDOW_TOPLEVEL;
705 window->focus_widget = NULL;
706 window->default_widget = NULL;
707 window->configure_request_count = 0;
708 window->allow_shrink = FALSE;
709 window->allow_grow = TRUE;
710 window->configure_notify_received = FALSE;
711 window->position = GTK_WIN_POS_NONE;
712 window->need_default_size = TRUE;
713 window->need_default_position = TRUE;
714 window->modal = FALSE;
715 window->frame = NULL;
716 window->has_frame = FALSE;
717 window->frame_left = 0;
718 window->frame_right = 0;
719 window->frame_top = 0;
720 window->frame_bottom = 0;
721 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
722 window->gravity = GDK_GRAVITY_NORTH_WEST;
723 window->decorated = TRUE;
724 window->mnemonic_modifier = GDK_MOD1_MASK;
725 window->screen = gdk_screen_get_default ();
727 colormap = _gtk_widget_peek_colormap ();
729 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
731 g_object_ref (window);
732 gtk_object_sink (GTK_OBJECT (window));
733 window->has_user_ref_count = TRUE;
734 toplevel_list = g_slist_prepend (toplevel_list, window);
736 gtk_decorated_window_init (window);
738 g_signal_connect (window,
740 G_CALLBACK (gtk_window_event),
745 gtk_window_set_property (GObject *object,
752 window = GTK_WINDOW (object);
757 window->type = g_value_get_enum (value);
760 gtk_window_set_title (window, g_value_get_string (value));
762 case PROP_ALLOW_SHRINK:
763 window->allow_shrink = g_value_get_boolean (value);
764 gtk_widget_queue_resize (GTK_WIDGET (window));
766 case PROP_ALLOW_GROW:
767 window->allow_grow = g_value_get_boolean (value);
768 gtk_widget_queue_resize (GTK_WIDGET (window));
769 g_object_notify (G_OBJECT (window), "resizable");
772 window->allow_grow = g_value_get_boolean (value);
773 gtk_widget_queue_resize (GTK_WIDGET (window));
774 g_object_notify (G_OBJECT (window), "allow_grow");
777 gtk_window_set_modal (window, g_value_get_boolean (value));
780 gtk_window_set_position (window, g_value_get_enum (value));
782 case PROP_DEFAULT_WIDTH:
783 gtk_window_set_default_size_internal (window,
784 TRUE, g_value_get_int (value),
787 case PROP_DEFAULT_HEIGHT:
788 gtk_window_set_default_size_internal (window,
790 TRUE, g_value_get_int (value), FALSE);
792 case PROP_DESTROY_WITH_PARENT:
793 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
796 gtk_window_set_icon (window,
797 g_value_get_object (value));
800 gtk_window_set_screen (window, g_value_get_object (value));
803 gtk_window_set_type_hint (window,
804 g_value_get_enum (value));
806 case PROP_SKIP_TASKBAR_HINT:
807 gtk_window_set_skip_taskbar_hint (window,
808 g_value_get_boolean (value));
810 case PROP_SKIP_PAGER_HINT:
811 gtk_window_set_skip_pager_hint (window,
812 g_value_get_boolean (value));
821 gtk_window_get_property (GObject *object,
828 window = GTK_WINDOW (object);
832 GtkWindowGeometryInfo *info;
834 g_value_set_enum (value, window->type);
837 g_value_set_string (value, window->title);
839 case PROP_ALLOW_SHRINK:
840 g_value_set_boolean (value, window->allow_shrink);
842 case PROP_ALLOW_GROW:
843 g_value_set_boolean (value, window->allow_grow);
846 g_value_set_boolean (value, window->allow_grow);
849 g_value_set_boolean (value, window->modal);
852 g_value_set_enum (value, window->position);
854 case PROP_DEFAULT_WIDTH:
855 info = gtk_window_get_geometry_info (window, FALSE);
857 g_value_set_int (value, -1);
859 g_value_set_int (value, info->default_width);
861 case PROP_DEFAULT_HEIGHT:
862 info = gtk_window_get_geometry_info (window, FALSE);
864 g_value_set_int (value, -1);
866 g_value_set_int (value, info->default_height);
868 case PROP_DESTROY_WITH_PARENT:
869 g_value_set_boolean (value, window->destroy_with_parent);
872 g_value_set_object (value, gtk_window_get_icon (window));
875 g_value_set_object (value, window->screen);
878 g_value_set_boolean (value, window->is_active);
880 case PROP_HAS_TOPLEVEL_FOCUS:
881 g_value_set_boolean (value, window->has_toplevel_focus);
884 g_value_set_enum (value,
887 case PROP_SKIP_TASKBAR_HINT:
888 g_value_set_boolean (value,
889 gtk_window_get_skip_taskbar_hint (window));
891 case PROP_SKIP_PAGER_HINT:
892 g_value_set_boolean (value,
893 gtk_window_get_skip_pager_hint (window));
896 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
903 * @type: type of window
905 * Creates a new #GtkWindow, which is a toplevel window that can
906 * contain other widgets. Nearly always, the type of the window should
907 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
908 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
909 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
910 * dialogs, though in some other toolkits dialogs are called "popups".
911 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
912 * On X11, popup windows are not controlled by the <link
913 * linkend="gtk-X11-arch">window manager</link>.
915 * If you simply want an undecorated window (no window borders), use
916 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
918 * Return value: a new #GtkWindow.
921 gtk_window_new (GtkWindowType type)
925 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
927 window = g_object_new (GTK_TYPE_WINDOW, NULL);
931 return GTK_WIDGET (window);
935 * gtk_window_set_title:
936 * @window: a #GtkWindow
937 * @title: title of the window
939 * Sets the title of the #GtkWindow. The title of a window will be
940 * displayed in its title bar; on the X Window System, the title bar
941 * is rendered by the <link linkend="gtk-X11-arch">window
942 * manager</link>, so exactly how the title appears to users may vary
943 * according to a user's exact configuration. The title should help a
944 * user distinguish this window from other windows they may have
945 * open. A good title might include the application name and current
946 * document filename, for example.
950 gtk_window_set_title (GtkWindow *window,
953 g_return_if_fail (GTK_IS_WINDOW (window));
956 g_free (window->title);
957 window->title = g_strdup (title);
959 if (GTK_WIDGET_REALIZED (window))
961 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
963 gtk_decorated_window_set_title (window, title);
966 g_object_notify (G_OBJECT (window), "title");
970 * gtk_window_get_title:
971 * @window: a #GtkWindow
973 * Retrieves the title of the window. See gtk_window_set_title().
975 * Return value: the title of the window, or %NULL if none has
976 * been set explicitely. The returned string is owned by the widget
977 * and must not be modified or freed.
979 G_CONST_RETURN gchar *
980 gtk_window_get_title (GtkWindow *window)
982 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
984 return window->title;
988 * gtk_window_set_wmclass:
989 * @window: a #GtkWindow
990 * @wmclass_name: window name hint
991 * @wmclass_class: window class hint
993 * Don't use this function. It sets the X Window System "class" and
994 * "name" hints for a window. According to the ICCCM, you should
995 * always set these to the same value for all windows in an
996 * application, and GTK+ sets them to that value by default, so calling
997 * this function is sort of pointless. However, you may want to call
998 * gtk_window_set_role() on each window in your application, for the
999 * benefit of the session manager. Setting the role allows the window
1000 * manager to restore window positions when loading a saved session.
1004 gtk_window_set_wmclass (GtkWindow *window,
1005 const gchar *wmclass_name,
1006 const gchar *wmclass_class)
1008 g_return_if_fail (GTK_IS_WINDOW (window));
1010 g_free (window->wmclass_name);
1011 window->wmclass_name = g_strdup (wmclass_name);
1013 g_free (window->wmclass_class);
1014 window->wmclass_class = g_strdup (wmclass_class);
1016 if (GTK_WIDGET_REALIZED (window))
1017 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1021 * gtk_window_set_role:
1022 * @window: a #GtkWindow
1023 * @role: unique identifier for the window to be used when restoring a session
1025 * This function is only useful on X11, not with other GTK+ targets.
1027 * In combination with the window title, the window role allows a
1028 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1029 * same" window when an application is restarted. So for example you
1030 * might set the "toolbox" role on your app's toolbox window, so that
1031 * when the user restarts their session, the window manager can put
1032 * the toolbox back in the same place.
1034 * If a window already has a unique title, you don't need to set the
1035 * role, since the WM can use the title to identify the window when
1036 * restoring the session.
1040 gtk_window_set_role (GtkWindow *window,
1043 g_return_if_fail (GTK_IS_WINDOW (window));
1045 if (role == window->wm_role)
1048 g_free (window->wm_role);
1049 window->wm_role = g_strdup (role);
1051 if (GTK_WIDGET_REALIZED (window))
1052 g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
1056 * gtk_window_get_role:
1057 * @window: a #GtkWindow
1059 * Returns the role of the window. See gtk_window_set_role() for
1060 * further explanation.
1062 * Return value: the role of the window if set, or %NULL. The
1063 * returned is owned by the widget and must not be modified
1066 G_CONST_RETURN gchar *
1067 gtk_window_get_role (GtkWindow *window)
1069 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1071 return window->wm_role;
1075 * gtk_window_set_focus:
1076 * @window: a #GtkWindow
1077 * @focus: widget to be the new focus widget, or %NULL to unset
1078 * any focus widget for the toplevel window.
1080 * If @focus is not the current focus widget, and is focusable, sets
1081 * it as the focus widget for the window. If @focus is %NULL, unsets
1082 * the focus widget for this window. To set the focus to a particular
1083 * widget in the toplevel, it is usually more convenient to use
1084 * gtk_widget_grab_focus() instead of this function.
1087 gtk_window_set_focus (GtkWindow *window,
1090 g_return_if_fail (GTK_IS_WINDOW (window));
1093 g_return_if_fail (GTK_IS_WIDGET (focus));
1094 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1098 gtk_widget_grab_focus (focus);
1101 /* Clear the existing focus chain, so that when we focus into
1102 * the window again, we start at the beginnning.
1104 GtkWidget *widget = window->focus_widget;
1107 while (widget->parent)
1109 widget = widget->parent;
1110 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1114 _gtk_window_internal_set_focus (window, NULL);
1119 _gtk_window_internal_set_focus (GtkWindow *window,
1122 g_return_if_fail (GTK_IS_WINDOW (window));
1124 if ((window->focus_widget != focus) ||
1125 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1126 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1130 * gtk_window_set_default:
1131 * @window: a #GtkWindow
1132 * @default_widget: widget to be the default, or %NULL to unset the
1133 * default widget for the toplevel.
1135 * The default widget is the widget that's activated when the user
1136 * presses Enter in a dialog (for example). This function sets or
1137 * unsets the default widget for a #GtkWindow about. When setting
1138 * (rather than unsetting) the default widget it's generally easier to
1139 * call gtk_widget_grab_focus() on the widget. Before making a widget
1140 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1141 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1144 gtk_window_set_default (GtkWindow *window,
1145 GtkWidget *default_widget)
1147 g_return_if_fail (GTK_IS_WINDOW (window));
1150 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1152 if (window->default_widget != default_widget)
1154 GtkWidget *old_default_widget = NULL;
1157 g_object_ref (default_widget);
1159 if (window->default_widget)
1161 old_default_widget = window->default_widget;
1163 if (window->focus_widget != window->default_widget ||
1164 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1165 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1166 gtk_widget_queue_draw (window->default_widget);
1169 window->default_widget = default_widget;
1171 if (window->default_widget)
1173 if (window->focus_widget == NULL ||
1174 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1175 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1176 gtk_widget_queue_draw (window->default_widget);
1179 if (old_default_widget)
1180 g_object_notify (G_OBJECT (old_default_widget), "has_default");
1184 g_object_notify (G_OBJECT (default_widget), "has_default");
1185 g_object_unref (default_widget);
1191 gtk_window_set_policy (GtkWindow *window,
1192 gboolean allow_shrink,
1193 gboolean allow_grow,
1194 gboolean auto_shrink)
1196 g_return_if_fail (GTK_IS_WINDOW (window));
1198 window->allow_shrink = (allow_shrink != FALSE);
1199 window->allow_grow = (allow_grow != FALSE);
1201 g_object_freeze_notify (G_OBJECT (window));
1202 g_object_notify (G_OBJECT (window), "allow_shrink");
1203 g_object_notify (G_OBJECT (window), "allow_grow");
1204 g_object_notify (G_OBJECT (window), "resizable");
1205 g_object_thaw_notify (G_OBJECT (window));
1207 gtk_widget_queue_resize (GTK_WIDGET (window));
1211 handle_keys_changed (gpointer data)
1215 GDK_THREADS_ENTER ();
1216 window = GTK_WINDOW (data);
1218 if (window->keys_changed_handler)
1220 gtk_idle_remove (window->keys_changed_handler);
1221 window->keys_changed_handler = 0;
1224 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1225 GDK_THREADS_LEAVE ();
1231 gtk_window_notify_keys_changed (GtkWindow *window)
1233 if (!window->keys_changed_handler)
1234 window->keys_changed_handler = gtk_idle_add (handle_keys_changed, window);
1238 * gtk_window_add_accel_group:
1239 * @window: window to attach accelerator group to
1240 * @accel_group: a #GtkAccelGroup
1242 * Associate @accel_group with @window, such that calling
1243 * gtk_accel_groups_activate() on @window will activate accelerators
1247 gtk_window_add_accel_group (GtkWindow *window,
1248 GtkAccelGroup *accel_group)
1250 g_return_if_fail (GTK_IS_WINDOW (window));
1251 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1253 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1254 g_signal_connect_object (accel_group, "accel_changed",
1255 G_CALLBACK (gtk_window_notify_keys_changed),
1256 window, G_CONNECT_SWAPPED);
1260 * gtk_window_remove_accel_group:
1261 * @window: a #GtkWindow
1262 * @accel_group: a #GtkAccelGroup
1264 * Reverses the effects of gtk_window_add_accel_group().
1267 gtk_window_remove_accel_group (GtkWindow *window,
1268 GtkAccelGroup *accel_group)
1270 g_return_if_fail (GTK_IS_WINDOW (window));
1271 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1273 g_signal_handlers_disconnect_by_func (accel_group,
1274 gtk_window_notify_keys_changed,
1276 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1280 * gtk_window_add_mnemonic:
1281 * @window: a #GtkWindow
1282 * @keyval: the mnemonic
1283 * @target: the widget that gets activated by the mnemonic
1285 * Adds a mnemonic to this window.
1288 gtk_window_add_mnemonic (GtkWindow *window,
1292 GtkWindowMnemonic key;
1293 GtkWindowMnemonic *mnemonic;
1295 g_return_if_fail (GTK_IS_WINDOW (window));
1296 g_return_if_fail (GTK_IS_WIDGET (target));
1298 key.window = window;
1299 key.keyval = keyval;
1300 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1304 g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1305 mnemonic->targets = g_slist_append (mnemonic->targets, target);
1309 mnemonic = g_new (GtkWindowMnemonic, 1);
1311 mnemonic->targets = g_slist_prepend (NULL, target);
1312 g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1314 gtk_window_notify_keys_changed (window);
1318 * gtk_window_remove_mnemonic:
1319 * @window: a #GtkWindow
1320 * @keyval: the mnemonic
1321 * @target: the widget that gets activated by the mnemonic
1323 * Removes a mnemonic from this window.
1326 gtk_window_remove_mnemonic (GtkWindow *window,
1330 GtkWindowMnemonic key;
1331 GtkWindowMnemonic *mnemonic;
1333 g_return_if_fail (GTK_IS_WINDOW (window));
1334 g_return_if_fail (GTK_IS_WIDGET (target));
1336 key.window = window;
1337 key.keyval = keyval;
1338 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1340 g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1342 mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1343 if (mnemonic->targets == NULL)
1345 g_hash_table_remove (mnemonic_hash_table, mnemonic);
1348 gtk_window_notify_keys_changed (window);
1352 * gtk_window_mnemonic_activate:
1353 * @window: a #GtkWindow
1354 * @keyval: the mnemonic
1355 * @modifier: the modifiers
1356 * @returns: %TRUE if the activation is done.
1358 * Activates the targets associated with the mnemonic.
1361 gtk_window_mnemonic_activate (GtkWindow *window,
1363 GdkModifierType modifier)
1365 GtkWindowMnemonic key;
1366 GtkWindowMnemonic *mnemonic;
1368 GtkWidget *widget, *chosen_widget;
1369 gboolean overloaded;
1371 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1373 if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1376 key.window = window;
1377 key.keyval = keyval;
1378 mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1384 chosen_widget = NULL;
1385 list = mnemonic->targets;
1388 widget = GTK_WIDGET (list->data);
1390 if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1391 GTK_WIDGET_MAPPED (widget))
1399 chosen_widget = widget;
1401 list = g_slist_next (list);
1406 /* For round robin we put the activated entry on
1407 * the end of the list after activation
1409 mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1410 mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1412 return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1418 * gtk_window_set_mnemonic_modifier:
1419 * @window: a #GtkWindow
1420 * @modifier: the modifier mask used to activate
1421 * mnemonics on this window.
1423 * Sets the mnemonic modifier for this window.
1426 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1427 GdkModifierType modifier)
1429 g_return_if_fail (GTK_IS_WINDOW (window));
1430 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1432 window->mnemonic_modifier = modifier;
1433 gtk_window_notify_keys_changed (window);
1437 * gtk_window_get_mnemonic_modifier:
1438 * @window: a #GtkWindow
1440 * Returns the mnemonic modifier for this window. See
1441 * gtk_window_set_mnemonic_modifier().
1443 * Return value: the modifier mask used to activate
1444 * mnemonics on this window.
1447 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1449 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1451 return window->mnemonic_modifier;
1455 * gtk_window_set_position:
1456 * @window: a #GtkWindow.
1457 * @position: a position constraint.
1459 * Sets a position constraint for this window. If the old or new
1460 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1461 * the window to be repositioned to satisfy the new constraint.
1464 gtk_window_set_position (GtkWindow *window,
1465 GtkWindowPosition position)
1467 g_return_if_fail (GTK_IS_WINDOW (window));
1469 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1470 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1472 GtkWindowGeometryInfo *info;
1474 info = gtk_window_get_geometry_info (window, TRUE);
1476 /* this flag causes us to re-request the CENTER_ALWAYS
1477 * constraint in gtk_window_move_resize(), see
1478 * comment in that function.
1480 info->position_constraints_changed = TRUE;
1482 gtk_widget_queue_resize (GTK_WIDGET (window));
1485 window->position = position;
1487 g_object_notify (G_OBJECT (window), "window_position");
1491 * gtk_window_activate_focus:
1492 * @window: a #GtkWindow
1494 * Activates the current focused widget within the window.
1496 * Return value: %TRUE if a widget got activated.
1499 gtk_window_activate_focus (GtkWindow *window)
1501 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1503 if (window->focus_widget)
1505 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1506 gtk_widget_activate (window->focus_widget);
1514 * gtk_window_get_focus:
1515 * @window: a #GtkWindow
1517 * Retrieves the current focused widget within the window.
1518 * Note that this is the widget that would have the focus
1519 * if the toplevel window focused; if the toplevel window
1520 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1521 * not be %TRUE for the widget.
1523 * Return value: the currently focused widget.
1526 gtk_window_get_focus (GtkWindow *window)
1528 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1530 return window->focus_widget;
1534 * gtk_window_activate_default:
1535 * @window: a #GtkWindow
1537 * Activates the default widget for the window, unless the current
1538 * focused widget has been configured to receive the default action
1539 * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
1540 * focused widget is activated.
1542 * Return value: %TRUE if a widget got activated.
1545 gtk_window_activate_default (GtkWindow *window)
1547 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1549 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1550 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1552 gtk_widget_activate (window->default_widget);
1555 else if (window->focus_widget)
1557 if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1558 gtk_widget_activate (window->focus_widget);
1566 * gtk_window_set_modal:
1567 * @window: a #GtkWindow
1568 * @modal: whether the window is modal
1570 * Sets a window modal or non-modal. Modal windows prevent interaction
1571 * with other windows in the same application. To keep modal dialogs
1572 * on top of main application windows, use
1573 * gtk_window_set_transient_for() to make the dialog transient for the
1574 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1575 * will then disallow lowering the dialog below the parent.
1580 gtk_window_set_modal (GtkWindow *window,
1583 g_return_if_fail (GTK_IS_WINDOW (window));
1585 window->modal = modal != FALSE;
1587 /* adjust desired modality state */
1588 if (GTK_WIDGET_VISIBLE (window) && window->modal)
1589 gtk_grab_add (GTK_WIDGET (window));
1591 gtk_grab_remove (GTK_WIDGET (window));
1593 g_object_notify (G_OBJECT (window), "modal");
1597 * gtk_window_get_modal:
1598 * @window: a #GtkWindow
1600 * Returns whether the window is modal. See gtk_window_set_modal().
1602 * Return value: %TRUE if the window is set to be modal and
1603 * establishes a grab when shown
1606 gtk_window_get_modal (GtkWindow *window)
1608 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1610 return window->modal;
1614 * gtk_window_list_toplevels:
1616 * Returns a list of all existing toplevel windows. The widgets
1617 * in the list are not individually referenced. If you want
1618 * to iterate through the list and perform actions involving
1619 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1620 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1621 * then unref all the widgets afterwards.
1623 * Return value: list of toplevel widgets
1626 gtk_window_list_toplevels (void)
1631 for (slist = toplevel_list; slist; slist = slist->next)
1632 list = g_list_prepend (list, slist->data);
1638 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1640 GList *embedded_windows;
1642 g_return_if_fail (GTK_IS_WINDOW (window));
1644 embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1645 if (embedded_windows)
1646 g_object_steal_qdata (G_OBJECT (window),
1647 g_quark_from_static_string ("gtk-embedded"));
1648 embedded_windows = g_list_prepend (embedded_windows,
1649 GUINT_TO_POINTER (xid));
1651 g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
1654 (GDestroyNotify) g_list_free : NULL);
1658 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1660 GList *embedded_windows;
1663 g_return_if_fail (GTK_IS_WINDOW (window));
1665 embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1666 if (embedded_windows)
1667 g_object_steal_qdata (G_OBJECT (window),
1668 g_quark_from_static_string ("gtk-embedded"));
1670 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1673 embedded_windows = g_list_remove_link (embedded_windows, node);
1674 g_list_free_1 (node);
1677 g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
1680 (GDestroyNotify) g_list_free : NULL);
1684 _gtk_window_reposition (GtkWindow *window,
1688 g_return_if_fail (GTK_IS_WINDOW (window));
1690 gtk_window_move (window, x, y);
1694 gtk_window_dispose (GObject *object)
1696 GtkWindow *window = GTK_WINDOW (object);
1698 gtk_window_set_focus (window, NULL);
1699 gtk_window_set_default (window, NULL);
1701 G_OBJECT_CLASS (parent_class)->dispose (object);
1705 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1707 gtk_widget_destroy (GTK_WIDGET (child));
1711 connect_parent_destroyed (GtkWindow *window)
1713 if (window->transient_parent)
1715 g_signal_connect (window->transient_parent,
1717 G_CALLBACK (parent_destroyed_callback),
1723 disconnect_parent_destroyed (GtkWindow *window)
1725 if (window->transient_parent)
1727 g_signal_handlers_disconnect_by_func (window->transient_parent,
1728 parent_destroyed_callback,
1734 gtk_window_transient_parent_realized (GtkWidget *parent,
1737 if (GTK_WIDGET_REALIZED (window))
1738 gdk_window_set_transient_for (window->window, parent->window);
1742 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1745 if (GTK_WIDGET_REALIZED (window))
1746 gdk_property_delete (window->window,
1747 gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1751 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
1755 gtk_window_set_screen (window, parent->screen);
1759 gtk_window_unset_transient_for (GtkWindow *window)
1761 if (window->transient_parent)
1763 g_signal_handlers_disconnect_by_func (window->transient_parent,
1764 gtk_window_transient_parent_realized,
1766 g_signal_handlers_disconnect_by_func (window->transient_parent,
1767 gtk_window_transient_parent_unrealized,
1769 g_signal_handlers_disconnect_by_func (window->transient_parent,
1770 gtk_window_transient_parent_screen_changed,
1772 g_signal_handlers_disconnect_by_func (window->transient_parent,
1773 gtk_widget_destroyed,
1774 &window->transient_parent);
1776 if (window->destroy_with_parent)
1777 disconnect_parent_destroyed (window);
1779 window->transient_parent = NULL;
1784 * gtk_window_set_transient_for:
1785 * @window: a #GtkWindow
1786 * @parent: parent window
1788 * Dialog windows should be set transient for the main application
1789 * window they were spawned from. This allows <link
1790 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1791 * dialog on top of the main window, or center the dialog over the
1792 * main window. gtk_dialog_new_with_buttons() and other convenience
1793 * functions in GTK+ will sometimes call
1794 * gtk_window_set_transient_for() on your behalf.
1796 * On Windows, this function will and put the child window
1797 * on top of the parent, much as the window manager would have
1802 gtk_window_set_transient_for (GtkWindow *window,
1805 g_return_if_fail (GTK_IS_WINDOW (window));
1806 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1807 g_return_if_fail (window != parent);
1810 if (window->transient_parent)
1812 if (GTK_WIDGET_REALIZED (window) &&
1813 GTK_WIDGET_REALIZED (window->transient_parent) &&
1814 (!parent || !GTK_WIDGET_REALIZED (parent)))
1815 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1816 GTK_WIDGET (window));
1818 gtk_window_unset_transient_for (window);
1821 window->transient_parent = parent;
1825 g_signal_connect (parent, "destroy",
1826 G_CALLBACK (gtk_widget_destroyed),
1827 &window->transient_parent);
1828 g_signal_connect (parent, "realize",
1829 G_CALLBACK (gtk_window_transient_parent_realized),
1831 g_signal_connect (parent, "unrealize",
1832 G_CALLBACK (gtk_window_transient_parent_unrealized),
1834 g_signal_connect (parent, "notify::screen",
1835 G_CALLBACK (gtk_window_transient_parent_screen_changed),
1838 gtk_window_set_screen (window, parent->screen);
1840 if (window->destroy_with_parent)
1841 connect_parent_destroyed (window);
1843 if (GTK_WIDGET_REALIZED (window) &&
1844 GTK_WIDGET_REALIZED (parent))
1845 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1846 GTK_WIDGET (window));
1851 * gtk_window_get_transient_for:
1852 * @window: a #GtkWindow
1854 * Fetches the transient parent for this window. See
1855 * gtk_window_set_transient_for().
1857 * Return value: the transient parent for this window, or %NULL
1858 * if no transient parent has been set.
1861 gtk_window_get_transient_for (GtkWindow *window)
1863 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1865 return window->transient_parent;
1869 * gtk_window_set_type_hint:
1870 * @window: a #GtkWindow
1871 * @hint: the window type
1873 * By setting the type hint for the window, you allow the window
1874 * manager to decorate and handle the window in a way which is
1875 * suitable to the function of the window in your application.
1877 * This function should be called before the window becomes visible.
1879 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1880 * will sometimes call gtk_window_set_type_hint() on your behalf.
1884 gtk_window_set_type_hint (GtkWindow *window,
1885 GdkWindowTypeHint hint)
1887 g_return_if_fail (GTK_IS_WINDOW (window));
1888 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1889 window->type_hint = hint;
1893 * gtk_window_get_type_hint:
1894 * @window: a #GtkWindow
1896 * Gets the type hint for this window. See gtk_window_set_type_hint().
1898 * Return value: the type hint for @window.
1901 gtk_window_get_type_hint (GtkWindow *window)
1903 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1905 return window->type_hint;
1909 * gtk_window_set_skip_taskbar_hint:
1910 * @window: a #GtkWindow
1911 * @setting: %TRUE to keep this window from appearing in the task bar
1913 * Windows may set a hint asking the desktop environment not to display
1914 * the window in the task bar. This function toggles this hint.
1919 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
1922 GtkWindowPrivate *priv;
1924 g_return_if_fail (GTK_IS_WINDOW (window));
1926 priv = gtk_window_get_private (window);
1928 setting = setting != FALSE;
1930 if (priv->skips_taskbar != setting)
1932 priv->skips_taskbar = setting;
1933 if (GTK_WIDGET_REALIZED (window))
1934 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
1935 priv->skips_taskbar);
1936 g_object_notify (G_OBJECT (window), "skip_taskbar_hint");
1941 * gtk_window_get_skip_taskbar_hint:
1942 * @window: a #GtkWindow
1944 * Gets the value set by gtk_window_set_skip_taskbar_hint()
1946 * Return value: %TRUE if window shouldn't be in taskbar
1951 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
1953 GtkWindowPrivate *priv;
1955 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1957 priv = gtk_window_get_private (window);
1959 return priv->skips_taskbar;
1963 * gtk_window_set_skip_pager_hint:
1964 * @window: a #GtkWindow
1965 * @setting: %TRUE to keep this window from appearing in the pager
1967 * Windows may set a hint asking the desktop environment not to display
1968 * the window in the pager. This function toggles this hint.
1969 * (A "pager" is any desktop navigation tool such as a workspace
1970 * switcher that displays a thumbnail representation of the windows
1976 gtk_window_set_skip_pager_hint (GtkWindow *window,
1979 GtkWindowPrivate *priv;
1981 g_return_if_fail (GTK_IS_WINDOW (window));
1983 priv = gtk_window_get_private (window);
1985 setting = setting != FALSE;
1987 if (priv->skips_pager != setting)
1989 priv->skips_pager = setting;
1990 if (GTK_WIDGET_REALIZED (window))
1991 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
1993 g_object_notify (G_OBJECT (window), "skip_pager_hint");
1998 * gtk_window_get_skip_pager_hint:
1999 * @window: a #GtkWindow
2001 * Gets the value set by gtk_window_set_skip_pager_hint().
2003 * Return value: %TRUE if window shouldn't be in pager
2008 gtk_window_get_skip_pager_hint (GtkWindow *window)
2010 GtkWindowPrivate *priv;
2012 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2014 priv = gtk_window_get_private (window);
2016 return priv->skips_pager;
2020 * gtk_window_set_destroy_with_parent:
2021 * @window: a #GtkWindow
2022 * @setting: whether to destroy @window with its transient parent
2024 * If @setting is %TRUE, then destroying the transient parent of @window
2025 * will also destroy @window itself. This is useful for dialogs that
2026 * shouldn't persist beyond the lifetime of the main window they're
2027 * associated with, for example.
2030 gtk_window_set_destroy_with_parent (GtkWindow *window,
2033 g_return_if_fail (GTK_IS_WINDOW (window));
2035 if (window->destroy_with_parent == (setting != FALSE))
2038 if (window->destroy_with_parent)
2040 disconnect_parent_destroyed (window);
2044 connect_parent_destroyed (window);
2047 window->destroy_with_parent = setting;
2049 g_object_notify (G_OBJECT (window), "destroy_with_parent");
2053 * gtk_window_get_destroy_with_parent:
2054 * @window: a #GtkWindow
2056 * Returns whether the window will be destroyed with its transient parent. See
2057 * gtk_window_set_destroy_with_parent ().
2059 * Return value: %TRUE if the window will be destroyed with its transient parent.
2062 gtk_window_get_destroy_with_parent (GtkWindow *window)
2064 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2066 return window->destroy_with_parent;
2069 static GtkWindowGeometryInfo*
2070 gtk_window_get_geometry_info (GtkWindow *window,
2073 GtkWindowGeometryInfo *info;
2075 info = window->geometry_info;
2076 if (!info && create)
2078 info = g_new0 (GtkWindowGeometryInfo, 1);
2080 info->default_width = -1;
2081 info->default_height = -1;
2082 info->resize_width = -1;
2083 info->resize_height = -1;
2084 info->initial_x = 0;
2085 info->initial_y = 0;
2086 info->initial_pos_set = FALSE;
2087 info->default_is_geometry = FALSE;
2088 info->position_constraints_changed = FALSE;
2089 info->last.configure_request.x = 0;
2090 info->last.configure_request.y = 0;
2091 info->last.configure_request.width = -1;
2092 info->last.configure_request.height = -1;
2093 info->widget = NULL;
2095 window->geometry_info = info;
2102 * gtk_window_set_geometry_hints:
2103 * @window: a #GtkWindow
2104 * @geometry_widget: widget the geometry hints will be applied to
2105 * @geometry: struct containing geometry information
2106 * @geom_mask: mask indicating which struct fields should be paid attention to
2108 * This function sets up hints about how a window can be resized by
2109 * the user. You can set a minimum and maximum size; allowed resize
2110 * increments (e.g. for xterm, you can only resize by the size of a
2111 * character); aspect ratios; and more. See the #GdkGeometry struct.
2115 gtk_window_set_geometry_hints (GtkWindow *window,
2116 GtkWidget *geometry_widget,
2117 GdkGeometry *geometry,
2118 GdkWindowHints geom_mask)
2120 GtkWindowGeometryInfo *info;
2122 g_return_if_fail (GTK_IS_WINDOW (window));
2123 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2125 info = gtk_window_get_geometry_info (window, TRUE);
2128 g_signal_handlers_disconnect_by_func (info->widget,
2129 gtk_widget_destroyed,
2132 info->widget = geometry_widget;
2134 g_signal_connect (geometry_widget, "destroy",
2135 G_CALLBACK (gtk_widget_destroyed),
2139 info->geometry = *geometry;
2141 /* We store gravity in window->gravity not in the hints. */
2142 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2144 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2146 gtk_window_set_gravity (window, geometry->win_gravity);
2149 gtk_widget_queue_resize (GTK_WIDGET (window));
2153 * gtk_window_set_decorated:
2154 * @window: a #GtkWindow
2155 * @setting: %TRUE to decorate the window
2157 * By default, windows are decorated with a title bar, resize
2158 * controls, etc. Some <link linkend="gtk-X11-arch">window
2159 * managers</link> allow GTK+ to disable these decorations, creating a
2160 * borderless window. If you set the decorated property to %FALSE
2161 * using this function, GTK+ will do its best to convince the window
2162 * manager not to decorate the window. Depending on the system, this
2163 * function may not have any effect when called on a window that is
2164 * already visible, so you should call it before calling gtk_window_show().
2166 * On Windows, this function always works, since there's no window manager
2171 gtk_window_set_decorated (GtkWindow *window,
2174 g_return_if_fail (GTK_IS_WINDOW (window));
2176 setting = setting != FALSE;
2178 if (setting == window->decorated)
2181 window->decorated = setting;
2183 if (GTK_WIDGET (window)->window)
2185 if (window->decorated)
2186 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2189 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2195 * gtk_window_get_decorated:
2196 * @window: a #GtkWindow
2198 * Returns whether the window has been set to have decorations
2199 * such as a title bar via gtk_window_set_decorated().
2201 * Return value: %TRUE if the window has been set to have decorations
2204 gtk_window_get_decorated (GtkWindow *window)
2206 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2208 return window->decorated;
2211 static GtkWindowIconInfo*
2212 get_icon_info (GtkWindow *window)
2214 return g_object_get_data (G_OBJECT (window),
2215 "gtk-window-icon-info");
2218 static GtkWindowIconInfo*
2219 ensure_icon_info (GtkWindow *window)
2221 GtkWindowIconInfo *info;
2223 info = get_icon_info (window);
2227 info = g_new0 (GtkWindowIconInfo, 1);
2228 g_object_set_data_full (G_OBJECT (window),
2229 "gtk-window-icon-info",
2244 get_screen_icon_info (GdkScreen *screen)
2246 ScreenIconInfo *info = g_object_get_data (G_OBJECT (screen),
2247 "gtk-window-default-icon-pixmap");
2250 info = g_new0 (ScreenIconInfo, 1);
2251 g_object_set_data (G_OBJECT (screen), "gtk-window-default-icon-pixmap", info);
2254 if (info->serial != default_icon_serial)
2258 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2259 info->pixmap = NULL;
2264 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2268 info->serial = default_icon_serial;
2275 get_pixmap_and_mask (GdkWindow *window,
2276 GtkWindowIconInfo *parent_info,
2277 gboolean is_default_list,
2279 GdkPixmap **pmap_return,
2280 GdkBitmap **mask_return)
2282 GdkScreen *screen = gdk_drawable_get_screen (window);
2283 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2284 GdkPixbuf *best_icon;
2288 *pmap_return = NULL;
2289 *mask_return = NULL;
2291 if (is_default_list &&
2292 default_icon_info->pixmap != NULL)
2294 /* Use shared icon pixmap for all windows on this screen.
2296 if (default_icon_info->pixmap)
2297 g_object_ref (default_icon_info->pixmap);
2298 if (default_icon_info->mask)
2299 g_object_ref (default_icon_info->mask);
2301 *pmap_return = default_icon_info->pixmap;
2302 *mask_return = default_icon_info->mask;
2304 else if (parent_info && parent_info->icon_pixmap)
2306 if (parent_info->icon_pixmap)
2307 g_object_ref (parent_info->icon_pixmap);
2308 if (parent_info->icon_mask)
2309 g_object_ref (parent_info->icon_mask);
2311 *pmap_return = parent_info->icon_pixmap;
2312 *mask_return = parent_info->icon_mask;
2316 #define IDEAL_SIZE 48
2318 best_size = G_MAXINT;
2320 tmp_list = icon_list;
2321 while (tmp_list != NULL)
2323 GdkPixbuf *pixbuf = tmp_list->data;
2326 /* average width and height - if someone passes in a rectangular
2327 * icon they deserve what they get.
2329 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2332 if (best_icon == NULL)
2339 /* icon is better if it's 32 pixels or larger, and closer to
2340 * the ideal size than the current best.
2343 (ABS (best_size - IDEAL_SIZE) <
2344 ABS (this - IDEAL_SIZE)))
2351 tmp_list = tmp_list->next;
2355 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2356 gdk_screen_get_system_colormap (screen),
2361 /* Save pmap/mask for others to use if appropriate */
2364 parent_info->icon_pixmap = *pmap_return;
2365 parent_info->icon_mask = *mask_return;
2367 if (parent_info->icon_pixmap)
2368 g_object_ref (parent_info->icon_pixmap);
2369 if (parent_info->icon_mask)
2370 g_object_ref (parent_info->icon_mask);
2372 else if (is_default_list)
2374 default_icon_info->pixmap = *pmap_return;
2375 default_icon_info->mask = *mask_return;
2377 if (default_icon_info->pixmap)
2378 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2379 (gpointer*)&default_icon_info->pixmap);
2380 if (default_icon_info->mask)
2381 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2382 (gpointer*)&default_icon_info->mask);
2388 gtk_window_realize_icon (GtkWindow *window)
2391 GtkWindowIconInfo *info;
2394 widget = GTK_WIDGET (window);
2396 g_return_if_fail (widget->window != NULL);
2398 /* no point setting an icon on override-redirect */
2399 if (window->type == GTK_WINDOW_POPUP)
2404 info = ensure_icon_info (window);
2409 g_return_if_fail (info->icon_pixmap == NULL);
2410 g_return_if_fail (info->icon_mask == NULL);
2412 info->using_default_icon = FALSE;
2413 info->using_parent_icon = FALSE;
2415 icon_list = info->icon_list;
2417 /* Inherit from transient parent */
2418 if (icon_list == NULL && window->transient_parent)
2420 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2422 info->using_parent_icon = TRUE;
2425 /* Inherit from default */
2426 if (icon_list == NULL)
2428 icon_list = default_icon_list;
2430 info->using_default_icon = TRUE;
2433 gdk_window_set_icon_list (widget->window, icon_list);
2435 get_pixmap_and_mask (widget->window,
2436 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2437 info->using_default_icon,
2442 /* This is a slight ICCCM violation since it's a color pixmap not
2443 * a bitmap, but everyone does it.
2445 gdk_window_set_icon (widget->window,
2450 info->realized = TRUE;
2454 gtk_window_unrealize_icon (GtkWindow *window)
2456 GtkWindowIconInfo *info;
2459 widget = GTK_WIDGET (window);
2461 info = get_icon_info (window);
2466 if (info->icon_pixmap)
2467 g_object_unref (info->icon_pixmap);
2469 if (info->icon_mask)
2470 g_object_unref (info->icon_mask);
2472 info->icon_pixmap = NULL;
2473 info->icon_mask = NULL;
2475 /* We don't clear the properties on the window, just figure the
2476 * window is going away.
2479 info->realized = FALSE;
2483 * gtk_window_set_icon_list:
2484 * @window: a #GtkWindow
2485 * @list: list of #GdkPixbuf
2487 * Sets up the icon representing a #GtkWindow. The icon is used when
2488 * the window is minimized (also known as iconified). Some window
2489 * managers or desktop environments may also place it in the window
2490 * frame, or display it in other contexts.
2492 * gtk_window_set_icon_list() allows you to pass in the same icon in
2493 * several hand-drawn sizes. The list should contain the natural sizes
2494 * your icon is available in; that is, don't scale the image before
2495 * passing it to GTK+. Scaling is postponed until the last minute,
2496 * when the desired final size is known, to allow best quality.
2498 * By passing several sizes, you may improve the final image quality
2499 * of the icon, by reducing or eliminating automatic image scaling.
2501 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2502 * larger images (64x64, 128x128) if you have them.
2504 * See also gtk_window_set_default_icon_list() to set the icon
2505 * for all windows in your application in one go.
2507 * Note that transient windows (those who have been set transient for another
2508 * window using gtk_window_set_transient_for()) will inherit their
2509 * icon from their transient parent. So there's no need to explicitly
2510 * set the icon on transient windows.
2513 gtk_window_set_icon_list (GtkWindow *window,
2516 GtkWindowIconInfo *info;
2518 g_return_if_fail (GTK_IS_WINDOW (window));
2520 info = ensure_icon_info (window);
2522 if (info->icon_list == list) /* check for NULL mostly */
2525 g_list_foreach (info->icon_list,
2526 (GFunc) g_object_unref, NULL);
2528 g_list_free (info->icon_list);
2530 info->icon_list = g_list_copy (list);
2531 g_list_foreach (info->icon_list,
2532 (GFunc) g_object_ref, NULL);
2534 g_object_notify (G_OBJECT (window), "icon");
2536 gtk_window_unrealize_icon (window);
2538 if (GTK_WIDGET_REALIZED (window))
2539 gtk_window_realize_icon (window);
2541 /* We could try to update our transient children, but I don't think
2542 * it's really worth it. If we did it, the best way would probably
2543 * be to have children connect to notify::icon_list
2548 * gtk_window_get_icon_list:
2549 * @window: a #GtkWindow
2551 * Retrieves the list of icons set by gtk_window_set_icon_list().
2552 * The list is copied, but the reference count on each
2553 * member won't be incremented.
2555 * Return value: copy of window's icon list
2558 gtk_window_get_icon_list (GtkWindow *window)
2560 GtkWindowIconInfo *info;
2562 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2564 info = get_icon_info (window);
2567 return g_list_copy (info->icon_list);
2573 * gtk_window_set_icon:
2574 * @window: a #GtkWindow
2575 * @icon: icon image, or %NULL
2577 * Sets up the icon representing a #GtkWindow. This icon is used when
2578 * the window is minimized (also known as iconified). Some window
2579 * managers or desktop environments may also place it in the window
2580 * frame, or display it in other contexts.
2582 * The icon should be provided in whatever size it was naturally
2583 * drawn; that is, don't scale the image before passing it to
2584 * GTK+. Scaling is postponed until the last minute, when the desired
2585 * final size is known, to allow best quality.
2587 * If you have your icon hand-drawn in multiple sizes, use
2588 * gtk_window_set_icon_list(). Then the best size will be used.
2590 * This function is equivalent to calling gtk_window_set_icon_list()
2591 * with a 1-element list.
2593 * See also gtk_window_set_default_icon_list() to set the icon
2594 * for all windows in your application in one go.
2597 gtk_window_set_icon (GtkWindow *window,
2602 g_return_if_fail (GTK_IS_WINDOW (window));
2603 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2608 list = g_list_append (list, icon);
2610 gtk_window_set_icon_list (window, list);
2615 * gtk_window_get_icon:
2616 * @window: a #GtkWindow
2618 * Gets the value set by gtk_window_set_icon() (or if you've
2619 * called gtk_window_set_icon_list(), gets the first icon in
2622 * Return value: icon for window
2625 gtk_window_get_icon (GtkWindow *window)
2627 GtkWindowIconInfo *info;
2629 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2631 info = get_icon_info (window);
2632 if (info && info->icon_list)
2633 return GDK_PIXBUF (info->icon_list->data);
2638 /* Load pixbuf, printing warning on failure if error == NULL
2641 load_pixbuf_verbosely (const char *filename,
2644 GError *local_err = NULL;
2647 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
2655 g_warning ("Error loading icon from file '%s':\n\t%s",
2656 filename, local_err->message);
2657 g_error_free (local_err);
2665 * gtk_window_set_icon_from_file:
2666 * @window: a #GtkWindow
2667 * @filename: location of icon file
2668 * @err: location to store error, or %NULL.
2670 * Sets the icon for @window.
2671 * Warns on failure if @err is %NULL.
2673 * This function is equivalent to calling gtk_window_set_icon()
2674 * with a pixbuf created by loading the image from @filename.
2676 * Returns: %TRUE if setting the icon succeeded.
2681 gtk_window_set_icon_from_file (GtkWindow *window,
2682 const gchar *filename,
2685 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2689 gtk_window_set_icon (window, pixbuf);
2690 g_object_unref (pixbuf);
2699 * gtk_window_set_default_icon_list:
2700 * @list: a list of #GdkPixbuf
2702 * Sets an icon list to be used as fallback for windows that haven't
2703 * had gtk_window_set_icon_list() called on them to set up a
2704 * window-specific icon list. This function allows you to set up the
2705 * icon for all windows in your app at once.
2707 * See gtk_window_set_icon_list() for more details.
2711 gtk_window_set_default_icon_list (GList *list)
2715 if (list == default_icon_list)
2718 /* Update serial so we don't used cached pixmaps/masks
2720 default_icon_serial++;
2722 g_list_foreach (default_icon_list,
2723 (GFunc) g_object_unref, NULL);
2725 g_list_free (default_icon_list);
2727 default_icon_list = g_list_copy (list);
2728 g_list_foreach (default_icon_list,
2729 (GFunc) g_object_ref, NULL);
2731 /* Update all toplevels */
2732 toplevels = gtk_window_list_toplevels ();
2733 tmp_list = toplevels;
2734 while (tmp_list != NULL)
2736 GtkWindowIconInfo *info;
2737 GtkWindow *w = tmp_list->data;
2739 info = get_icon_info (w);
2740 if (info && info->using_default_icon)
2742 gtk_window_unrealize_icon (w);
2743 if (GTK_WIDGET_REALIZED (w))
2744 gtk_window_realize_icon (w);
2747 tmp_list = tmp_list->next;
2749 g_list_free (toplevels);
2753 * gtk_window_set_default_icon_from_file:
2754 * @filename: location of icon file
2755 * @err: location to store error, or %NULL.
2757 * Sets an icon to be used as fallback for windows that haven't
2758 * had gtk_window_set_icon_list() called on them from a file
2759 * on disk. Warns on failure if @err is %NULL.
2761 * Returns: %TRUE if setting the icon succeeded.
2766 gtk_window_set_default_icon_from_file (const gchar *filename,
2769 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2773 GList *list = g_list_prepend (NULL, pixbuf);
2774 gtk_window_set_default_icon_list (list);
2777 g_object_unref (pixbuf);
2786 * gtk_window_get_default_icon_list:
2788 * Gets the value set by gtk_window_set_default_icon_list().
2789 * The list is a copy and should be freed with g_list_free(),
2790 * but the pixbufs in the list have not had their reference count
2793 * Return value: copy of default icon list
2796 gtk_window_get_default_icon_list (void)
2798 return g_list_copy (default_icon_list);
2802 gtk_window_set_default_size_internal (GtkWindow *window,
2803 gboolean change_width,
2805 gboolean change_height,
2807 gboolean is_geometry)
2809 GtkWindowGeometryInfo *info;
2811 g_return_if_fail (change_width == FALSE || width >= -1);
2812 g_return_if_fail (change_height == FALSE || height >= -1);
2814 info = gtk_window_get_geometry_info (window, TRUE);
2816 g_object_freeze_notify (G_OBJECT (window));
2818 info->default_is_geometry = is_geometry != FALSE;
2828 info->default_width = width;
2830 g_object_notify (G_OBJECT (window), "default_width");
2841 info->default_height = height;
2843 g_object_notify (G_OBJECT (window), "default_height");
2846 g_object_thaw_notify (G_OBJECT (window));
2848 gtk_widget_queue_resize (GTK_WIDGET (window));
2852 * gtk_window_set_default_size:
2853 * @window: a #GtkWindow
2854 * @width: width in pixels, or -1 to unset the default width
2855 * @height: height in pixels, or -1 to unset the default height
2857 * Sets the default size of a window. If the window's "natural" size
2858 * (its size request) is larger than the default, the default will be
2859 * ignored. More generally, if the default size does not obey the
2860 * geometry hints for the window (gtk_window_set_geometry_hints() can
2861 * be used to set these explicitly), the default size will be clamped
2862 * to the nearest permitted size.
2864 * Unlike gtk_widget_set_size_request(), which sets a size request for
2865 * a widget and thus would keep users from shrinking the window, this
2866 * function only sets the initial size, just as if the user had
2867 * resized the window themselves. Users can still shrink the window
2868 * again as they normally would. Setting a default size of -1 means to
2869 * use the "natural" default size (the size request of the window).
2871 * For more control over a window's initial size and how resizing works,
2872 * investigate gtk_window_set_geometry_hints().
2874 * For some uses, gtk_window_resize() is a more appropriate function.
2875 * gtk_window_resize() changes the current size of the window, rather
2876 * than the size to be used on initial display. gtk_window_resize() always
2877 * affects the window itself, not the geometry widget.
2879 * The default size of a window only affects the first time a window is
2880 * shown; if a window is hidden and re-shown, it will remember the size
2881 * it had prior to hiding, rather than using the default size.
2883 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2884 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2887 gtk_window_set_default_size (GtkWindow *window,
2891 g_return_if_fail (GTK_IS_WINDOW (window));
2892 g_return_if_fail (width >= -1);
2893 g_return_if_fail (height >= -1);
2895 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
2899 * gtk_window_get_default_size:
2900 * @window: a #GtkWindow
2901 * @width: location to store the default width, or %NULL
2902 * @height: location to store the default height, or %NULL
2904 * Gets the default size of the window. A value of -1 for the width or
2905 * height indicates that a default size has not been explicitly set
2906 * for that dimension, so the "natural" size of the window will be
2911 gtk_window_get_default_size (GtkWindow *window,
2915 GtkWindowGeometryInfo *info;
2917 g_return_if_fail (GTK_IS_WINDOW (window));
2919 info = gtk_window_get_geometry_info (window, FALSE);
2922 *width = info->default_width;
2925 *height = info->default_height;
2929 * gtk_window_resize:
2930 * @window: a #GtkWindow
2931 * @width: width in pixels to resize the window to
2932 * @height: height in pixels to resize the window to
2934 * Resizes the window as if the user had done so, obeying geometry
2935 * constraints. The default geometry constraint is that windows may
2936 * not be smaller than their size request; to override this
2937 * constraint, call gtk_widget_set_size_request() to set the window's
2938 * request to a smaller value.
2940 * If gtk_window_resize() is called before showing a window for the
2941 * first time, it overrides any default size set with
2942 * gtk_window_set_default_size().
2944 * Windows may not be resized smaller than 1 by 1 pixels.
2948 gtk_window_resize (GtkWindow *window,
2952 GtkWindowGeometryInfo *info;
2954 g_return_if_fail (GTK_IS_WINDOW (window));
2955 g_return_if_fail (width > 0);
2956 g_return_if_fail (height > 0);
2958 info = gtk_window_get_geometry_info (window, TRUE);
2960 info->resize_width = width;
2961 info->resize_height = height;
2963 gtk_widget_queue_resize (GTK_WIDGET (window));
2967 * gtk_window_get_size:
2968 * @window: a #GtkWindow
2969 * @width: return location for width, or %NULL
2970 * @height: return location for height, or %NULL
2972 * Obtains the current size of @window. If @window is not onscreen,
2973 * it returns the size GTK+ will suggest to the <link
2974 * linkend="gtk-X11-arch">window manager</link> for the initial window
2975 * size (but this is not reliably the same as the size the window
2976 * manager will actually select). The size obtained by
2977 * gtk_window_get_size() is the last size received in a
2978 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
2979 * rather than querying the X server for the size. As a result, if you
2980 * call gtk_window_resize() then immediately call
2981 * gtk_window_get_size(), the size won't have taken effect yet. After
2982 * the window manager processes the resize request, GTK+ receives
2983 * notification that the size has changed via a configure event, and
2984 * the size of the window gets updated.
2986 * Note 1: Nearly any use of this function creates a race condition,
2987 * because the size of the window may change between the time that you
2988 * get the size and the time that you perform some action assuming
2989 * that size is the current size. To avoid race conditions, connect to
2990 * "configure_event" on the window and adjust your size-dependent
2991 * state to match the size delivered in the #GdkEventConfigure.
2993 * Note 2: The returned size does <emphasis>not</emphasis> include the
2994 * size of the window manager decorations (aka the window frame or
2995 * border). Those are not drawn by GTK+ and GTK+ has no reliable
2996 * method of determining their size.
2998 * Note 3: If you are getting a window size in order to position
2999 * the window onscreen, there may be a better way. The preferred
3000 * way is to simply set the window's semantic type with
3001 * gtk_window_set_type_hint(), which allows the window manager to
3002 * e.g. center dialogs. Also, if you set the transient parent of
3003 * dialogs with gtk_window_set_transient_for() window managers
3004 * will often center the dialog over its parent window. It's
3005 * much preferred to let the window manager handle these
3006 * things rather than doing it yourself, because all apps will
3007 * behave consistently and according to user prefs if the window
3008 * manager handles it. Also, the window manager can take the size
3009 * of the window decorations/border into account, while your
3010 * application cannot.
3012 * In any case, if you insist on application-specified window
3013 * positioning, there's <emphasis>still</emphasis> a better way than
3014 * doing it yourself - gtk_window_set_position() will frequently
3015 * handle the details for you.
3019 gtk_window_get_size (GtkWindow *window,
3026 g_return_if_fail (GTK_IS_WINDOW (window));
3028 widget = GTK_WIDGET (window);
3030 if (width == NULL && height == NULL)
3033 if (GTK_WIDGET_MAPPED (window))
3035 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3040 GdkRectangle configure_request;
3042 gtk_window_compute_configure_request (window,
3046 w = configure_request.width;
3047 h = configure_request.height;
3058 * @window: a #GtkWindow
3059 * @x: X coordinate to move window to
3060 * @y: Y coordinate to move window to
3062 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3063 * @window to the given position. Window managers are free to ignore
3064 * this; most window managers ignore requests for initial window
3065 * positions (instead using a user-defined placement algorithm) and
3066 * honor requests after the window has already been shown.
3068 * Note: the position is the position of the gravity-determined
3069 * reference point for the window. The gravity determines two things:
3070 * first, the location of the reference point in root window
3071 * coordinates; and second, which point on the window is positioned at
3072 * the reference point.
3074 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3075 * point is simply the @x, @y supplied to gtk_window_move(). The
3076 * top-left corner of the window decorations (aka window frame or
3077 * border) will be placed at @x, @y. Therefore, to position a window
3078 * at the top left of the screen, you want to use the default gravity
3079 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3081 * To position a window at the bottom right corner of the screen, you
3082 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3083 * point is at @x + the window width and @y + the window height, and
3084 * the bottom-right corner of the window border will be placed at that
3085 * reference point. So, to place a window in the bottom right corner
3086 * you would first set gravity to south east, then write:
3087 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3088 * gdk_screen_height () - window_height)</literal>.
3090 * The extended window manager hints specification at <ulink
3091 * url="http://www.freedesktop.org/standards/wm-spec.html">
3092 * http://www.freedesktop.org/standards/wm-spec.html</ulink> has a
3093 * nice table of gravities in the "implementation notes" section.
3095 * The gtk_window_get_position() documentation may also be relevant.
3099 gtk_window_move (GtkWindow *window,
3103 GtkWindowGeometryInfo *info;
3106 g_return_if_fail (GTK_IS_WINDOW (window));
3108 widget = GTK_WIDGET (window);
3110 info = gtk_window_get_geometry_info (window, TRUE);
3112 if (GTK_WIDGET_MAPPED (window))
3114 /* we have now sent a request with this position
3115 * with currently-active constraints, so toggle flag.
3117 info->position_constraints_changed = FALSE;
3119 /* we only constrain if mapped - if not mapped,
3120 * then gtk_window_compute_configure_request()
3121 * will apply the constraints later, and we
3122 * don't want to lose information about
3123 * what position the user set before then.
3124 * i.e. if you do a move() then turn off POS_CENTER
3125 * then show the window, your move() will work.
3127 gtk_window_constrain_position (window,
3128 widget->allocation.width,
3129 widget->allocation.height,
3132 /* Note that this request doesn't go through our standard request
3133 * framework, e.g. doesn't increment configure_request_count,
3134 * doesn't set info->last, etc.; that's because
3135 * we don't save the info needed to arrive at this same request
3138 * To gtk_window_move_resize(), this will end up looking exactly
3139 * the same as the position being changed by the window
3143 /* FIXME are we handling gravity properly for framed windows? */
3145 gdk_window_move (window->frame,
3146 x - window->frame_left,
3147 y - window->frame_top);
3149 gdk_window_move (GTK_WIDGET (window)->window,
3154 /* Save this position to apply on mapping */
3155 info->initial_x = x;
3156 info->initial_y = y;
3157 info->initial_pos_set = TRUE;
3162 * gtk_window_get_position:
3163 * @window: a #GtkWindow
3164 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3165 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3167 * This function returns the position you need to pass to
3168 * gtk_window_move() to keep @window in its current position. This
3169 * means that the meaning of the returned value varies with window
3170 * gravity. See gtk_window_move() for more details.
3172 * If you haven't changed the window gravity, its gravity will be
3173 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3174 * gets the position of the top-left corner of the window manager
3175 * frame for the window. gtk_window_move() sets the position of this
3176 * same top-left corner.
3178 * gtk_window_get_position() is not 100% reliable because the X Window System
3179 * does not specify a way to obtain the geometry of the
3180 * decorations placed on a window by the window manager.
3181 * Thus GTK+ is using a "best guess" that works with most
3184 * Moreover, nearly all window managers are historically broken with
3185 * respect to their handling of window gravity. So moving a window to
3186 * its current position as returned by gtk_window_get_position() tends
3187 * to result in moving the window slightly. Window managers are
3188 * slowly getting better over time.
3190 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3191 * frame is not relevant, and thus gtk_window_get_position() will
3192 * always produce accurate results. However you can't use static
3193 * gravity to do things like place a window in a corner of the screen,
3194 * because static gravity ignores the window manager decorations.
3196 * If you are saving and restoring your application's window
3197 * positions, you should know that it's impossible for applications to
3198 * do this without getting it somewhat wrong because applications do
3199 * not have sufficient knowledge of window manager state. The Correct
3200 * Mechanism is to support the session management protocol (see the
3201 * "GnomeClient" object in the GNOME libraries for example) and allow
3202 * the window manager to save your window sizes and positions.
3207 gtk_window_get_position (GtkWindow *window,
3213 g_return_if_fail (GTK_IS_WINDOW (window));
3215 widget = GTK_WIDGET (window);
3217 if (window->gravity == GDK_GRAVITY_STATIC)
3219 if (GTK_WIDGET_MAPPED (widget))
3221 /* This does a server round-trip, which is sort of wrong;
3222 * but a server round-trip is inevitable for
3223 * gdk_window_get_frame_extents() in the usual
3224 * NorthWestGravity case below, so not sure what else to
3225 * do. We should likely be consistent about whether we get
3226 * the client-side info or the server-side info.
3228 gdk_window_get_origin (widget->window, root_x, root_y);
3232 GdkRectangle configure_request;
3234 gtk_window_compute_configure_request (window,
3238 *root_x = configure_request.x;
3239 *root_y = configure_request.y;
3244 GdkRectangle frame_extents;
3249 if (GTK_WIDGET_MAPPED (widget))
3252 gdk_window_get_frame_extents (window->frame, &frame_extents);
3254 gdk_window_get_frame_extents (widget->window, &frame_extents);
3255 x = frame_extents.x;
3256 y = frame_extents.y;
3257 gtk_window_get_size (window, &w, &h);
3261 /* We just say the frame has 0 size on all sides.
3262 * Not sure what else to do.
3264 gtk_window_compute_configure_request (window,
3267 x = frame_extents.x;
3268 y = frame_extents.y;
3269 w = frame_extents.width;
3270 h = frame_extents.height;
3273 switch (window->gravity)
3275 case GDK_GRAVITY_NORTH:
3276 case GDK_GRAVITY_CENTER:
3277 case GDK_GRAVITY_SOUTH:
3278 /* Find center of frame. */
3279 x += frame_extents.width / 2;
3280 /* Center client window on that point. */
3284 case GDK_GRAVITY_SOUTH_EAST:
3285 case GDK_GRAVITY_EAST:
3286 case GDK_GRAVITY_NORTH_EAST:
3287 /* Find right edge of frame */
3288 x += frame_extents.width;
3289 /* Align left edge of client at that point. */
3296 switch (window->gravity)
3298 case GDK_GRAVITY_WEST:
3299 case GDK_GRAVITY_CENTER:
3300 case GDK_GRAVITY_EAST:
3301 /* Find center of frame. */
3302 y += frame_extents.height / 2;
3303 /* Center client window there. */
3306 case GDK_GRAVITY_SOUTH_WEST:
3307 case GDK_GRAVITY_SOUTH:
3308 case GDK_GRAVITY_SOUTH_EAST:
3309 /* Find south edge of frame */
3310 y += frame_extents.height;
3311 /* Place bottom edge of client there */
3326 * gtk_window_reshow_with_initial_size:
3327 * @window: a #GtkWindow
3329 * Hides @window, then reshows it, resetting the
3330 * default size and position of the window. Used
3331 * by GUI builders only.
3334 gtk_window_reshow_with_initial_size (GtkWindow *window)
3338 g_return_if_fail (GTK_IS_WINDOW (window));
3340 widget = GTK_WIDGET (window);
3342 gtk_widget_hide (widget);
3343 gtk_widget_unrealize (widget);
3344 gtk_widget_show (widget);
3348 gtk_window_destroy (GtkObject *object)
3350 GtkWindow *window = GTK_WINDOW (object);
3352 if (window->transient_parent)
3353 gtk_window_set_transient_for (window, NULL);
3355 /* frees the icons */
3356 gtk_window_set_icon_list (window, NULL);
3358 if (window->has_user_ref_count)
3360 window->has_user_ref_count = FALSE;
3361 g_object_unref (window);
3365 gtk_window_group_remove_window (window->group, window);
3367 gtk_window_free_key_hash (window);
3369 GTK_OBJECT_CLASS (parent_class)->destroy (object);
3373 gtk_window_mnemonic_hash_remove (gpointer key,
3377 GtkWindowMnemonic *mnemonic = key;
3378 GtkWindow *window = user;
3380 if (mnemonic->window == window)
3382 if (mnemonic->targets)
3384 gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
3386 g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
3387 name, mnemonic->targets->data);
3390 g_slist_free (mnemonic->targets);
3399 gtk_window_private_finalize (GtkWindowPrivate *priv)
3406 gtk_window_finalize (GObject *object)
3408 GtkWindow *window = GTK_WINDOW (object);
3410 toplevel_list = g_slist_remove (toplevel_list, window);
3412 g_free (window->title);
3413 g_free (window->wmclass_name);
3414 g_free (window->wmclass_class);
3415 g_free (window->wm_role);
3417 g_hash_table_foreach_remove (mnemonic_hash_table,
3418 gtk_window_mnemonic_hash_remove,
3420 if (window->geometry_info)
3422 if (window->geometry_info->widget)
3423 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3424 gtk_widget_destroyed,
3425 &window->geometry_info->widget);
3426 g_free (window->geometry_info);
3429 if (window->keys_changed_handler)
3431 gtk_idle_remove (window->keys_changed_handler);
3432 window->keys_changed_handler = 0;
3435 G_OBJECT_CLASS (parent_class)->finalize (object);
3439 gtk_window_show (GtkWidget *widget)
3441 GtkWindow *window = GTK_WINDOW (widget);
3442 GtkContainer *container = GTK_CONTAINER (window);
3443 gboolean need_resize;
3445 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3447 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3448 container->need_resize = FALSE;
3452 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3453 GtkAllocation allocation = { 0, 0 };
3454 GdkRectangle configure_request;
3455 GdkGeometry new_geometry;
3457 gboolean was_realized;
3459 /* We are going to go ahead and perform this configure request
3460 * and then emulate a configure notify by going ahead and
3461 * doing a size allocate. Sort of a synchronous
3462 * mini-copy of gtk_window_move_resize() here.
3464 gtk_window_compute_configure_request (window,
3469 /* We update this because we are going to go ahead
3470 * and gdk_window_resize() below, rather than
3473 info->last.configure_request.width = configure_request.width;
3474 info->last.configure_request.height = configure_request.height;
3476 /* and allocate the window - this is normally done
3477 * in move_resize in response to configure notify
3479 allocation.width = configure_request.width;
3480 allocation.height = configure_request.height;
3481 gtk_widget_size_allocate (widget, &allocation);
3483 /* Then we guarantee we have a realize */
3484 was_realized = FALSE;
3485 if (!GTK_WIDGET_REALIZED (widget))
3487 gtk_widget_realize (widget);
3488 was_realized = TRUE;
3491 /* Must be done after the windows are realized,
3492 * so that the decorations can be read
3494 gtk_decorated_window_calculate_frame_size (window);
3496 /* We only send configure request if we didn't just finish
3497 * creating the window; if we just created the window
3498 * then we created it with widget->allocation anyhow.
3501 gdk_window_resize (widget->window,
3502 configure_request.width,
3503 configure_request.height);
3506 gtk_container_check_resize (container);
3508 gtk_widget_map (widget);
3510 /* Try to make sure that we have some focused widget
3512 #ifdef GDK_WINDOWING_X11
3513 if (!window->focus_widget && !GTK_IS_PLUG (window))
3515 if (!window->focus_widget)
3517 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
3520 gtk_grab_add (widget);
3524 gtk_window_hide (GtkWidget *widget)
3526 GtkWindow *window = GTK_WINDOW (widget);
3528 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3529 gtk_widget_unmap (widget);
3532 gtk_grab_remove (widget);
3536 gtk_window_map (GtkWidget *widget)
3538 GtkWindow *window = GTK_WINDOW (widget);
3539 GdkWindow *toplevel;
3540 GtkWindowPrivate *priv;
3542 priv = gtk_window_get_private (window);
3544 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3546 if (window->bin.child &&
3547 GTK_WIDGET_VISIBLE (window->bin.child) &&
3548 !GTK_WIDGET_MAPPED (window->bin.child))
3549 gtk_widget_map (window->bin.child);
3552 toplevel = window->frame;
3554 toplevel = widget->window;
3556 if (window->maximize_initially)
3557 gdk_window_maximize (toplevel);
3559 gdk_window_unmaximize (toplevel);
3561 if (window->stick_initially)
3562 gdk_window_stick (toplevel);
3564 gdk_window_unstick (toplevel);
3566 if (window->iconify_initially)
3567 gdk_window_iconify (toplevel);
3569 gdk_window_deiconify (toplevel);
3571 if (priv->fullscreen_initially)
3572 gdk_window_fullscreen (toplevel);
3574 gdk_window_unfullscreen (toplevel);
3576 /* No longer use the default settings */
3577 window->need_default_size = FALSE;
3578 window->need_default_position = FALSE;
3580 gdk_window_show (widget->window);
3583 gdk_window_show (window->frame);
3585 if (!disable_startup_notification &&
3586 !sent_startup_notification)
3588 sent_startup_notification = TRUE;
3589 gdk_notify_startup_complete ();
3594 gtk_window_unmap (GtkWidget *widget)
3596 GtkWindow *window = GTK_WINDOW (widget);
3597 GtkWindowGeometryInfo *info;
3598 GdkWindowState state;
3600 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3602 gdk_window_withdraw (window->frame);
3604 gdk_window_withdraw (widget->window);
3606 window->configure_request_count = 0;
3607 window->configure_notify_received = FALSE;
3609 /* on unmap, we reset the default positioning of the window,
3610 * so it's placed again, but we don't reset the default
3611 * size of the window, so it's remembered.
3613 window->need_default_position = TRUE;
3615 info = gtk_window_get_geometry_info (window, FALSE);
3618 info->initial_pos_set = FALSE;
3619 info->position_constraints_changed = FALSE;
3622 state = gdk_window_get_state (widget->window);
3623 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
3624 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
3625 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
3629 gtk_window_realize (GtkWidget *widget)
3632 GdkWindow *parent_window;
3633 GdkWindowAttr attributes;
3634 gint attributes_mask;
3636 window = GTK_WINDOW (widget);
3638 /* ensure widget tree is properly size allocated */
3639 if (widget->allocation.x == -1 &&
3640 widget->allocation.y == -1 &&
3641 widget->allocation.width == 1 &&
3642 widget->allocation.height == 1)
3644 GtkRequisition requisition;
3645 GtkAllocation allocation = { 0, 0, 200, 200 };
3647 gtk_widget_size_request (widget, &requisition);
3648 if (requisition.width || requisition.height)
3650 /* non-empty window */
3651 allocation.width = requisition.width;
3652 allocation.height = requisition.height;
3654 gtk_widget_size_allocate (widget, &allocation);
3656 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3658 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3661 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3663 switch (window->type)
3665 case GTK_WINDOW_TOPLEVEL:
3666 attributes.window_type = GDK_WINDOW_TOPLEVEL;
3668 case GTK_WINDOW_POPUP:
3669 attributes.window_type = GDK_WINDOW_TEMP;
3672 g_warning (G_STRLOC": Unknown window type %d!", window->type);
3676 attributes.title = window->title;
3677 attributes.wmclass_name = window->wmclass_name;
3678 attributes.wmclass_class = window->wmclass_class;
3679 attributes.wclass = GDK_INPUT_OUTPUT;
3680 attributes.visual = gtk_widget_get_visual (widget);
3681 attributes.colormap = gtk_widget_get_colormap (widget);
3683 if (window->has_frame)
3685 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3686 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3687 attributes.event_mask = (GDK_EXPOSURE_MASK |
3688 GDK_KEY_PRESS_MASK |
3689 GDK_ENTER_NOTIFY_MASK |
3690 GDK_LEAVE_NOTIFY_MASK |
3691 GDK_FOCUS_CHANGE_MASK |
3692 GDK_STRUCTURE_MASK |
3693 GDK_BUTTON_MOTION_MASK |
3694 GDK_POINTER_MOTION_HINT_MASK |
3695 GDK_BUTTON_PRESS_MASK |
3696 GDK_BUTTON_RELEASE_MASK);
3698 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3700 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
3701 &attributes, attributes_mask);
3703 gdk_window_set_user_data (window->frame, widget);
3705 attributes.window_type = GDK_WINDOW_CHILD;
3706 attributes.x = window->frame_left;
3707 attributes.y = window->frame_top;
3709 attributes_mask = GDK_WA_X | GDK_WA_Y;
3711 parent_window = window->frame;
3715 attributes_mask = 0;
3716 parent_window = gtk_widget_get_root_window (widget);
3719 attributes.width = widget->allocation.width;
3720 attributes.height = widget->allocation.height;
3721 attributes.event_mask = gtk_widget_get_events (widget);
3722 attributes.event_mask |= (GDK_EXPOSURE_MASK |
3723 GDK_KEY_PRESS_MASK |
3724 GDK_KEY_RELEASE_MASK |
3725 GDK_ENTER_NOTIFY_MASK |
3726 GDK_LEAVE_NOTIFY_MASK |
3727 GDK_FOCUS_CHANGE_MASK |
3728 GDK_STRUCTURE_MASK);
3730 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3731 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3732 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3734 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3736 gdk_window_set_user_data (widget->window, window);
3738 widget->style = gtk_style_attach (widget->style, widget->window);
3739 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3741 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3743 /* This is a bad hack to set the window background. */
3744 gtk_window_paint (widget, NULL);
3746 if (window->transient_parent &&
3747 GTK_WIDGET_REALIZED (window->transient_parent))
3748 gdk_window_set_transient_for (widget->window,
3749 GTK_WIDGET (window->transient_parent)->window);
3751 if (window->wm_role)
3752 gdk_window_set_role (widget->window, window->wm_role);
3754 if (!window->decorated)
3755 gdk_window_set_decorations (widget->window, 0);
3757 gdk_window_set_type_hint (widget->window, window->type_hint);
3759 if (gtk_window_get_skip_pager_hint (window))
3760 gdk_window_set_skip_pager_hint (widget->window, TRUE);
3762 if (gtk_window_get_skip_taskbar_hint (window))
3763 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
3765 /* transient_for must be set to allow the modal hint */
3766 if (window->transient_parent && window->modal)
3767 gdk_window_set_modal_hint (widget->window, TRUE);
3769 gdk_window_set_modal_hint (widget->window, FALSE);
3772 gtk_window_realize_icon (window);
3776 gtk_window_unrealize (GtkWidget *widget)
3779 GtkWindowGeometryInfo *info;
3781 window = GTK_WINDOW (widget);
3783 /* On unrealize, we reset the size of the window such
3784 * that we will re-apply the default sizing stuff
3785 * next time we show the window.
3787 * Default positioning is reset on unmap, instead of unrealize.
3789 window->need_default_size = TRUE;
3790 info = gtk_window_get_geometry_info (window, FALSE);
3793 info->resize_width = -1;
3794 info->resize_height = -1;
3795 info->last.configure_request.x = 0;
3796 info->last.configure_request.y = 0;
3797 info->last.configure_request.width = -1;
3798 info->last.configure_request.height = -1;
3799 /* be sure we reset geom hints on re-realize */
3800 info->last.flags = 0;
3805 gdk_window_set_user_data (window->frame, NULL);
3806 gdk_window_destroy (window->frame);
3807 window->frame = NULL;
3811 gtk_window_unrealize_icon (window);
3813 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3817 gtk_window_size_request (GtkWidget *widget,
3818 GtkRequisition *requisition)
3823 window = GTK_WINDOW (widget);
3824 bin = GTK_BIN (window);
3826 requisition->width = GTK_CONTAINER (window)->border_width * 2;
3827 requisition->height = GTK_CONTAINER (window)->border_width * 2;
3829 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3831 GtkRequisition child_requisition;
3833 gtk_widget_size_request (bin->child, &child_requisition);
3835 requisition->width += child_requisition.width;
3836 requisition->height += child_requisition.height;
3841 gtk_window_size_allocate (GtkWidget *widget,
3842 GtkAllocation *allocation)
3845 GtkAllocation child_allocation;
3847 window = GTK_WINDOW (widget);
3848 widget->allocation = *allocation;
3850 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3852 child_allocation.x = GTK_CONTAINER (window)->border_width;
3853 child_allocation.y = GTK_CONTAINER (window)->border_width;
3854 child_allocation.width =
3855 MAX (1, (gint)allocation->width - child_allocation.x * 2);
3856 child_allocation.height =
3857 MAX (1, (gint)allocation->height - child_allocation.y * 2);
3859 gtk_widget_size_allocate (window->bin.child, &child_allocation);
3862 if (GTK_WIDGET_REALIZED (widget) && window->frame)
3864 gdk_window_resize (window->frame,
3865 allocation->width + window->frame_left + window->frame_right,
3866 allocation->height + window->frame_top + window->frame_bottom);
3871 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3874 gboolean return_val;
3876 window = GTK_WINDOW (widget);
3878 if (window->frame && (event->any.window == window->frame))
3880 if ((event->type != GDK_KEY_PRESS) &&
3881 (event->type != GDK_KEY_RELEASE) &&
3882 (event->type != GDK_FOCUS_CHANGE))
3884 g_signal_stop_emission_by_name (widget, "event");
3886 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
3891 g_object_unref (event->any.window);
3892 event->any.window = g_object_ref (widget->window);
3900 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3902 GdkEventConfigure *configure_event;
3905 switch (event->type)
3908 configure_event = (GdkEventConfigure *)event;
3910 /* Invalidate the decorations */
3913 rect.width = configure_event->width;
3914 rect.height = configure_event->height;
3916 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3918 /* Pass on the (modified) configure event */
3919 configure_event->width -= window->frame_left + window->frame_right;
3920 configure_event->height -= window->frame_top + window->frame_bottom;
3921 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
3930 gtk_window_configure_event (GtkWidget *widget,
3931 GdkEventConfigure *event)
3933 GtkWindow *window = GTK_WINDOW (widget);
3934 gboolean expected_reply = window->configure_request_count > 0;
3936 /* window->configure_request_count incremented for each
3937 * configure request, and decremented to a min of 0 for
3938 * each configure notify.
3940 * All it means is that we know we will get at least
3941 * window->configure_request_count more configure notifies.
3942 * We could get more configure notifies than that; some
3943 * of the configure notifies we get may be unrelated to
3944 * the configure requests. But we will get at least
3945 * window->configure_request_count notifies.
3948 if (window->configure_request_count > 0)
3949 window->configure_request_count -= 1;
3951 /* As an optimization, we avoid a resize when possible.
3953 * The only times we can avoid a resize are:
3954 * - we know only the position changed, not the size
3955 * - we know we have made more requests and so will get more
3956 * notifies and can wait to resize when we get them
3959 if (!expected_reply &&
3960 (widget->allocation.width == event->width &&
3961 widget->allocation.height == event->height))
3965 * If we do need to resize, we do that by:
3966 * - filling in widget->allocation with the new size
3967 * - setting configure_notify_received to TRUE
3968 * for use in gtk_window_move_resize()
3969 * - queueing a resize, leading to invocation of
3970 * gtk_window_move_resize() in an idle handler
3974 window->configure_notify_received = TRUE;
3976 widget->allocation.width = event->width;
3977 widget->allocation.height = event->height;
3979 _gtk_container_queue_resize (GTK_CONTAINER (widget));
3984 /* the accel_key and accel_mods fields of the key have to be setup
3985 * upon calling this function. it'll then return whether that key
3986 * is at all used as accelerator, and if so will OR in the
3987 * accel_flags member of the key.
3990 _gtk_window_query_nonaccels (GtkWindow *window,
3992 GdkModifierType accel_mods)
3994 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3996 /* movement keys are considered locked accels */
3999 static const guint bindings[] = {
4000 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
4001 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
4005 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
4006 if (bindings[i] == accel_key)
4010 /* mnemonics are considered locked accels */
4011 if (accel_mods == window->mnemonic_modifier)
4013 GtkWindowMnemonic mkey;
4015 mkey.window = window;
4016 mkey.keyval = accel_key;
4017 if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
4025 gtk_window_key_press_event (GtkWidget *widget,
4032 window = GTK_WINDOW (widget);
4036 /* Check for mnemonics and accelerators
4039 handled = _gtk_window_activate_key (window, event);
4043 focus = window->focus_widget;
4045 g_object_ref (focus);
4048 focus && focus != widget &&
4049 gtk_widget_get_toplevel (focus) == widget)
4053 if (GTK_WIDGET_IS_SENSITIVE (focus))
4054 handled = gtk_widget_event (focus, (GdkEvent*) event);
4056 parent = focus->parent;
4058 g_object_ref (parent);
4060 g_object_unref (focus);
4066 g_object_unref (focus);
4069 /* Chain up, invokes binding set */
4070 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
4071 handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4077 gtk_window_key_release_event (GtkWidget *widget,
4083 window = GTK_WINDOW (widget);
4085 if (window->focus_widget &&
4086 window->focus_widget != widget &&
4087 GTK_WIDGET_SENSITIVE (window->focus_widget))
4089 handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
4092 if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
4093 handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
4099 gtk_window_real_activate_default (GtkWindow *window)
4101 gtk_window_activate_default (window);
4105 gtk_window_real_activate_focus (GtkWindow *window)
4107 gtk_window_activate_focus (window);
4111 gtk_window_move_focus (GtkWindow *window,
4112 GtkDirectionType dir)
4114 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4116 if (!GTK_CONTAINER (window)->focus_child)
4117 gtk_window_set_focus (window, NULL);
4121 gtk_window_enter_notify_event (GtkWidget *widget,
4122 GdkEventCrossing *event)
4128 gtk_window_leave_notify_event (GtkWidget *widget,
4129 GdkEventCrossing *event)
4135 do_focus_change (GtkWidget *widget,
4138 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4140 g_object_ref (widget);
4143 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4145 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4147 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4148 fevent->focus_change.window = widget->window;
4150 g_object_ref (widget->window);
4151 fevent->focus_change.in = in;
4153 gtk_widget_event (widget, fevent);
4155 g_object_notify (G_OBJECT (widget), "has_focus");
4157 g_object_unref (widget);
4158 gdk_event_free (fevent);
4162 gtk_window_focus_in_event (GtkWidget *widget,
4163 GdkEventFocus *event)
4165 GtkWindow *window = GTK_WINDOW (widget);
4167 /* It appears spurious focus in events can occur when
4168 * the window is hidden. So we'll just check to see if
4169 * the window is visible before actually handling the
4172 if (GTK_WIDGET_VISIBLE (widget))
4174 _gtk_window_set_has_toplevel_focus (window, TRUE);
4175 _gtk_window_set_is_active (window, TRUE);
4182 gtk_window_focus_out_event (GtkWidget *widget,
4183 GdkEventFocus *event)
4185 GtkWindow *window = GTK_WINDOW (widget);
4187 _gtk_window_set_has_toplevel_focus (window, FALSE);
4188 _gtk_window_set_is_active (window, FALSE);
4193 static GdkAtom atom_rcfiles = GDK_NONE;
4196 gtk_window_read_rcfiles (GtkWidget *widget,
4197 GdkEventClient *event)
4199 GList *embedded_windows;
4201 embedded_windows = g_object_get_data (G_OBJECT (widget), "gtk-embedded");
4202 if (embedded_windows)
4204 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4207 for (i = 0; i < 5; i++)
4208 send_event->client.data.l[i] = 0;
4209 send_event->client.data_format = 32;
4210 send_event->client.message_type = atom_rcfiles;
4212 while (embedded_windows)
4214 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4215 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4216 embedded_windows = embedded_windows->next;
4219 gdk_event_free (send_event);
4222 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4226 gtk_window_client_event (GtkWidget *widget,
4227 GdkEventClient *event)
4230 atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
4232 if (event->message_type == atom_rcfiles)
4233 gtk_window_read_rcfiles (widget, event);
4239 gtk_window_check_resize (GtkContainer *container)
4241 GtkWindow *window = GTK_WINDOW (container);
4243 if (GTK_WIDGET_VISIBLE (container))
4244 gtk_window_move_resize (window);
4248 gtk_window_focus (GtkWidget *widget,
4249 GtkDirectionType direction)
4253 GtkContainer *container;
4254 GtkWidget *old_focus_child;
4257 container = GTK_CONTAINER (widget);
4258 window = GTK_WINDOW (widget);
4259 bin = GTK_BIN (widget);
4261 old_focus_child = container->focus_child;
4263 /* We need a special implementation here to deal properly with wrapping
4264 * around in the tab chain without the danger of going into an
4267 if (old_focus_child)
4269 if (gtk_widget_child_focus (old_focus_child, direction))
4273 if (window->focus_widget)
4275 /* Wrapped off the end, clear the focus setting for the toplpevel */
4276 parent = window->focus_widget->parent;
4279 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4280 parent = GTK_WIDGET (parent)->parent;
4283 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4286 /* Now try to focus the first widget in the window */
4289 if (gtk_widget_child_focus (bin->child, direction))
4297 gtk_window_real_set_focus (GtkWindow *window,
4300 GtkWidget *old_focus = window->focus_widget;
4301 gboolean def_flags = 0;
4305 g_object_ref (old_focus);
4306 g_object_freeze_notify (G_OBJECT (old_focus));
4310 g_object_ref (focus);
4311 g_object_freeze_notify (G_OBJECT (focus));
4314 if (window->default_widget)
4315 def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4317 if (window->focus_widget)
4319 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4320 (window->focus_widget != window->default_widget))
4322 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4324 if (window->default_widget)
4325 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4328 if (window->has_focus)
4329 do_focus_change (window->focus_widget, FALSE);
4331 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4334 window->focus_widget = focus;
4336 if (window->focus_widget)
4338 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4339 (window->focus_widget != window->default_widget))
4341 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4342 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4344 if (window->default_widget)
4345 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4348 if (window->has_focus)
4349 do_focus_change (window->focus_widget, TRUE);
4351 g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4354 if (window->default_widget &&
4355 (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
4356 gtk_widget_queue_draw (window->default_widget);
4360 g_object_thaw_notify (G_OBJECT (old_focus));
4361 g_object_unref (old_focus);
4365 g_object_thaw_notify (G_OBJECT (focus));
4366 g_object_unref (focus);
4371 * _gtk_window_unset_focus_and_default:
4372 * @window: a #GtkWindow
4373 * @widget: a widget inside of @window
4375 * Checks whether the focus and default widgets of @window are
4376 * @widget or a descendent of @widget, and if so, unset them.
4379 _gtk_window_unset_focus_and_default (GtkWindow *window,
4385 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
4387 child = window->focus_widget;
4389 while (child && child != widget)
4390 child = child->parent;
4392 if (child == widget)
4393 gtk_window_set_focus (GTK_WINDOW (window), NULL);
4396 child = window->default_widget;
4398 while (child && child != widget)
4399 child = child->parent;
4401 if (child == widget)
4402 gtk_window_set_default (window, NULL);
4405 /*********************************
4406 * Functions related to resizing *
4407 *********************************/
4409 /* This function doesn't constrain to geometry hints */
4411 gtk_window_compute_configure_request_size (GtkWindow *window,
4415 GtkRequisition requisition;
4416 GtkWindowGeometryInfo *info;
4420 * - we've done a size request
4423 widget = GTK_WIDGET (window);
4425 info = gtk_window_get_geometry_info (window, FALSE);
4427 if (window->need_default_size)
4429 gtk_widget_get_child_requisition (widget, &requisition);
4431 /* Default to requisition */
4432 *width = requisition.width;
4433 *height = requisition.height;
4435 /* If window is empty so requests 0, default to random nonzero size */
4436 if (*width == 0 && *height == 0)
4442 /* Override requisition with default size */
4446 gint base_width = 0;
4447 gint base_height = 0;
4449 gint height_inc = 1;
4451 if (info->default_is_geometry &&
4452 (info->default_width > 0 || info->default_height > 0))
4454 GdkGeometry geometry;
4457 gtk_window_compute_hints (window, &geometry, &flags);
4459 if (flags & GDK_HINT_BASE_SIZE)
4461 base_width = geometry.base_width;
4462 base_height = geometry.base_height;
4464 else if (flags & GDK_HINT_MIN_SIZE)
4466 base_width = geometry.min_width;
4467 base_height = geometry.min_height;
4469 if (flags & GDK_HINT_RESIZE_INC)
4471 width_inc = geometry.width_inc;
4472 height_inc = geometry.height_inc;
4476 if (info->default_width > 0)
4477 *width = info->default_width * width_inc + base_width;
4479 if (info->default_height > 0)
4480 *height = info->default_height * height_inc + base_height;
4485 /* Default to keeping current size */
4486 *width = widget->allocation.width;
4487 *height = widget->allocation.height;
4490 /* Override any size with gtk_window_resize() values */
4493 if (info->resize_width > 0)
4494 *width = info->resize_width;
4496 if (info->resize_height > 0)
4497 *height = info->resize_height;
4501 static GtkWindowPosition
4502 get_effective_position (GtkWindow *window)
4504 GtkWindowPosition pos = window->position;
4505 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
4506 (window->transient_parent == NULL ||
4507 !GTK_WIDGET_MAPPED (window->transient_parent)))
4508 pos = GTK_WIN_POS_NONE;
4514 get_center_monitor_of_window (GtkWindow *window)
4516 /* We could try to sort out the relative positions of the monitors and
4517 * stuff, or we could just be losers and assume you have a row
4518 * or column of monitors.
4520 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
4524 get_monitor_containing_pointer (GtkWindow *window)
4528 GdkScreen *window_screen;
4529 GdkScreen *pointer_screen;
4531 window_screen = gtk_window_check_screen (window);
4532 gdk_display_get_pointer (gdk_screen_get_display (window_screen),
4536 if (pointer_screen == window_screen)
4537 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
4545 center_window_on_monitor (GtkWindow *window,
4551 GdkRectangle monitor;
4554 monitor_num = get_monitor_containing_pointer (window);
4556 if (monitor_num == -1)
4557 monitor_num = get_center_monitor_of_window (window);
4559 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
4560 monitor_num, &monitor);
4562 *x = (monitor.width - w) / 2 + monitor.x;
4563 *y = (monitor.height - h) / 2 + monitor.y;
4565 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
4566 * and WM decorations.
4575 clamp_window_to_rectangle (gint *x,
4579 const GdkRectangle *rect)
4581 gint outside_w, outside_h;
4583 outside_w = (*x + w) - (rect->x + rect->width);
4587 outside_h = (*y + h) - (rect->y + rect->height);
4591 /* if larger than the screen, center on the screen. */
4593 *x += (rect->x - *x) / 2;
4595 *y += (rect->y - *y) / 2;
4600 gtk_window_compute_configure_request (GtkWindow *window,
4601 GdkRectangle *request,
4602 GdkGeometry *geometry,
4605 GdkGeometry new_geometry;
4609 GtkWindowPosition pos;
4610 GtkWidget *parent_widget;
4611 GtkWindowGeometryInfo *info;
4615 widget = GTK_WIDGET (window);
4617 screen = gtk_window_check_screen (window);
4619 gtk_widget_size_request (widget, NULL);
4620 gtk_window_compute_configure_request_size (window, &w, &h);
4622 gtk_window_compute_hints (window, &new_geometry, &new_flags);
4623 gtk_window_constrain_size (window,
4624 &new_geometry, new_flags,
4628 parent_widget = (GtkWidget*) window->transient_parent;
4630 pos = get_effective_position (window);
4631 info = gtk_window_get_geometry_info (window, TRUE);
4633 /* by default, don't change position requested */
4634 x = info->last.configure_request.x;
4635 y = info->last.configure_request.y;
4637 if (window->need_default_position)
4640 /* FIXME this all interrelates with window gravity.
4641 * For most of them I think we want to set GRAVITY_CENTER.
4643 * Not sure how to go about that.
4648 /* here we are only handling CENTER_ALWAYS
4649 * as it relates to default positioning,
4650 * where it's equivalent to simply CENTER
4652 case GTK_WIN_POS_CENTER_ALWAYS:
4653 case GTK_WIN_POS_CENTER:
4654 center_window_on_monitor (window, w, h, &x, &y);
4657 case GTK_WIN_POS_CENTER_ON_PARENT:
4660 GdkRectangle monitor;
4663 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
4665 if (parent_widget->window != NULL)
4666 monitor_num = gdk_screen_get_monitor_at_window (screen,
4667 parent_widget->window);
4671 gdk_window_get_origin (parent_widget->window,
4674 x = ox + (parent_widget->allocation.width - w) / 2;
4675 y = oy + (parent_widget->allocation.height - h) / 2;
4677 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4678 * WM decorations. If parent wasn't on a monitor, just
4681 if (monitor_num >= 0)
4683 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
4684 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4689 case GTK_WIN_POS_MOUSE:
4691 gint screen_width = gdk_screen_get_width (screen);
4692 gint screen_height = gdk_screen_get_height (screen);
4694 GdkRectangle monitor;
4695 GdkScreen *pointer_screen;
4698 gdk_display_get_pointer (gdk_screen_get_display (screen),
4702 if (pointer_screen == screen)
4703 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
4709 x = CLAMP (x, 0, screen_width - w);
4710 y = CLAMP (y, 0, screen_height - h);
4712 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4713 * WM decorations. Don't try to figure out what's going
4714 * on if the mouse wasn't inside a monitor.
4716 if (monitor_num >= 0)
4718 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
4719 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4727 } /* if (window->need_default_position) */
4729 if (window->need_default_position &&
4730 info->initial_pos_set)
4732 x = info->initial_x;
4733 y = info->initial_y;
4734 gtk_window_constrain_position (window, w, h, &x, &y);
4740 request->height = h;
4743 *geometry = new_geometry;
4749 gtk_window_constrain_position (GtkWindow *window,
4755 /* See long comments in gtk_window_move_resize()
4756 * on when it's safe to call this function.
4758 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4760 gint center_x, center_y;
4762 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
4770 gtk_window_move_resize (GtkWindow *window)
4774 * First we determine whether any information has changed that would
4775 * cause us to revise our last configure request. If we would send
4776 * a different configure request from last time, then
4777 * configure_request_size_changed = TRUE or
4778 * configure_request_pos_changed = TRUE. configure_request_size_changed
4779 * may be true due to new hints, a gtk_window_resize(), or whatever.
4780 * configure_request_pos_changed may be true due to gtk_window_set_position()
4781 * or gtk_window_move().
4783 * If the configure request has changed, we send off a new one. To
4784 * ensure GTK+ invariants are maintained (resize queue does what it
4785 * should), we go ahead and size_allocate the requested size in this
4788 * If the configure request has not changed, we don't ever resend
4789 * it, because it could mean fighting the user or window manager.
4792 * To prepare the configure request, we come up with a base size/pos:
4793 * - the one from gtk_window_move()/gtk_window_resize()
4794 * - else default_width, default_height if we haven't ever
4796 * - else the size request if we haven't ever been mapped,
4797 * as a substitute default size
4798 * - else the current size of the window, as received from
4799 * configure notifies (i.e. the current allocation)
4801 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4802 * the position request to be centered.
4805 GtkContainer *container;
4806 GtkWindowGeometryInfo *info;
4807 GdkGeometry new_geometry;
4809 GdkRectangle new_request;
4810 gboolean configure_request_size_changed;
4811 gboolean configure_request_pos_changed;
4812 gboolean hints_changed; /* do we need to send these again */
4813 GtkWindowLastGeometryInfo saved_last_info;
4815 widget = GTK_WIDGET (window);
4816 container = GTK_CONTAINER (widget);
4817 info = gtk_window_get_geometry_info (window, TRUE);
4819 configure_request_size_changed = FALSE;
4820 configure_request_pos_changed = FALSE;
4822 gtk_window_compute_configure_request (window, &new_request,
4823 &new_geometry, &new_flags);
4825 /* This check implies the invariant that we never set info->last
4826 * without setting the hints and sending off a configure request.
4828 * If we change info->last without sending the request, we may
4831 if (info->last.configure_request.x != new_request.x ||
4832 info->last.configure_request.y != new_request.y)
4833 configure_request_pos_changed = TRUE;
4835 if ((info->last.configure_request.width != new_request.width ||
4836 info->last.configure_request.height != new_request.height))
4837 configure_request_size_changed = TRUE;
4839 hints_changed = FALSE;
4841 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4842 &new_geometry, new_flags))
4844 hints_changed = TRUE;
4847 /* Position Constraints
4848 * ====================
4850 * POS_CENTER_ALWAYS is conceptually a constraint rather than
4851 * a default. The other POS_ values are used only when the
4852 * window is shown, not after that.
4854 * However, we can't implement a position constraint as
4855 * "anytime the window size changes, center the window"
4856 * because this may well end up fighting the WM or user. In
4857 * fact it gets in an infinite loop with at least one WM.
4859 * Basically, applications are in no way in a position to
4860 * constrain the position of a window, with one exception:
4861 * override redirect windows. (Really the intended purpose
4862 * of CENTER_ALWAYS anyhow, I would think.)
4864 * So the way we implement this "constraint" is to say that when WE
4865 * cause a move or resize, i.e. we make a configure request changing
4866 * window size, we recompute the CENTER_ALWAYS position to reflect
4867 * the new window size, and include it in our request. Also, if we
4868 * just turned on CENTER_ALWAYS we snap to center with a new
4869 * request. Otherwise, if we are just NOTIFIED of a move or resize
4870 * done by someone else e.g. the window manager, we do NOT send a
4871 * new configure request.
4873 * For override redirect windows, this works fine; all window
4874 * sizes are from our configure requests. For managed windows,
4875 * it is at least semi-sane, though who knows what the
4876 * app author is thinking.
4879 /* This condition should be kept in sync with the condition later on
4880 * that determines whether we send a configure request. i.e. we
4881 * should do this position constraining anytime we were going to
4882 * send a configure request anyhow, plus when constraints have
4885 if (configure_request_pos_changed ||
4886 configure_request_size_changed ||
4888 info->position_constraints_changed)
4890 /* We request the constrained position if:
4891 * - we were changing position, and need to clamp
4892 * the change to the constraint
4893 * - we're changing the size anyway
4894 * - set_position() was called to toggle CENTER_ALWAYS on
4897 gtk_window_constrain_position (window,
4903 /* Update whether we need to request a move */
4904 if (info->last.configure_request.x != new_request.x ||
4905 info->last.configure_request.y != new_request.y)
4906 configure_request_pos_changed = TRUE;
4908 configure_request_pos_changed = FALSE;
4912 if (window->type == GTK_WINDOW_TOPLEVEL)
4914 int notify_x, notify_y;
4916 /* this is the position from the last configure notify */
4917 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
4919 g_message ("--- %s ---\n"
4920 "last : %d,%d\t%d x %d\n"
4921 "this : %d,%d\t%d x %d\n"
4922 "alloc : %d,%d\t%d x %d\n"
4924 "resize: \t%d x %d\n"
4925 "size_changed: %d pos_changed: %d hints_changed: %d\n"
4926 "configure_notify_received: %d\n"
4927 "configure_request_count: %d\n"
4928 "position_constraints_changed: %d\n",
4929 window->title ? window->title : "(no title)",
4930 info->last.configure_request.x,
4931 info->last.configure_request.y,
4932 info->last.configure_request.width,
4933 info->last.configure_request.height,
4939 widget->allocation.width,
4940 widget->allocation.height,
4941 widget->requisition.width,
4942 widget->requisition.height,
4944 info->resize_height,
4945 configure_request_pos_changed,
4946 configure_request_size_changed,
4948 window->configure_notify_received,
4949 window->configure_request_count,
4950 info->position_constraints_changed);
4954 saved_last_info = info->last;
4955 info->last.geometry = new_geometry;
4956 info->last.flags = new_flags;
4957 info->last.configure_request = new_request;
4959 /* need to set PPosition so the WM will look at our position,
4960 * but we don't want to count PPosition coming and going as a hints
4961 * change for future iterations. So we saved info->last prior to
4965 /* Also, if the initial position was explicitly set, then we always
4966 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
4970 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
4971 * this is an initial map
4974 if ((configure_request_pos_changed ||
4975 info->initial_pos_set ||
4976 (window->need_default_position &&
4977 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
4978 (new_flags & GDK_HINT_POS) == 0)
4980 new_flags |= GDK_HINT_POS;
4981 hints_changed = TRUE;
4984 /* Set hints if necessary
4987 gdk_window_set_geometry_hints (widget->window,
4991 /* handle resizing/moving and widget tree allocation
4993 if (window->configure_notify_received)
4995 GtkAllocation allocation;
4997 /* If we have received a configure event since
4998 * the last time in this function, we need to
4999 * accept our new size and size_allocate child widgets.
5000 * (see gtk_window_configure_event() for more details).
5002 * 1 or more configure notifies may have been received.
5003 * Also, configure_notify_received will only be TRUE
5004 * if all expected configure notifies have been received
5005 * (one per configure request), as an optimization.
5008 window->configure_notify_received = FALSE;
5010 /* gtk_window_configure_event() filled in widget->allocation */
5011 allocation = widget->allocation;
5012 gtk_widget_size_allocate (widget, &allocation);
5014 /* If the configure request changed, it means that
5016 * 1) coincidentally changed hints or widget properties
5017 * impacting the configure request before getting
5018 * a configure notify, or
5019 * 2) some broken widget is changing its size request
5020 * during size allocation, resulting in
5021 * a false appearance of changed configure request.
5023 * For 1), we could just go ahead and ask for the
5024 * new size right now, but doing that for 2)
5025 * might well be fighting the user (and can even
5026 * trigger a loop). Since we really don't want to
5027 * do that, we requeue a resize in hopes that
5028 * by the time it gets handled, the child has seen
5029 * the light and is willing to go along with the
5030 * new size. (this happens for the zvt widget, since
5031 * the size_allocate() above will have stored the
5032 * requisition corresponding to the new size in the
5035 * This doesn't buy us anything for 1), but it shouldn't
5036 * hurt us too badly, since it is what would have
5037 * happened if we had gotten the configure event before
5038 * the new size had been set.
5041 if (configure_request_size_changed ||
5042 configure_request_pos_changed)
5044 /* Don't change the recorded last info after all, because we
5045 * haven't actually updated to the new info yet - we decided
5046 * to postpone our configure request until later.
5048 info->last = saved_last_info;
5050 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
5053 return; /* Bail out, we didn't really process the move/resize */
5055 else if ((configure_request_size_changed || hints_changed) &&
5056 (widget->allocation.width != new_request.width ||
5057 widget->allocation.height != new_request.height))
5060 /* We are in one of the following situations:
5061 * A. configure_request_size_changed
5062 * our requisition has changed and we need a different window size,
5063 * so we request it from the window manager.
5064 * B. !configure_request_size_changed && hints_changed
5065 * the window manager rejects our size, but we have just changed the
5066 * window manager hints, so there's a chance our request will
5067 * be honoured this time, so we try again.
5069 * However, if the new requisition is the same as the current allocation,
5070 * we don't request it again, since we won't get a ConfigureNotify back from
5071 * the window manager unless it decides to change our requisition. If
5072 * we don't get the ConfigureNotify back, the resize queue will never be run.
5075 /* Now send the configure request */
5076 if (configure_request_pos_changed)
5080 gdk_window_move_resize (window->frame,
5081 new_request.x - window->frame_left,
5082 new_request.y - window->frame_top,
5083 new_request.width + window->frame_left + window->frame_right,
5084 new_request.height + window->frame_top + window->frame_bottom);
5085 gdk_window_resize (widget->window,
5086 new_request.width, new_request.height);
5089 gdk_window_move_resize (widget->window,
5090 new_request.x, new_request.y,
5091 new_request.width, new_request.height);
5093 else /* only size changed */
5096 gdk_window_resize (window->frame,
5097 new_request.width + window->frame_left + window->frame_right,
5098 new_request.height + window->frame_top + window->frame_bottom);
5099 gdk_window_resize (widget->window,
5100 new_request.width, new_request.height);
5103 /* Increment the number of have-not-yet-received-notify requests */
5104 window->configure_request_count += 1;
5106 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5107 * configure event in response to our resizing request.
5108 * the configure event will cause a new resize with
5109 * ->configure_notify_received=TRUE.
5110 * until then, we want to
5111 * - discard expose events
5112 * - coalesce resizes for our children
5113 * - defer any window resizes until the configure event arrived
5114 * to achieve this, we queue a resize for the window, but remove its
5115 * resizing handler, so resizing will not be handled from the next
5116 * idle handler but when the configure event arrives.
5118 * FIXME: we should also dequeue the pending redraws here, since
5119 * we handle those ourselves upon ->configure_notify_received==TRUE.
5121 if (container->resize_mode == GTK_RESIZE_QUEUE)
5123 gtk_widget_queue_resize (widget);
5124 _gtk_container_dequeue_resize_handler (container);
5129 /* Handle any position changes.
5131 if (configure_request_pos_changed)
5135 gdk_window_move (window->frame,
5136 new_request.x - window->frame_left,
5137 new_request.y - window->frame_top);
5140 gdk_window_move (widget->window,
5141 new_request.x, new_request.y);
5144 /* And run the resize queue.
5146 gtk_container_resize_children (container);
5149 /* We have now processed a move/resize since the last position
5150 * constraint change, setting of the initial position, or resize.
5151 * (Not resetting these flags here can lead to infinite loops for
5152 * GTK_RESIZE_IMMEDIATE containers)
5154 info->position_constraints_changed = FALSE;
5155 info->initial_pos_set = FALSE;
5156 info->resize_width = -1;
5157 info->resize_height = -1;
5160 /* Compare two sets of Geometry hints for equality.
5163 gtk_window_compare_hints (GdkGeometry *geometry_a,
5165 GdkGeometry *geometry_b,
5168 if (flags_a != flags_b)
5171 if ((flags_a & GDK_HINT_MIN_SIZE) &&
5172 (geometry_a->min_width != geometry_b->min_width ||
5173 geometry_a->min_height != geometry_b->min_height))
5176 if ((flags_a & GDK_HINT_MAX_SIZE) &&
5177 (geometry_a->max_width != geometry_b->max_width ||
5178 geometry_a->max_height != geometry_b->max_height))
5181 if ((flags_a & GDK_HINT_BASE_SIZE) &&
5182 (geometry_a->base_width != geometry_b->base_width ||
5183 geometry_a->base_height != geometry_b->base_height))
5186 if ((flags_a & GDK_HINT_ASPECT) &&
5187 (geometry_a->min_aspect != geometry_b->min_aspect ||
5188 geometry_a->max_aspect != geometry_b->max_aspect))
5191 if ((flags_a & GDK_HINT_RESIZE_INC) &&
5192 (geometry_a->width_inc != geometry_b->width_inc ||
5193 geometry_a->height_inc != geometry_b->height_inc))
5196 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5197 geometry_a->win_gravity != geometry_b->win_gravity)
5204 _gtk_window_constrain_size (GtkWindow *window,
5210 GtkWindowGeometryInfo *info;
5212 g_return_if_fail (GTK_IS_WINDOW (window));
5214 info = window->geometry_info;
5217 GdkWindowHints flags = info->last.flags;
5218 GdkGeometry *geometry = &info->last.geometry;
5220 gtk_window_constrain_size (window,
5231 gtk_window_constrain_size (GtkWindow *window,
5232 GdkGeometry *geometry,
5239 gdk_window_constrain_size (geometry, flags, width, height,
5240 new_width, new_height);
5243 /* Compute the set of geometry hints and flags for a window
5244 * based on the application set geometry, and requisiition
5245 * of the window. gtk_widget_size_request() must have been
5249 gtk_window_compute_hints (GtkWindow *window,
5250 GdkGeometry *new_geometry,
5254 gint extra_width = 0;
5255 gint extra_height = 0;
5256 GtkWindowGeometryInfo *geometry_info;
5257 GtkRequisition requisition;
5259 widget = GTK_WIDGET (window);
5261 gtk_widget_get_child_requisition (widget, &requisition);
5262 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5266 *new_flags = geometry_info->mask;
5267 *new_geometry = geometry_info->geometry;
5274 if (geometry_info && geometry_info->widget)
5276 GtkRequisition child_requisition;
5278 /* FIXME: This really isn't right. It gets the min size wrong and forces
5279 * callers to do horrible hacks like set a huge usize on the child requisition
5280 * to get the base size right. We really want to find the answers to:
5282 * - If the geometry widget was infinitely big, how much extra space
5283 * would be needed for the stuff around it.
5285 * - If the geometry widget was infinitely small, how big would the
5286 * window still have to be.
5288 * Finding these answers would be a bit of a mess here. (Bug #68668)
5290 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5292 extra_width = widget->requisition.width - child_requisition.width;
5293 extra_height = widget->requisition.height - child_requisition.height;
5296 /* We don't want to set GDK_HINT_POS in here, we just set it
5297 * in gtk_window_move_resize() when we want the position
5301 if (*new_flags & GDK_HINT_BASE_SIZE)
5303 new_geometry->base_width += extra_width;
5304 new_geometry->base_height += extra_height;
5306 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5307 (*new_flags & GDK_HINT_RESIZE_INC) &&
5308 ((extra_width != 0) || (extra_height != 0)))
5310 *new_flags |= GDK_HINT_BASE_SIZE;
5312 new_geometry->base_width = extra_width;
5313 new_geometry->base_height = extra_height;
5316 if (*new_flags & GDK_HINT_MIN_SIZE)
5318 if (new_geometry->min_width < 0)
5319 new_geometry->min_width = requisition.width;
5321 new_geometry->min_width += extra_width;
5323 if (new_geometry->min_height < 0)
5324 new_geometry->min_height = requisition.height;
5326 new_geometry->min_height += extra_height;
5328 else if (!window->allow_shrink)
5330 *new_flags |= GDK_HINT_MIN_SIZE;
5332 new_geometry->min_width = requisition.width;
5333 new_geometry->min_height = requisition.height;
5336 if (*new_flags & GDK_HINT_MAX_SIZE)
5338 if (new_geometry->max_width < 0)
5339 new_geometry->max_width = requisition.width;
5341 new_geometry->max_width += extra_width;
5343 if (new_geometry->max_height < 0)
5344 new_geometry->max_width = requisition.height;
5346 new_geometry->max_height += extra_height;
5348 else if (!window->allow_grow)
5350 *new_flags |= GDK_HINT_MAX_SIZE;
5352 new_geometry->max_width = requisition.width;
5353 new_geometry->max_height = requisition.height;
5356 *new_flags |= GDK_HINT_WIN_GRAVITY;
5357 new_geometry->win_gravity = window->gravity;
5360 /***********************
5361 * Redrawing functions *
5362 ***********************/
5365 gtk_window_paint (GtkWidget *widget,
5368 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
5369 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
5373 gtk_window_expose (GtkWidget *widget,
5374 GdkEventExpose *event)
5376 if (!GTK_WIDGET_APP_PAINTABLE (widget))
5377 gtk_window_paint (widget, &event->area);
5379 if (GTK_WIDGET_CLASS (parent_class)->expose_event)
5380 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
5386 * gtk_window_set_has_frame:
5387 * @window: a #GtkWindow
5388 * @setting: a boolean
5390 * (Note: this is a special-purpose function for the framebuffer port,
5391 * that causes GTK+ to draw its own window border. For most applications,
5392 * you want gtk_window_set_decorated() instead, which tells the window
5393 * manager whether to draw the window border.)
5395 * If this function is called on a window with setting of %TRUE, before
5396 * it is realized or showed, it will have a "frame" window around
5397 * @window->window, accessible in @window->frame. Using the signal
5398 * frame_event you can recieve all events targeted at the frame.
5400 * This function is used by the linux-fb port to implement managed
5401 * windows, but it could concievably be used by X-programs that
5402 * want to do their own window decorations.
5406 gtk_window_set_has_frame (GtkWindow *window,
5409 g_return_if_fail (GTK_IS_WINDOW (window));
5410 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
5412 window->has_frame = setting != FALSE;
5416 * gtk_window_get_has_frame:
5417 * @window: a #GtkWindow
5419 * Accessor for whether the window has a frame window exterior to
5420 * @window->window. Gets the value set by gtk_window_set_has_frame ().
5422 * Return value: %TRUE if a frame has been added to the window
5423 * via gtk_window_set_has_frame().
5426 gtk_window_get_has_frame (GtkWindow *window)
5428 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5430 return window->has_frame;
5434 * gtk_window_set_frame_dimensions:
5435 * @window: a #GtkWindow that has a frame
5436 * @left: The width of the left border
5437 * @top: The height of the top border
5438 * @right: The width of the right border
5439 * @bottom: The height of the bottom border
5441 * (Note: this is a special-purpose function intended for the framebuffer
5442 * port; see gtk_window_set_has_frame(). It will have no effect on the
5443 * window border drawn by the window manager, which is the normal
5444 * case when using the X Window system.)
5446 * For windows with frames (see gtk_window_set_has_frame()) this function
5447 * can be used to change the size of the frame border.
5450 gtk_window_set_frame_dimensions (GtkWindow *window,
5458 g_return_if_fail (GTK_IS_WINDOW (window));
5460 widget = GTK_WIDGET (window);
5462 if (window->frame_left == left &&
5463 window->frame_top == top &&
5464 window->frame_right == right &&
5465 window->frame_bottom == bottom)
5468 window->frame_left = left;
5469 window->frame_top = top;
5470 window->frame_right = right;
5471 window->frame_bottom = bottom;
5473 if (GTK_WIDGET_REALIZED (widget) && window->frame)
5475 gint width = widget->allocation.width + left + right;
5476 gint height = widget->allocation.height + top + bottom;
5477 gdk_window_resize (window->frame, width, height);
5478 gtk_decorated_window_move_resize_window (window,
5480 widget->allocation.width,
5481 widget->allocation.height);
5486 * gtk_window_present:
5487 * @window: a #GtkWindow
5489 * Presents a window to the user. This may mean raising the window
5490 * in the stacking order, deiconifying it, moving it to the current
5491 * desktop, and/or giving it the keyboard focus, possibly dependent
5492 * on the user's platform, window manager, and preferences.
5494 * If @window is hidden, this function calls gtk_widget_show()
5497 * This function should be used when the user tries to open a window
5498 * that's already open. Say for example the preferences dialog is
5499 * currently open, and the user chooses Preferences from the menu
5500 * a second time; use gtk_window_present() to move the already-open dialog
5501 * where the user can see it.
5505 gtk_window_present (GtkWindow *window)
5509 g_return_if_fail (GTK_IS_WINDOW (window));
5511 widget = GTK_WIDGET (window);
5513 if (GTK_WIDGET_VISIBLE (window))
5515 g_assert (widget->window != NULL);
5517 gdk_window_show (widget->window);
5519 /* note that gdk_window_focus() will also move the window to
5520 * the current desktop, for WM spec compliant window managers.
5522 gdk_window_focus (widget->window,
5523 gtk_get_current_event_time ());
5527 gtk_widget_show (widget);
5532 * gtk_window_iconify:
5533 * @window: a #GtkWindow
5535 * Asks to iconify (i.e. minimize) the specified @window. Note that
5536 * you shouldn't assume the window is definitely iconified afterward,
5537 * because other entities (e.g. the user or <link
5538 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
5539 * again, or there may not be a window manager in which case
5540 * iconification isn't possible, etc. But normally the window will end
5541 * up iconified. Just don't write code that crashes if not.
5543 * It's permitted to call this function before showing a window,
5544 * in which case the window will be iconified before it ever appears
5547 * You can track iconification via the "window_state_event" signal
5552 gtk_window_iconify (GtkWindow *window)
5555 GdkWindow *toplevel;
5557 g_return_if_fail (GTK_IS_WINDOW (window));
5559 widget = GTK_WIDGET (window);
5561 window->iconify_initially = TRUE;
5564 toplevel = window->frame;
5566 toplevel = widget->window;
5568 if (toplevel != NULL)
5569 gdk_window_iconify (toplevel);
5573 * gtk_window_deiconify:
5574 * @window: a #GtkWindow
5576 * Asks to deiconify (i.e. unminimize) the specified @window. Note
5577 * that you shouldn't assume the window is definitely deiconified
5578 * afterward, because other entities (e.g. the user or <link
5579 * linkend="gtk-X11-arch">window manager</link>) could iconify it
5580 * again before your code which assumes deiconification gets to run.
5582 * You can track iconification via the "window_state_event" signal
5586 gtk_window_deiconify (GtkWindow *window)
5589 GdkWindow *toplevel;
5591 g_return_if_fail (GTK_IS_WINDOW (window));
5593 widget = GTK_WIDGET (window);
5595 window->iconify_initially = FALSE;
5598 toplevel = window->frame;
5600 toplevel = widget->window;
5602 if (toplevel != NULL)
5603 gdk_window_deiconify (toplevel);
5608 * @window: a #GtkWindow
5610 * Asks to stick @window, which means that it will appear on all user
5611 * desktops. Note that you shouldn't assume the window is definitely
5612 * stuck afterward, because other entities (e.g. the user or <link
5613 * linkend="gtk-X11-arch">window manager</link>) could unstick it
5614 * again, and some window managers do not support sticking
5615 * windows. But normally the window will end up stuck. Just don't
5616 * write code that crashes if not.
5618 * It's permitted to call this function before showing a window.
5620 * You can track stickiness via the "window_state_event" signal
5625 gtk_window_stick (GtkWindow *window)
5628 GdkWindow *toplevel;
5630 g_return_if_fail (GTK_IS_WINDOW (window));
5632 widget = GTK_WIDGET (window);
5634 window->stick_initially = TRUE;
5637 toplevel = window->frame;
5639 toplevel = widget->window;
5641 if (toplevel != NULL)
5642 gdk_window_stick (toplevel);
5646 * gtk_window_unstick:
5647 * @window: a #GtkWindow
5649 * Asks to unstick @window, which means that it will appear on only
5650 * one of the user's desktops. Note that you shouldn't assume the
5651 * window is definitely unstuck afterward, because other entities
5652 * (e.g. the user or <link linkend="gtk-X11-arch">window
5653 * manager</link>) could stick it again. But normally the window will
5654 * end up stuck. Just don't write code that crashes if not.
5656 * You can track stickiness via the "window_state_event" signal
5661 gtk_window_unstick (GtkWindow *window)
5664 GdkWindow *toplevel;
5666 g_return_if_fail (GTK_IS_WINDOW (window));
5668 widget = GTK_WIDGET (window);
5670 window->stick_initially = FALSE;
5673 toplevel = window->frame;
5675 toplevel = widget->window;
5677 if (toplevel != NULL)
5678 gdk_window_unstick (toplevel);
5682 * gtk_window_maximize:
5683 * @window: a #GtkWindow
5685 * Asks to maximize @window, so that it becomes full-screen. Note that
5686 * you shouldn't assume the window is definitely maximized afterward,
5687 * because other entities (e.g. the user or <link
5688 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
5689 * again, and not all window managers support maximization. But
5690 * normally the window will end up maximized. Just don't write code
5691 * that crashes if not.
5693 * It's permitted to call this function before showing a window,
5694 * in which case the window will be maximized when it appears onscreen
5697 * You can track maximization via the "window_state_event" signal
5702 gtk_window_maximize (GtkWindow *window)
5705 GdkWindow *toplevel;
5707 g_return_if_fail (GTK_IS_WINDOW (window));
5709 widget = GTK_WIDGET (window);
5711 window->maximize_initially = TRUE;
5714 toplevel = window->frame;
5716 toplevel = widget->window;
5718 if (toplevel != NULL)
5719 gdk_window_maximize (toplevel);
5723 * gtk_window_unmaximize:
5724 * @window: a #GtkWindow
5726 * Asks to unmaximize @window. Note that you shouldn't assume the
5727 * window is definitely unmaximized afterward, because other entities
5728 * (e.g. the user or <link linkend="gtk-X11-arch">window
5729 * manager</link>) could maximize it again, and not all window
5730 * managers honor requests to unmaximize. But normally the window will
5731 * end up unmaximized. Just don't write code that crashes if not.
5733 * You can track maximization via the "window_state_event" signal
5738 gtk_window_unmaximize (GtkWindow *window)
5741 GdkWindow *toplevel;
5743 g_return_if_fail (GTK_IS_WINDOW (window));
5745 widget = GTK_WIDGET (window);
5747 window->maximize_initially = FALSE;
5750 toplevel = window->frame;
5752 toplevel = widget->window;
5754 if (toplevel != NULL)
5755 gdk_window_unmaximize (toplevel);
5759 * gtk_window_fullscreen:
5760 * @window: a #GtkWindow
5762 * Asks to place @window in the fullscreen state. Note that you
5763 * shouldn't assume the window is definitely full screen afterward,
5764 * because other entities (e.g. the user or <link
5765 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
5766 * again, and not all window managers honor requests to fullscreen
5767 * windows. But normally the window will end up fullscreen. Just
5768 * don't write code that crashes if not.
5770 * You can track the fullscreen state via the "window_state_event" signal
5776 gtk_window_fullscreen (GtkWindow *window)
5779 GdkWindow *toplevel;
5780 GtkWindowPrivate *priv;
5782 g_return_if_fail (GTK_IS_WINDOW (window));
5784 widget = GTK_WIDGET (window);
5785 priv = gtk_window_get_private (window);
5787 priv->fullscreen_initially = TRUE;
5790 toplevel = window->frame;
5792 toplevel = widget->window;
5794 if (toplevel != NULL)
5795 gdk_window_fullscreen (toplevel);
5799 * gtk_window_unfullscreen:
5800 * @window: a #GtkWindow
5802 * Asks to toggle off the fullscreen state for @window. Note that you
5803 * shouldn't assume the window is definitely not full screen
5804 * afterward, because other entities (e.g. the user or <link
5805 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
5806 * again, and not all window managers honor requests to unfullscreen
5807 * windows. But normally the window will end up restored to its normal
5808 * state. Just don't write code that crashes if not.
5810 * You can track the fullscreen state via the "window_state_event" signal
5816 gtk_window_unfullscreen (GtkWindow *window)
5819 GdkWindow *toplevel;
5820 GtkWindowPrivate *priv;
5822 g_return_if_fail (GTK_IS_WINDOW (window));
5824 widget = GTK_WIDGET (window);
5825 priv = gtk_window_get_private (window);
5827 priv->fullscreen_initially = FALSE;
5830 toplevel = window->frame;
5832 toplevel = widget->window;
5834 if (toplevel != NULL)
5835 gdk_window_unfullscreen (toplevel);
5840 * gtk_window_set_resizable:
5841 * @window: a #GtkWindow
5842 * @resizable: %TRUE if the user can resize this window
5844 * Sets whether the user can resize a window. Windows are user resizable
5848 gtk_window_set_resizable (GtkWindow *window,
5851 g_return_if_fail (GTK_IS_WINDOW (window));
5853 gtk_window_set_policy (window, FALSE, resizable, FALSE);
5857 * gtk_window_get_resizable:
5858 * @window: a #GtkWindow
5860 * Gets the value set by gtk_window_set_resizable().
5862 * Return value: %TRUE if the user can resize the window
5865 gtk_window_get_resizable (GtkWindow *window)
5867 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5869 /* allow_grow is most likely to indicate the semantic concept we
5870 * mean by "resizable" (and will be a reliable indicator if
5871 * set_policy() hasn't been called)
5873 return window->allow_grow;
5877 * gtk_window_set_gravity:
5878 * @window: a #GtkWindow
5879 * @gravity: window gravity
5881 * Window gravity defines the meaning of coordinates passed to
5882 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
5885 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
5886 * typically "do what you mean."
5890 gtk_window_set_gravity (GtkWindow *window,
5893 g_return_if_fail (GTK_IS_WINDOW (window));
5895 if (gravity != window->gravity)
5897 window->gravity = gravity;
5899 /* gtk_window_move_resize() will adapt gravity
5901 gtk_widget_queue_resize (GTK_WIDGET (window));
5906 * gtk_window_get_gravity:
5907 * @window: a #GtkWindow
5909 * Gets the value set by gtk_window_set_gravity().
5911 * Return value: window gravity
5914 gtk_window_get_gravity (GtkWindow *window)
5916 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
5918 return window->gravity;
5922 * gtk_window_begin_resize_drag:
5923 * @window: a #GtkWindow
5924 * @button: mouse button that initiated the drag
5925 * @edge: position of the resize control
5926 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
5927 * @root_y: Y position where the user clicked to initiate the drag
5928 * @timestamp: timestamp from the click event that initiated the drag
5930 * Starts resizing a window. This function is used if an application
5931 * has window resizing controls. When GDK can support it, the resize
5932 * will be done using the standard mechanism for the <link
5933 * linkend="gtk-X11-arch">window manager</link> or windowing
5934 * system. Otherwise, GDK will try to emulate window resizing,
5935 * potentially not all that well, depending on the windowing system.
5939 gtk_window_begin_resize_drag (GtkWindow *window,
5947 GdkWindow *toplevel;
5949 g_return_if_fail (GTK_IS_WINDOW (window));
5950 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
5952 widget = GTK_WIDGET (window);
5955 toplevel = window->frame;
5957 toplevel = widget->window;
5959 gdk_window_begin_resize_drag (toplevel,
5966 * gtk_window_get_frame_dimensions:
5967 * @window: a #GtkWindow
5968 * @left: location to store the width of the frame at the left, or %NULL
5969 * @top: location to store the height of the frame at the top, or %NULL
5970 * @right: location to store the width of the frame at the returns, or %NULL
5971 * @bottom: location to store the height of the frame at the bottom, or %NULL
5973 * (Note: this is a special-purpose function intended for the
5974 * framebuffer port; see gtk_window_set_has_frame(). It will not
5975 * return the size of the window border drawn by the <link
5976 * linkend="gtk-X11-arch">window manager</link>, which is the normal
5977 * case when using a windowing system. See
5978 * gdk_window_get_frame_extents() to get the standard window border
5981 * Retrieves the dimensions of the frame window for this toplevel.
5982 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
5985 gtk_window_get_frame_dimensions (GtkWindow *window,
5991 g_return_if_fail (GTK_IS_WINDOW (window));
5994 *left = window->frame_left;
5996 *top = window->frame_top;
5998 *right = window->frame_right;
6000 *bottom = window->frame_bottom;
6004 * gtk_window_begin_move_drag:
6005 * @window: a #GtkWindow
6006 * @button: mouse button that initiated the drag
6007 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6008 * @root_y: Y position where the user clicked to initiate the drag
6009 * @timestamp: timestamp from the click event that initiated the drag
6011 * Starts moving a window. This function is used if an application has
6012 * window movement grips. When GDK can support it, the window movement
6013 * will be done using the standard mechanism for the <link
6014 * linkend="gtk-X11-arch">window manager</link> or windowing
6015 * system. Otherwise, GDK will try to emulate window movement,
6016 * potentially not all that well, depending on the windowing system.
6020 gtk_window_begin_move_drag (GtkWindow *window,
6027 GdkWindow *toplevel;
6029 g_return_if_fail (GTK_IS_WINDOW (window));
6030 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6032 widget = GTK_WIDGET (window);
6035 toplevel = window->frame;
6037 toplevel = widget->window;
6039 gdk_window_begin_move_drag (toplevel,
6046 * gtk_window_set_screen:
6047 * @window: a #GtkWindow.
6048 * @screen: a #GdkScreen.
6050 * Sets the #GdkScreen where the @window is displayed; if
6051 * the window is already mapped, it will be unmapped, and
6052 * then remapped on the new screen.
6057 gtk_window_set_screen (GtkWindow *window,
6061 GdkScreen *previous_screen;
6062 gboolean was_mapped;
6064 g_return_if_fail (GTK_IS_WINDOW (window));
6065 g_return_if_fail (GDK_IS_SCREEN (screen));
6067 if (screen == window->screen)
6070 widget = GTK_WIDGET (window);
6072 previous_screen = window->screen;
6073 was_mapped = GTK_WIDGET_MAPPED (widget);
6076 gtk_widget_unmap (widget);
6077 if (GTK_WIDGET_REALIZED (widget))
6078 gtk_widget_unrealize (widget);
6080 gtk_window_free_key_hash (window);
6081 window->screen = screen;
6082 gtk_widget_reset_rc_styles (widget);
6083 if (screen != previous_screen)
6084 _gtk_widget_propagate_screen_changed (widget, previous_screen);
6085 g_object_notify (G_OBJECT (window), "screen");
6088 gtk_widget_map (widget);
6092 gtk_window_check_screen (GtkWindow *window)
6095 return window->screen;
6098 g_warning ("Screen for GtkWindow not set; you must always set\n"
6099 "a screen for a GtkWindow before using the window");
6105 * gtk_window_get_screen:
6106 * @window: a #GtkWindow.
6108 * Returns the #GdkScreen associated with @window.
6110 * Return value: a #GdkScreen.
6115 gtk_window_get_screen (GtkWindow *window)
6117 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6119 return window->screen;
6124 gtk_window_group_class_init (GtkWindowGroupClass *klass)
6129 gtk_window_group_get_type (void)
6131 static GType window_group_type = 0;
6133 if (!window_group_type)
6135 static const GTypeInfo window_group_info =
6137 sizeof (GtkWindowGroupClass),
6138 NULL, /* base_init */
6139 NULL, /* base_finalize */
6140 (GClassInitFunc) gtk_window_group_class_init,
6141 NULL, /* class_finalize */
6142 NULL, /* class_data */
6143 sizeof (GtkWindowGroup),
6144 16, /* n_preallocs */
6145 (GInstanceInitFunc) NULL,
6148 window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
6151 return window_group_type;
6155 * gtk_window_group_new:
6157 * Creates a new #GtkWindowGroup object. Grabs added with
6158 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
6160 * Return value: a new #GtkWindowGroup.
6163 gtk_window_group_new (void)
6165 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
6169 window_group_cleanup_grabs (GtkWindowGroup *group,
6173 GSList *to_remove = NULL;
6175 tmp_list = group->grabs;
6178 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
6179 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
6180 tmp_list = tmp_list->next;
6185 gtk_grab_remove (to_remove->data);
6186 g_object_unref (to_remove->data);
6187 to_remove = g_slist_delete_link (to_remove, to_remove);
6192 * gtk_window_group_add_window:
6193 * @window_group: a #GtkWindowGroup
6194 * @window: the #GtkWindow to add
6196 * Adds a window to a #GtkWindowGroup.
6199 gtk_window_group_add_window (GtkWindowGroup *window_group,
6202 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6203 g_return_if_fail (GTK_IS_WINDOW (window));
6205 if (window->group != window_group)
6207 g_object_ref (window);
6208 g_object_ref (window_group);
6211 gtk_window_group_remove_window (window->group, window);
6213 window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
6215 window->group = window_group;
6217 g_object_unref (window);
6222 * gtk_window_group_remove_window:
6223 * @window_group: a #GtkWindowGroup
6224 * @window: the #GtkWindow to remove
6226 * Removes a window from a #GtkWindowGroup.
6229 gtk_window_group_remove_window (GtkWindowGroup *window_group,
6232 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6233 g_return_if_fail (GTK_IS_WIDGET (window));
6234 g_return_if_fail (window->group == window_group);
6236 g_object_ref (window);
6238 window_group_cleanup_grabs (window_group, window);
6239 window->group = NULL;
6241 g_object_unref (window_group);
6242 g_object_unref (window);
6245 /* Return the group for the window or the default group
6248 _gtk_window_get_group (GtkWindow *window)
6250 if (window && window->group)
6251 return window->group;
6254 static GtkWindowGroup *default_group = NULL;
6257 default_group = gtk_window_group_new ();
6259 return default_group;
6265 Derived from XParseGeometry() in XFree86
6267 Copyright 1985, 1986, 1987,1998 The Open Group
6269 All Rights Reserved.
6271 The above copyright notice and this permission notice shall be included
6272 in all copies or substantial portions of the Software.
6274 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
6275 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6276 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6277 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
6278 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
6279 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
6280 OTHER DEALINGS IN THE SOFTWARE.
6282 Except as contained in this notice, the name of The Open Group shall
6283 not be used in advertising or otherwise to promote the sale, use or
6284 other dealings in this Software without prior written authorization
6285 from The Open Group.
6290 * XParseGeometry parses strings of the form
6291 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
6292 * width, height, xoffset, and yoffset are unsigned integers.
6293 * Example: "=80x24+300-49"
6294 * The equal sign is optional.
6295 * It returns a bitmask that indicates which of the four values
6296 * were actually found in the string. For each value found,
6297 * the corresponding argument is updated; for each value
6298 * not found, the corresponding argument is left unchanged.
6301 /* The following code is from Xlib, and is minimally modified, so we
6302 * can track any upstream changes if required. Don't change this
6303 * code. Or if you do, put in a huge comment marking which thing
6308 read_int (gchar *string,
6316 else if (*string == '-')
6322 for (; (*string >= '0') && (*string <= '9'); string++)
6324 result = (result * 10) + (*string - '0');
6336 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
6337 * value (x, y, width, height) was found in the parsed string.
6339 #define NoValue 0x0000
6340 #define XValue 0x0001
6341 #define YValue 0x0002
6342 #define WidthValue 0x0004
6343 #define HeightValue 0x0008
6344 #define AllValues 0x000F
6345 #define XNegative 0x0010
6346 #define YNegative 0x0020
6348 /* Try not to reformat/modify, so we can compare/sync with X sources */
6350 gtk_XParseGeometry (const char *string,
6353 unsigned int *width,
6354 unsigned int *height)
6358 unsigned int tempWidth, tempHeight;
6360 char *nextCharacter;
6362 /* These initializations are just to silence gcc */
6368 if ( (string == NULL) || (*string == '\0')) return(mask);
6370 string++; /* ignore possible '=' at beg of geometry spec */
6372 strind = (char *)string;
6373 if (*strind != '+' && *strind != '-' && *strind != 'x') {
6374 tempWidth = read_int(strind, &nextCharacter);
6375 if (strind == nextCharacter)
6377 strind = nextCharacter;
6381 if (*strind == 'x' || *strind == 'X') {
6383 tempHeight = read_int(strind, &nextCharacter);
6384 if (strind == nextCharacter)
6386 strind = nextCharacter;
6387 mask |= HeightValue;
6390 if ((*strind == '+') || (*strind == '-')) {
6391 if (*strind == '-') {
6393 tempX = -read_int(strind, &nextCharacter);
6394 if (strind == nextCharacter)
6396 strind = nextCharacter;
6402 tempX = read_int(strind, &nextCharacter);
6403 if (strind == nextCharacter)
6405 strind = nextCharacter;
6408 if ((*strind == '+') || (*strind == '-')) {
6409 if (*strind == '-') {
6411 tempY = -read_int(strind, &nextCharacter);
6412 if (strind == nextCharacter)
6414 strind = nextCharacter;
6421 tempY = read_int(strind, &nextCharacter);
6422 if (strind == nextCharacter)
6424 strind = nextCharacter;
6430 /* If strind isn't at the end of the string the it's an invalid
6431 geometry specification. */
6433 if (*strind != '\0') return (0);
6439 if (mask & WidthValue)
6441 if (mask & HeightValue)
6442 *height = tempHeight;
6447 * gtk_window_parse_geometry:
6448 * @window: a #GtkWindow
6449 * @geometry: geometry string
6451 * Parses a standard X Window System geometry string - see the
6452 * manual page for X (type 'man X') for details on this.
6453 * gtk_window_parse_geometry() does work on all GTK+ ports
6454 * including Win32 but is primarily intended for an X environment.
6456 * If either a size or a position can be extracted from the
6457 * geometry string, gtk_window_parse_geometry() returns %TRUE
6458 * and calls gtk_window_set_default_size() and/or gtk_window_move()
6459 * to resize/move the window.
6461 * If gtk_window_parse_geometry() returns %TRUE, it will also
6462 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
6463 * indicating to the window manager that the size/position of
6464 * the window was user-specified. This causes most window
6465 * managers to honor the geometry.
6467 * Return value: %TRUE if string was parsed successfully
6470 gtk_window_parse_geometry (GtkWindow *window,
6471 const gchar *geometry)
6476 gboolean size_set, pos_set;
6479 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6480 g_return_val_if_fail (geometry != NULL, FALSE);
6482 screen = gtk_window_check_screen (window);
6484 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
6486 if ((result & WidthValue) == 0 ||
6489 if ((result & HeightValue) == 0 ||
6494 if ((result & WidthValue) || (result & HeightValue))
6496 gtk_window_set_default_size_internal (window, TRUE, w, TRUE, h, TRUE);
6500 gtk_window_get_size (window, &w, &h);
6502 grav = GDK_GRAVITY_NORTH_WEST;
6504 if ((result & XNegative) && (result & YNegative))
6505 grav = GDK_GRAVITY_SOUTH_EAST;
6506 else if (result & XNegative)
6507 grav = GDK_GRAVITY_NORTH_EAST;
6508 else if (result & YNegative)
6509 grav = GDK_GRAVITY_SOUTH_WEST;
6511 if ((result & XValue) == 0)
6514 if ((result & YValue) == 0)
6517 if (grav == GDK_GRAVITY_SOUTH_WEST ||
6518 grav == GDK_GRAVITY_SOUTH_EAST)
6519 y = gdk_screen_get_height (screen) - h + y;
6521 if (grav == GDK_GRAVITY_SOUTH_EAST ||
6522 grav == GDK_GRAVITY_NORTH_EAST)
6523 x = gdk_screen_get_width (screen) - w + x;
6525 /* we don't let you put a window offscreen; maybe some people would
6526 * prefer to be able to, but it's kind of a bogus thing to do.
6535 if ((result & XValue) || (result & YValue))
6537 gtk_window_set_gravity (window, grav);
6538 gtk_window_move (window, x, y);
6542 if (size_set || pos_set)
6544 /* Set USSize, USPosition hints */
6545 GtkWindowGeometryInfo *info;
6547 info = gtk_window_get_geometry_info (window, TRUE);
6550 info->mask |= GDK_HINT_USER_POS;
6552 info->mask |= GDK_HINT_USER_SIZE;
6559 gtk_window_mnemonic_hash_foreach (gpointer key,
6565 GtkWindowKeysForeachFunc func;
6569 GtkWindowMnemonic *mnemonic = value;
6571 if (mnemonic->window == info->window)
6572 (*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
6576 _gtk_window_keys_foreach (GtkWindow *window,
6577 GtkWindowKeysForeachFunc func,
6584 GtkWindowKeysForeachFunc func;
6588 info.window = window;
6590 info.func_data = func_data;
6592 g_hash_table_foreach (mnemonic_hash_table,
6593 gtk_window_mnemonic_hash_foreach,
6596 groups = gtk_accel_groups_from_object (G_OBJECT (window));
6599 GtkAccelGroup *group = groups->data;
6602 for (i = 0; i < group->n_accels; i++)
6604 GtkAccelKey *key = &group->priv_accels[i].key;
6607 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
6610 groups = groups->next;
6615 gtk_window_keys_changed (GtkWindow *window)
6617 gtk_window_free_key_hash (window);
6618 gtk_window_get_key_hash (window);
6621 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
6623 struct _GtkWindowKeyEntry
6627 gboolean is_mnemonic;
6631 add_to_key_hash (GtkWindow *window,
6633 GdkModifierType modifiers,
6634 gboolean is_mnemonic,
6637 GtkKeyHash *key_hash = data;
6639 GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
6641 entry->keyval = keyval;
6642 entry->modifiers = modifiers;
6643 entry->is_mnemonic = is_mnemonic;
6645 /* GtkAccelGroup stores lowercased accelerators. To deal
6646 * with this, if <Shift> was specified, uppercase.
6648 if (modifiers & GDK_SHIFT_MASK)
6650 if (keyval == GDK_Tab)
6651 keyval = GDK_ISO_Left_Tab;
6653 keyval = gdk_keyval_to_upper (keyval);
6656 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
6660 gtk_window_get_key_hash (GtkWindow *window)
6662 GdkScreen *screen = gtk_window_check_screen (window);
6663 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6668 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
6669 (GDestroyNotify)g_free);
6670 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
6671 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
6677 gtk_window_free_key_hash (GtkWindow *window)
6679 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6682 _gtk_key_hash_free (key_hash);
6683 g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
6688 * _gtk_window_activate_key:
6689 * @window: a #GtkWindow
6690 * @event: a #GdkEventKey
6692 * Activates mnemonics and accelerators for this #GtKWindow
6694 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
6697 _gtk_window_activate_key (GtkWindow *window,
6700 GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6701 GtkWindowKeyEntry *found_entry = NULL;
6705 gtk_window_keys_changed (window);
6706 key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6711 GSList *entries = _gtk_key_hash_lookup (key_hash,
6712 event->hardware_keycode,
6713 event->state & gtk_accelerator_get_default_mod_mask (),
6717 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
6719 GtkWindowKeyEntry *entry = tmp_list->data;
6720 if (entry->is_mnemonic)
6722 found_entry = entry;
6727 if (!found_entry && entries)
6728 found_entry = entries->data;
6730 g_slist_free (entries);
6735 if (found_entry->is_mnemonic)
6736 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
6738 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
6745 window_update_has_focus (GtkWindow *window)
6747 GtkWidget *widget = GTK_WIDGET (window);
6748 gboolean has_focus = window->has_toplevel_focus && window->is_active;
6750 if (has_focus != window->has_focus)
6752 window->has_focus = has_focus;
6756 if (window->focus_widget &&
6757 window->focus_widget != widget &&
6758 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6759 do_focus_change (window->focus_widget, TRUE);
6763 if (window->focus_widget &&
6764 window->focus_widget != widget &&
6765 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
6766 do_focus_change (window->focus_widget, FALSE);
6772 * _gtk_window_set_is_active:
6773 * @window: a #GtkWindow
6774 * @is_active: %TRUE if the window is in the currently active toplevel
6776 * Internal function that sets whether the #GtkWindow is part
6777 * of the currently active toplevel window (taking into account inter-process
6781 _gtk_window_set_is_active (GtkWindow *window,
6784 g_return_if_fail (GTK_IS_WINDOW (window));
6786 is_active = is_active != FALSE;
6788 if (is_active != window->is_active)
6790 window->is_active = is_active;
6791 window_update_has_focus (window);
6793 g_object_notify (G_OBJECT (window), "is_active");
6798 * _gtk_window_set_has_toplevel_focus:
6799 * @window: a #GtkWindow
6800 * @has_toplevel_focus: %TRUE if the in
6802 * Internal function that sets whether the keyboard focus for the
6803 * toplevel window (taking into account inter-process embedding.)
6806 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
6807 gboolean has_toplevel_focus)
6809 g_return_if_fail (GTK_IS_WINDOW (window));
6811 has_toplevel_focus = has_toplevel_focus != FALSE;
6813 if (has_toplevel_focus != window->has_toplevel_focus)
6815 window->has_toplevel_focus = has_toplevel_focus;
6816 window_update_has_focus (window);
6818 g_object_notify (G_OBJECT (window), "has_toplevel_focus");
6823 * gtk_window_set_auto_startup_notification:
6824 * @setting: %TRUE to automatically do startup notification
6826 * By default, after showing the first #GtkWindow for each #GdkScreen,
6827 * GTK+ calls gdk_screen_notify_startup_complete(). Call this
6828 * function to disable the automatic startup notification. You might
6829 * do this if your first window is a splash screen, and you want to
6830 * delay notification until after your real main window has been
6831 * shown, for example.
6833 * In that example, you would disable startup notification
6834 * temporarily, show your splash screen, then re-enable it so that
6835 * showing the main window would automatically result in notification.
6840 gtk_window_set_auto_startup_notification (gboolean setting)
6842 disable_startup_notification = !setting;