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/.
31 #include "gdk/gdkkeysyms.h"
35 #include "gtkprivate.h"
37 #include "gtkwindow.h"
38 #include "gtkwindow-decorate.h"
39 #include "gtkbindings.h"
40 #include "gtkkeyhash.h"
42 #include "gtkmnemonichash.h"
43 #include "gtkiconfactory.h"
44 #include "gtkicontheme.h"
45 #include "gtkmarshalers.h"
49 #ifdef GDK_WINDOWING_X11
79 PROP_DESTROY_WITH_PARENT,
84 PROP_SKIP_TASKBAR_HINT,
93 /* Readonly properties */
95 PROP_HAS_TOPLEVEL_FOCUS,
103 GdkPixmap *icon_pixmap;
104 GdkPixmap *icon_mask;
107 guint using_default_icon : 1;
108 guint using_parent_icon : 1;
109 guint using_themed_icon : 1;
113 GdkGeometry geometry; /* Last set of geometry hints we set */
114 GdkWindowHints flags;
115 GdkRectangle configure_request;
116 } GtkWindowLastGeometryInfo;
118 struct _GtkWindowGeometryInfo
120 /* Properties that the app has set on the window
122 GdkGeometry geometry; /* Geometry hints */
124 GtkWidget *widget; /* subwidget to which hints apply */
125 /* from last gtk_window_resize () - if > 0, indicates that
126 * we should resize to this size.
131 /* From last gtk_window_move () prior to mapping -
132 * only used if initial_pos_set
137 /* Default size - used only the FIRST time we map a window,
142 /* whether to use initial_x, initial_y */
143 guint initial_pos_set : 1;
144 /* CENTER_ALWAYS or other position constraint changed since
145 * we sent the last configure request.
147 guint position_constraints_changed : 1;
149 /* if true, default_width, height come from gtk_window_parse_geometry,
150 * and thus should be multiplied by the increments and affect the
151 * geometry widget only
153 guint default_is_geometry : 1;
155 GtkWindowLastGeometryInfo last;
158 #define GTK_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW, GtkWindowPrivate))
160 typedef struct _GtkWindowPrivate GtkWindowPrivate;
162 struct _GtkWindowPrivate
164 GtkMnemonicHash *mnemonic_hash;
166 guint above_initially : 1;
167 guint below_initially : 1;
168 guint fullscreen_initially : 1;
169 guint skips_taskbar : 1;
170 guint skips_pager : 1;
172 guint accept_focus : 1;
173 guint focus_on_map : 1;
176 guint reset_type_hint : 1;
177 GdkWindowTypeHint type_hint;
180 static void gtk_window_dispose (GObject *object);
181 static void gtk_window_destroy (GtkObject *object);
182 static void gtk_window_finalize (GObject *object);
183 static void gtk_window_show (GtkWidget *widget);
184 static void gtk_window_hide (GtkWidget *widget);
185 static void gtk_window_map (GtkWidget *widget);
186 static void gtk_window_unmap (GtkWidget *widget);
187 static void gtk_window_realize (GtkWidget *widget);
188 static void gtk_window_unrealize (GtkWidget *widget);
189 static void gtk_window_size_request (GtkWidget *widget,
190 GtkRequisition *requisition);
191 static void gtk_window_size_allocate (GtkWidget *widget,
192 GtkAllocation *allocation);
193 static gint gtk_window_event (GtkWidget *widget,
195 static gboolean gtk_window_map_event (GtkWidget *widget,
197 static gboolean gtk_window_frame_event (GtkWindow *window,
199 static gint gtk_window_configure_event (GtkWidget *widget,
200 GdkEventConfigure *event);
201 static gint gtk_window_key_press_event (GtkWidget *widget,
203 static gint gtk_window_key_release_event (GtkWidget *widget,
205 static gint gtk_window_enter_notify_event (GtkWidget *widget,
206 GdkEventCrossing *event);
207 static gint gtk_window_leave_notify_event (GtkWidget *widget,
208 GdkEventCrossing *event);
209 static gint gtk_window_focus_in_event (GtkWidget *widget,
210 GdkEventFocus *event);
211 static gint gtk_window_focus_out_event (GtkWidget *widget,
212 GdkEventFocus *event);
213 static gint gtk_window_client_event (GtkWidget *widget,
214 GdkEventClient *event);
215 static void gtk_window_check_resize (GtkContainer *container);
216 static gint gtk_window_focus (GtkWidget *widget,
217 GtkDirectionType direction);
218 static void gtk_window_real_set_focus (GtkWindow *window,
221 static void gtk_window_real_activate_default (GtkWindow *window);
222 static void gtk_window_real_activate_focus (GtkWindow *window);
223 static void gtk_window_move_focus (GtkWindow *window,
224 GtkDirectionType dir);
225 static void gtk_window_keys_changed (GtkWindow *window);
226 static void gtk_window_paint (GtkWidget *widget,
228 static gint gtk_window_expose (GtkWidget *widget,
229 GdkEventExpose *event);
230 static void gtk_window_unset_transient_for (GtkWindow *window);
231 static void gtk_window_transient_parent_realized (GtkWidget *parent,
233 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
236 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
238 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
241 static void gtk_window_move_resize (GtkWindow *window);
242 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
244 GdkGeometry *geometry_b,
246 static void gtk_window_constrain_size (GtkWindow *window,
247 GdkGeometry *geometry,
253 static void gtk_window_constrain_position (GtkWindow *window,
258 static void gtk_window_compute_hints (GtkWindow *window,
259 GdkGeometry *new_geometry,
261 static void gtk_window_compute_configure_request (GtkWindow *window,
262 GdkRectangle *request,
263 GdkGeometry *geometry,
266 static void gtk_window_set_default_size_internal (GtkWindow *window,
267 gboolean change_width,
269 gboolean change_height,
271 gboolean is_geometry);
273 static void update_themed_icon (GtkIconTheme *theme,
275 static GList *icon_list_from_theme (GtkWidget *widget,
277 static void gtk_window_realize_icon (GtkWindow *window);
278 static void gtk_window_unrealize_icon (GtkWindow *window);
280 static void gtk_window_notify_keys_changed (GtkWindow *window);
281 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
282 static void gtk_window_free_key_hash (GtkWindow *window);
283 static void gtk_window_on_composited_changed (GdkScreen *screen,
286 static GSList *toplevel_list = NULL;
287 static guint window_signals[LAST_SIGNAL] = { 0 };
288 static GList *default_icon_list = NULL;
289 static gchar *default_icon_name = NULL;
290 static guint default_icon_serial = 0;
291 static gboolean disable_startup_notification = FALSE;
292 static gboolean sent_startup_notification = FALSE;
294 static GQuark quark_gtk_embedded = 0;
295 static GQuark quark_gtk_window_key_hash = 0;
296 static GQuark quark_gtk_window_default_icon_pixmap = 0;
297 static GQuark quark_gtk_window_icon_info = 0;
299 static void gtk_window_set_property (GObject *object,
303 static void gtk_window_get_property (GObject *object,
309 G_DEFINE_TYPE (GtkWindow, gtk_window, GTK_TYPE_BIN);
312 add_tab_bindings (GtkBindingSet *binding_set,
313 GdkModifierType modifiers,
314 GtkDirectionType direction)
316 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
318 GTK_TYPE_DIRECTION_TYPE, direction);
319 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
321 GTK_TYPE_DIRECTION_TYPE, direction);
325 add_arrow_bindings (GtkBindingSet *binding_set,
327 GtkDirectionType direction)
329 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
331 gtk_binding_entry_add_signal (binding_set, keysym, 0,
333 GTK_TYPE_DIRECTION_TYPE, direction);
334 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
336 GTK_TYPE_DIRECTION_TYPE, direction);
337 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
339 GTK_TYPE_DIRECTION_TYPE, direction);
340 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
342 GTK_TYPE_DIRECTION_TYPE, direction);
347 gtk_window_class_init (GtkWindowClass *klass)
349 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
350 GtkObjectClass *object_class;
351 GtkWidgetClass *widget_class;
352 GtkContainerClass *container_class;
353 GtkBindingSet *binding_set;
355 object_class = (GtkObjectClass*) klass;
356 widget_class = (GtkWidgetClass*) klass;
357 container_class = (GtkContainerClass*) klass;
359 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
360 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
361 quark_gtk_window_default_icon_pixmap = g_quark_from_static_string ("gtk-window-default-icon-pixmap");
362 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
364 gobject_class->dispose = gtk_window_dispose;
365 gobject_class->finalize = gtk_window_finalize;
367 gobject_class->set_property = gtk_window_set_property;
368 gobject_class->get_property = gtk_window_get_property;
370 object_class->destroy = gtk_window_destroy;
372 widget_class->show = gtk_window_show;
373 widget_class->hide = gtk_window_hide;
374 widget_class->map = gtk_window_map;
375 widget_class->map_event = gtk_window_map_event;
376 widget_class->unmap = gtk_window_unmap;
377 widget_class->realize = gtk_window_realize;
378 widget_class->unrealize = gtk_window_unrealize;
379 widget_class->size_request = gtk_window_size_request;
380 widget_class->size_allocate = gtk_window_size_allocate;
381 widget_class->configure_event = gtk_window_configure_event;
382 widget_class->key_press_event = gtk_window_key_press_event;
383 widget_class->key_release_event = gtk_window_key_release_event;
384 widget_class->enter_notify_event = gtk_window_enter_notify_event;
385 widget_class->leave_notify_event = gtk_window_leave_notify_event;
386 widget_class->focus_in_event = gtk_window_focus_in_event;
387 widget_class->focus_out_event = gtk_window_focus_out_event;
388 widget_class->client_event = gtk_window_client_event;
389 widget_class->focus = gtk_window_focus;
391 widget_class->expose_event = gtk_window_expose;
393 container_class->check_resize = gtk_window_check_resize;
395 klass->set_focus = gtk_window_real_set_focus;
396 klass->frame_event = gtk_window_frame_event;
398 klass->activate_default = gtk_window_real_activate_default;
399 klass->activate_focus = gtk_window_real_activate_focus;
400 klass->move_focus = gtk_window_move_focus;
401 klass->keys_changed = gtk_window_keys_changed;
403 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
406 g_object_class_install_property (gobject_class,
408 g_param_spec_enum ("type",
410 P_("The type of the window"),
411 GTK_TYPE_WINDOW_TYPE,
413 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
415 g_object_class_install_property (gobject_class,
417 g_param_spec_string ("title",
419 P_("The title of the window"),
421 GTK_PARAM_READWRITE));
423 g_object_class_install_property (gobject_class,
425 g_param_spec_string ("role",
427 P_("Unique identifier for the window to be used when restoring a session"),
429 GTK_PARAM_READWRITE));
431 g_object_class_install_property (gobject_class,
433 g_param_spec_boolean ("allow-shrink",
435 /* xgettext:no-c-format */
436 P_("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
438 GTK_PARAM_READWRITE));
440 g_object_class_install_property (gobject_class,
442 g_param_spec_boolean ("allow-grow",
444 P_("If TRUE, users can expand the window beyond its minimum size"),
446 GTK_PARAM_READWRITE));
448 g_object_class_install_property (gobject_class,
450 g_param_spec_boolean ("resizable",
452 P_("If TRUE, users can resize the window"),
454 GTK_PARAM_READWRITE));
456 g_object_class_install_property (gobject_class,
458 g_param_spec_boolean ("modal",
460 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
462 GTK_PARAM_READWRITE));
464 g_object_class_install_property (gobject_class,
466 g_param_spec_enum ("window-position",
467 P_("Window Position"),
468 P_("The initial position of the window"),
469 GTK_TYPE_WINDOW_POSITION,
471 GTK_PARAM_READWRITE));
473 g_object_class_install_property (gobject_class,
475 g_param_spec_int ("default-width",
477 P_("The default width of the window, used when initially showing the window"),
481 GTK_PARAM_READWRITE));
483 g_object_class_install_property (gobject_class,
485 g_param_spec_int ("default-height",
486 P_("Default Height"),
487 P_("The default height of the window, used when initially showing the window"),
491 GTK_PARAM_READWRITE));
493 g_object_class_install_property (gobject_class,
494 PROP_DESTROY_WITH_PARENT,
495 g_param_spec_boolean ("destroy-with-parent",
496 P_("Destroy with Parent"),
497 P_("If this window should be destroyed when the parent is destroyed"),
499 GTK_PARAM_READWRITE));
501 g_object_class_install_property (gobject_class,
503 g_param_spec_object ("icon",
505 P_("Icon for this window"),
507 GTK_PARAM_READWRITE));
510 * GtkWindow:icon-name:
512 * The :icon-name property specifies the name of the themed icon to
513 * use as the window icon. See #GtkIconTheme for more details.
517 g_object_class_install_property (gobject_class,
519 g_param_spec_string ("icon-name",
521 P_("Name of the themed icon for this window"),
523 GTK_PARAM_READWRITE));
525 g_object_class_install_property (gobject_class,
527 g_param_spec_object ("screen",
529 P_("The screen where this window will be displayed"),
531 GTK_PARAM_READWRITE));
533 g_object_class_install_property (gobject_class,
535 g_param_spec_boolean ("is-active",
537 P_("Whether the toplevel is the current active window"),
539 GTK_PARAM_READABLE));
541 g_object_class_install_property (gobject_class,
542 PROP_HAS_TOPLEVEL_FOCUS,
543 g_param_spec_boolean ("has-toplevel-focus",
544 P_("Focus in Toplevel"),
545 P_("Whether the input focus is within this GtkWindow"),
547 GTK_PARAM_READABLE));
549 g_object_class_install_property (gobject_class,
551 g_param_spec_enum ("type-hint",
553 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
554 GDK_TYPE_WINDOW_TYPE_HINT,
555 GDK_WINDOW_TYPE_HINT_NORMAL,
556 GTK_PARAM_READWRITE));
558 g_object_class_install_property (gobject_class,
559 PROP_SKIP_TASKBAR_HINT,
560 g_param_spec_boolean ("skip-taskbar-hint",
562 P_("TRUE if the window should not be in the task bar."),
564 GTK_PARAM_READWRITE));
566 g_object_class_install_property (gobject_class,
567 PROP_SKIP_PAGER_HINT,
568 g_param_spec_boolean ("skip-pager-hint",
570 P_("TRUE if the window should not be in the pager."),
572 GTK_PARAM_READWRITE));
574 g_object_class_install_property (gobject_class,
576 g_param_spec_boolean ("urgency-hint",
578 P_("TRUE if the window should be brought to the user's attention."),
580 GTK_PARAM_READWRITE));
583 * GtkWindow:accept-focus-hint:
585 * Whether the window should receive the input focus.
589 g_object_class_install_property (gobject_class,
591 g_param_spec_boolean ("accept-focus",
593 P_("TRUE if the window should receive the input focus."),
595 GTK_PARAM_READWRITE));
598 * GtkWindow:focus-on-map-hint:
600 * Whether the window should receive the input focus when mapped.
604 g_object_class_install_property (gobject_class,
606 g_param_spec_boolean ("focus-on-map",
608 P_("TRUE if the window should receive the input focus when mapped."),
610 GTK_PARAM_READWRITE));
613 * GtkWindow:decorated:
615 * Whether the window should be decorated by the window manager.
619 g_object_class_install_property (gobject_class,
621 g_param_spec_boolean ("decorated",
623 P_("Whether the window should be decorated by the window manager"),
625 GTK_PARAM_READWRITE));
628 * GtkWindow:deletable:
630 * Whether the window frame should have a close button.
634 g_object_class_install_property (gobject_class,
636 g_param_spec_boolean ("deletable",
638 P_("Whether the window frame should have a close button"),
640 GTK_PARAM_READWRITE));
646 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
647 * more details about window gravity.
651 g_object_class_install_property (gobject_class,
653 g_param_spec_enum ("gravity",
655 P_("The window gravity of the window"),
657 GDK_GRAVITY_NORTH_WEST,
658 GTK_PARAM_READWRITE));
660 window_signals[SET_FOCUS] =
661 g_signal_new (I_("set_focus"),
662 G_TYPE_FROM_CLASS (gobject_class),
664 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
666 _gtk_marshal_VOID__OBJECT,
670 window_signals[FRAME_EVENT] =
671 g_signal_new (I_("frame_event"),
672 G_TYPE_FROM_CLASS (gobject_class),
674 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
675 _gtk_boolean_handled_accumulator, NULL,
676 _gtk_marshal_BOOLEAN__BOXED,
680 window_signals[ACTIVATE_FOCUS] =
681 g_signal_new (I_("activate_focus"),
682 G_TYPE_FROM_CLASS (gobject_class),
683 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
684 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
686 _gtk_marshal_VOID__VOID,
690 window_signals[ACTIVATE_DEFAULT] =
691 g_signal_new (I_("activate_default"),
692 G_TYPE_FROM_CLASS (gobject_class),
693 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
694 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
696 _gtk_marshal_VOID__VOID,
700 window_signals[MOVE_FOCUS] =
701 g_signal_new (I_("move_focus"),
702 G_TYPE_FROM_CLASS (gobject_class),
703 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
704 G_STRUCT_OFFSET (GtkWindowClass, move_focus),
706 _gtk_marshal_VOID__ENUM,
709 GTK_TYPE_DIRECTION_TYPE);
711 window_signals[KEYS_CHANGED] =
712 g_signal_new (I_("keys_changed"),
713 G_TYPE_FROM_CLASS (gobject_class),
715 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
717 _gtk_marshal_VOID__VOID,
725 binding_set = gtk_binding_set_by_class (klass);
727 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
728 "activate_focus", 0);
729 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
730 "activate_focus", 0);
732 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
733 "activate_default", 0);
735 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
736 "activate_default", 0);
738 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
739 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
740 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
741 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
743 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
744 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
745 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
746 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
750 gtk_window_init (GtkWindow *window)
752 GdkColormap *colormap;
753 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
755 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
756 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
758 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
760 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
762 window->title = NULL;
763 window->wmclass_name = g_strdup (g_get_prgname ());
764 window->wmclass_class = g_strdup (gdk_get_program_class ());
765 window->wm_role = NULL;
766 window->geometry_info = NULL;
767 window->type = GTK_WINDOW_TOPLEVEL;
768 window->focus_widget = NULL;
769 window->default_widget = NULL;
770 window->configure_request_count = 0;
771 window->allow_shrink = FALSE;
772 window->allow_grow = TRUE;
773 window->configure_notify_received = FALSE;
774 window->position = GTK_WIN_POS_NONE;
775 window->need_default_size = TRUE;
776 window->need_default_position = TRUE;
777 window->modal = FALSE;
778 window->frame = NULL;
779 window->has_frame = FALSE;
780 window->frame_left = 0;
781 window->frame_right = 0;
782 window->frame_top = 0;
783 window->frame_bottom = 0;
784 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
785 window->gravity = GDK_GRAVITY_NORTH_WEST;
786 window->decorated = TRUE;
787 window->mnemonic_modifier = GDK_MOD1_MASK;
788 window->screen = gdk_screen_get_default ();
790 priv->accept_focus = TRUE;
791 priv->focus_on_map = TRUE;
792 priv->deletable = TRUE;
793 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
795 colormap = _gtk_widget_peek_colormap ();
797 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
799 g_object_ref_sink (window);
800 window->has_user_ref_count = TRUE;
801 toplevel_list = g_slist_prepend (toplevel_list, window);
803 gtk_decorated_window_init (window);
805 g_signal_connect (window->screen, "composited_changed",
806 G_CALLBACK (gtk_window_on_composited_changed), window);
810 gtk_window_set_property (GObject *object,
817 window = GTK_WINDOW (object);
822 window->type = g_value_get_enum (value);
825 gtk_window_set_title (window, g_value_get_string (value));
828 gtk_window_set_role (window, g_value_get_string (value));
830 case PROP_ALLOW_SHRINK:
831 window->allow_shrink = g_value_get_boolean (value);
832 gtk_widget_queue_resize (GTK_WIDGET (window));
834 case PROP_ALLOW_GROW:
835 window->allow_grow = g_value_get_boolean (value);
836 gtk_widget_queue_resize (GTK_WIDGET (window));
837 g_object_notify (G_OBJECT (window), "resizable");
840 window->allow_grow = g_value_get_boolean (value);
841 gtk_widget_queue_resize (GTK_WIDGET (window));
842 g_object_notify (G_OBJECT (window), "allow-grow");
845 gtk_window_set_modal (window, g_value_get_boolean (value));
848 gtk_window_set_position (window, g_value_get_enum (value));
850 case PROP_DEFAULT_WIDTH:
851 gtk_window_set_default_size_internal (window,
852 TRUE, g_value_get_int (value),
855 case PROP_DEFAULT_HEIGHT:
856 gtk_window_set_default_size_internal (window,
858 TRUE, g_value_get_int (value), FALSE);
860 case PROP_DESTROY_WITH_PARENT:
861 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
864 gtk_window_set_icon (window,
865 g_value_get_object (value));
868 gtk_window_set_icon_name (window, g_value_get_string (value));
871 gtk_window_set_screen (window, g_value_get_object (value));
874 gtk_window_set_type_hint (window,
875 g_value_get_enum (value));
877 case PROP_SKIP_TASKBAR_HINT:
878 gtk_window_set_skip_taskbar_hint (window,
879 g_value_get_boolean (value));
881 case PROP_SKIP_PAGER_HINT:
882 gtk_window_set_skip_pager_hint (window,
883 g_value_get_boolean (value));
885 case PROP_URGENCY_HINT:
886 gtk_window_set_urgency_hint (window,
887 g_value_get_boolean (value));
889 case PROP_ACCEPT_FOCUS:
890 gtk_window_set_accept_focus (window,
891 g_value_get_boolean (value));
893 case PROP_FOCUS_ON_MAP:
894 gtk_window_set_focus_on_map (window,
895 g_value_get_boolean (value));
898 gtk_window_set_decorated (window, g_value_get_boolean (value));
901 gtk_window_set_deletable (window, g_value_get_boolean (value));
904 gtk_window_set_gravity (window, g_value_get_enum (value));
912 gtk_window_get_property (GObject *object,
918 GtkWindowPrivate *priv;
920 window = GTK_WINDOW (object);
921 priv = GTK_WINDOW_GET_PRIVATE (window);
925 GtkWindowGeometryInfo *info;
927 g_value_set_enum (value, window->type);
930 g_value_set_string (value, window->wm_role);
933 g_value_set_string (value, window->title);
935 case PROP_ALLOW_SHRINK:
936 g_value_set_boolean (value, window->allow_shrink);
938 case PROP_ALLOW_GROW:
939 g_value_set_boolean (value, window->allow_grow);
942 g_value_set_boolean (value, window->allow_grow);
945 g_value_set_boolean (value, window->modal);
948 g_value_set_enum (value, window->position);
950 case PROP_DEFAULT_WIDTH:
951 info = gtk_window_get_geometry_info (window, FALSE);
953 g_value_set_int (value, -1);
955 g_value_set_int (value, info->default_width);
957 case PROP_DEFAULT_HEIGHT:
958 info = gtk_window_get_geometry_info (window, FALSE);
960 g_value_set_int (value, -1);
962 g_value_set_int (value, info->default_height);
964 case PROP_DESTROY_WITH_PARENT:
965 g_value_set_boolean (value, window->destroy_with_parent);
968 g_value_set_object (value, gtk_window_get_icon (window));
971 g_value_set_string (value, gtk_window_get_icon_name (window));
974 g_value_set_object (value, window->screen);
977 g_value_set_boolean (value, window->is_active);
979 case PROP_HAS_TOPLEVEL_FOCUS:
980 g_value_set_boolean (value, window->has_toplevel_focus);
983 g_value_set_enum (value, priv->type_hint);
985 case PROP_SKIP_TASKBAR_HINT:
986 g_value_set_boolean (value,
987 gtk_window_get_skip_taskbar_hint (window));
989 case PROP_SKIP_PAGER_HINT:
990 g_value_set_boolean (value,
991 gtk_window_get_skip_pager_hint (window));
993 case PROP_URGENCY_HINT:
994 g_value_set_boolean (value,
995 gtk_window_get_urgency_hint (window));
997 case PROP_ACCEPT_FOCUS:
998 g_value_set_boolean (value,
999 gtk_window_get_accept_focus (window));
1001 case PROP_FOCUS_ON_MAP:
1002 g_value_set_boolean (value,
1003 gtk_window_get_focus_on_map (window));
1005 case PROP_DECORATED:
1006 g_value_set_boolean (value, gtk_window_get_decorated (window));
1008 case PROP_DELETABLE:
1009 g_value_set_boolean (value, gtk_window_get_deletable (window));
1012 g_value_set_enum (value, gtk_window_get_gravity (window));
1015 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1022 * @type: type of window
1024 * Creates a new #GtkWindow, which is a toplevel window that can
1025 * contain other widgets. Nearly always, the type of the window should
1026 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1027 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1028 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1029 * dialogs, though in some other toolkits dialogs are called "popups".
1030 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1031 * On X11, popup windows are not controlled by the <link
1032 * linkend="gtk-X11-arch">window manager</link>.
1034 * If you simply want an undecorated window (no window borders), use
1035 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1037 * Return value: a new #GtkWindow.
1040 gtk_window_new (GtkWindowType type)
1044 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1046 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1048 window->type = type;
1050 return GTK_WIDGET (window);
1054 * gtk_window_set_title:
1055 * @window: a #GtkWindow
1056 * @title: title of the window
1058 * Sets the title of the #GtkWindow. The title of a window will be
1059 * displayed in its title bar; on the X Window System, the title bar
1060 * is rendered by the <link linkend="gtk-X11-arch">window
1061 * manager</link>, so exactly how the title appears to users may vary
1062 * according to a user's exact configuration. The title should help a
1063 * user distinguish this window from other windows they may have
1064 * open. A good title might include the application name and current
1065 * document filename, for example.
1069 gtk_window_set_title (GtkWindow *window,
1074 g_return_if_fail (GTK_IS_WINDOW (window));
1076 new_title = g_strdup (title);
1077 g_free (window->title);
1078 window->title = new_title;
1080 if (GTK_WIDGET_REALIZED (window))
1082 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
1084 gtk_decorated_window_set_title (window, title);
1087 g_object_notify (G_OBJECT (window), "title");
1091 * gtk_window_get_title:
1092 * @window: a #GtkWindow
1094 * Retrieves the title of the window. See gtk_window_set_title().
1096 * Return value: the title of the window, or %NULL if none has
1097 * been set explicitely. The returned string is owned by the widget
1098 * and must not be modified or freed.
1100 G_CONST_RETURN gchar *
1101 gtk_window_get_title (GtkWindow *window)
1103 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1105 return window->title;
1109 * gtk_window_set_wmclass:
1110 * @window: a #GtkWindow
1111 * @wmclass_name: window name hint
1112 * @wmclass_class: window class hint
1114 * Don't use this function. It sets the X Window System "class" and
1115 * "name" hints for a window. According to the ICCCM, you should
1116 * always set these to the same value for all windows in an
1117 * application, and GTK+ sets them to that value by default, so calling
1118 * this function is sort of pointless. However, you may want to call
1119 * gtk_window_set_role() on each window in your application, for the
1120 * benefit of the session manager. Setting the role allows the window
1121 * manager to restore window positions when loading a saved session.
1125 gtk_window_set_wmclass (GtkWindow *window,
1126 const gchar *wmclass_name,
1127 const gchar *wmclass_class)
1129 g_return_if_fail (GTK_IS_WINDOW (window));
1131 g_free (window->wmclass_name);
1132 window->wmclass_name = g_strdup (wmclass_name);
1134 g_free (window->wmclass_class);
1135 window->wmclass_class = g_strdup (wmclass_class);
1137 if (GTK_WIDGET_REALIZED (window))
1138 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1142 * gtk_window_set_role:
1143 * @window: a #GtkWindow
1144 * @role: unique identifier for the window to be used when restoring a session
1146 * This function is only useful on X11, not with other GTK+ targets.
1148 * In combination with the window title, the window role allows a
1149 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1150 * same" window when an application is restarted. So for example you
1151 * might set the "toolbox" role on your app's toolbox window, so that
1152 * when the user restarts their session, the window manager can put
1153 * the toolbox back in the same place.
1155 * If a window already has a unique title, you don't need to set the
1156 * role, since the WM can use the title to identify the window when
1157 * restoring the session.
1161 gtk_window_set_role (GtkWindow *window,
1166 g_return_if_fail (GTK_IS_WINDOW (window));
1168 new_role = g_strdup (role);
1169 g_free (window->wm_role);
1170 window->wm_role = new_role;
1172 if (GTK_WIDGET_REALIZED (window))
1173 gdk_window_set_role (GTK_WIDGET (window)->window, window->wm_role);
1175 g_object_notify (G_OBJECT (window), "role");
1179 * gtk_window_get_role:
1180 * @window: a #GtkWindow
1182 * Returns the role of the window. See gtk_window_set_role() for
1183 * further explanation.
1185 * Return value: the role of the window if set, or %NULL. The
1186 * returned is owned by the widget and must not be modified
1189 G_CONST_RETURN gchar *
1190 gtk_window_get_role (GtkWindow *window)
1192 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1194 return window->wm_role;
1198 * gtk_window_set_focus:
1199 * @window: a #GtkWindow
1200 * @focus: widget to be the new focus widget, or %NULL to unset
1201 * any focus widget for the toplevel window.
1203 * If @focus is not the current focus widget, and is focusable, sets
1204 * it as the focus widget for the window. If @focus is %NULL, unsets
1205 * the focus widget for this window. To set the focus to a particular
1206 * widget in the toplevel, it is usually more convenient to use
1207 * gtk_widget_grab_focus() instead of this function.
1210 gtk_window_set_focus (GtkWindow *window,
1213 g_return_if_fail (GTK_IS_WINDOW (window));
1216 g_return_if_fail (GTK_IS_WIDGET (focus));
1217 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1221 gtk_widget_grab_focus (focus);
1224 /* Clear the existing focus chain, so that when we focus into
1225 * the window again, we start at the beginnning.
1227 GtkWidget *widget = window->focus_widget;
1230 while (widget->parent)
1232 widget = widget->parent;
1233 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1237 _gtk_window_internal_set_focus (window, NULL);
1242 _gtk_window_internal_set_focus (GtkWindow *window,
1245 g_return_if_fail (GTK_IS_WINDOW (window));
1247 if ((window->focus_widget != focus) ||
1248 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1249 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1253 * gtk_window_set_default:
1254 * @window: a #GtkWindow
1255 * @default_widget: widget to be the default, or %NULL to unset the
1256 * default widget for the toplevel.
1258 * The default widget is the widget that's activated when the user
1259 * presses Enter in a dialog (for example). This function sets or
1260 * unsets the default widget for a #GtkWindow about. When setting
1261 * (rather than unsetting) the default widget it's generally easier to
1262 * call gtk_widget_grab_focus() on the widget. Before making a widget
1263 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1264 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1267 gtk_window_set_default (GtkWindow *window,
1268 GtkWidget *default_widget)
1270 g_return_if_fail (GTK_IS_WINDOW (window));
1273 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1275 if (window->default_widget != default_widget)
1277 GtkWidget *old_default_widget = NULL;
1280 g_object_ref (default_widget);
1282 if (window->default_widget)
1284 old_default_widget = window->default_widget;
1286 if (window->focus_widget != window->default_widget ||
1287 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1288 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1289 gtk_widget_queue_draw (window->default_widget);
1292 window->default_widget = default_widget;
1294 if (window->default_widget)
1296 if (window->focus_widget == NULL ||
1297 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1298 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1299 gtk_widget_queue_draw (window->default_widget);
1302 if (old_default_widget)
1303 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1307 g_object_notify (G_OBJECT (default_widget), "has-default");
1308 g_object_unref (default_widget);
1314 gtk_window_set_policy (GtkWindow *window,
1315 gboolean allow_shrink,
1316 gboolean allow_grow,
1317 gboolean auto_shrink)
1319 g_return_if_fail (GTK_IS_WINDOW (window));
1321 window->allow_shrink = (allow_shrink != FALSE);
1322 window->allow_grow = (allow_grow != FALSE);
1324 g_object_freeze_notify (G_OBJECT (window));
1325 g_object_notify (G_OBJECT (window), "allow-shrink");
1326 g_object_notify (G_OBJECT (window), "allow-grow");
1327 g_object_notify (G_OBJECT (window), "resizable");
1328 g_object_thaw_notify (G_OBJECT (window));
1330 gtk_widget_queue_resize (GTK_WIDGET (window));
1334 handle_keys_changed (gpointer data)
1338 GDK_THREADS_ENTER ();
1339 window = GTK_WINDOW (data);
1341 if (window->keys_changed_handler)
1343 g_source_remove (window->keys_changed_handler);
1344 window->keys_changed_handler = 0;
1347 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1348 GDK_THREADS_LEAVE ();
1354 gtk_window_notify_keys_changed (GtkWindow *window)
1356 if (!window->keys_changed_handler)
1357 window->keys_changed_handler = g_idle_add (handle_keys_changed, window);
1361 * gtk_window_add_accel_group:
1362 * @window: window to attach accelerator group to
1363 * @accel_group: a #GtkAccelGroup
1365 * Associate @accel_group with @window, such that calling
1366 * gtk_accel_groups_activate() on @window will activate accelerators
1370 gtk_window_add_accel_group (GtkWindow *window,
1371 GtkAccelGroup *accel_group)
1373 g_return_if_fail (GTK_IS_WINDOW (window));
1374 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1376 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1377 g_signal_connect_object (accel_group, "accel_changed",
1378 G_CALLBACK (gtk_window_notify_keys_changed),
1379 window, G_CONNECT_SWAPPED);
1383 * gtk_window_remove_accel_group:
1384 * @window: a #GtkWindow
1385 * @accel_group: a #GtkAccelGroup
1387 * Reverses the effects of gtk_window_add_accel_group().
1390 gtk_window_remove_accel_group (GtkWindow *window,
1391 GtkAccelGroup *accel_group)
1393 g_return_if_fail (GTK_IS_WINDOW (window));
1394 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1396 g_signal_handlers_disconnect_by_func (accel_group,
1397 gtk_window_notify_keys_changed,
1399 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1402 static GtkMnemonicHash *
1403 gtk_window_get_mnemonic_hash (GtkWindow *window,
1406 GtkWindowPrivate *private = GTK_WINDOW_GET_PRIVATE (window);
1407 if (!private->mnemonic_hash && create)
1408 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1410 return private->mnemonic_hash;
1414 * gtk_window_add_mnemonic:
1415 * @window: a #GtkWindow
1416 * @keyval: the mnemonic
1417 * @target: the widget that gets activated by the mnemonic
1419 * Adds a mnemonic to this window.
1422 gtk_window_add_mnemonic (GtkWindow *window,
1426 g_return_if_fail (GTK_IS_WINDOW (window));
1427 g_return_if_fail (GTK_IS_WIDGET (target));
1429 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1431 gtk_window_notify_keys_changed (window);
1435 * gtk_window_remove_mnemonic:
1436 * @window: a #GtkWindow
1437 * @keyval: the mnemonic
1438 * @target: the widget that gets activated by the mnemonic
1440 * Removes a mnemonic from this window.
1443 gtk_window_remove_mnemonic (GtkWindow *window,
1447 g_return_if_fail (GTK_IS_WINDOW (window));
1448 g_return_if_fail (GTK_IS_WIDGET (target));
1450 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
1452 gtk_window_notify_keys_changed (window);
1456 * gtk_window_mnemonic_activate:
1457 * @window: a #GtkWindow
1458 * @keyval: the mnemonic
1459 * @modifier: the modifiers
1460 * @returns: %TRUE if the activation is done.
1462 * Activates the targets associated with the mnemonic.
1465 gtk_window_mnemonic_activate (GtkWindow *window,
1467 GdkModifierType modifier)
1469 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1471 if (window->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
1473 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
1475 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
1482 * gtk_window_set_mnemonic_modifier:
1483 * @window: a #GtkWindow
1484 * @modifier: the modifier mask used to activate
1485 * mnemonics on this window.
1487 * Sets the mnemonic modifier for this window.
1490 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1491 GdkModifierType modifier)
1493 g_return_if_fail (GTK_IS_WINDOW (window));
1494 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1496 window->mnemonic_modifier = modifier;
1497 gtk_window_notify_keys_changed (window);
1501 * gtk_window_get_mnemonic_modifier:
1502 * @window: a #GtkWindow
1504 * Returns the mnemonic modifier for this window. See
1505 * gtk_window_set_mnemonic_modifier().
1507 * Return value: the modifier mask used to activate
1508 * mnemonics on this window.
1511 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1513 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1515 return window->mnemonic_modifier;
1519 * gtk_window_set_position:
1520 * @window: a #GtkWindow.
1521 * @position: a position constraint.
1523 * Sets a position constraint for this window. If the old or new
1524 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1525 * the window to be repositioned to satisfy the new constraint.
1528 gtk_window_set_position (GtkWindow *window,
1529 GtkWindowPosition position)
1531 g_return_if_fail (GTK_IS_WINDOW (window));
1533 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1534 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1536 GtkWindowGeometryInfo *info;
1538 info = gtk_window_get_geometry_info (window, TRUE);
1540 /* this flag causes us to re-request the CENTER_ALWAYS
1541 * constraint in gtk_window_move_resize(), see
1542 * comment in that function.
1544 info->position_constraints_changed = TRUE;
1546 gtk_widget_queue_resize (GTK_WIDGET (window));
1549 window->position = position;
1551 g_object_notify (G_OBJECT (window), "window-position");
1555 * gtk_window_activate_focus:
1556 * @window: a #GtkWindow
1558 * Activates the current focused widget within the window.
1560 * Return value: %TRUE if a widget got activated.
1563 gtk_window_activate_focus (GtkWindow *window)
1565 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1567 if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1568 return gtk_widget_activate (window->focus_widget);
1574 * gtk_window_get_focus:
1575 * @window: a #GtkWindow
1577 * Retrieves the current focused widget within the window.
1578 * Note that this is the widget that would have the focus
1579 * if the toplevel window focused; if the toplevel window
1580 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1581 * not be %TRUE for the widget.
1583 * Return value: the currently focused widget, or %NULL if there is none.
1586 gtk_window_get_focus (GtkWindow *window)
1588 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1590 return window->focus_widget;
1594 * gtk_window_activate_default:
1595 * @window: a #GtkWindow
1597 * Activates the default widget for the window, unless the current
1598 * focused widget has been configured to receive the default action
1599 * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
1600 * focused widget is activated.
1602 * Return value: %TRUE if a widget got activated.
1605 gtk_window_activate_default (GtkWindow *window)
1607 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1609 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1610 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1611 return gtk_widget_activate (window->default_widget);
1612 else if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1613 return gtk_widget_activate (window->focus_widget);
1619 * gtk_window_set_modal:
1620 * @window: a #GtkWindow
1621 * @modal: whether the window is modal
1623 * Sets a window modal or non-modal. Modal windows prevent interaction
1624 * with other windows in the same application. To keep modal dialogs
1625 * on top of main application windows, use
1626 * gtk_window_set_transient_for() to make the dialog transient for the
1627 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1628 * will then disallow lowering the dialog below the parent.
1633 gtk_window_set_modal (GtkWindow *window,
1636 g_return_if_fail (GTK_IS_WINDOW (window));
1638 modal = modal != FALSE;
1639 if (window->modal == modal)
1642 window->modal = modal;
1644 /* adjust desired modality state */
1645 if (GTK_WIDGET_REALIZED (window))
1647 GtkWidget *widget = GTK_WIDGET (window);
1650 gdk_window_set_modal_hint (widget->window, TRUE);
1652 gdk_window_set_modal_hint (widget->window, FALSE);
1655 if (GTK_WIDGET_VISIBLE (window))
1658 gtk_grab_add (GTK_WIDGET (window));
1660 gtk_grab_remove (GTK_WIDGET (window));
1663 g_object_notify (G_OBJECT (window), "modal");
1667 * gtk_window_get_modal:
1668 * @window: a #GtkWindow
1670 * Returns whether the window is modal. See gtk_window_set_modal().
1672 * Return value: %TRUE if the window is set to be modal and
1673 * establishes a grab when shown
1676 gtk_window_get_modal (GtkWindow *window)
1678 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1680 return window->modal;
1684 * gtk_window_list_toplevels:
1686 * Returns a list of all existing toplevel windows. The widgets
1687 * in the list are not individually referenced. If you want
1688 * to iterate through the list and perform actions involving
1689 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1690 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1691 * then unref all the widgets afterwards.
1693 * Return value: list of toplevel widgets
1696 gtk_window_list_toplevels (void)
1701 for (slist = toplevel_list; slist; slist = slist->next)
1702 list = g_list_prepend (list, slist->data);
1708 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1710 GList *embedded_windows;
1712 g_return_if_fail (GTK_IS_WINDOW (window));
1714 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
1715 if (embedded_windows)
1716 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
1717 embedded_windows = g_list_prepend (embedded_windows,
1718 GUINT_TO_POINTER (xid));
1720 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
1723 (GDestroyNotify) g_list_free : NULL);
1727 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1729 GList *embedded_windows;
1732 g_return_if_fail (GTK_IS_WINDOW (window));
1734 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
1735 if (embedded_windows)
1736 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
1738 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1741 embedded_windows = g_list_remove_link (embedded_windows, node);
1742 g_list_free_1 (node);
1745 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
1748 (GDestroyNotify) g_list_free : NULL);
1752 _gtk_window_reposition (GtkWindow *window,
1756 g_return_if_fail (GTK_IS_WINDOW (window));
1758 gtk_window_move (window, x, y);
1762 gtk_window_dispose (GObject *object)
1764 GtkWindow *window = GTK_WINDOW (object);
1766 gtk_window_set_focus (window, NULL);
1767 gtk_window_set_default (window, NULL);
1769 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
1773 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1775 gtk_widget_destroy (GTK_WIDGET (child));
1779 connect_parent_destroyed (GtkWindow *window)
1781 if (window->transient_parent)
1783 g_signal_connect (window->transient_parent,
1785 G_CALLBACK (parent_destroyed_callback),
1791 disconnect_parent_destroyed (GtkWindow *window)
1793 if (window->transient_parent)
1795 g_signal_handlers_disconnect_by_func (window->transient_parent,
1796 parent_destroyed_callback,
1802 gtk_window_transient_parent_realized (GtkWidget *parent,
1805 if (GTK_WIDGET_REALIZED (window))
1806 gdk_window_set_transient_for (window->window, parent->window);
1810 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1813 if (GTK_WIDGET_REALIZED (window))
1814 gdk_property_delete (window->window,
1815 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
1819 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
1823 gtk_window_set_screen (window, parent->screen);
1827 gtk_window_unset_transient_for (GtkWindow *window)
1829 if (window->transient_parent)
1831 if (window->transient_parent->group)
1832 gtk_window_group_remove_window (window->transient_parent->group,
1835 g_signal_handlers_disconnect_by_func (window->transient_parent,
1836 gtk_window_transient_parent_realized,
1838 g_signal_handlers_disconnect_by_func (window->transient_parent,
1839 gtk_window_transient_parent_unrealized,
1841 g_signal_handlers_disconnect_by_func (window->transient_parent,
1842 gtk_window_transient_parent_screen_changed,
1844 g_signal_handlers_disconnect_by_func (window->transient_parent,
1845 gtk_widget_destroyed,
1846 &window->transient_parent);
1848 if (window->destroy_with_parent)
1849 disconnect_parent_destroyed (window);
1851 window->transient_parent = NULL;
1856 * gtk_window_set_transient_for:
1857 * @window: a #GtkWindow
1858 * @parent: parent window
1860 * Dialog windows should be set transient for the main application
1861 * window they were spawned from. This allows <link
1862 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1863 * dialog on top of the main window, or center the dialog over the
1864 * main window. gtk_dialog_new_with_buttons() and other convenience
1865 * functions in GTK+ will sometimes call
1866 * gtk_window_set_transient_for() on your behalf.
1868 * On Windows, this function will and put the child window
1869 * on top of the parent, much as the window manager would have
1874 gtk_window_set_transient_for (GtkWindow *window,
1877 g_return_if_fail (GTK_IS_WINDOW (window));
1878 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1879 g_return_if_fail (window != parent);
1882 if (window->transient_parent)
1884 if (GTK_WIDGET_REALIZED (window) &&
1885 GTK_WIDGET_REALIZED (window->transient_parent) &&
1886 (!parent || !GTK_WIDGET_REALIZED (parent)))
1887 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1888 GTK_WIDGET (window));
1890 gtk_window_unset_transient_for (window);
1893 window->transient_parent = parent;
1897 g_signal_connect (parent, "destroy",
1898 G_CALLBACK (gtk_widget_destroyed),
1899 &window->transient_parent);
1900 g_signal_connect (parent, "realize",
1901 G_CALLBACK (gtk_window_transient_parent_realized),
1903 g_signal_connect (parent, "unrealize",
1904 G_CALLBACK (gtk_window_transient_parent_unrealized),
1906 g_signal_connect (parent, "notify::screen",
1907 G_CALLBACK (gtk_window_transient_parent_screen_changed),
1910 gtk_window_set_screen (window, parent->screen);
1912 if (window->destroy_with_parent)
1913 connect_parent_destroyed (window);
1915 if (GTK_WIDGET_REALIZED (window) &&
1916 GTK_WIDGET_REALIZED (parent))
1917 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1918 GTK_WIDGET (window));
1921 gtk_window_group_add_window (parent->group, window);
1926 * gtk_window_get_transient_for:
1927 * @window: a #GtkWindow
1929 * Fetches the transient parent for this window. See
1930 * gtk_window_set_transient_for().
1932 * Return value: the transient parent for this window, or %NULL
1933 * if no transient parent has been set.
1936 gtk_window_get_transient_for (GtkWindow *window)
1938 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1940 return window->transient_parent;
1944 * gtk_window_set_type_hint:
1945 * @window: a #GtkWindow
1946 * @hint: the window type
1948 * By setting the type hint for the window, you allow the window
1949 * manager to decorate and handle the window in a way which is
1950 * suitable to the function of the window in your application.
1952 * This function should be called before the window becomes visible.
1954 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1955 * will sometimes call gtk_window_set_type_hint() on your behalf.
1959 gtk_window_set_type_hint (GtkWindow *window,
1960 GdkWindowTypeHint hint)
1962 GtkWindowPrivate *priv;
1964 g_return_if_fail (GTK_IS_WINDOW (window));
1965 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1967 priv = GTK_WINDOW_GET_PRIVATE (window);
1969 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
1970 window->type_hint = hint;
1972 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1974 priv->reset_type_hint = TRUE;
1975 priv->type_hint = hint;
1979 * gtk_window_get_type_hint:
1980 * @window: a #GtkWindow
1982 * Gets the type hint for this window. See gtk_window_set_type_hint().
1984 * Return value: the type hint for @window.
1987 gtk_window_get_type_hint (GtkWindow *window)
1989 GtkWindowPrivate *priv;
1991 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1993 priv = GTK_WINDOW_GET_PRIVATE (window);
1995 return priv->type_hint;
1999 * gtk_window_set_skip_taskbar_hint:
2000 * @window: a #GtkWindow
2001 * @setting: %TRUE to keep this window from appearing in the task bar
2003 * Windows may set a hint asking the desktop environment not to display
2004 * the window in the task bar. This function sets this hint.
2009 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2012 GtkWindowPrivate *priv;
2014 g_return_if_fail (GTK_IS_WINDOW (window));
2016 priv = GTK_WINDOW_GET_PRIVATE (window);
2018 setting = setting != FALSE;
2020 if (priv->skips_taskbar != setting)
2022 priv->skips_taskbar = setting;
2023 if (GTK_WIDGET_REALIZED (window))
2024 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
2025 priv->skips_taskbar);
2026 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2031 * gtk_window_get_skip_taskbar_hint:
2032 * @window: a #GtkWindow
2034 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2036 * Return value: %TRUE if window shouldn't be in taskbar
2041 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2043 GtkWindowPrivate *priv;
2045 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2047 priv = GTK_WINDOW_GET_PRIVATE (window);
2049 return priv->skips_taskbar;
2053 * gtk_window_set_skip_pager_hint:
2054 * @window: a #GtkWindow
2055 * @setting: %TRUE to keep this window from appearing in the pager
2057 * Windows may set a hint asking the desktop environment not to display
2058 * the window in the pager. This function sets this hint.
2059 * (A "pager" is any desktop navigation tool such as a workspace
2060 * switcher that displays a thumbnail representation of the windows
2066 gtk_window_set_skip_pager_hint (GtkWindow *window,
2069 GtkWindowPrivate *priv;
2071 g_return_if_fail (GTK_IS_WINDOW (window));
2073 priv = GTK_WINDOW_GET_PRIVATE (window);
2075 setting = setting != FALSE;
2077 if (priv->skips_pager != setting)
2079 priv->skips_pager = setting;
2080 if (GTK_WIDGET_REALIZED (window))
2081 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2083 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2088 * gtk_window_get_skip_pager_hint:
2089 * @window: a #GtkWindow
2091 * Gets the value set by gtk_window_set_skip_pager_hint().
2093 * Return value: %TRUE if window shouldn't be in pager
2098 gtk_window_get_skip_pager_hint (GtkWindow *window)
2100 GtkWindowPrivate *priv;
2102 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2104 priv = GTK_WINDOW_GET_PRIVATE (window);
2106 return priv->skips_pager;
2110 * gtk_window_set_urgency_hint:
2111 * @window: a #GtkWindow
2112 * @setting: %TRUE to mark this window as urgent
2114 * Windows may set a hint asking the desktop environment to draw
2115 * the users attention to the window. This function sets this hint.
2120 gtk_window_set_urgency_hint (GtkWindow *window,
2123 GtkWindowPrivate *priv;
2125 g_return_if_fail (GTK_IS_WINDOW (window));
2127 priv = GTK_WINDOW_GET_PRIVATE (window);
2129 setting = setting != FALSE;
2131 if (priv->urgent != setting)
2133 priv->urgent = setting;
2134 if (GTK_WIDGET_REALIZED (window))
2135 gdk_window_set_urgency_hint (GTK_WIDGET (window)->window,
2137 g_object_notify (G_OBJECT (window), "urgency-hint");
2142 * gtk_window_get_urgency_hint:
2143 * @window: a #GtkWindow
2145 * Gets the value set by gtk_window_set_urgency_hint()
2147 * Return value: %TRUE if window is urgent
2152 gtk_window_get_urgency_hint (GtkWindow *window)
2154 GtkWindowPrivate *priv;
2156 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2158 priv = GTK_WINDOW_GET_PRIVATE (window);
2160 return priv->urgent;
2164 * gtk_window_set_accept_focus:
2165 * @window: a #GtkWindow
2166 * @setting: %TRUE to let this window receive input focus
2168 * Windows may set a hint asking the desktop environment not to receive
2169 * the input focus. This function sets this hint.
2174 gtk_window_set_accept_focus (GtkWindow *window,
2177 GtkWindowPrivate *priv;
2179 g_return_if_fail (GTK_IS_WINDOW (window));
2181 priv = GTK_WINDOW_GET_PRIVATE (window);
2183 setting = setting != FALSE;
2185 if (priv->accept_focus != setting)
2187 priv->accept_focus = setting;
2188 if (GTK_WIDGET_REALIZED (window))
2189 gdk_window_set_accept_focus (GTK_WIDGET (window)->window,
2190 priv->accept_focus);
2191 g_object_notify (G_OBJECT (window), "accept-focus");
2196 * gtk_window_get_accept_focus:
2197 * @window: a #GtkWindow
2199 * Gets the value set by gtk_window_set_accept_focus().
2201 * Return value: %TRUE if window should receive the input focus
2206 gtk_window_get_accept_focus (GtkWindow *window)
2208 GtkWindowPrivate *priv;
2210 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2212 priv = GTK_WINDOW_GET_PRIVATE (window);
2214 return priv->accept_focus;
2218 * gtk_window_set_focus_on_map:
2219 * @window: a #GtkWindow
2220 * @setting: %TRUE to let this window receive input focus on map
2222 * Windows may set a hint asking the desktop environment not to receive
2223 * the input focus when the window is mapped. This function sets this
2229 gtk_window_set_focus_on_map (GtkWindow *window,
2232 GtkWindowPrivate *priv;
2234 g_return_if_fail (GTK_IS_WINDOW (window));
2236 priv = GTK_WINDOW_GET_PRIVATE (window);
2238 setting = setting != FALSE;
2240 if (priv->focus_on_map != setting)
2242 priv->focus_on_map = setting;
2243 if (GTK_WIDGET_REALIZED (window))
2244 gdk_window_set_focus_on_map (GTK_WIDGET (window)->window,
2245 priv->focus_on_map);
2246 g_object_notify (G_OBJECT (window), "focus-on-map");
2251 * gtk_window_get_focus_on_map:
2252 * @window: a #GtkWindow
2254 * Gets the value set by gtk_window_set_focus_on_map().
2256 * Return value: %TRUE if window should receive the input focus when
2262 gtk_window_get_focus_on_map (GtkWindow *window)
2264 GtkWindowPrivate *priv;
2266 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2268 priv = GTK_WINDOW_GET_PRIVATE (window);
2270 return priv->focus_on_map;
2274 * gtk_window_set_destroy_with_parent:
2275 * @window: a #GtkWindow
2276 * @setting: whether to destroy @window with its transient parent
2278 * If @setting is %TRUE, then destroying the transient parent of @window
2279 * will also destroy @window itself. This is useful for dialogs that
2280 * shouldn't persist beyond the lifetime of the main window they're
2281 * associated with, for example.
2284 gtk_window_set_destroy_with_parent (GtkWindow *window,
2287 g_return_if_fail (GTK_IS_WINDOW (window));
2289 if (window->destroy_with_parent == (setting != FALSE))
2292 if (window->destroy_with_parent)
2294 disconnect_parent_destroyed (window);
2298 connect_parent_destroyed (window);
2301 window->destroy_with_parent = setting;
2303 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2307 * gtk_window_get_destroy_with_parent:
2308 * @window: a #GtkWindow
2310 * Returns whether the window will be destroyed with its transient parent. See
2311 * gtk_window_set_destroy_with_parent ().
2313 * Return value: %TRUE if the window will be destroyed with its transient parent.
2316 gtk_window_get_destroy_with_parent (GtkWindow *window)
2318 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2320 return window->destroy_with_parent;
2323 static GtkWindowGeometryInfo*
2324 gtk_window_get_geometry_info (GtkWindow *window,
2327 GtkWindowGeometryInfo *info;
2329 info = window->geometry_info;
2330 if (!info && create)
2332 info = g_new0 (GtkWindowGeometryInfo, 1);
2334 info->default_width = -1;
2335 info->default_height = -1;
2336 info->resize_width = -1;
2337 info->resize_height = -1;
2338 info->initial_x = 0;
2339 info->initial_y = 0;
2340 info->initial_pos_set = FALSE;
2341 info->default_is_geometry = FALSE;
2342 info->position_constraints_changed = FALSE;
2343 info->last.configure_request.x = 0;
2344 info->last.configure_request.y = 0;
2345 info->last.configure_request.width = -1;
2346 info->last.configure_request.height = -1;
2347 info->widget = NULL;
2349 window->geometry_info = info;
2356 * gtk_window_set_geometry_hints:
2357 * @window: a #GtkWindow
2358 * @geometry_widget: widget the geometry hints will be applied to
2359 * @geometry: struct containing geometry information
2360 * @geom_mask: mask indicating which struct fields should be paid attention to
2362 * This function sets up hints about how a window can be resized by
2363 * the user. You can set a minimum and maximum size; allowed resize
2364 * increments (e.g. for xterm, you can only resize by the size of a
2365 * character); aspect ratios; and more. See the #GdkGeometry struct.
2369 gtk_window_set_geometry_hints (GtkWindow *window,
2370 GtkWidget *geometry_widget,
2371 GdkGeometry *geometry,
2372 GdkWindowHints geom_mask)
2374 GtkWindowGeometryInfo *info;
2376 g_return_if_fail (GTK_IS_WINDOW (window));
2377 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2379 info = gtk_window_get_geometry_info (window, TRUE);
2382 g_signal_handlers_disconnect_by_func (info->widget,
2383 gtk_widget_destroyed,
2386 info->widget = geometry_widget;
2388 g_signal_connect (geometry_widget, "destroy",
2389 G_CALLBACK (gtk_widget_destroyed),
2393 info->geometry = *geometry;
2395 /* We store gravity in window->gravity not in the hints. */
2396 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2398 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2400 gtk_window_set_gravity (window, geometry->win_gravity);
2403 gtk_widget_queue_resize (GTK_WIDGET (window));
2407 * gtk_window_set_decorated:
2408 * @window: a #GtkWindow
2409 * @setting: %TRUE to decorate the window
2411 * By default, windows are decorated with a title bar, resize
2412 * controls, etc. Some <link linkend="gtk-X11-arch">window
2413 * managers</link> allow GTK+ to disable these decorations, creating a
2414 * borderless window. If you set the decorated property to %FALSE
2415 * using this function, GTK+ will do its best to convince the window
2416 * manager not to decorate the window. Depending on the system, this
2417 * function may not have any effect when called on a window that is
2418 * already visible, so you should call it before calling gtk_window_show().
2420 * On Windows, this function always works, since there's no window manager
2425 gtk_window_set_decorated (GtkWindow *window,
2428 g_return_if_fail (GTK_IS_WINDOW (window));
2430 setting = setting != FALSE;
2432 if (setting == window->decorated)
2435 window->decorated = setting;
2437 if (GTK_WIDGET (window)->window)
2439 if (window->decorated)
2440 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2443 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2447 g_object_notify (G_OBJECT (window), "decorated");
2451 * gtk_window_get_decorated:
2452 * @window: a #GtkWindow
2454 * Returns whether the window has been set to have decorations
2455 * such as a title bar via gtk_window_set_decorated().
2457 * Return value: %TRUE if the window has been set to have decorations
2460 gtk_window_get_decorated (GtkWindow *window)
2462 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2464 return window->decorated;
2468 * gtk_window_set_deletable:
2469 * @window: a #GtkWindow
2470 * @setting: %TRUE to decorate the window as deletable
2472 * By default, windows have a close button in the window frame. Some
2473 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
2474 * disable this button. If you set the deletable property to %FALSE
2475 * using this function, GTK+ will do its best to convince the window
2476 * manager not to show a close button. Depending on the system, this
2477 * function may not have any effect when called on a window that is
2478 * already visible, so you should call it before calling gtk_window_show().
2480 * On Windows, this function always works, since there's no window manager
2486 gtk_window_set_deletable (GtkWindow *window,
2489 GtkWindowPrivate *priv;
2491 g_return_if_fail (GTK_IS_WINDOW (window));
2493 priv = GTK_WINDOW_GET_PRIVATE (window);
2495 setting = setting != FALSE;
2497 if (setting == priv->deletable)
2500 priv->deletable = setting;
2502 if (GTK_WIDGET (window)->window)
2504 if (priv->deletable)
2505 gdk_window_set_functions (GTK_WIDGET (window)->window,
2508 gdk_window_set_functions (GTK_WIDGET (window)->window,
2509 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
2512 g_object_notify (G_OBJECT (window), "deletable");
2516 * gtk_window_get_deletable:
2517 * @window: a #GtkWindow
2519 * Returns whether the window has been set to have a close button
2520 * via gtk_window_set_deletable().
2522 * Return value: %TRUE if the window has been set to have a close button
2527 gtk_window_get_deletable (GtkWindow *window)
2529 GtkWindowPrivate *priv;
2531 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2533 priv = GTK_WINDOW_GET_PRIVATE (window);
2535 return priv->deletable;
2538 static GtkWindowIconInfo*
2539 get_icon_info (GtkWindow *window)
2541 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
2545 free_icon_info (GtkWindowIconInfo *info)
2547 g_free (info->icon_name);
2548 g_slice_free (GtkWindowIconInfo, info);
2552 static GtkWindowIconInfo*
2553 ensure_icon_info (GtkWindow *window)
2555 GtkWindowIconInfo *info;
2557 info = get_icon_info (window);
2561 info = g_slice_new0 (GtkWindowIconInfo);
2562 g_object_set_qdata_full (G_OBJECT (window),
2563 quark_gtk_window_icon_info,
2565 (GDestroyNotify)free_icon_info);
2577 static ScreenIconInfo *
2578 get_screen_icon_info (GdkScreen *screen)
2580 ScreenIconInfo *info = g_object_get_qdata (G_OBJECT (screen),
2581 quark_gtk_window_default_icon_pixmap);
2584 info = g_slice_new0 (ScreenIconInfo);
2585 g_object_set_qdata (G_OBJECT (screen),
2586 quark_gtk_window_default_icon_pixmap, info);
2589 if (info->serial != default_icon_serial)
2593 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2594 info->pixmap = NULL;
2599 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2603 info->serial = default_icon_serial;
2610 get_pixmap_and_mask (GdkWindow *window,
2611 GtkWindowIconInfo *parent_info,
2612 gboolean is_default_list,
2614 GdkPixmap **pmap_return,
2615 GdkBitmap **mask_return)
2617 GdkScreen *screen = gdk_drawable_get_screen (window);
2618 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2619 GdkPixbuf *best_icon;
2623 *pmap_return = NULL;
2624 *mask_return = NULL;
2626 if (is_default_list &&
2627 default_icon_info->pixmap != NULL)
2629 /* Use shared icon pixmap for all windows on this screen.
2631 if (default_icon_info->pixmap)
2632 g_object_ref (default_icon_info->pixmap);
2633 if (default_icon_info->mask)
2634 g_object_ref (default_icon_info->mask);
2636 *pmap_return = default_icon_info->pixmap;
2637 *mask_return = default_icon_info->mask;
2639 else if (parent_info && parent_info->icon_pixmap)
2641 if (parent_info->icon_pixmap)
2642 g_object_ref (parent_info->icon_pixmap);
2643 if (parent_info->icon_mask)
2644 g_object_ref (parent_info->icon_mask);
2646 *pmap_return = parent_info->icon_pixmap;
2647 *mask_return = parent_info->icon_mask;
2651 #define IDEAL_SIZE 48
2653 best_size = G_MAXINT;
2655 tmp_list = icon_list;
2656 while (tmp_list != NULL)
2658 GdkPixbuf *pixbuf = tmp_list->data;
2661 /* average width and height - if someone passes in a rectangular
2662 * icon they deserve what they get.
2664 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2667 if (best_icon == NULL)
2674 /* icon is better if it's 32 pixels or larger, and closer to
2675 * the ideal size than the current best.
2678 (ABS (best_size - IDEAL_SIZE) <
2679 ABS (this - IDEAL_SIZE)))
2686 tmp_list = tmp_list->next;
2690 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2691 gdk_screen_get_system_colormap (screen),
2696 /* Save pmap/mask for others to use if appropriate */
2699 parent_info->icon_pixmap = *pmap_return;
2700 parent_info->icon_mask = *mask_return;
2702 if (parent_info->icon_pixmap)
2703 g_object_ref (parent_info->icon_pixmap);
2704 if (parent_info->icon_mask)
2705 g_object_ref (parent_info->icon_mask);
2707 else if (is_default_list)
2709 default_icon_info->pixmap = *pmap_return;
2710 default_icon_info->mask = *mask_return;
2712 if (default_icon_info->pixmap)
2713 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2714 (gpointer*)&default_icon_info->pixmap);
2715 if (default_icon_info->mask)
2716 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2717 (gpointer*)&default_icon_info->mask);
2723 icon_list_from_theme (GtkWidget *widget,
2728 GtkIconTheme *icon_theme;
2733 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
2735 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
2738 for (i = 0; sizes[i]; i++)
2741 * We need an EWMH extension to handle scalable icons
2742 * by passing their name to the WM. For now just use a
2746 icon = gtk_icon_theme_load_icon (icon_theme, name,
2749 icon = gtk_icon_theme_load_icon (icon_theme, name,
2752 list = g_list_append (list, icon);
2762 gtk_window_realize_icon (GtkWindow *window)
2765 GtkWindowIconInfo *info;
2768 widget = GTK_WIDGET (window);
2770 g_return_if_fail (widget->window != NULL);
2772 /* no point setting an icon on override-redirect */
2773 if (window->type == GTK_WINDOW_POPUP)
2778 info = ensure_icon_info (window);
2783 g_return_if_fail (info->icon_pixmap == NULL);
2784 g_return_if_fail (info->icon_mask == NULL);
2786 info->using_default_icon = FALSE;
2787 info->using_parent_icon = FALSE;
2788 info->using_themed_icon = FALSE;
2790 icon_list = info->icon_list;
2792 /* Look up themed icon */
2793 if (icon_list == NULL && info->icon_name)
2795 icon_list = icon_list_from_theme (widget, info->icon_name);
2797 info->using_themed_icon = TRUE;
2800 /* Inherit from transient parent */
2801 if (icon_list == NULL && window->transient_parent)
2803 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2805 info->using_parent_icon = TRUE;
2808 /* Inherit from default */
2809 if (icon_list == NULL)
2811 icon_list = default_icon_list;
2813 info->using_default_icon = TRUE;
2816 /* Look up themed icon */
2817 if (icon_list == NULL && default_icon_name)
2819 icon_list = icon_list_from_theme (widget, default_icon_name);
2820 info->using_default_icon = TRUE;
2821 info->using_themed_icon = TRUE;
2824 gdk_window_set_icon_list (widget->window, icon_list);
2826 get_pixmap_and_mask (widget->window,
2827 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2828 info->using_default_icon,
2833 /* This is a slight ICCCM violation since it's a color pixmap not
2834 * a bitmap, but everyone does it.
2836 gdk_window_set_icon (widget->window,
2841 info->realized = TRUE;
2843 if (info->using_themed_icon)
2845 GtkIconTheme *icon_theme;
2847 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
2848 g_list_free (icon_list);
2850 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2851 g_signal_connect (icon_theme, "changed",
2852 G_CALLBACK (update_themed_icon), window);
2857 gtk_window_unrealize_icon (GtkWindow *window)
2859 GtkWindowIconInfo *info;
2861 info = get_icon_info (window);
2866 if (info->icon_pixmap)
2867 g_object_unref (info->icon_pixmap);
2869 if (info->icon_mask)
2870 g_object_unref (info->icon_mask);
2872 info->icon_pixmap = NULL;
2873 info->icon_mask = NULL;
2875 if (info->using_themed_icon)
2877 GtkIconTheme *icon_theme;
2879 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2881 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
2884 /* We don't clear the properties on the window, just figure the
2885 * window is going away.
2888 info->realized = FALSE;
2893 * gtk_window_set_icon_list:
2894 * @window: a #GtkWindow
2895 * @list: list of #GdkPixbuf
2897 * Sets up the icon representing a #GtkWindow. The icon is used when
2898 * the window is minimized (also known as iconified). Some window
2899 * managers or desktop environments may also place it in the window
2900 * frame, or display it in other contexts.
2902 * gtk_window_set_icon_list() allows you to pass in the same icon in
2903 * several hand-drawn sizes. The list should contain the natural sizes
2904 * your icon is available in; that is, don't scale the image before
2905 * passing it to GTK+. Scaling is postponed until the last minute,
2906 * when the desired final size is known, to allow best quality.
2908 * By passing several sizes, you may improve the final image quality
2909 * of the icon, by reducing or eliminating automatic image scaling.
2911 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2912 * larger images (64x64, 128x128) if you have them.
2914 * See also gtk_window_set_default_icon_list() to set the icon
2915 * for all windows in your application in one go.
2917 * Note that transient windows (those who have been set transient for another
2918 * window using gtk_window_set_transient_for()) will inherit their
2919 * icon from their transient parent. So there's no need to explicitly
2920 * set the icon on transient windows.
2923 gtk_window_set_icon_list (GtkWindow *window,
2926 GtkWindowIconInfo *info;
2928 g_return_if_fail (GTK_IS_WINDOW (window));
2930 info = ensure_icon_info (window);
2932 if (info->icon_list == list) /* check for NULL mostly */
2935 g_list_foreach (list,
2936 (GFunc) g_object_ref, NULL);
2938 g_list_foreach (info->icon_list,
2939 (GFunc) g_object_unref, NULL);
2941 g_list_free (info->icon_list);
2943 info->icon_list = g_list_copy (list);
2945 g_object_notify (G_OBJECT (window), "icon");
2947 gtk_window_unrealize_icon (window);
2949 if (GTK_WIDGET_REALIZED (window))
2950 gtk_window_realize_icon (window);
2952 /* We could try to update our transient children, but I don't think
2953 * it's really worth it. If we did it, the best way would probably
2954 * be to have children connect to notify::icon-list
2959 * gtk_window_get_icon_list:
2960 * @window: a #GtkWindow
2962 * Retrieves the list of icons set by gtk_window_set_icon_list().
2963 * The list is copied, but the reference count on each
2964 * member won't be incremented.
2966 * Return value: copy of window's icon list
2969 gtk_window_get_icon_list (GtkWindow *window)
2971 GtkWindowIconInfo *info;
2973 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2975 info = get_icon_info (window);
2978 return g_list_copy (info->icon_list);
2984 * gtk_window_set_icon:
2985 * @window: a #GtkWindow
2986 * @icon: icon image, or %NULL
2988 * Sets up the icon representing a #GtkWindow. This icon is used when
2989 * the window is minimized (also known as iconified). Some window
2990 * managers or desktop environments may also place it in the window
2991 * frame, or display it in other contexts.
2993 * The icon should be provided in whatever size it was naturally
2994 * drawn; that is, don't scale the image before passing it to
2995 * GTK+. Scaling is postponed until the last minute, when the desired
2996 * final size is known, to allow best quality.
2998 * If you have your icon hand-drawn in multiple sizes, use
2999 * gtk_window_set_icon_list(). Then the best size will be used.
3001 * This function is equivalent to calling gtk_window_set_icon_list()
3002 * with a 1-element list.
3004 * See also gtk_window_set_default_icon_list() to set the icon
3005 * for all windows in your application in one go.
3008 gtk_window_set_icon (GtkWindow *window,
3013 g_return_if_fail (GTK_IS_WINDOW (window));
3014 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3019 list = g_list_append (list, icon);
3021 gtk_window_set_icon_list (window, list);
3027 update_themed_icon (GtkIconTheme *icon_theme,
3030 g_object_notify (G_OBJECT (window), "icon");
3032 gtk_window_unrealize_icon (window);
3034 if (GTK_WIDGET_REALIZED (window))
3035 gtk_window_realize_icon (window);
3039 * gtk_window_set_icon_name:
3040 * @window: a #GtkWindow
3041 * @name: the name of the themed icon
3043 * Sets the icon for the window from a named themed icon. See
3044 * the docs for #GtkIconTheme for more details.
3046 * Note that this has nothing to do with the WM_ICON_NAME
3047 * property which is mentioned in the ICCCM.
3052 gtk_window_set_icon_name (GtkWindow *window,
3055 GtkWindowIconInfo *info;
3058 g_return_if_fail (GTK_IS_WINDOW (window));
3060 info = ensure_icon_info (window);
3062 tmp = info->icon_name;
3063 info->icon_name = g_strdup (name);
3066 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3067 g_list_free (info->icon_list);
3068 info->icon_list = NULL;
3070 update_themed_icon (NULL, window);
3072 g_object_notify (G_OBJECT (window), "icon-name");
3076 * gtk_window_get_icon_name:
3077 * @window: a #GtkWindow
3079 * Returns the name of the themed icon for the window,
3080 * see gtk_window_set_icon_name().
3082 * Returns: the icon name or %NULL if the window has
3087 G_CONST_RETURN gchar *
3088 gtk_window_get_icon_name (GtkWindow *window)
3090 GtkWindowIconInfo *info;
3092 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3094 info = ensure_icon_info (window);
3096 return info->icon_name;
3100 * gtk_window_get_icon:
3101 * @window: a #GtkWindow
3103 * Gets the value set by gtk_window_set_icon() (or if you've
3104 * called gtk_window_set_icon_list(), gets the first icon in
3107 * Return value: icon for window
3110 gtk_window_get_icon (GtkWindow *window)
3112 GtkWindowIconInfo *info;
3114 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3116 info = get_icon_info (window);
3117 if (info && info->icon_list)
3118 return GDK_PIXBUF (info->icon_list->data);
3123 /* Load pixbuf, printing warning on failure if error == NULL
3126 load_pixbuf_verbosely (const char *filename,
3129 GError *local_err = NULL;
3132 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3140 g_warning ("Error loading icon from file '%s':\n\t%s",
3141 filename, local_err->message);
3142 g_error_free (local_err);
3150 * gtk_window_set_icon_from_file:
3151 * @window: a #GtkWindow
3152 * @filename: location of icon file
3153 * @err: location to store error, or %NULL.
3155 * Sets the icon for @window.
3156 * Warns on failure if @err is %NULL.
3158 * This function is equivalent to calling gtk_window_set_icon()
3159 * with a pixbuf created by loading the image from @filename.
3161 * Returns: %TRUE if setting the icon succeeded.
3166 gtk_window_set_icon_from_file (GtkWindow *window,
3167 const gchar *filename,
3170 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3174 gtk_window_set_icon (window, pixbuf);
3175 g_object_unref (pixbuf);
3184 * gtk_window_set_default_icon_list:
3185 * @list: a list of #GdkPixbuf
3187 * Sets an icon list to be used as fallback for windows that haven't
3188 * had gtk_window_set_icon_list() called on them to set up a
3189 * window-specific icon list. This function allows you to set up the
3190 * icon for all windows in your app at once.
3192 * See gtk_window_set_icon_list() for more details.
3196 gtk_window_set_default_icon_list (GList *list)
3200 if (list == default_icon_list)
3203 /* Update serial so we don't used cached pixmaps/masks
3205 default_icon_serial++;
3207 g_list_foreach (list,
3208 (GFunc) g_object_ref, NULL);
3210 g_list_foreach (default_icon_list,
3211 (GFunc) g_object_unref, NULL);
3213 g_list_free (default_icon_list);
3215 default_icon_list = g_list_copy (list);
3217 /* Update all toplevels */
3218 toplevels = gtk_window_list_toplevels ();
3219 tmp_list = toplevels;
3220 while (tmp_list != NULL)
3222 GtkWindowIconInfo *info;
3223 GtkWindow *w = tmp_list->data;
3225 info = get_icon_info (w);
3226 if (info && info->using_default_icon)
3228 gtk_window_unrealize_icon (w);
3229 if (GTK_WIDGET_REALIZED (w))
3230 gtk_window_realize_icon (w);
3233 tmp_list = tmp_list->next;
3235 g_list_free (toplevels);
3239 * gtk_window_set_default_icon:
3242 * Sets an icon to be used as fallback for windows that haven't
3243 * had gtk_window_set_icon() called on them from a pixbuf.
3248 gtk_window_set_default_icon (GdkPixbuf *icon)
3252 g_return_if_fail (GDK_IS_PIXBUF (icon));
3254 list = g_list_prepend (NULL, icon);
3255 gtk_window_set_default_icon_list (list);
3260 * gtk_window_set_default_icon_name:
3261 * @name: the name of the themed icon
3263 * Sets an icon to be used as fallback for windows that haven't
3264 * had gtk_window_set_icon_list() called on them from a named
3265 * themed icon, see gtk_window_set_icon_name().
3270 gtk_window_set_default_icon_name (const gchar *name)
3275 /* Update serial so we don't used cached pixmaps/masks
3277 default_icon_serial++;
3279 g_free (default_icon_name);
3280 default_icon_name = g_strdup (name);
3282 g_list_foreach (default_icon_list,
3283 (GFunc) g_object_unref, NULL);
3285 g_list_free (default_icon_list);
3286 default_icon_list = NULL;
3288 /* Update all toplevels */
3289 toplevels = gtk_window_list_toplevels ();
3290 tmp_list = toplevels;
3291 while (tmp_list != NULL)
3293 GtkWindowIconInfo *info;
3294 GtkWindow *w = tmp_list->data;
3296 info = get_icon_info (w);
3297 if (info && info->using_default_icon && info->using_themed_icon)
3299 gtk_window_unrealize_icon (w);
3300 if (GTK_WIDGET_REALIZED (w))
3301 gtk_window_realize_icon (w);
3304 tmp_list = tmp_list->next;
3306 g_list_free (toplevels);
3310 * gtk_window_set_default_icon_from_file:
3311 * @filename: location of icon file
3312 * @err: location to store error, or %NULL.
3314 * Sets an icon to be used as fallback for windows that haven't
3315 * had gtk_window_set_icon_list() called on them from a file
3316 * on disk. Warns on failure if @err is %NULL.
3318 * Returns: %TRUE if setting the icon succeeded.
3323 gtk_window_set_default_icon_from_file (const gchar *filename,
3326 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3330 gtk_window_set_default_icon (pixbuf);
3331 g_object_unref (pixbuf);
3340 * gtk_window_get_default_icon_list:
3342 * Gets the value set by gtk_window_set_default_icon_list().
3343 * The list is a copy and should be freed with g_list_free(),
3344 * but the pixbufs in the list have not had their reference count
3347 * Return value: copy of default icon list
3350 gtk_window_get_default_icon_list (void)
3352 return g_list_copy (default_icon_list);
3356 gtk_window_set_default_size_internal (GtkWindow *window,
3357 gboolean change_width,
3359 gboolean change_height,
3361 gboolean is_geometry)
3363 GtkWindowGeometryInfo *info;
3365 g_return_if_fail (change_width == FALSE || width >= -1);
3366 g_return_if_fail (change_height == FALSE || height >= -1);
3368 info = gtk_window_get_geometry_info (window, TRUE);
3370 g_object_freeze_notify (G_OBJECT (window));
3372 info->default_is_geometry = is_geometry != FALSE;
3382 info->default_width = width;
3384 g_object_notify (G_OBJECT (window), "default-width");
3395 info->default_height = height;
3397 g_object_notify (G_OBJECT (window), "default-height");
3400 g_object_thaw_notify (G_OBJECT (window));
3402 gtk_widget_queue_resize (GTK_WIDGET (window));
3406 * gtk_window_set_default_size:
3407 * @window: a #GtkWindow
3408 * @width: width in pixels, or -1 to unset the default width
3409 * @height: height in pixels, or -1 to unset the default height
3411 * Sets the default size of a window. If the window's "natural" size
3412 * (its size request) is larger than the default, the default will be
3413 * ignored. More generally, if the default size does not obey the
3414 * geometry hints for the window (gtk_window_set_geometry_hints() can
3415 * be used to set these explicitly), the default size will be clamped
3416 * to the nearest permitted size.
3418 * Unlike gtk_widget_set_size_request(), which sets a size request for
3419 * a widget and thus would keep users from shrinking the window, this
3420 * function only sets the initial size, just as if the user had
3421 * resized the window themselves. Users can still shrink the window
3422 * again as they normally would. Setting a default size of -1 means to
3423 * use the "natural" default size (the size request of the window).
3425 * For more control over a window's initial size and how resizing works,
3426 * investigate gtk_window_set_geometry_hints().
3428 * For some uses, gtk_window_resize() is a more appropriate function.
3429 * gtk_window_resize() changes the current size of the window, rather
3430 * than the size to be used on initial display. gtk_window_resize() always
3431 * affects the window itself, not the geometry widget.
3433 * The default size of a window only affects the first time a window is
3434 * shown; if a window is hidden and re-shown, it will remember the size
3435 * it had prior to hiding, rather than using the default size.
3437 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3438 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3441 gtk_window_set_default_size (GtkWindow *window,
3445 g_return_if_fail (GTK_IS_WINDOW (window));
3446 g_return_if_fail (width >= -1);
3447 g_return_if_fail (height >= -1);
3449 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3453 * gtk_window_get_default_size:
3454 * @window: a #GtkWindow
3455 * @width: location to store the default width, or %NULL
3456 * @height: location to store the default height, or %NULL
3458 * Gets the default size of the window. A value of -1 for the width or
3459 * height indicates that a default size has not been explicitly set
3460 * for that dimension, so the "natural" size of the window will be
3465 gtk_window_get_default_size (GtkWindow *window,
3469 GtkWindowGeometryInfo *info;
3471 g_return_if_fail (GTK_IS_WINDOW (window));
3473 info = gtk_window_get_geometry_info (window, FALSE);
3476 *width = info ? info->default_width : -1;
3479 *height = info ? info->default_height : -1;
3483 * gtk_window_resize:
3484 * @window: a #GtkWindow
3485 * @width: width in pixels to resize the window to
3486 * @height: height in pixels to resize the window to
3488 * Resizes the window as if the user had done so, obeying geometry
3489 * constraints. The default geometry constraint is that windows may
3490 * not be smaller than their size request; to override this
3491 * constraint, call gtk_widget_set_size_request() to set the window's
3492 * request to a smaller value.
3494 * If gtk_window_resize() is called before showing a window for the
3495 * first time, it overrides any default size set with
3496 * gtk_window_set_default_size().
3498 * Windows may not be resized smaller than 1 by 1 pixels.
3502 gtk_window_resize (GtkWindow *window,
3506 GtkWindowGeometryInfo *info;
3508 g_return_if_fail (GTK_IS_WINDOW (window));
3509 g_return_if_fail (width > 0);
3510 g_return_if_fail (height > 0);
3512 info = gtk_window_get_geometry_info (window, TRUE);
3514 info->resize_width = width;
3515 info->resize_height = height;
3517 gtk_widget_queue_resize (GTK_WIDGET (window));
3521 * gtk_window_get_size:
3522 * @window: a #GtkWindow
3523 * @width: return location for width, or %NULL
3524 * @height: return location for height, or %NULL
3526 * Obtains the current size of @window. If @window is not onscreen,
3527 * it returns the size GTK+ will suggest to the <link
3528 * linkend="gtk-X11-arch">window manager</link> for the initial window
3529 * size (but this is not reliably the same as the size the window
3530 * manager will actually select). The size obtained by
3531 * gtk_window_get_size() is the last size received in a
3532 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
3533 * rather than querying the X server for the size. As a result, if you
3534 * call gtk_window_resize() then immediately call
3535 * gtk_window_get_size(), the size won't have taken effect yet. After
3536 * the window manager processes the resize request, GTK+ receives
3537 * notification that the size has changed via a configure event, and
3538 * the size of the window gets updated.
3540 * Note 1: Nearly any use of this function creates a race condition,
3541 * because the size of the window may change between the time that you
3542 * get the size and the time that you perform some action assuming
3543 * that size is the current size. To avoid race conditions, connect to
3544 * "configure_event" on the window and adjust your size-dependent
3545 * state to match the size delivered in the #GdkEventConfigure.
3547 * Note 2: The returned size does <emphasis>not</emphasis> include the
3548 * size of the window manager decorations (aka the window frame or
3549 * border). Those are not drawn by GTK+ and GTK+ has no reliable
3550 * method of determining their size.
3552 * Note 3: If you are getting a window size in order to position
3553 * the window onscreen, there may be a better way. The preferred
3554 * way is to simply set the window's semantic type with
3555 * gtk_window_set_type_hint(), which allows the window manager to
3556 * e.g. center dialogs. Also, if you set the transient parent of
3557 * dialogs with gtk_window_set_transient_for() window managers
3558 * will often center the dialog over its parent window. It's
3559 * much preferred to let the window manager handle these
3560 * things rather than doing it yourself, because all apps will
3561 * behave consistently and according to user prefs if the window
3562 * manager handles it. Also, the window manager can take the size
3563 * of the window decorations/border into account, while your
3564 * application cannot.
3566 * In any case, if you insist on application-specified window
3567 * positioning, there's <emphasis>still</emphasis> a better way than
3568 * doing it yourself - gtk_window_set_position() will frequently
3569 * handle the details for you.
3573 gtk_window_get_size (GtkWindow *window,
3579 g_return_if_fail (GTK_IS_WINDOW (window));
3581 if (width == NULL && height == NULL)
3584 if (GTK_WIDGET_MAPPED (window))
3586 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3591 GdkRectangle configure_request;
3593 gtk_window_compute_configure_request (window,
3597 w = configure_request.width;
3598 h = configure_request.height;
3609 * @window: a #GtkWindow
3610 * @x: X coordinate to move window to
3611 * @y: Y coordinate to move window to
3613 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3614 * @window to the given position. Window managers are free to ignore
3615 * this; most window managers ignore requests for initial window
3616 * positions (instead using a user-defined placement algorithm) and
3617 * honor requests after the window has already been shown.
3619 * Note: the position is the position of the gravity-determined
3620 * reference point for the window. The gravity determines two things:
3621 * first, the location of the reference point in root window
3622 * coordinates; and second, which point on the window is positioned at
3623 * the reference point.
3625 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3626 * point is simply the @x, @y supplied to gtk_window_move(). The
3627 * top-left corner of the window decorations (aka window frame or
3628 * border) will be placed at @x, @y. Therefore, to position a window
3629 * at the top left of the screen, you want to use the default gravity
3630 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3632 * To position a window at the bottom right corner of the screen, you
3633 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3634 * point is at @x + the window width and @y + the window height, and
3635 * the bottom-right corner of the window border will be placed at that
3636 * reference point. So, to place a window in the bottom right corner
3637 * you would first set gravity to south east, then write:
3638 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3639 * gdk_screen_height () - window_height)</literal>.
3641 * The Extended Window Manager Hints specification at <ulink
3642 * url="http://www.freedesktop.org/Standards/wm-spec">
3643 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
3644 * nice table of gravities in the "implementation notes" section.
3646 * The gtk_window_get_position() documentation may also be relevant.
3650 gtk_window_move (GtkWindow *window,
3654 GtkWindowGeometryInfo *info;
3657 g_return_if_fail (GTK_IS_WINDOW (window));
3659 widget = GTK_WIDGET (window);
3661 info = gtk_window_get_geometry_info (window, TRUE);
3663 if (GTK_WIDGET_MAPPED (window))
3665 /* we have now sent a request with this position
3666 * with currently-active constraints, so toggle flag.
3668 info->position_constraints_changed = FALSE;
3670 /* we only constrain if mapped - if not mapped,
3671 * then gtk_window_compute_configure_request()
3672 * will apply the constraints later, and we
3673 * don't want to lose information about
3674 * what position the user set before then.
3675 * i.e. if you do a move() then turn off POS_CENTER
3676 * then show the window, your move() will work.
3678 gtk_window_constrain_position (window,
3679 widget->allocation.width,
3680 widget->allocation.height,
3683 /* Note that this request doesn't go through our standard request
3684 * framework, e.g. doesn't increment configure_request_count,
3685 * doesn't set info->last, etc.; that's because
3686 * we don't save the info needed to arrive at this same request
3689 * To gtk_window_move_resize(), this will end up looking exactly
3690 * the same as the position being changed by the window
3694 /* FIXME are we handling gravity properly for framed windows? */
3696 gdk_window_move (window->frame,
3697 x - window->frame_left,
3698 y - window->frame_top);
3700 gdk_window_move (GTK_WIDGET (window)->window,
3705 /* Save this position to apply on mapping */
3706 info->initial_x = x;
3707 info->initial_y = y;
3708 info->initial_pos_set = TRUE;
3713 * gtk_window_get_position:
3714 * @window: a #GtkWindow
3715 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3716 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3718 * This function returns the position you need to pass to
3719 * gtk_window_move() to keep @window in its current position. This
3720 * means that the meaning of the returned value varies with window
3721 * gravity. See gtk_window_move() for more details.
3723 * If you haven't changed the window gravity, its gravity will be
3724 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3725 * gets the position of the top-left corner of the window manager
3726 * frame for the window. gtk_window_move() sets the position of this
3727 * same top-left corner.
3729 * gtk_window_get_position() is not 100% reliable because the X Window System
3730 * does not specify a way to obtain the geometry of the
3731 * decorations placed on a window by the window manager.
3732 * Thus GTK+ is using a "best guess" that works with most
3735 * Moreover, nearly all window managers are historically broken with
3736 * respect to their handling of window gravity. So moving a window to
3737 * its current position as returned by gtk_window_get_position() tends
3738 * to result in moving the window slightly. Window managers are
3739 * slowly getting better over time.
3741 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3742 * frame is not relevant, and thus gtk_window_get_position() will
3743 * always produce accurate results. However you can't use static
3744 * gravity to do things like place a window in a corner of the screen,
3745 * because static gravity ignores the window manager decorations.
3747 * If you are saving and restoring your application's window
3748 * positions, you should know that it's impossible for applications to
3749 * do this without getting it somewhat wrong because applications do
3750 * not have sufficient knowledge of window manager state. The Correct
3751 * Mechanism is to support the session management protocol (see the
3752 * "GnomeClient" object in the GNOME libraries for example) and allow
3753 * the window manager to save your window sizes and positions.
3758 gtk_window_get_position (GtkWindow *window,
3764 g_return_if_fail (GTK_IS_WINDOW (window));
3766 widget = GTK_WIDGET (window);
3768 if (window->gravity == GDK_GRAVITY_STATIC)
3770 if (GTK_WIDGET_MAPPED (widget))
3772 /* This does a server round-trip, which is sort of wrong;
3773 * but a server round-trip is inevitable for
3774 * gdk_window_get_frame_extents() in the usual
3775 * NorthWestGravity case below, so not sure what else to
3776 * do. We should likely be consistent about whether we get
3777 * the client-side info or the server-side info.
3779 gdk_window_get_origin (widget->window, root_x, root_y);
3783 GdkRectangle configure_request;
3785 gtk_window_compute_configure_request (window,
3789 *root_x = configure_request.x;
3790 *root_y = configure_request.y;
3795 GdkRectangle frame_extents;
3800 if (GTK_WIDGET_MAPPED (widget))
3803 gdk_window_get_frame_extents (window->frame, &frame_extents);
3805 gdk_window_get_frame_extents (widget->window, &frame_extents);
3806 x = frame_extents.x;
3807 y = frame_extents.y;
3808 gtk_window_get_size (window, &w, &h);
3812 /* We just say the frame has 0 size on all sides.
3813 * Not sure what else to do.
3815 gtk_window_compute_configure_request (window,
3818 x = frame_extents.x;
3819 y = frame_extents.y;
3820 w = frame_extents.width;
3821 h = frame_extents.height;
3824 switch (window->gravity)
3826 case GDK_GRAVITY_NORTH:
3827 case GDK_GRAVITY_CENTER:
3828 case GDK_GRAVITY_SOUTH:
3829 /* Find center of frame. */
3830 x += frame_extents.width / 2;
3831 /* Center client window on that point. */
3835 case GDK_GRAVITY_SOUTH_EAST:
3836 case GDK_GRAVITY_EAST:
3837 case GDK_GRAVITY_NORTH_EAST:
3838 /* Find right edge of frame */
3839 x += frame_extents.width;
3840 /* Align left edge of client at that point. */
3847 switch (window->gravity)
3849 case GDK_GRAVITY_WEST:
3850 case GDK_GRAVITY_CENTER:
3851 case GDK_GRAVITY_EAST:
3852 /* Find center of frame. */
3853 y += frame_extents.height / 2;
3854 /* Center client window there. */
3857 case GDK_GRAVITY_SOUTH_WEST:
3858 case GDK_GRAVITY_SOUTH:
3859 case GDK_GRAVITY_SOUTH_EAST:
3860 /* Find south edge of frame */
3861 y += frame_extents.height;
3862 /* Place bottom edge of client there */
3877 * gtk_window_reshow_with_initial_size:
3878 * @window: a #GtkWindow
3880 * Hides @window, then reshows it, resetting the
3881 * default size and position of the window. Used
3882 * by GUI builders only.
3885 gtk_window_reshow_with_initial_size (GtkWindow *window)
3889 g_return_if_fail (GTK_IS_WINDOW (window));
3891 widget = GTK_WIDGET (window);
3893 gtk_widget_hide (widget);
3894 gtk_widget_unrealize (widget);
3895 gtk_widget_show (widget);
3899 gtk_window_destroy (GtkObject *object)
3901 GtkWindow *window = GTK_WINDOW (object);
3903 toplevel_list = g_slist_remove (toplevel_list, window);
3905 if (window->transient_parent)
3906 gtk_window_set_transient_for (window, NULL);
3908 /* frees the icons */
3909 gtk_window_set_icon_list (window, NULL);
3911 if (window->has_user_ref_count)
3913 window->has_user_ref_count = FALSE;
3914 g_object_unref (window);
3918 gtk_window_group_remove_window (window->group, window);
3920 gtk_window_free_key_hash (window);
3922 GTK_OBJECT_CLASS (gtk_window_parent_class)->destroy (object);
3926 gtk_window_finalize (GObject *object)
3928 GtkWindow *window = GTK_WINDOW (object);
3929 GtkMnemonicHash *mnemonic_hash;
3931 g_free (window->title);
3932 g_free (window->wmclass_name);
3933 g_free (window->wmclass_class);
3934 g_free (window->wm_role);
3936 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
3938 _gtk_mnemonic_hash_free (mnemonic_hash);
3940 if (window->geometry_info)
3942 if (window->geometry_info->widget)
3943 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3944 gtk_widget_destroyed,
3945 &window->geometry_info->widget);
3946 g_free (window->geometry_info);
3949 if (window->keys_changed_handler)
3951 g_source_remove (window->keys_changed_handler);
3952 window->keys_changed_handler = 0;
3957 g_signal_handlers_disconnect_by_func (window->screen,
3958 gtk_window_on_composited_changed, window);
3961 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
3965 gtk_window_show (GtkWidget *widget)
3967 GtkWindow *window = GTK_WINDOW (widget);
3968 GtkContainer *container = GTK_CONTAINER (window);
3969 gboolean need_resize;
3971 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3973 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3974 container->need_resize = FALSE;
3978 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3979 GtkAllocation allocation = { 0, 0 };
3980 GdkRectangle configure_request;
3981 GdkGeometry new_geometry;
3983 gboolean was_realized;
3985 /* We are going to go ahead and perform this configure request
3986 * and then emulate a configure notify by going ahead and
3987 * doing a size allocate. Sort of a synchronous
3988 * mini-copy of gtk_window_move_resize() here.
3990 gtk_window_compute_configure_request (window,
3995 /* We update this because we are going to go ahead
3996 * and gdk_window_resize() below, rather than
3999 info->last.configure_request.width = configure_request.width;
4000 info->last.configure_request.height = configure_request.height;
4002 /* and allocate the window - this is normally done
4003 * in move_resize in response to configure notify
4005 allocation.width = configure_request.width;
4006 allocation.height = configure_request.height;
4007 gtk_widget_size_allocate (widget, &allocation);
4009 /* Then we guarantee we have a realize */
4010 was_realized = FALSE;
4011 if (!GTK_WIDGET_REALIZED (widget))
4013 gtk_widget_realize (widget);
4014 was_realized = TRUE;
4017 /* Must be done after the windows are realized,
4018 * so that the decorations can be read
4020 gtk_decorated_window_calculate_frame_size (window);
4022 /* We only send configure request if we didn't just finish
4023 * creating the window; if we just created the window
4024 * then we created it with widget->allocation anyhow.
4027 gdk_window_move_resize (widget->window,
4028 configure_request.x,
4029 configure_request.y,
4030 configure_request.width,
4031 configure_request.height);
4034 gtk_container_check_resize (container);
4036 gtk_widget_map (widget);
4038 /* Try to make sure that we have some focused widget
4040 if (!window->focus_widget && !GTK_IS_PLUG (window))
4041 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4044 gtk_grab_add (widget);
4048 gtk_window_hide (GtkWidget *widget)
4050 GtkWindow *window = GTK_WINDOW (widget);
4052 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4053 gtk_widget_unmap (widget);
4056 gtk_grab_remove (widget);
4060 gtk_window_map (GtkWidget *widget)
4062 GtkWindow *window = GTK_WINDOW (widget);
4063 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4064 GdkWindow *toplevel;
4066 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4068 if (window->bin.child &&
4069 GTK_WIDGET_VISIBLE (window->bin.child) &&
4070 !GTK_WIDGET_MAPPED (window->bin.child))
4071 gtk_widget_map (window->bin.child);
4074 toplevel = window->frame;
4076 toplevel = widget->window;
4078 if (window->maximize_initially)
4079 gdk_window_maximize (toplevel);
4081 gdk_window_unmaximize (toplevel);
4083 if (window->stick_initially)
4084 gdk_window_stick (toplevel);
4086 gdk_window_unstick (toplevel);
4088 if (window->iconify_initially)
4089 gdk_window_iconify (toplevel);
4091 gdk_window_deiconify (toplevel);
4093 if (priv->fullscreen_initially)
4094 gdk_window_fullscreen (toplevel);
4096 gdk_window_unfullscreen (toplevel);
4098 gdk_window_set_keep_above (toplevel, priv->above_initially);
4100 gdk_window_set_keep_below (toplevel, priv->below_initially);
4102 /* No longer use the default settings */
4103 window->need_default_size = FALSE;
4104 window->need_default_position = FALSE;
4106 if (priv->reset_type_hint)
4108 /* We should only reset the type hint when the application
4109 * used gtk_window_set_type_hint() to change the hint.
4110 * Some applications use X directly to change the properties;
4111 * in that case, we shouldn't overwrite what they did.
4113 gdk_window_set_type_hint (widget->window, priv->type_hint);
4114 priv->reset_type_hint = FALSE;
4117 gdk_window_show (widget->window);
4120 gdk_window_show (window->frame);
4122 if (!disable_startup_notification &&
4123 !sent_startup_notification)
4125 sent_startup_notification = TRUE;
4126 gdk_notify_startup_complete ();
4131 gtk_window_map_event (GtkWidget *widget,
4134 if (!GTK_WIDGET_MAPPED (widget))
4136 /* we should be be unmapped, but are getting a MapEvent, this may happen
4137 * to toplevel XWindows if mapping was intercepted by a window manager
4138 * and an unmap request occoured while the MapRequestEvent was still
4139 * being handled. we work around this situaiton here by re-requesting
4140 * the window being unmapped. more details can be found in:
4141 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4143 gdk_window_hide (widget->window);
4149 gtk_window_unmap (GtkWidget *widget)
4151 GtkWindow *window = GTK_WINDOW (widget);
4152 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
4153 GtkWindowGeometryInfo *info;
4154 GdkWindowState state;
4156 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4158 gdk_window_withdraw (window->frame);
4160 gdk_window_withdraw (widget->window);
4162 window->configure_request_count = 0;
4163 window->configure_notify_received = FALSE;
4165 /* on unmap, we reset the default positioning of the window,
4166 * so it's placed again, but we don't reset the default
4167 * size of the window, so it's remembered.
4169 window->need_default_position = TRUE;
4171 info = gtk_window_get_geometry_info (window, FALSE);
4174 info->initial_pos_set = FALSE;
4175 info->position_constraints_changed = FALSE;
4178 state = gdk_window_get_state (widget->window);
4179 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
4180 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
4181 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
4182 priv->above_initially = state & GDK_WINDOW_STATE_ABOVE;
4183 priv->below_initially = state & GDK_WINDOW_STATE_BELOW;
4187 gtk_window_realize (GtkWidget *widget)
4190 GdkWindow *parent_window;
4191 GdkWindowAttr attributes;
4192 gint attributes_mask;
4193 GtkWindowPrivate *priv;
4195 window = GTK_WINDOW (widget);
4197 priv = GTK_WINDOW_GET_PRIVATE (window);
4199 /* ensure widget tree is properly size allocated */
4200 if (widget->allocation.x == -1 &&
4201 widget->allocation.y == -1 &&
4202 widget->allocation.width == 1 &&
4203 widget->allocation.height == 1)
4205 GtkRequisition requisition;
4206 GtkAllocation allocation = { 0, 0, 200, 200 };
4208 gtk_widget_size_request (widget, &requisition);
4209 if (requisition.width || requisition.height)
4211 /* non-empty window */
4212 allocation.width = requisition.width;
4213 allocation.height = requisition.height;
4215 gtk_widget_size_allocate (widget, &allocation);
4217 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4219 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
4222 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4224 switch (window->type)
4226 case GTK_WINDOW_TOPLEVEL:
4227 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4229 case GTK_WINDOW_POPUP:
4230 attributes.window_type = GDK_WINDOW_TEMP;
4233 g_warning (G_STRLOC": Unknown window type %d!", window->type);
4237 attributes.title = window->title;
4238 attributes.wmclass_name = window->wmclass_name;
4239 attributes.wmclass_class = window->wmclass_class;
4240 attributes.wclass = GDK_INPUT_OUTPUT;
4241 attributes.visual = gtk_widget_get_visual (widget);
4242 attributes.colormap = gtk_widget_get_colormap (widget);
4244 if (window->has_frame)
4246 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
4247 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
4248 attributes.event_mask = (GDK_EXPOSURE_MASK |
4249 GDK_KEY_PRESS_MASK |
4250 GDK_ENTER_NOTIFY_MASK |
4251 GDK_LEAVE_NOTIFY_MASK |
4252 GDK_FOCUS_CHANGE_MASK |
4253 GDK_STRUCTURE_MASK |
4254 GDK_BUTTON_MOTION_MASK |
4255 GDK_POINTER_MOTION_HINT_MASK |
4256 GDK_BUTTON_PRESS_MASK |
4257 GDK_BUTTON_RELEASE_MASK);
4259 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4261 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4262 &attributes, attributes_mask);
4264 gdk_window_set_user_data (window->frame, widget);
4266 attributes.window_type = GDK_WINDOW_CHILD;
4267 attributes.x = window->frame_left;
4268 attributes.y = window->frame_top;
4270 attributes_mask = GDK_WA_X | GDK_WA_Y;
4272 parent_window = window->frame;
4274 g_signal_connect (window,
4276 G_CALLBACK (gtk_window_event),
4281 attributes_mask = 0;
4282 parent_window = gtk_widget_get_root_window (widget);
4285 attributes.width = widget->allocation.width;
4286 attributes.height = widget->allocation.height;
4287 attributes.event_mask = gtk_widget_get_events (widget);
4288 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4289 GDK_KEY_PRESS_MASK |
4290 GDK_KEY_RELEASE_MASK |
4291 GDK_ENTER_NOTIFY_MASK |
4292 GDK_LEAVE_NOTIFY_MASK |
4293 GDK_FOCUS_CHANGE_MASK |
4294 GDK_STRUCTURE_MASK);
4296 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
4297 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
4298 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
4300 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
4302 gdk_window_enable_synchronized_configure (widget->window);
4304 gdk_window_set_user_data (widget->window, window);
4306 widget->style = gtk_style_attach (widget->style, widget->window);
4307 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4309 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
4311 /* This is a bad hack to set the window background. */
4312 gtk_window_paint (widget, NULL);
4314 if (window->transient_parent &&
4315 GTK_WIDGET_REALIZED (window->transient_parent))
4316 gdk_window_set_transient_for (widget->window,
4317 GTK_WIDGET (window->transient_parent)->window);
4319 if (window->wm_role)
4320 gdk_window_set_role (widget->window, window->wm_role);
4322 if (!window->decorated)
4323 gdk_window_set_decorations (widget->window, 0);
4325 if (!priv->deletable)
4326 gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4328 gdk_window_set_type_hint (widget->window, priv->type_hint);
4330 if (gtk_window_get_skip_pager_hint (window))
4331 gdk_window_set_skip_pager_hint (widget->window, TRUE);
4333 if (gtk_window_get_skip_taskbar_hint (window))
4334 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
4336 if (gtk_window_get_accept_focus (window))
4337 gdk_window_set_accept_focus (widget->window, TRUE);
4339 gdk_window_set_accept_focus (widget->window, FALSE);
4341 if (gtk_window_get_focus_on_map (window))
4342 gdk_window_set_focus_on_map (widget->window, TRUE);
4344 gdk_window_set_focus_on_map (widget->window, FALSE);
4347 gdk_window_set_modal_hint (widget->window, TRUE);
4349 gdk_window_set_modal_hint (widget->window, FALSE);
4352 gtk_window_realize_icon (window);
4356 gtk_window_unrealize (GtkWidget *widget)
4359 GtkWindowGeometryInfo *info;
4361 window = GTK_WINDOW (widget);
4363 /* On unrealize, we reset the size of the window such
4364 * that we will re-apply the default sizing stuff
4365 * next time we show the window.
4367 * Default positioning is reset on unmap, instead of unrealize.
4369 window->need_default_size = TRUE;
4370 info = gtk_window_get_geometry_info (window, FALSE);
4373 info->resize_width = -1;
4374 info->resize_height = -1;
4375 info->last.configure_request.x = 0;
4376 info->last.configure_request.y = 0;
4377 info->last.configure_request.width = -1;
4378 info->last.configure_request.height = -1;
4379 /* be sure we reset geom hints on re-realize */
4380 info->last.flags = 0;
4385 gdk_window_set_user_data (window->frame, NULL);
4386 gdk_window_destroy (window->frame);
4387 window->frame = NULL;
4391 gtk_window_unrealize_icon (window);
4393 (* GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize) (widget);
4397 gtk_window_size_request (GtkWidget *widget,
4398 GtkRequisition *requisition)
4403 window = GTK_WINDOW (widget);
4404 bin = GTK_BIN (window);
4406 requisition->width = GTK_CONTAINER (window)->border_width * 2;
4407 requisition->height = GTK_CONTAINER (window)->border_width * 2;
4409 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
4411 GtkRequisition child_requisition;
4413 gtk_widget_size_request (bin->child, &child_requisition);
4415 requisition->width += child_requisition.width;
4416 requisition->height += child_requisition.height;
4421 gtk_window_size_allocate (GtkWidget *widget,
4422 GtkAllocation *allocation)
4425 GtkAllocation child_allocation;
4427 window = GTK_WINDOW (widget);
4428 widget->allocation = *allocation;
4430 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
4432 child_allocation.x = GTK_CONTAINER (window)->border_width;
4433 child_allocation.y = GTK_CONTAINER (window)->border_width;
4434 child_allocation.width =
4435 MAX (1, (gint)allocation->width - child_allocation.x * 2);
4436 child_allocation.height =
4437 MAX (1, (gint)allocation->height - child_allocation.y * 2);
4439 gtk_widget_size_allocate (window->bin.child, &child_allocation);
4442 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4444 gdk_window_resize (window->frame,
4445 allocation->width + window->frame_left + window->frame_right,
4446 allocation->height + window->frame_top + window->frame_bottom);
4451 gtk_window_event (GtkWidget *widget, GdkEvent *event)
4454 gboolean return_val;
4456 window = GTK_WINDOW (widget);
4458 if (window->frame && (event->any.window == window->frame))
4460 if ((event->type != GDK_KEY_PRESS) &&
4461 (event->type != GDK_KEY_RELEASE) &&
4462 (event->type != GDK_FOCUS_CHANGE))
4464 g_signal_stop_emission_by_name (widget, "event");
4466 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
4471 g_object_unref (event->any.window);
4472 event->any.window = g_object_ref (widget->window);
4480 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
4482 GdkEventConfigure *configure_event;
4485 switch (event->type)
4488 configure_event = (GdkEventConfigure *)event;
4490 /* Invalidate the decorations */
4493 rect.width = configure_event->width;
4494 rect.height = configure_event->height;
4496 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
4498 /* Pass on the (modified) configure event */
4499 configure_event->width -= window->frame_left + window->frame_right;
4500 configure_event->height -= window->frame_top + window->frame_bottom;
4501 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
4510 gtk_window_configure_event (GtkWidget *widget,
4511 GdkEventConfigure *event)
4513 GtkWindow *window = GTK_WINDOW (widget);
4514 gboolean expected_reply = window->configure_request_count > 0;
4516 /* window->configure_request_count incremented for each
4517 * configure request, and decremented to a min of 0 for
4518 * each configure notify.
4520 * All it means is that we know we will get at least
4521 * window->configure_request_count more configure notifies.
4522 * We could get more configure notifies than that; some
4523 * of the configure notifies we get may be unrelated to
4524 * the configure requests. But we will get at least
4525 * window->configure_request_count notifies.
4528 if (window->configure_request_count > 0)
4529 window->configure_request_count -= 1;
4531 /* As an optimization, we avoid a resize when possible.
4533 * The only times we can avoid a resize are:
4534 * - we know only the position changed, not the size
4535 * - we know we have made more requests and so will get more
4536 * notifies and can wait to resize when we get them
4539 if (!expected_reply &&
4540 (widget->allocation.width == event->width &&
4541 widget->allocation.height == event->height))
4543 gdk_window_configure_finished (widget->window);
4548 * If we do need to resize, we do that by:
4549 * - filling in widget->allocation with the new size
4550 * - setting configure_notify_received to TRUE
4551 * for use in gtk_window_move_resize()
4552 * - queueing a resize, leading to invocation of
4553 * gtk_window_move_resize() in an idle handler
4557 window->configure_notify_received = TRUE;
4559 widget->allocation.width = event->width;
4560 widget->allocation.height = event->height;
4562 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4567 /* the accel_key and accel_mods fields of the key have to be setup
4568 * upon calling this function. it'll then return whether that key
4569 * is at all used as accelerator, and if so will OR in the
4570 * accel_flags member of the key.
4573 _gtk_window_query_nonaccels (GtkWindow *window,
4575 GdkModifierType accel_mods)
4577 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4579 /* movement keys are considered locked accels */
4582 static const guint bindings[] = {
4583 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
4584 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
4588 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
4589 if (bindings[i] == accel_key)
4593 /* mnemonics are considered locked accels */
4594 if (accel_mods == window->mnemonic_modifier)
4596 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4597 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
4605 * gtk_window_propagate_key_event:
4606 * @window: a #GtkWindow
4607 * @event: a #GdkEventKey
4609 * Propagate a key press or release event to the focus widget and
4610 * up the focus container chain until a widget handles @event.
4611 * This is normally called by the default ::key_press_event and
4612 * ::key_release_event handlers for toplevel windows,
4613 * however in some cases it may be useful to call this directly when
4614 * overriding the standard key handling for a toplevel window.
4616 * Return value: %TRUE if a widget in the focus chain handled the event.
4619 gtk_window_propagate_key_event (GtkWindow *window,
4622 gboolean handled = FALSE;
4623 GtkWidget *widget, *focus;
4625 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4627 widget = GTK_WIDGET (window);
4628 focus = window->focus_widget;
4630 g_object_ref (focus);
4633 focus && focus != widget &&
4634 gtk_widget_get_toplevel (focus) == widget)
4638 if (GTK_WIDGET_IS_SENSITIVE (focus))
4639 handled = gtk_widget_event (focus, (GdkEvent*) event);
4641 parent = focus->parent;
4643 g_object_ref (parent);
4645 g_object_unref (focus);
4651 g_object_unref (focus);
4657 gtk_window_key_press_event (GtkWidget *widget,
4660 GtkWindow *window = GTK_WINDOW (widget);
4661 gboolean handled = FALSE;
4663 /* handle mnemonics and accelerators */
4665 handled = gtk_window_activate_key (window, event);
4667 /* handle focus widget key events */
4669 handled = gtk_window_propagate_key_event (window, event);
4671 /* Chain up, invokes binding set */
4673 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
4679 gtk_window_key_release_event (GtkWidget *widget,
4682 GtkWindow *window = GTK_WINDOW (widget);
4683 gboolean handled = FALSE;
4685 /* handle focus widget key events */
4687 handled = gtk_window_propagate_key_event (window, event);
4689 /* Chain up, invokes binding set */
4691 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
4697 gtk_window_real_activate_default (GtkWindow *window)
4699 gtk_window_activate_default (window);
4703 gtk_window_real_activate_focus (GtkWindow *window)
4705 gtk_window_activate_focus (window);
4709 gtk_window_move_focus (GtkWindow *window,
4710 GtkDirectionType dir)
4712 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4714 if (!GTK_CONTAINER (window)->focus_child)
4715 gtk_window_set_focus (window, NULL);
4719 gtk_window_enter_notify_event (GtkWidget *widget,
4720 GdkEventCrossing *event)
4726 gtk_window_leave_notify_event (GtkWidget *widget,
4727 GdkEventCrossing *event)
4733 do_focus_change (GtkWidget *widget,
4736 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4738 g_object_ref (widget);
4741 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4743 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4745 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4746 fevent->focus_change.window = widget->window;
4748 g_object_ref (widget->window);
4749 fevent->focus_change.in = in;
4751 gtk_widget_event (widget, fevent);
4753 g_object_notify (G_OBJECT (widget), "has-focus");
4755 g_object_unref (widget);
4756 gdk_event_free (fevent);
4760 gtk_window_focus_in_event (GtkWidget *widget,
4761 GdkEventFocus *event)
4763 GtkWindow *window = GTK_WINDOW (widget);
4765 /* It appears spurious focus in events can occur when
4766 * the window is hidden. So we'll just check to see if
4767 * the window is visible before actually handling the
4770 if (GTK_WIDGET_VISIBLE (widget))
4772 _gtk_window_set_has_toplevel_focus (window, TRUE);
4773 _gtk_window_set_is_active (window, TRUE);
4780 gtk_window_focus_out_event (GtkWidget *widget,
4781 GdkEventFocus *event)
4783 GtkWindow *window = GTK_WINDOW (widget);
4785 _gtk_window_set_has_toplevel_focus (window, FALSE);
4786 _gtk_window_set_is_active (window, FALSE);
4791 static GdkAtom atom_rcfiles = GDK_NONE;
4792 static GdkAtom atom_iconthemes = GDK_NONE;
4795 send_client_message_to_embedded_windows (GtkWidget *widget,
4796 GdkAtom message_type)
4798 GList *embedded_windows;
4800 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
4801 if (embedded_windows)
4803 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4806 for (i = 0; i < 5; i++)
4807 send_event->client.data.l[i] = 0;
4808 send_event->client.data_format = 32;
4809 send_event->client.message_type = message_type;
4811 while (embedded_windows)
4813 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4814 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4815 embedded_windows = embedded_windows->next;
4818 gdk_event_free (send_event);
4823 gtk_window_client_event (GtkWidget *widget,
4824 GdkEventClient *event)
4828 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
4829 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
4832 if (event->message_type == atom_rcfiles)
4834 send_client_message_to_embedded_windows (widget, atom_rcfiles);
4835 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4838 if (event->message_type == atom_iconthemes)
4840 send_client_message_to_embedded_windows (widget, atom_iconthemes);
4841 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
4848 gtk_window_check_resize (GtkContainer *container)
4850 GtkWindow *window = GTK_WINDOW (container);
4852 if (GTK_WIDGET_VISIBLE (container))
4853 gtk_window_move_resize (window);
4857 gtk_window_focus (GtkWidget *widget,
4858 GtkDirectionType direction)
4862 GtkContainer *container;
4863 GtkWidget *old_focus_child;
4866 container = GTK_CONTAINER (widget);
4867 window = GTK_WINDOW (widget);
4868 bin = GTK_BIN (widget);
4870 old_focus_child = container->focus_child;
4872 /* We need a special implementation here to deal properly with wrapping
4873 * around in the tab chain without the danger of going into an
4876 if (old_focus_child)
4878 if (gtk_widget_child_focus (old_focus_child, direction))
4882 if (window->focus_widget)
4884 if (direction == GTK_DIR_LEFT ||
4885 direction == GTK_DIR_RIGHT ||
4886 direction == GTK_DIR_UP ||
4887 direction == GTK_DIR_DOWN)
4892 /* Wrapped off the end, clear the focus setting for the toplpevel */
4893 parent = window->focus_widget->parent;
4896 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4897 parent = GTK_WIDGET (parent)->parent;
4900 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4903 /* Now try to focus the first widget in the window */
4906 if (gtk_widget_child_focus (bin->child, direction))
4914 gtk_window_real_set_focus (GtkWindow *window,
4917 GtkWidget *old_focus = window->focus_widget;
4918 gboolean had_default = FALSE;
4919 gboolean focus_had_default = FALSE;
4920 gboolean old_focus_had_default = FALSE;
4924 g_object_ref (old_focus);
4925 g_object_freeze_notify (G_OBJECT (old_focus));
4926 old_focus_had_default = GTK_WIDGET_HAS_DEFAULT (old_focus);
4930 g_object_ref (focus);
4931 g_object_freeze_notify (G_OBJECT (focus));
4932 focus_had_default = GTK_WIDGET_HAS_DEFAULT (focus);
4935 if (window->default_widget)
4936 had_default = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4938 if (window->focus_widget)
4940 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4941 (window->focus_widget != window->default_widget))
4943 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4944 gtk_widget_queue_draw (window->focus_widget);
4946 if (window->default_widget)
4947 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4950 window->focus_widget = NULL;
4952 if (window->has_focus)
4953 do_focus_change (old_focus, FALSE);
4955 g_object_notify (G_OBJECT (old_focus), "is-focus");
4958 /* The above notifications may have set a new focus widget,
4959 * if so, we don't want to override it.
4961 if (focus && !window->focus_widget)
4963 window->focus_widget = focus;
4965 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4966 (window->focus_widget != window->default_widget))
4968 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4969 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4971 if (window->default_widget)
4972 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4975 if (window->has_focus)
4976 do_focus_change (window->focus_widget, TRUE);
4978 g_object_notify (G_OBJECT (window->focus_widget), "is-focus");
4981 /* If the default widget changed, a redraw will have been queued
4982 * on the old and new default widgets by gtk_window_set_default(), so
4983 * we only have to worry about the case where it didn't change.
4984 * We'll sometimes queue a draw twice on the new widget but that
4987 if (window->default_widget &&
4988 (had_default != GTK_WIDGET_HAS_DEFAULT (window->default_widget)))
4989 gtk_widget_queue_draw (window->default_widget);
4993 if (old_focus_had_default != GTK_WIDGET_HAS_DEFAULT (old_focus))
4994 gtk_widget_queue_draw (old_focus);
4996 g_object_thaw_notify (G_OBJECT (old_focus));
4997 g_object_unref (old_focus);
5001 if (focus_had_default != GTK_WIDGET_HAS_DEFAULT (focus))
5002 gtk_widget_queue_draw (focus);
5004 g_object_thaw_notify (G_OBJECT (focus));
5005 g_object_unref (focus);
5010 * _gtk_window_unset_focus_and_default:
5011 * @window: a #GtkWindow
5012 * @widget: a widget inside of @window
5014 * Checks whether the focus and default widgets of @window are
5015 * @widget or a descendent of @widget, and if so, unset them.
5018 _gtk_window_unset_focus_and_default (GtkWindow *window,
5024 g_object_ref (window);
5025 g_object_ref (widget);
5027 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
5029 child = window->focus_widget;
5031 while (child && child != widget)
5032 child = child->parent;
5034 if (child == widget)
5035 gtk_window_set_focus (GTK_WINDOW (window), NULL);
5038 child = window->default_widget;
5040 while (child && child != widget)
5041 child = child->parent;
5043 if (child == widget)
5044 gtk_window_set_default (window, NULL);
5046 g_object_unref (widget);
5047 g_object_unref (window);
5050 /*********************************
5051 * Functions related to resizing *
5052 *********************************/
5054 /* This function doesn't constrain to geometry hints */
5056 gtk_window_compute_configure_request_size (GtkWindow *window,
5060 GtkRequisition requisition;
5061 GtkWindowGeometryInfo *info;
5065 * - we've done a size request
5068 widget = GTK_WIDGET (window);
5070 info = gtk_window_get_geometry_info (window, FALSE);
5072 if (window->need_default_size)
5074 gtk_widget_get_child_requisition (widget, &requisition);
5076 /* Default to requisition */
5077 *width = requisition.width;
5078 *height = requisition.height;
5080 /* If window is empty so requests 0, default to random nonzero size */
5081 if (*width == 0 && *height == 0)
5087 /* Override requisition with default size */
5091 gint base_width = 0;
5092 gint base_height = 0;
5094 gint height_inc = 1;
5096 if (info->default_is_geometry &&
5097 (info->default_width > 0 || info->default_height > 0))
5099 GdkGeometry geometry;
5102 gtk_window_compute_hints (window, &geometry, &flags);
5104 if (flags & GDK_HINT_BASE_SIZE)
5106 base_width = geometry.base_width;
5107 base_height = geometry.base_height;
5109 else if (flags & GDK_HINT_MIN_SIZE)
5111 base_width = geometry.min_width;
5112 base_height = geometry.min_height;
5114 if (flags & GDK_HINT_RESIZE_INC)
5116 width_inc = geometry.width_inc;
5117 height_inc = geometry.height_inc;
5121 if (info->default_width > 0)
5122 *width = info->default_width * width_inc + base_width;
5124 if (info->default_height > 0)
5125 *height = info->default_height * height_inc + base_height;
5130 /* Default to keeping current size */
5131 *width = widget->allocation.width;
5132 *height = widget->allocation.height;
5135 /* Override any size with gtk_window_resize() values */
5138 if (info->resize_width > 0)
5139 *width = info->resize_width;
5141 if (info->resize_height > 0)
5142 *height = info->resize_height;
5146 static GtkWindowPosition
5147 get_effective_position (GtkWindow *window)
5149 GtkWindowPosition pos = window->position;
5150 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5151 (window->transient_parent == NULL ||
5152 !GTK_WIDGET_MAPPED (window->transient_parent)))
5153 pos = GTK_WIN_POS_NONE;
5159 get_center_monitor_of_window (GtkWindow *window)
5161 /* We could try to sort out the relative positions of the monitors and
5162 * stuff, or we could just be losers and assume you have a row
5163 * or column of monitors.
5165 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5169 get_monitor_containing_pointer (GtkWindow *window)
5173 GdkScreen *window_screen;
5174 GdkScreen *pointer_screen;
5176 window_screen = gtk_window_check_screen (window);
5177 gdk_display_get_pointer (gdk_screen_get_display (window_screen),
5181 if (pointer_screen == window_screen)
5182 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5190 center_window_on_monitor (GtkWindow *window,
5196 GdkRectangle monitor;
5199 monitor_num = get_monitor_containing_pointer (window);
5201 if (monitor_num == -1)
5202 monitor_num = get_center_monitor_of_window (window);
5204 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5205 monitor_num, &monitor);
5207 *x = (monitor.width - w) / 2 + monitor.x;
5208 *y = (monitor.height - h) / 2 + monitor.y;
5210 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5211 * and WM decorations.
5220 clamp_window_to_rectangle (gint *x,
5224 const GdkRectangle *rect)
5226 gint outside_w, outside_h;
5228 outside_w = (*x + w) - (rect->x + rect->width);
5232 outside_h = (*y + h) - (rect->y + rect->height);
5236 /* if larger than the screen, center on the screen. */
5238 *x += (rect->x - *x) / 2;
5240 *y += (rect->y - *y) / 2;
5245 gtk_window_compute_configure_request (GtkWindow *window,
5246 GdkRectangle *request,
5247 GdkGeometry *geometry,
5250 GdkGeometry new_geometry;
5254 GtkWindowPosition pos;
5255 GtkWidget *parent_widget;
5256 GtkWindowGeometryInfo *info;
5260 widget = GTK_WIDGET (window);
5262 screen = gtk_window_check_screen (window);
5264 gtk_widget_size_request (widget, NULL);
5265 gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
5267 gtk_window_compute_hints (window, &new_geometry, &new_flags);
5268 gtk_window_constrain_size (window,
5269 &new_geometry, new_flags,
5273 parent_widget = (GtkWidget*) window->transient_parent;
5275 pos = get_effective_position (window);
5276 info = gtk_window_get_geometry_info (window, FALSE);
5278 /* by default, don't change position requested */
5281 x = info->last.configure_request.x;
5282 y = info->last.configure_request.y;
5291 if (window->need_default_position)
5294 /* FIXME this all interrelates with window gravity.
5295 * For most of them I think we want to set GRAVITY_CENTER.
5297 * Not sure how to go about that.
5302 /* here we are only handling CENTER_ALWAYS
5303 * as it relates to default positioning,
5304 * where it's equivalent to simply CENTER
5306 case GTK_WIN_POS_CENTER_ALWAYS:
5307 case GTK_WIN_POS_CENTER:
5308 center_window_on_monitor (window, w, h, &x, &y);
5311 case GTK_WIN_POS_CENTER_ON_PARENT:
5314 GdkRectangle monitor;
5317 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
5319 if (parent_widget->window != NULL)
5320 monitor_num = gdk_screen_get_monitor_at_window (screen,
5321 parent_widget->window);
5325 gdk_window_get_origin (parent_widget->window,
5328 x = ox + (parent_widget->allocation.width - w) / 2;
5329 y = oy + (parent_widget->allocation.height - h) / 2;
5331 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5332 * WM decorations. If parent wasn't on a monitor, just
5335 if (monitor_num >= 0)
5337 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5338 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5343 case GTK_WIN_POS_MOUSE:
5345 gint screen_width = gdk_screen_get_width (screen);
5346 gint screen_height = gdk_screen_get_height (screen);
5348 GdkRectangle monitor;
5349 GdkScreen *pointer_screen;
5352 gdk_display_get_pointer (gdk_screen_get_display (screen),
5356 if (pointer_screen == screen)
5357 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
5363 x = CLAMP (x, 0, screen_width - w);
5364 y = CLAMP (y, 0, screen_height - h);
5366 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5367 * WM decorations. Don't try to figure out what's going
5368 * on if the mouse wasn't inside a monitor.
5370 if (monitor_num >= 0)
5372 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5373 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5381 } /* if (window->need_default_position) */
5383 if (window->need_default_position && info &&
5384 info->initial_pos_set)
5386 x = info->initial_x;
5387 y = info->initial_y;
5388 gtk_window_constrain_position (window, w, h, &x, &y);
5394 request->height = h;
5397 *geometry = new_geometry;
5403 gtk_window_constrain_position (GtkWindow *window,
5409 /* See long comments in gtk_window_move_resize()
5410 * on when it's safe to call this function.
5412 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
5414 gint center_x, center_y;
5416 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
5424 gtk_window_move_resize (GtkWindow *window)
5428 * First we determine whether any information has changed that would
5429 * cause us to revise our last configure request. If we would send
5430 * a different configure request from last time, then
5431 * configure_request_size_changed = TRUE or
5432 * configure_request_pos_changed = TRUE. configure_request_size_changed
5433 * may be true due to new hints, a gtk_window_resize(), or whatever.
5434 * configure_request_pos_changed may be true due to gtk_window_set_position()
5435 * or gtk_window_move().
5437 * If the configure request has changed, we send off a new one. To
5438 * ensure GTK+ invariants are maintained (resize queue does what it
5439 * should), we go ahead and size_allocate the requested size in this
5442 * If the configure request has not changed, we don't ever resend
5443 * it, because it could mean fighting the user or window manager.
5446 * To prepare the configure request, we come up with a base size/pos:
5447 * - the one from gtk_window_move()/gtk_window_resize()
5448 * - else default_width, default_height if we haven't ever
5450 * - else the size request if we haven't ever been mapped,
5451 * as a substitute default size
5452 * - else the current size of the window, as received from
5453 * configure notifies (i.e. the current allocation)
5455 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
5456 * the position request to be centered.
5459 GtkContainer *container;
5460 GtkWindowGeometryInfo *info;
5461 GdkGeometry new_geometry;
5463 GdkRectangle new_request;
5464 gboolean configure_request_size_changed;
5465 gboolean configure_request_pos_changed;
5466 gboolean hints_changed; /* do we need to send these again */
5467 GtkWindowLastGeometryInfo saved_last_info;
5469 widget = GTK_WIDGET (window);
5470 container = GTK_CONTAINER (widget);
5471 info = gtk_window_get_geometry_info (window, TRUE);
5473 configure_request_size_changed = FALSE;
5474 configure_request_pos_changed = FALSE;
5476 gtk_window_compute_configure_request (window, &new_request,
5477 &new_geometry, &new_flags);
5479 /* This check implies the invariant that we never set info->last
5480 * without setting the hints and sending off a configure request.
5482 * If we change info->last without sending the request, we may
5485 if (info->last.configure_request.x != new_request.x ||
5486 info->last.configure_request.y != new_request.y)
5487 configure_request_pos_changed = TRUE;
5489 if ((info->last.configure_request.width != new_request.width ||
5490 info->last.configure_request.height != new_request.height))
5491 configure_request_size_changed = TRUE;
5493 hints_changed = FALSE;
5495 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
5496 &new_geometry, new_flags))
5498 hints_changed = TRUE;
5501 /* Position Constraints
5502 * ====================
5504 * POS_CENTER_ALWAYS is conceptually a constraint rather than
5505 * a default. The other POS_ values are used only when the
5506 * window is shown, not after that.
5508 * However, we can't implement a position constraint as
5509 * "anytime the window size changes, center the window"
5510 * because this may well end up fighting the WM or user. In
5511 * fact it gets in an infinite loop with at least one WM.
5513 * Basically, applications are in no way in a position to
5514 * constrain the position of a window, with one exception:
5515 * override redirect windows. (Really the intended purpose
5516 * of CENTER_ALWAYS anyhow, I would think.)
5518 * So the way we implement this "constraint" is to say that when WE
5519 * cause a move or resize, i.e. we make a configure request changing
5520 * window size, we recompute the CENTER_ALWAYS position to reflect
5521 * the new window size, and include it in our request. Also, if we
5522 * just turned on CENTER_ALWAYS we snap to center with a new
5523 * request. Otherwise, if we are just NOTIFIED of a move or resize
5524 * done by someone else e.g. the window manager, we do NOT send a
5525 * new configure request.
5527 * For override redirect windows, this works fine; all window
5528 * sizes are from our configure requests. For managed windows,
5529 * it is at least semi-sane, though who knows what the
5530 * app author is thinking.
5533 /* This condition should be kept in sync with the condition later on
5534 * that determines whether we send a configure request. i.e. we
5535 * should do this position constraining anytime we were going to
5536 * send a configure request anyhow, plus when constraints have
5539 if (configure_request_pos_changed ||
5540 configure_request_size_changed ||
5542 info->position_constraints_changed)
5544 /* We request the constrained position if:
5545 * - we were changing position, and need to clamp
5546 * the change to the constraint
5547 * - we're changing the size anyway
5548 * - set_position() was called to toggle CENTER_ALWAYS on
5551 gtk_window_constrain_position (window,
5557 /* Update whether we need to request a move */
5558 if (info->last.configure_request.x != new_request.x ||
5559 info->last.configure_request.y != new_request.y)
5560 configure_request_pos_changed = TRUE;
5562 configure_request_pos_changed = FALSE;
5566 if (window->type == GTK_WINDOW_TOPLEVEL)
5568 int notify_x, notify_y;
5570 /* this is the position from the last configure notify */
5571 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
5573 g_message ("--- %s ---\n"
5574 "last : %d,%d\t%d x %d\n"
5575 "this : %d,%d\t%d x %d\n"
5576 "alloc : %d,%d\t%d x %d\n"
5578 "resize: \t%d x %d\n"
5579 "size_changed: %d pos_changed: %d hints_changed: %d\n"
5580 "configure_notify_received: %d\n"
5581 "configure_request_count: %d\n"
5582 "position_constraints_changed: %d\n",
5583 window->title ? window->title : "(no title)",
5584 info->last.configure_request.x,
5585 info->last.configure_request.y,
5586 info->last.configure_request.width,
5587 info->last.configure_request.height,
5593 widget->allocation.width,
5594 widget->allocation.height,
5595 widget->requisition.width,
5596 widget->requisition.height,
5598 info->resize_height,
5599 configure_request_pos_changed,
5600 configure_request_size_changed,
5602 window->configure_notify_received,
5603 window->configure_request_count,
5604 info->position_constraints_changed);
5608 saved_last_info = info->last;
5609 info->last.geometry = new_geometry;
5610 info->last.flags = new_flags;
5611 info->last.configure_request = new_request;
5613 /* need to set PPosition so the WM will look at our position,
5614 * but we don't want to count PPosition coming and going as a hints
5615 * change for future iterations. So we saved info->last prior to
5619 /* Also, if the initial position was explicitly set, then we always
5620 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
5624 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
5625 * this is an initial map
5628 if ((configure_request_pos_changed ||
5629 info->initial_pos_set ||
5630 (window->need_default_position &&
5631 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
5632 (new_flags & GDK_HINT_POS) == 0)
5634 new_flags |= GDK_HINT_POS;
5635 hints_changed = TRUE;
5638 /* Set hints if necessary
5641 gdk_window_set_geometry_hints (widget->window,
5645 /* handle resizing/moving and widget tree allocation
5647 if (window->configure_notify_received)
5649 GtkAllocation allocation;
5651 /* If we have received a configure event since
5652 * the last time in this function, we need to
5653 * accept our new size and size_allocate child widgets.
5654 * (see gtk_window_configure_event() for more details).
5656 * 1 or more configure notifies may have been received.
5657 * Also, configure_notify_received will only be TRUE
5658 * if all expected configure notifies have been received
5659 * (one per configure request), as an optimization.
5662 window->configure_notify_received = FALSE;
5664 /* gtk_window_configure_event() filled in widget->allocation */
5665 allocation = widget->allocation;
5666 gtk_widget_size_allocate (widget, &allocation);
5668 gdk_window_process_all_updates ();
5670 gdk_window_configure_finished (widget->window);
5672 /* If the configure request changed, it means that
5674 * 1) coincidentally changed hints or widget properties
5675 * impacting the configure request before getting
5676 * a configure notify, or
5677 * 2) some broken widget is changing its size request
5678 * during size allocation, resulting in
5679 * a false appearance of changed configure request.
5681 * For 1), we could just go ahead and ask for the
5682 * new size right now, but doing that for 2)
5683 * might well be fighting the user (and can even
5684 * trigger a loop). Since we really don't want to
5685 * do that, we requeue a resize in hopes that
5686 * by the time it gets handled, the child has seen
5687 * the light and is willing to go along with the
5688 * new size. (this happens for the zvt widget, since
5689 * the size_allocate() above will have stored the
5690 * requisition corresponding to the new size in the
5693 * This doesn't buy us anything for 1), but it shouldn't
5694 * hurt us too badly, since it is what would have
5695 * happened if we had gotten the configure event before
5696 * the new size had been set.
5699 if (configure_request_size_changed ||
5700 configure_request_pos_changed)
5702 /* Don't change the recorded last info after all, because we
5703 * haven't actually updated to the new info yet - we decided
5704 * to postpone our configure request until later.
5706 info->last = saved_last_info;
5708 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
5711 return; /* Bail out, we didn't really process the move/resize */
5713 else if ((configure_request_size_changed || hints_changed) &&
5714 (widget->allocation.width != new_request.width ||
5715 widget->allocation.height != new_request.height))
5718 /* We are in one of the following situations:
5719 * A. configure_request_size_changed
5720 * our requisition has changed and we need a different window size,
5721 * so we request it from the window manager.
5722 * B. !configure_request_size_changed && hints_changed
5723 * the window manager rejects our size, but we have just changed the
5724 * window manager hints, so there's a chance our request will
5725 * be honoured this time, so we try again.
5727 * However, if the new requisition is the same as the current allocation,
5728 * we don't request it again, since we won't get a ConfigureNotify back from
5729 * the window manager unless it decides to change our requisition. If
5730 * we don't get the ConfigureNotify back, the resize queue will never be run.
5733 /* Now send the configure request */
5734 if (configure_request_pos_changed)
5738 gdk_window_move_resize (window->frame,
5739 new_request.x - window->frame_left,
5740 new_request.y - window->frame_top,
5741 new_request.width + window->frame_left + window->frame_right,
5742 new_request.height + window->frame_top + window->frame_bottom);
5743 gdk_window_resize (widget->window,
5744 new_request.width, new_request.height);
5747 gdk_window_move_resize (widget->window,
5748 new_request.x, new_request.y,
5749 new_request.width, new_request.height);
5751 else /* only size changed */
5754 gdk_window_resize (window->frame,
5755 new_request.width + window->frame_left + window->frame_right,
5756 new_request.height + window->frame_top + window->frame_bottom);
5757 gdk_window_resize (widget->window,
5758 new_request.width, new_request.height);
5761 /* Increment the number of have-not-yet-received-notify requests */
5762 window->configure_request_count += 1;
5764 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5765 * configure event in response to our resizing request.
5766 * the configure event will cause a new resize with
5767 * ->configure_notify_received=TRUE.
5768 * until then, we want to
5769 * - discard expose events
5770 * - coalesce resizes for our children
5771 * - defer any window resizes until the configure event arrived
5772 * to achieve this, we queue a resize for the window, but remove its
5773 * resizing handler, so resizing will not be handled from the next
5774 * idle handler but when the configure event arrives.
5776 * FIXME: we should also dequeue the pending redraws here, since
5777 * we handle those ourselves upon ->configure_notify_received==TRUE.
5779 if (container->resize_mode == GTK_RESIZE_QUEUE)
5781 gtk_widget_queue_resize (widget);
5782 _gtk_container_dequeue_resize_handler (container);
5787 /* Handle any position changes.
5789 if (configure_request_pos_changed)
5793 gdk_window_move (window->frame,
5794 new_request.x - window->frame_left,
5795 new_request.y - window->frame_top);
5798 gdk_window_move (widget->window,
5799 new_request.x, new_request.y);
5802 /* And run the resize queue.
5804 gtk_container_resize_children (container);
5807 /* We have now processed a move/resize since the last position
5808 * constraint change, setting of the initial position, or resize.
5809 * (Not resetting these flags here can lead to infinite loops for
5810 * GTK_RESIZE_IMMEDIATE containers)
5812 info->position_constraints_changed = FALSE;
5813 info->initial_pos_set = FALSE;
5814 info->resize_width = -1;
5815 info->resize_height = -1;
5818 /* Compare two sets of Geometry hints for equality.
5821 gtk_window_compare_hints (GdkGeometry *geometry_a,
5823 GdkGeometry *geometry_b,
5826 if (flags_a != flags_b)
5829 if ((flags_a & GDK_HINT_MIN_SIZE) &&
5830 (geometry_a->min_width != geometry_b->min_width ||
5831 geometry_a->min_height != geometry_b->min_height))
5834 if ((flags_a & GDK_HINT_MAX_SIZE) &&
5835 (geometry_a->max_width != geometry_b->max_width ||
5836 geometry_a->max_height != geometry_b->max_height))
5839 if ((flags_a & GDK_HINT_BASE_SIZE) &&
5840 (geometry_a->base_width != geometry_b->base_width ||
5841 geometry_a->base_height != geometry_b->base_height))
5844 if ((flags_a & GDK_HINT_ASPECT) &&
5845 (geometry_a->min_aspect != geometry_b->min_aspect ||
5846 geometry_a->max_aspect != geometry_b->max_aspect))
5849 if ((flags_a & GDK_HINT_RESIZE_INC) &&
5850 (geometry_a->width_inc != geometry_b->width_inc ||
5851 geometry_a->height_inc != geometry_b->height_inc))
5854 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5855 geometry_a->win_gravity != geometry_b->win_gravity)
5862 _gtk_window_constrain_size (GtkWindow *window,
5868 GtkWindowGeometryInfo *info;
5870 g_return_if_fail (GTK_IS_WINDOW (window));
5872 info = window->geometry_info;
5875 GdkWindowHints flags = info->last.flags;
5876 GdkGeometry *geometry = &info->last.geometry;
5878 gtk_window_constrain_size (window,
5889 gtk_window_constrain_size (GtkWindow *window,
5890 GdkGeometry *geometry,
5897 gdk_window_constrain_size (geometry, flags, width, height,
5898 new_width, new_height);
5901 /* Compute the set of geometry hints and flags for a window
5902 * based on the application set geometry, and requisiition
5903 * of the window. gtk_widget_size_request() must have been
5907 gtk_window_compute_hints (GtkWindow *window,
5908 GdkGeometry *new_geometry,
5912 gint extra_width = 0;
5913 gint extra_height = 0;
5914 GtkWindowGeometryInfo *geometry_info;
5915 GtkRequisition requisition;
5917 widget = GTK_WIDGET (window);
5919 gtk_widget_get_child_requisition (widget, &requisition);
5920 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5924 *new_flags = geometry_info->mask;
5925 *new_geometry = geometry_info->geometry;
5932 if (geometry_info && geometry_info->widget)
5934 GtkRequisition child_requisition;
5936 /* FIXME: This really isn't right. It gets the min size wrong and forces
5937 * callers to do horrible hacks like set a huge usize on the child requisition
5938 * to get the base size right. We really want to find the answers to:
5940 * - If the geometry widget was infinitely big, how much extra space
5941 * would be needed for the stuff around it.
5943 * - If the geometry widget was infinitely small, how big would the
5944 * window still have to be.
5946 * Finding these answers would be a bit of a mess here. (Bug #68668)
5948 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5950 extra_width = widget->requisition.width - child_requisition.width;
5951 extra_height = widget->requisition.height - child_requisition.height;
5954 /* We don't want to set GDK_HINT_POS in here, we just set it
5955 * in gtk_window_move_resize() when we want the position
5959 if (*new_flags & GDK_HINT_BASE_SIZE)
5961 new_geometry->base_width += extra_width;
5962 new_geometry->base_height += extra_height;
5964 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5965 (*new_flags & GDK_HINT_RESIZE_INC) &&
5966 ((extra_width != 0) || (extra_height != 0)))
5968 *new_flags |= GDK_HINT_BASE_SIZE;
5970 new_geometry->base_width = extra_width;
5971 new_geometry->base_height = extra_height;
5974 if (*new_flags & GDK_HINT_MIN_SIZE)
5976 if (new_geometry->min_width < 0)
5977 new_geometry->min_width = requisition.width;
5979 new_geometry->min_width += extra_width;
5981 if (new_geometry->min_height < 0)
5982 new_geometry->min_height = requisition.height;
5984 new_geometry->min_height += extra_height;
5986 else if (!window->allow_shrink)
5988 *new_flags |= GDK_HINT_MIN_SIZE;
5990 new_geometry->min_width = requisition.width;
5991 new_geometry->min_height = requisition.height;
5994 if (*new_flags & GDK_HINT_MAX_SIZE)
5996 if (new_geometry->max_width < 0)
5997 new_geometry->max_width = requisition.width;
5999 new_geometry->max_width += extra_width;
6001 if (new_geometry->max_height < 0)
6002 new_geometry->max_height = requisition.height;
6004 new_geometry->max_height += extra_height;
6006 else if (!window->allow_grow)
6008 *new_flags |= GDK_HINT_MAX_SIZE;
6010 new_geometry->max_width = requisition.width;
6011 new_geometry->max_height = requisition.height;
6014 *new_flags |= GDK_HINT_WIN_GRAVITY;
6015 new_geometry->win_gravity = window->gravity;
6018 /***********************
6019 * Redrawing functions *
6020 ***********************/
6023 gtk_window_paint (GtkWidget *widget,
6026 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
6027 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
6031 gtk_window_expose (GtkWidget *widget,
6032 GdkEventExpose *event)
6034 if (!GTK_WIDGET_APP_PAINTABLE (widget))
6035 gtk_window_paint (widget, &event->area);
6037 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event)
6038 return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event);
6044 * gtk_window_set_has_frame:
6045 * @window: a #GtkWindow
6046 * @setting: a boolean
6048 * (Note: this is a special-purpose function for the framebuffer port,
6049 * that causes GTK+ to draw its own window border. For most applications,
6050 * you want gtk_window_set_decorated() instead, which tells the window
6051 * manager whether to draw the window border.)
6053 * If this function is called on a window with setting of %TRUE, before
6054 * it is realized or showed, it will have a "frame" window around
6055 * @window->window, accessible in @window->frame. Using the signal
6056 * frame_event you can receive all events targeted at the frame.
6058 * This function is used by the linux-fb port to implement managed
6059 * windows, but it could conceivably be used by X-programs that
6060 * want to do their own window decorations.
6064 gtk_window_set_has_frame (GtkWindow *window,
6067 g_return_if_fail (GTK_IS_WINDOW (window));
6068 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
6070 window->has_frame = setting != FALSE;
6074 * gtk_window_get_has_frame:
6075 * @window: a #GtkWindow
6077 * Accessor for whether the window has a frame window exterior to
6078 * @window->window. Gets the value set by gtk_window_set_has_frame ().
6080 * Return value: %TRUE if a frame has been added to the window
6081 * via gtk_window_set_has_frame().
6084 gtk_window_get_has_frame (GtkWindow *window)
6086 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6088 return window->has_frame;
6092 * gtk_window_set_frame_dimensions:
6093 * @window: a #GtkWindow that has a frame
6094 * @left: The width of the left border
6095 * @top: The height of the top border
6096 * @right: The width of the right border
6097 * @bottom: The height of the bottom border
6099 * (Note: this is a special-purpose function intended for the framebuffer
6100 * port; see gtk_window_set_has_frame(). It will have no effect on the
6101 * window border drawn by the window manager, which is the normal
6102 * case when using the X Window system.)
6104 * For windows with frames (see gtk_window_set_has_frame()) this function
6105 * can be used to change the size of the frame border.
6108 gtk_window_set_frame_dimensions (GtkWindow *window,
6116 g_return_if_fail (GTK_IS_WINDOW (window));
6118 widget = GTK_WIDGET (window);
6120 if (window->frame_left == left &&
6121 window->frame_top == top &&
6122 window->frame_right == right &&
6123 window->frame_bottom == bottom)
6126 window->frame_left = left;
6127 window->frame_top = top;
6128 window->frame_right = right;
6129 window->frame_bottom = bottom;
6131 if (GTK_WIDGET_REALIZED (widget) && window->frame)
6133 gint width = widget->allocation.width + left + right;
6134 gint height = widget->allocation.height + top + bottom;
6135 gdk_window_resize (window->frame, width, height);
6136 gtk_decorated_window_move_resize_window (window,
6138 widget->allocation.width,
6139 widget->allocation.height);
6144 * gtk_window_present:
6145 * @window: a #GtkWindow
6147 * Presents a window to the user. This may mean raising the window
6148 * in the stacking order, deiconifying it, moving it to the current
6149 * desktop, and/or giving it the keyboard focus, possibly dependent
6150 * on the user's platform, window manager, and preferences.
6152 * If @window is hidden, this function calls gtk_widget_show()
6155 * This function should be used when the user tries to open a window
6156 * that's already open. Say for example the preferences dialog is
6157 * currently open, and the user chooses Preferences from the menu
6158 * a second time; use gtk_window_present() to move the already-open dialog
6159 * where the user can see it.
6161 * If you are calling this function in response to a user interaction,
6162 * it is preferable to use gtk_window_present_with_time().
6166 gtk_window_present (GtkWindow *window)
6168 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6172 * gtk_window_present_with_time:
6173 * @window: a #GtkWindow
6174 * @timestamp: the timestamp of the user interaction (typically a
6175 * button or key press event) which triggered this call
6177 * Presents a window to the user in response to a user interaction.
6178 * If you need to present a window without a timestamp, use
6179 * gtk_window_present(). See gtk_window_present() for details.
6184 gtk_window_present_with_time (GtkWindow *window,
6189 g_return_if_fail (GTK_IS_WINDOW (window));
6191 widget = GTK_WIDGET (window);
6193 if (GTK_WIDGET_VISIBLE (window))
6195 g_assert (widget->window != NULL);
6197 gdk_window_show (widget->window);
6199 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
6200 if (timestamp == GDK_CURRENT_TIME)
6202 #ifdef GDK_WINDOWING_X11
6203 GdkDisplay *display;
6205 display = gtk_widget_get_display (GTK_WIDGET (window));
6206 timestamp = gdk_x11_display_get_user_time (display);
6208 timestamp = gtk_get_current_event_time ();
6212 gdk_window_focus (widget->window, timestamp);
6216 gtk_widget_show (widget);
6221 * gtk_window_iconify:
6222 * @window: a #GtkWindow
6224 * Asks to iconify (i.e. minimize) the specified @window. Note that
6225 * you shouldn't assume the window is definitely iconified afterward,
6226 * because other entities (e.g. the user or <link
6227 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
6228 * again, or there may not be a window manager in which case
6229 * iconification isn't possible, etc. But normally the window will end
6230 * up iconified. Just don't write code that crashes if not.
6232 * It's permitted to call this function before showing a window,
6233 * in which case the window will be iconified before it ever appears
6236 * You can track iconification via the "window_state_event" signal
6241 gtk_window_iconify (GtkWindow *window)
6244 GdkWindow *toplevel;
6246 g_return_if_fail (GTK_IS_WINDOW (window));
6248 widget = GTK_WIDGET (window);
6250 window->iconify_initially = TRUE;
6253 toplevel = window->frame;
6255 toplevel = widget->window;
6257 if (toplevel != NULL)
6258 gdk_window_iconify (toplevel);
6262 * gtk_window_deiconify:
6263 * @window: a #GtkWindow
6265 * Asks to deiconify (i.e. unminimize) the specified @window. Note
6266 * that you shouldn't assume the window is definitely deiconified
6267 * afterward, because other entities (e.g. the user or <link
6268 * linkend="gtk-X11-arch">window manager</link>) could iconify it
6269 * again before your code which assumes deiconification gets to run.
6271 * You can track iconification via the "window_state_event" signal
6275 gtk_window_deiconify (GtkWindow *window)
6278 GdkWindow *toplevel;
6280 g_return_if_fail (GTK_IS_WINDOW (window));
6282 widget = GTK_WIDGET (window);
6284 window->iconify_initially = FALSE;
6287 toplevel = window->frame;
6289 toplevel = widget->window;
6291 if (toplevel != NULL)
6292 gdk_window_deiconify (toplevel);
6297 * @window: a #GtkWindow
6299 * Asks to stick @window, which means that it will appear on all user
6300 * desktops. Note that you shouldn't assume the window is definitely
6301 * stuck afterward, because other entities (e.g. the user or <link
6302 * linkend="gtk-X11-arch">window manager</link>) could unstick it
6303 * again, and some window managers do not support sticking
6304 * windows. But normally the window will end up stuck. Just don't
6305 * write code that crashes if not.
6307 * It's permitted to call this function before showing a window.
6309 * You can track stickiness via the "window_state_event" signal
6314 gtk_window_stick (GtkWindow *window)
6317 GdkWindow *toplevel;
6319 g_return_if_fail (GTK_IS_WINDOW (window));
6321 widget = GTK_WIDGET (window);
6323 window->stick_initially = TRUE;
6326 toplevel = window->frame;
6328 toplevel = widget->window;
6330 if (toplevel != NULL)
6331 gdk_window_stick (toplevel);
6335 * gtk_window_unstick:
6336 * @window: a #GtkWindow
6338 * Asks to unstick @window, which means that it will appear on only
6339 * one of the user's desktops. Note that you shouldn't assume the
6340 * window is definitely unstuck afterward, because other entities
6341 * (e.g. the user or <link linkend="gtk-X11-arch">window
6342 * manager</link>) could stick it again. But normally the window will
6343 * end up stuck. Just don't write code that crashes if not.
6345 * You can track stickiness via the "window_state_event" signal
6350 gtk_window_unstick (GtkWindow *window)
6353 GdkWindow *toplevel;
6355 g_return_if_fail (GTK_IS_WINDOW (window));
6357 widget = GTK_WIDGET (window);
6359 window->stick_initially = FALSE;
6362 toplevel = window->frame;
6364 toplevel = widget->window;
6366 if (toplevel != NULL)
6367 gdk_window_unstick (toplevel);
6371 * gtk_window_maximize:
6372 * @window: a #GtkWindow
6374 * Asks to maximize @window, so that it becomes full-screen. Note that
6375 * you shouldn't assume the window is definitely maximized afterward,
6376 * because other entities (e.g. the user or <link
6377 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
6378 * again, and not all window managers support maximization. But
6379 * normally the window will end up maximized. Just don't write code
6380 * that crashes if not.
6382 * It's permitted to call this function before showing a window,
6383 * in which case the window will be maximized when it appears onscreen
6386 * You can track maximization via the "window_state_event" signal
6391 gtk_window_maximize (GtkWindow *window)
6394 GdkWindow *toplevel;
6396 g_return_if_fail (GTK_IS_WINDOW (window));
6398 widget = GTK_WIDGET (window);
6400 window->maximize_initially = TRUE;
6403 toplevel = window->frame;
6405 toplevel = widget->window;
6407 if (toplevel != NULL)
6408 gdk_window_maximize (toplevel);
6412 * gtk_window_unmaximize:
6413 * @window: a #GtkWindow
6415 * Asks to unmaximize @window. Note that you shouldn't assume the
6416 * window is definitely unmaximized afterward, because other entities
6417 * (e.g. the user or <link linkend="gtk-X11-arch">window
6418 * manager</link>) could maximize it again, and not all window
6419 * managers honor requests to unmaximize. But normally the window will
6420 * end up unmaximized. Just don't write code that crashes if not.
6422 * You can track maximization via the "window_state_event" signal
6427 gtk_window_unmaximize (GtkWindow *window)
6430 GdkWindow *toplevel;
6432 g_return_if_fail (GTK_IS_WINDOW (window));
6434 widget = GTK_WIDGET (window);
6436 window->maximize_initially = FALSE;
6439 toplevel = window->frame;
6441 toplevel = widget->window;
6443 if (toplevel != NULL)
6444 gdk_window_unmaximize (toplevel);
6448 * gtk_window_fullscreen:
6449 * @window: a #GtkWindow
6451 * Asks to place @window in the fullscreen state. Note that you
6452 * shouldn't assume the window is definitely full screen afterward,
6453 * because other entities (e.g. the user or <link
6454 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
6455 * again, and not all window managers honor requests to fullscreen
6456 * windows. But normally the window will end up fullscreen. Just
6457 * don't write code that crashes if not.
6459 * You can track the fullscreen state via the "window_state_event" signal
6465 gtk_window_fullscreen (GtkWindow *window)
6468 GdkWindow *toplevel;
6469 GtkWindowPrivate *priv;
6471 g_return_if_fail (GTK_IS_WINDOW (window));
6473 widget = GTK_WIDGET (window);
6474 priv = GTK_WINDOW_GET_PRIVATE (window);
6476 priv->fullscreen_initially = TRUE;
6479 toplevel = window->frame;
6481 toplevel = widget->window;
6483 if (toplevel != NULL)
6484 gdk_window_fullscreen (toplevel);
6488 * gtk_window_unfullscreen:
6489 * @window: a #GtkWindow
6491 * Asks to toggle off the fullscreen state for @window. Note that you
6492 * shouldn't assume the window is definitely not full screen
6493 * afterward, because other entities (e.g. the user or <link
6494 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
6495 * again, and not all window managers honor requests to unfullscreen
6496 * windows. But normally the window will end up restored to its normal
6497 * state. Just don't write code that crashes if not.
6499 * You can track the fullscreen state via the "window_state_event" signal
6505 gtk_window_unfullscreen (GtkWindow *window)
6508 GdkWindow *toplevel;
6509 GtkWindowPrivate *priv;
6511 g_return_if_fail (GTK_IS_WINDOW (window));
6513 widget = GTK_WIDGET (window);
6514 priv = GTK_WINDOW_GET_PRIVATE (window);
6516 priv->fullscreen_initially = FALSE;
6519 toplevel = window->frame;
6521 toplevel = widget->window;
6523 if (toplevel != NULL)
6524 gdk_window_unfullscreen (toplevel);
6528 * gtk_window_set_keep_above:
6529 * @window: a #GtkWindow
6530 * @setting: whether to keep @window above other windows
6532 * Asks to keep @window above, so that it stays on top. Note that
6533 * you shouldn't assume the window is definitely above afterward,
6534 * because other entities (e.g. the user or <link
6535 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
6536 * and not all window managers support keeping windows above. But
6537 * normally the window will end kept above. Just don't write code
6538 * that crashes if not.
6540 * It's permitted to call this function before showing a window,
6541 * in which case the window will be kept above when it appears onscreen
6544 * You can track the above state via the "window_state_event" signal
6547 * Note that, according to the <ulink
6548 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
6549 * Manager Hints</ulink> specification, the above state is mainly meant
6550 * for user preferences and should not be used by applications e.g. for
6551 * drawing attention to their dialogs.
6556 gtk_window_set_keep_above (GtkWindow *window,
6560 GtkWindowPrivate *priv;
6561 GdkWindow *toplevel;
6563 g_return_if_fail (GTK_IS_WINDOW (window));
6565 widget = GTK_WIDGET (window);
6566 priv = GTK_WINDOW_GET_PRIVATE (window);
6568 priv->above_initially = setting;
6570 priv->below_initially = FALSE;
6573 toplevel = window->frame;
6575 toplevel = widget->window;
6577 if (toplevel != NULL)
6578 gdk_window_set_keep_above (toplevel, setting);
6582 * gtk_window_set_keep_below:
6583 * @window: a #GtkWindow
6584 * @setting: whether to keep @window below other windows
6586 * Asks to keep @window below, so that it stays in bottom. Note that
6587 * you shouldn't assume the window is definitely below afterward,
6588 * because other entities (e.g. the user or <link
6589 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
6590 * and not all window managers support putting windows below. But
6591 * normally the window will be kept below. Just don't write code
6592 * that crashes if not.
6594 * It's permitted to call this function before showing a window,
6595 * in which case the window will be kept below when it appears onscreen
6598 * You can track the below state via the "window_state_event" signal
6601 * Note that, according to the <ulink
6602 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
6603 * Manager Hints</ulink> specification, the above state is mainly meant
6604 * for user preferences and should not be used by applications e.g. for
6605 * drawing attention to their dialogs.
6610 gtk_window_set_keep_below (GtkWindow *window,
6614 GtkWindowPrivate *priv;
6615 GdkWindow *toplevel;
6617 g_return_if_fail (GTK_IS_WINDOW (window));
6619 widget = GTK_WIDGET (window);
6620 priv = GTK_WINDOW_GET_PRIVATE (window);
6622 priv->below_initially = setting;
6624 priv->above_initially = FALSE;
6627 toplevel = window->frame;
6629 toplevel = widget->window;
6631 if (toplevel != NULL)
6632 gdk_window_set_keep_below (toplevel, setting);
6636 * gtk_window_set_resizable:
6637 * @window: a #GtkWindow
6638 * @resizable: %TRUE if the user can resize this window
6640 * Sets whether the user can resize a window. Windows are user resizable
6644 gtk_window_set_resizable (GtkWindow *window,
6647 g_return_if_fail (GTK_IS_WINDOW (window));
6649 gtk_window_set_policy (window, FALSE, resizable, FALSE);
6653 * gtk_window_get_resizable:
6654 * @window: a #GtkWindow
6656 * Gets the value set by gtk_window_set_resizable().
6658 * Return value: %TRUE if the user can resize the window
6661 gtk_window_get_resizable (GtkWindow *window)
6663 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6665 /* allow_grow is most likely to indicate the semantic concept we
6666 * mean by "resizable" (and will be a reliable indicator if
6667 * set_policy() hasn't been called)
6669 return window->allow_grow;
6673 * gtk_window_set_gravity:
6674 * @window: a #GtkWindow
6675 * @gravity: window gravity
6677 * Window gravity defines the meaning of coordinates passed to
6678 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
6681 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
6682 * typically "do what you mean."
6686 gtk_window_set_gravity (GtkWindow *window,
6689 g_return_if_fail (GTK_IS_WINDOW (window));
6691 if (gravity != window->gravity)
6693 window->gravity = gravity;
6695 /* gtk_window_move_resize() will adapt gravity
6697 gtk_widget_queue_resize (GTK_WIDGET (window));
6699 g_object_notify (G_OBJECT (window), "gravity");
6704 * gtk_window_get_gravity:
6705 * @window: a #GtkWindow
6707 * Gets the value set by gtk_window_set_gravity().
6709 * Return value: window gravity
6712 gtk_window_get_gravity (GtkWindow *window)
6714 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
6716 return window->gravity;
6720 * gtk_window_begin_resize_drag:
6721 * @window: a #GtkWindow
6722 * @button: mouse button that initiated the drag
6723 * @edge: position of the resize control
6724 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6725 * @root_y: Y position where the user clicked to initiate the drag
6726 * @timestamp: timestamp from the click event that initiated the drag
6728 * Starts resizing a window. This function is used if an application
6729 * has window resizing controls. When GDK can support it, the resize
6730 * will be done using the standard mechanism for the <link
6731 * linkend="gtk-X11-arch">window manager</link> or windowing
6732 * system. Otherwise, GDK will try to emulate window resizing,
6733 * potentially not all that well, depending on the windowing system.
6737 gtk_window_begin_resize_drag (GtkWindow *window,
6745 GdkWindow *toplevel;
6747 g_return_if_fail (GTK_IS_WINDOW (window));
6748 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6750 widget = GTK_WIDGET (window);
6753 toplevel = window->frame;
6755 toplevel = widget->window;
6757 gdk_window_begin_resize_drag (toplevel,
6764 * gtk_window_get_frame_dimensions:
6765 * @window: a #GtkWindow
6766 * @left: location to store the width of the frame at the left, or %NULL
6767 * @top: location to store the height of the frame at the top, or %NULL
6768 * @right: location to store the width of the frame at the returns, or %NULL
6769 * @bottom: location to store the height of the frame at the bottom, or %NULL
6771 * (Note: this is a special-purpose function intended for the
6772 * framebuffer port; see gtk_window_set_has_frame(). It will not
6773 * return the size of the window border drawn by the <link
6774 * linkend="gtk-X11-arch">window manager</link>, which is the normal
6775 * case when using a windowing system. See
6776 * gdk_window_get_frame_extents() to get the standard window border
6779 * Retrieves the dimensions of the frame window for this toplevel.
6780 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
6783 gtk_window_get_frame_dimensions (GtkWindow *window,
6789 g_return_if_fail (GTK_IS_WINDOW (window));
6792 *left = window->frame_left;
6794 *top = window->frame_top;
6796 *right = window->frame_right;
6798 *bottom = window->frame_bottom;
6802 * gtk_window_begin_move_drag:
6803 * @window: a #GtkWindow
6804 * @button: mouse button that initiated the drag
6805 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6806 * @root_y: Y position where the user clicked to initiate the drag
6807 * @timestamp: timestamp from the click event that initiated the drag
6809 * Starts moving a window. This function is used if an application has
6810 * window movement grips. When GDK can support it, the window movement
6811 * will be done using the standard mechanism for the <link
6812 * linkend="gtk-X11-arch">window manager</link> or windowing
6813 * system. Otherwise, GDK will try to emulate window movement,
6814 * potentially not all that well, depending on the windowing system.
6818 gtk_window_begin_move_drag (GtkWindow *window,
6825 GdkWindow *toplevel;
6827 g_return_if_fail (GTK_IS_WINDOW (window));
6828 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6830 widget = GTK_WIDGET (window);
6833 toplevel = window->frame;
6835 toplevel = widget->window;
6837 gdk_window_begin_move_drag (toplevel,
6844 * gtk_window_set_screen:
6845 * @window: a #GtkWindow.
6846 * @screen: a #GdkScreen.
6848 * Sets the #GdkScreen where the @window is displayed; if
6849 * the window is already mapped, it will be unmapped, and
6850 * then remapped on the new screen.
6855 gtk_window_set_screen (GtkWindow *window,
6859 GdkScreen *previous_screen;
6860 gboolean was_mapped;
6862 g_return_if_fail (GTK_IS_WINDOW (window));
6863 g_return_if_fail (GDK_IS_SCREEN (screen));
6865 if (screen == window->screen)
6868 widget = GTK_WIDGET (window);
6870 previous_screen = window->screen;
6871 was_mapped = GTK_WIDGET_MAPPED (widget);
6874 gtk_widget_unmap (widget);
6875 if (GTK_WIDGET_REALIZED (widget))
6876 gtk_widget_unrealize (widget);
6878 gtk_window_free_key_hash (window);
6879 window->screen = screen;
6880 gtk_widget_reset_rc_styles (widget);
6881 if (screen != previous_screen)
6883 g_signal_handlers_disconnect_by_func (previous_screen,
6884 gtk_window_on_composited_changed, window);
6885 g_signal_connect (screen, "composited_changed",
6886 G_CALLBACK (gtk_window_on_composited_changed), window);
6888 _gtk_widget_propagate_screen_changed (widget, previous_screen);
6889 _gtk_widget_propagate_composited_changed (widget);
6891 g_object_notify (G_OBJECT (window), "screen");
6894 gtk_widget_map (widget);
6898 gtk_window_on_composited_changed (GdkScreen *screen,
6901 gtk_widget_queue_draw (GTK_WIDGET (window));
6903 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
6907 gtk_window_check_screen (GtkWindow *window)
6910 return window->screen;
6913 g_warning ("Screen for GtkWindow not set; you must always set\n"
6914 "a screen for a GtkWindow before using the window");
6920 * gtk_window_get_screen:
6921 * @window: a #GtkWindow.
6923 * Returns the #GdkScreen associated with @window.
6925 * Return value: a #GdkScreen.
6930 gtk_window_get_screen (GtkWindow *window)
6932 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6934 return window->screen;
6938 * gtk_window_is_active:
6939 * @window: a #GtkWindow
6941 * Returns whether the window is part of the current active toplevel.
6942 * (That is, the toplevel window receiving keystrokes.)
6943 * The return value is %TRUE if the window is active toplevel
6944 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
6945 * You might use this function if you wanted to draw a widget
6946 * differently in an active window from a widget in an inactive window.
6947 * See gtk_window_has_toplevel_focus()
6949 * Return value: %TRUE if the window part of the current active window.
6954 gtk_window_is_active (GtkWindow *window)
6956 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6958 return window->is_active;
6962 * gtk_window_has_toplevel_focus:
6963 * @window: a #GtkWindow
6965 * Returns whether the input focus is within this GtkWindow.
6966 * For real toplevel windows, this is identical to gtk_window_is_active(),
6967 * but for embedded windows, like #GtkPlug, the results will differ.
6969 * Return value: %TRUE if the input focus is within this GtkWindow
6974 gtk_window_has_toplevel_focus (GtkWindow *window)
6976 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6978 return window->has_toplevel_focus;
6982 gtk_window_group_class_init (GtkWindowGroupClass *klass)
6987 gtk_window_group_get_type (void)
6989 static GType window_group_type = 0;
6991 if (!window_group_type)
6993 static const GTypeInfo window_group_info =
6995 sizeof (GtkWindowGroupClass),
6996 NULL, /* base_init */
6997 NULL, /* base_finalize */
6998 (GClassInitFunc) gtk_window_group_class_init,
6999 NULL, /* class_finalize */
7000 NULL, /* class_data */
7001 sizeof (GtkWindowGroup),
7002 0, /* n_preallocs */
7003 (GInstanceInitFunc) NULL,
7006 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
7007 &window_group_info, 0);
7010 return window_group_type;
7014 * gtk_window_group_new:
7016 * Creates a new #GtkWindowGroup object. Grabs added with
7017 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
7019 * Return value: a new #GtkWindowGroup.
7022 gtk_window_group_new (void)
7024 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
7028 window_group_cleanup_grabs (GtkWindowGroup *group,
7032 GSList *to_remove = NULL;
7034 tmp_list = group->grabs;
7037 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
7038 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
7039 tmp_list = tmp_list->next;
7044 gtk_grab_remove (to_remove->data);
7045 g_object_unref (to_remove->data);
7046 to_remove = g_slist_delete_link (to_remove, to_remove);
7051 * gtk_window_group_add_window:
7052 * @window_group: a #GtkWindowGroup
7053 * @window: the #GtkWindow to add
7055 * Adds a window to a #GtkWindowGroup.
7058 gtk_window_group_add_window (GtkWindowGroup *window_group,
7061 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7062 g_return_if_fail (GTK_IS_WINDOW (window));
7064 if (window->group != window_group)
7066 g_object_ref (window);
7067 g_object_ref (window_group);
7070 gtk_window_group_remove_window (window->group, window);
7072 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
7074 window->group = window_group;
7076 g_object_unref (window);
7081 * gtk_window_group_remove_window:
7082 * @window_group: a #GtkWindowGroup
7083 * @window: the #GtkWindow to remove
7085 * Removes a window from a #GtkWindowGroup.
7088 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7091 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7092 g_return_if_fail (GTK_IS_WIDGET (window));
7093 g_return_if_fail (window->group == window_group);
7095 g_object_ref (window);
7097 window_group_cleanup_grabs (window_group, window);
7098 window->group = NULL;
7100 g_object_unref (window_group);
7101 g_object_unref (window);
7105 * gtk_window_get_group:
7106 * @window: a #GtkWindow, or %NULL
7108 * Returns the group for @window or the default group, if
7109 * @window is %NULL or if @window does not have an explicit
7112 * Returns: the #GtkWindowGroup for a window or the default group
7117 gtk_window_get_group (GtkWindow *window)
7119 if (window && window->group)
7120 return window->group;
7123 static GtkWindowGroup *default_group = NULL;
7126 default_group = gtk_window_group_new ();
7128 return default_group;
7132 /* Return the current grab widget of the given group
7135 _gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
7137 if (window_group->grabs)
7138 return GTK_WIDGET (window_group->grabs->data);
7143 Derived from XParseGeometry() in XFree86
7145 Copyright 1985, 1986, 1987,1998 The Open Group
7147 All Rights Reserved.
7149 The above copyright notice and this permission notice shall be included
7150 in all copies or substantial portions of the Software.
7152 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
7153 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7154 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7155 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
7156 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7157 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
7158 OTHER DEALINGS IN THE SOFTWARE.
7160 Except as contained in this notice, the name of The Open Group shall
7161 not be used in advertising or otherwise to promote the sale, use or
7162 other dealings in this Software without prior written authorization
7163 from The Open Group.
7168 * XParseGeometry parses strings of the form
7169 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
7170 * width, height, xoffset, and yoffset are unsigned integers.
7171 * Example: "=80x24+300-49"
7172 * The equal sign is optional.
7173 * It returns a bitmask that indicates which of the four values
7174 * were actually found in the string. For each value found,
7175 * the corresponding argument is updated; for each value
7176 * not found, the corresponding argument is left unchanged.
7179 /* The following code is from Xlib, and is minimally modified, so we
7180 * can track any upstream changes if required. Don't change this
7181 * code. Or if you do, put in a huge comment marking which thing
7186 read_int (gchar *string,
7194 else if (*string == '-')
7200 for (; (*string >= '0') && (*string <= '9'); string++)
7202 result = (result * 10) + (*string - '0');
7214 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
7215 * value (x, y, width, height) was found in the parsed string.
7217 #define NoValue 0x0000
7218 #define XValue 0x0001
7219 #define YValue 0x0002
7220 #define WidthValue 0x0004
7221 #define HeightValue 0x0008
7222 #define AllValues 0x000F
7223 #define XNegative 0x0010
7224 #define YNegative 0x0020
7226 /* Try not to reformat/modify, so we can compare/sync with X sources */
7228 gtk_XParseGeometry (const char *string,
7231 unsigned int *width,
7232 unsigned int *height)
7236 unsigned int tempWidth, tempHeight;
7238 char *nextCharacter;
7240 /* These initializations are just to silence gcc */
7246 if ( (string == NULL) || (*string == '\0')) return(mask);
7248 string++; /* ignore possible '=' at beg of geometry spec */
7250 strind = (char *)string;
7251 if (*strind != '+' && *strind != '-' && *strind != 'x') {
7252 tempWidth = read_int(strind, &nextCharacter);
7253 if (strind == nextCharacter)
7255 strind = nextCharacter;
7259 if (*strind == 'x' || *strind == 'X') {
7261 tempHeight = read_int(strind, &nextCharacter);
7262 if (strind == nextCharacter)
7264 strind = nextCharacter;
7265 mask |= HeightValue;
7268 if ((*strind == '+') || (*strind == '-')) {
7269 if (*strind == '-') {
7271 tempX = -read_int(strind, &nextCharacter);
7272 if (strind == nextCharacter)
7274 strind = nextCharacter;
7280 tempX = read_int(strind, &nextCharacter);
7281 if (strind == nextCharacter)
7283 strind = nextCharacter;
7286 if ((*strind == '+') || (*strind == '-')) {
7287 if (*strind == '-') {
7289 tempY = -read_int(strind, &nextCharacter);
7290 if (strind == nextCharacter)
7292 strind = nextCharacter;
7299 tempY = read_int(strind, &nextCharacter);
7300 if (strind == nextCharacter)
7302 strind = nextCharacter;
7308 /* If strind isn't at the end of the string the it's an invalid
7309 geometry specification. */
7311 if (*strind != '\0') return (0);
7317 if (mask & WidthValue)
7319 if (mask & HeightValue)
7320 *height = tempHeight;
7325 * gtk_window_parse_geometry:
7326 * @window: a #GtkWindow
7327 * @geometry: geometry string
7329 * Parses a standard X Window System geometry string - see the
7330 * manual page for X (type 'man X') for details on this.
7331 * gtk_window_parse_geometry() does work on all GTK+ ports
7332 * including Win32 but is primarily intended for an X environment.
7334 * If either a size or a position can be extracted from the
7335 * geometry string, gtk_window_parse_geometry() returns %TRUE
7336 * and calls gtk_window_set_default_size() and/or gtk_window_move()
7337 * to resize/move the window.
7339 * If gtk_window_parse_geometry() returns %TRUE, it will also
7340 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
7341 * indicating to the window manager that the size/position of
7342 * the window was user-specified. This causes most window
7343 * managers to honor the geometry.
7345 * Note that for gtk_window_parse_geometry() to work as expected, it has
7346 * to be called when the window has its "final" size, i.e. after calling
7347 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
7350 * <informalexample><programlisting>
7351 * #include <gtk/gtk.h>
7354 * fill_with_content (GtkWidget *vbox)
7356 * /<!-- -->* fill with content... *<!-- -->/
7360 * main (int argc, char *argv[])
7362 * GtkWidget *window, *vbox;
7363 * GdkGeometry size_hints = {
7364 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
7367 * gtk_init (&argc, &argv);
7369 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7370 * vbox = gtk_vbox_new (FALSE, 0);
7372 * gtk_container_add (GTK_CONTAINER (window), vbox);
7373 * fill_with_content (vbox);
7374 * gtk_widget_show_all (vbox);
7376 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
7379 * GDK_HINT_MIN_SIZE |
7380 * GDK_HINT_BASE_SIZE |
7381 * GDK_HINT_RESIZE_INC);
7385 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
7386 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
7389 * gtk_widget_show_all (window);
7394 * </programlisting></informalexample>
7396 * Return value: %TRUE if string was parsed successfully
7399 gtk_window_parse_geometry (GtkWindow *window,
7400 const gchar *geometry)
7402 gint result, x = 0, y = 0;
7405 gboolean size_set, pos_set;
7408 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7409 g_return_val_if_fail (geometry != NULL, FALSE);
7411 screen = gtk_window_check_screen (window);
7413 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
7416 if ((result & WidthValue) || (result & HeightValue))
7418 gtk_window_set_default_size_internal (window,
7419 TRUE, result & WidthValue ? w : -1,
7420 TRUE, result & HeightValue ? h : -1,
7425 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
7427 grav = GDK_GRAVITY_NORTH_WEST;
7429 if ((result & XNegative) && (result & YNegative))
7430 grav = GDK_GRAVITY_SOUTH_EAST;
7431 else if (result & XNegative)
7432 grav = GDK_GRAVITY_NORTH_EAST;
7433 else if (result & YNegative)
7434 grav = GDK_GRAVITY_SOUTH_WEST;
7436 if ((result & XValue) == 0)
7439 if ((result & YValue) == 0)
7442 if (grav == GDK_GRAVITY_SOUTH_WEST ||
7443 grav == GDK_GRAVITY_SOUTH_EAST)
7444 y = gdk_screen_get_height (screen) - h + y;
7446 if (grav == GDK_GRAVITY_SOUTH_EAST ||
7447 grav == GDK_GRAVITY_NORTH_EAST)
7448 x = gdk_screen_get_width (screen) - w + x;
7450 /* we don't let you put a window offscreen; maybe some people would
7451 * prefer to be able to, but it's kind of a bogus thing to do.
7460 if ((result & XValue) || (result & YValue))
7462 gtk_window_set_gravity (window, grav);
7463 gtk_window_move (window, x, y);
7467 if (size_set || pos_set)
7469 /* Set USSize, USPosition hints */
7470 GtkWindowGeometryInfo *info;
7472 info = gtk_window_get_geometry_info (window, TRUE);
7475 info->mask |= GDK_HINT_USER_POS;
7477 info->mask |= GDK_HINT_USER_SIZE;
7484 gtk_window_mnemonic_hash_foreach (guint keyval,
7490 GtkWindowKeysForeachFunc func;
7494 (*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
7498 _gtk_window_keys_foreach (GtkWindow *window,
7499 GtkWindowKeysForeachFunc func,
7503 GtkMnemonicHash *mnemonic_hash;
7507 GtkWindowKeysForeachFunc func;
7511 info.window = window;
7513 info.func_data = func_data;
7515 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
7517 _gtk_mnemonic_hash_foreach (mnemonic_hash,
7518 gtk_window_mnemonic_hash_foreach, &info);
7520 groups = gtk_accel_groups_from_object (G_OBJECT (window));
7523 GtkAccelGroup *group = groups->data;
7526 for (i = 0; i < group->n_accels; i++)
7528 GtkAccelKey *key = &group->priv_accels[i].key;
7531 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
7534 groups = groups->next;
7539 gtk_window_keys_changed (GtkWindow *window)
7541 gtk_window_free_key_hash (window);
7542 gtk_window_get_key_hash (window);
7545 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
7547 struct _GtkWindowKeyEntry
7551 guint is_mnemonic : 1;
7555 window_key_entry_destroy (gpointer data)
7557 g_slice_free (GtkWindowKeyEntry, data);
7561 add_to_key_hash (GtkWindow *window,
7563 GdkModifierType modifiers,
7564 gboolean is_mnemonic,
7567 GtkKeyHash *key_hash = data;
7569 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
7571 entry->keyval = keyval;
7572 entry->modifiers = modifiers;
7573 entry->is_mnemonic = is_mnemonic;
7575 /* GtkAccelGroup stores lowercased accelerators. To deal
7576 * with this, if <Shift> was specified, uppercase.
7578 if (modifiers & GDK_SHIFT_MASK)
7580 if (keyval == GDK_Tab)
7581 keyval = GDK_ISO_Left_Tab;
7583 keyval = gdk_keyval_to_upper (keyval);
7586 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
7590 gtk_window_get_key_hash (GtkWindow *window)
7592 GdkScreen *screen = gtk_window_check_screen (window);
7593 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7598 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
7599 (GDestroyNotify)window_key_entry_destroy);
7600 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
7601 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
7607 gtk_window_free_key_hash (GtkWindow *window)
7609 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7612 _gtk_key_hash_free (key_hash);
7613 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
7618 * gtk_window_activate_key:
7619 * @window: a #GtkWindow
7620 * @event: a #GdkEventKey
7622 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
7623 * called by the default ::key_press_event handler for toplevel windows,
7624 * however in some cases it may be useful to call this directly when
7625 * overriding the standard key handling for a toplevel window.
7627 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
7630 gtk_window_activate_key (GtkWindow *window,
7633 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7634 GtkWindowKeyEntry *found_entry = NULL;
7638 gtk_window_keys_changed (window);
7639 key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7644 GSList *entries = _gtk_key_hash_lookup (key_hash,
7645 event->hardware_keycode,
7647 gtk_accelerator_get_default_mod_mask (),
7651 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
7653 GtkWindowKeyEntry *entry = tmp_list->data;
7654 if (entry->is_mnemonic)
7656 found_entry = entry;
7661 if (!found_entry && entries)
7662 found_entry = entries->data;
7664 g_slist_free (entries);
7669 if (found_entry->is_mnemonic)
7670 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
7672 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
7679 window_update_has_focus (GtkWindow *window)
7681 GtkWidget *widget = GTK_WIDGET (window);
7682 gboolean has_focus = window->has_toplevel_focus && window->is_active;
7684 if (has_focus != window->has_focus)
7686 window->has_focus = has_focus;
7690 if (window->focus_widget &&
7691 window->focus_widget != widget &&
7692 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7693 do_focus_change (window->focus_widget, TRUE);
7697 if (window->focus_widget &&
7698 window->focus_widget != widget &&
7699 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7700 do_focus_change (window->focus_widget, FALSE);
7706 * _gtk_window_set_is_active:
7707 * @window: a #GtkWindow
7708 * @is_active: %TRUE if the window is in the currently active toplevel
7710 * Internal function that sets whether the #GtkWindow is part
7711 * of the currently active toplevel window (taking into account inter-process
7715 _gtk_window_set_is_active (GtkWindow *window,
7718 g_return_if_fail (GTK_IS_WINDOW (window));
7720 is_active = is_active != FALSE;
7722 if (is_active != window->is_active)
7724 window->is_active = is_active;
7725 window_update_has_focus (window);
7727 g_object_notify (G_OBJECT (window), "is-active");
7732 * _gtk_window_set_has_toplevel_focus:
7733 * @window: a #GtkWindow
7734 * @has_toplevel_focus: %TRUE if the in
7736 * Internal function that sets whether the keyboard focus for the
7737 * toplevel window (taking into account inter-process embedding.)
7740 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
7741 gboolean has_toplevel_focus)
7743 g_return_if_fail (GTK_IS_WINDOW (window));
7745 has_toplevel_focus = has_toplevel_focus != FALSE;
7747 if (has_toplevel_focus != window->has_toplevel_focus)
7749 window->has_toplevel_focus = has_toplevel_focus;
7750 window_update_has_focus (window);
7752 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
7757 * gtk_window_set_auto_startup_notification:
7758 * @setting: %TRUE to automatically do startup notification
7760 * By default, after showing the first #GtkWindow, GTK+ calls
7761 * gdk_notify_startup_complete(). Call this function to disable
7762 * the automatic startup notification. You might do this if your
7763 * first window is a splash screen, and you want to delay notification
7764 * until after your real main window has been shown, for example.
7766 * In that example, you would disable startup notification
7767 * temporarily, show your splash screen, then re-enable it so that
7768 * showing the main window would automatically result in notification.
7773 gtk_window_set_auto_startup_notification (gboolean setting)
7775 disable_startup_notification = !setting;
7780 #undef gtk_window_set_icon_from_file
7783 gtk_window_set_icon_from_file (GtkWindow *window,
7784 const gchar *filename,
7787 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
7790 if (utf8_filename == NULL)
7793 retval = gtk_window_set_icon_from_file_utf8 (window, utf8_filename, err);
7795 g_free (utf8_filename);
7800 #undef gtk_window_set_default_icon_from_file
7803 gtk_window_set_default_icon_from_file (const gchar *filename,
7806 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
7809 if (utf8_filename == NULL)
7812 retval = gtk_window_set_default_icon_from_file_utf8 (utf8_filename, err);
7814 g_free (utf8_filename);
7821 #define __GTK_WINDOW_C__
7822 #include "gtkaliasdef.c"