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,
94 /* Readonly properties */
96 PROP_HAS_TOPLEVEL_FOCUS,
104 GdkPixmap *icon_pixmap;
105 GdkPixmap *icon_mask;
108 guint using_default_icon : 1;
109 guint using_parent_icon : 1;
110 guint using_themed_icon : 1;
114 GdkGeometry geometry; /* Last set of geometry hints we set */
115 GdkWindowHints flags;
116 GdkRectangle configure_request;
117 } GtkWindowLastGeometryInfo;
119 struct _GtkWindowGeometryInfo
121 /* Properties that the app has set on the window
123 GdkGeometry geometry; /* Geometry hints */
125 GtkWidget *widget; /* subwidget to which hints apply */
126 /* from last gtk_window_resize () - if > 0, indicates that
127 * we should resize to this size.
132 /* From last gtk_window_move () prior to mapping -
133 * only used if initial_pos_set
138 /* Default size - used only the FIRST time we map a window,
143 /* whether to use initial_x, initial_y */
144 guint initial_pos_set : 1;
145 /* CENTER_ALWAYS or other position constraint changed since
146 * we sent the last configure request.
148 guint position_constraints_changed : 1;
150 /* if true, default_width, height come from gtk_window_parse_geometry,
151 * and thus should be multiplied by the increments and affect the
152 * geometry widget only
154 guint default_is_geometry : 1;
156 GtkWindowLastGeometryInfo last;
159 #define GTK_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW, GtkWindowPrivate))
161 typedef struct _GtkWindowPrivate GtkWindowPrivate;
163 struct _GtkWindowPrivate
165 GtkMnemonicHash *mnemonic_hash;
167 guint above_initially : 1;
168 guint below_initially : 1;
169 guint fullscreen_initially : 1;
170 guint skips_taskbar : 1;
171 guint skips_pager : 1;
173 guint accept_focus : 1;
174 guint focus_on_map : 1;
176 guint transient_parent_group : 1;
178 guint reset_type_hint : 1;
179 GdkWindowTypeHint type_hint;
182 static void gtk_window_dispose (GObject *object);
183 static void gtk_window_destroy (GtkObject *object);
184 static void gtk_window_finalize (GObject *object);
185 static void gtk_window_show (GtkWidget *widget);
186 static void gtk_window_hide (GtkWidget *widget);
187 static void gtk_window_map (GtkWidget *widget);
188 static void gtk_window_unmap (GtkWidget *widget);
189 static void gtk_window_realize (GtkWidget *widget);
190 static void gtk_window_unrealize (GtkWidget *widget);
191 static void gtk_window_size_request (GtkWidget *widget,
192 GtkRequisition *requisition);
193 static void gtk_window_size_allocate (GtkWidget *widget,
194 GtkAllocation *allocation);
195 static gint gtk_window_event (GtkWidget *widget,
197 static gboolean gtk_window_map_event (GtkWidget *widget,
199 static gboolean gtk_window_frame_event (GtkWindow *window,
201 static gint gtk_window_configure_event (GtkWidget *widget,
202 GdkEventConfigure *event);
203 static gint gtk_window_key_press_event (GtkWidget *widget,
205 static gint gtk_window_key_release_event (GtkWidget *widget,
207 static gint gtk_window_enter_notify_event (GtkWidget *widget,
208 GdkEventCrossing *event);
209 static gint gtk_window_leave_notify_event (GtkWidget *widget,
210 GdkEventCrossing *event);
211 static gint gtk_window_focus_in_event (GtkWidget *widget,
212 GdkEventFocus *event);
213 static gint gtk_window_focus_out_event (GtkWidget *widget,
214 GdkEventFocus *event);
215 static gint gtk_window_client_event (GtkWidget *widget,
216 GdkEventClient *event);
217 static void gtk_window_check_resize (GtkContainer *container);
218 static gint gtk_window_focus (GtkWidget *widget,
219 GtkDirectionType direction);
220 static void gtk_window_real_set_focus (GtkWindow *window,
223 static void gtk_window_real_activate_default (GtkWindow *window);
224 static void gtk_window_real_activate_focus (GtkWindow *window);
225 static void gtk_window_move_focus (GtkWindow *window,
226 GtkDirectionType dir);
227 static void gtk_window_keys_changed (GtkWindow *window);
228 static void gtk_window_paint (GtkWidget *widget,
230 static gint gtk_window_expose (GtkWidget *widget,
231 GdkEventExpose *event);
232 static void gtk_window_unset_transient_for (GtkWindow *window);
233 static void gtk_window_transient_parent_realized (GtkWidget *parent,
235 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
238 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
240 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
243 static void gtk_window_move_resize (GtkWindow *window);
244 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
246 GdkGeometry *geometry_b,
248 static void gtk_window_constrain_size (GtkWindow *window,
249 GdkGeometry *geometry,
255 static void gtk_window_constrain_position (GtkWindow *window,
260 static void gtk_window_compute_hints (GtkWindow *window,
261 GdkGeometry *new_geometry,
263 static void gtk_window_compute_configure_request (GtkWindow *window,
264 GdkRectangle *request,
265 GdkGeometry *geometry,
268 static void gtk_window_set_default_size_internal (GtkWindow *window,
269 gboolean change_width,
271 gboolean change_height,
273 gboolean is_geometry);
275 static void update_themed_icon (GtkIconTheme *theme,
277 static GList *icon_list_from_theme (GtkWidget *widget,
279 static void gtk_window_realize_icon (GtkWindow *window);
280 static void gtk_window_unrealize_icon (GtkWindow *window);
282 static void gtk_window_notify_keys_changed (GtkWindow *window);
283 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
284 static void gtk_window_free_key_hash (GtkWindow *window);
285 static void gtk_window_on_composited_changed (GdkScreen *screen,
288 static GSList *toplevel_list = NULL;
289 static guint window_signals[LAST_SIGNAL] = { 0 };
290 static GList *default_icon_list = NULL;
291 static gchar *default_icon_name = NULL;
292 static guint default_icon_serial = 0;
293 static gboolean disable_startup_notification = FALSE;
294 static gboolean sent_startup_notification = FALSE;
296 static GQuark quark_gtk_embedded = 0;
297 static GQuark quark_gtk_window_key_hash = 0;
298 static GQuark quark_gtk_window_default_icon_pixmap = 0;
299 static GQuark quark_gtk_window_icon_info = 0;
301 static void gtk_window_set_property (GObject *object,
305 static void gtk_window_get_property (GObject *object,
311 G_DEFINE_TYPE (GtkWindow, gtk_window, GTK_TYPE_BIN)
314 add_tab_bindings (GtkBindingSet *binding_set,
315 GdkModifierType modifiers,
316 GtkDirectionType direction)
318 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
320 GTK_TYPE_DIRECTION_TYPE, direction);
321 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
323 GTK_TYPE_DIRECTION_TYPE, direction);
327 add_arrow_bindings (GtkBindingSet *binding_set,
329 GtkDirectionType direction)
331 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
333 gtk_binding_entry_add_signal (binding_set, keysym, 0,
335 GTK_TYPE_DIRECTION_TYPE, direction);
336 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
338 GTK_TYPE_DIRECTION_TYPE, direction);
339 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
341 GTK_TYPE_DIRECTION_TYPE, direction);
342 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
344 GTK_TYPE_DIRECTION_TYPE, direction);
349 gtk_window_class_init (GtkWindowClass *klass)
351 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
352 GtkObjectClass *object_class;
353 GtkWidgetClass *widget_class;
354 GtkContainerClass *container_class;
355 GtkBindingSet *binding_set;
357 object_class = (GtkObjectClass*) klass;
358 widget_class = (GtkWidgetClass*) klass;
359 container_class = (GtkContainerClass*) klass;
361 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
362 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
363 quark_gtk_window_default_icon_pixmap = g_quark_from_static_string ("gtk-window-default-icon-pixmap");
364 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
366 gobject_class->dispose = gtk_window_dispose;
367 gobject_class->finalize = gtk_window_finalize;
369 gobject_class->set_property = gtk_window_set_property;
370 gobject_class->get_property = gtk_window_get_property;
372 object_class->destroy = gtk_window_destroy;
374 widget_class->show = gtk_window_show;
375 widget_class->hide = gtk_window_hide;
376 widget_class->map = gtk_window_map;
377 widget_class->map_event = gtk_window_map_event;
378 widget_class->unmap = gtk_window_unmap;
379 widget_class->realize = gtk_window_realize;
380 widget_class->unrealize = gtk_window_unrealize;
381 widget_class->size_request = gtk_window_size_request;
382 widget_class->size_allocate = gtk_window_size_allocate;
383 widget_class->configure_event = gtk_window_configure_event;
384 widget_class->key_press_event = gtk_window_key_press_event;
385 widget_class->key_release_event = gtk_window_key_release_event;
386 widget_class->enter_notify_event = gtk_window_enter_notify_event;
387 widget_class->leave_notify_event = gtk_window_leave_notify_event;
388 widget_class->focus_in_event = gtk_window_focus_in_event;
389 widget_class->focus_out_event = gtk_window_focus_out_event;
390 widget_class->client_event = gtk_window_client_event;
391 widget_class->focus = gtk_window_focus;
393 widget_class->expose_event = gtk_window_expose;
395 container_class->check_resize = gtk_window_check_resize;
397 klass->set_focus = gtk_window_real_set_focus;
398 klass->frame_event = gtk_window_frame_event;
400 klass->activate_default = gtk_window_real_activate_default;
401 klass->activate_focus = gtk_window_real_activate_focus;
402 klass->move_focus = gtk_window_move_focus;
403 klass->keys_changed = gtk_window_keys_changed;
405 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
408 g_object_class_install_property (gobject_class,
410 g_param_spec_enum ("type",
412 P_("The type of the window"),
413 GTK_TYPE_WINDOW_TYPE,
415 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
417 g_object_class_install_property (gobject_class,
419 g_param_spec_string ("title",
421 P_("The title of the window"),
423 GTK_PARAM_READWRITE));
425 g_object_class_install_property (gobject_class,
427 g_param_spec_string ("role",
429 P_("Unique identifier for the window to be used when restoring a session"),
431 GTK_PARAM_READWRITE));
433 g_object_class_install_property (gobject_class,
435 g_param_spec_boolean ("allow-shrink",
437 /* xgettext:no-c-format */
438 P_("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
440 GTK_PARAM_READWRITE));
442 g_object_class_install_property (gobject_class,
444 g_param_spec_boolean ("allow-grow",
446 P_("If TRUE, users can expand the window beyond its minimum size"),
448 GTK_PARAM_READWRITE));
450 g_object_class_install_property (gobject_class,
452 g_param_spec_boolean ("resizable",
454 P_("If TRUE, users can resize the window"),
456 GTK_PARAM_READWRITE));
458 g_object_class_install_property (gobject_class,
460 g_param_spec_boolean ("modal",
462 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
464 GTK_PARAM_READWRITE));
466 g_object_class_install_property (gobject_class,
468 g_param_spec_enum ("window-position",
469 P_("Window Position"),
470 P_("The initial position of the window"),
471 GTK_TYPE_WINDOW_POSITION,
473 GTK_PARAM_READWRITE));
475 g_object_class_install_property (gobject_class,
477 g_param_spec_int ("default-width",
479 P_("The default width of the window, used when initially showing the window"),
483 GTK_PARAM_READWRITE));
485 g_object_class_install_property (gobject_class,
487 g_param_spec_int ("default-height",
488 P_("Default Height"),
489 P_("The default height of the window, used when initially showing the window"),
493 GTK_PARAM_READWRITE));
495 g_object_class_install_property (gobject_class,
496 PROP_DESTROY_WITH_PARENT,
497 g_param_spec_boolean ("destroy-with-parent",
498 P_("Destroy with Parent"),
499 P_("If this window should be destroyed when the parent is destroyed"),
501 GTK_PARAM_READWRITE));
503 g_object_class_install_property (gobject_class,
505 g_param_spec_object ("icon",
507 P_("Icon for this window"),
509 GTK_PARAM_READWRITE));
512 * GtkWindow:icon-name:
514 * The :icon-name property specifies the name of the themed icon to
515 * use as the window icon. See #GtkIconTheme for more details.
519 g_object_class_install_property (gobject_class,
521 g_param_spec_string ("icon-name",
523 P_("Name of the themed icon for this window"),
525 GTK_PARAM_READWRITE));
527 g_object_class_install_property (gobject_class,
529 g_param_spec_object ("screen",
531 P_("The screen where this window will be displayed"),
533 GTK_PARAM_READWRITE));
535 g_object_class_install_property (gobject_class,
537 g_param_spec_boolean ("is-active",
539 P_("Whether the toplevel is the current active window"),
541 GTK_PARAM_READABLE));
543 g_object_class_install_property (gobject_class,
544 PROP_HAS_TOPLEVEL_FOCUS,
545 g_param_spec_boolean ("has-toplevel-focus",
546 P_("Focus in Toplevel"),
547 P_("Whether the input focus is within this GtkWindow"),
549 GTK_PARAM_READABLE));
551 g_object_class_install_property (gobject_class,
553 g_param_spec_enum ("type-hint",
555 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
556 GDK_TYPE_WINDOW_TYPE_HINT,
557 GDK_WINDOW_TYPE_HINT_NORMAL,
558 GTK_PARAM_READWRITE));
560 g_object_class_install_property (gobject_class,
561 PROP_SKIP_TASKBAR_HINT,
562 g_param_spec_boolean ("skip-taskbar-hint",
564 P_("TRUE if the window should not be in the task bar."),
566 GTK_PARAM_READWRITE));
568 g_object_class_install_property (gobject_class,
569 PROP_SKIP_PAGER_HINT,
570 g_param_spec_boolean ("skip-pager-hint",
572 P_("TRUE if the window should not be in the pager."),
574 GTK_PARAM_READWRITE));
576 g_object_class_install_property (gobject_class,
578 g_param_spec_boolean ("urgency-hint",
580 P_("TRUE if the window should be brought to the user's attention."),
582 GTK_PARAM_READWRITE));
585 * GtkWindow:accept-focus-hint:
587 * Whether the window should receive the input focus.
591 g_object_class_install_property (gobject_class,
593 g_param_spec_boolean ("accept-focus",
595 P_("TRUE if the window should receive the input focus."),
597 GTK_PARAM_READWRITE));
600 * GtkWindow:focus-on-map-hint:
602 * Whether the window should receive the input focus when mapped.
606 g_object_class_install_property (gobject_class,
608 g_param_spec_boolean ("focus-on-map",
610 P_("TRUE if the window should receive the input focus when mapped."),
612 GTK_PARAM_READWRITE));
615 * GtkWindow:decorated:
617 * Whether the window should be decorated by the window manager.
621 g_object_class_install_property (gobject_class,
623 g_param_spec_boolean ("decorated",
625 P_("Whether the window should be decorated by the window manager"),
627 GTK_PARAM_READWRITE));
630 * GtkWindow:deletable:
632 * Whether the window frame should have a close button.
636 g_object_class_install_property (gobject_class,
638 g_param_spec_boolean ("deletable",
640 P_("Whether the window frame should have a close button"),
642 GTK_PARAM_READWRITE));
648 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
649 * more details about window gravity.
653 g_object_class_install_property (gobject_class,
655 g_param_spec_enum ("gravity",
657 P_("The window gravity of the window"),
659 GDK_GRAVITY_NORTH_WEST,
660 GTK_PARAM_READWRITE));
664 * GtkWindow:transient-for:
666 * The transient parent of the window. See gtk_window_set_transient_for() for
667 * more details about transient windows.
671 g_object_class_install_property (gobject_class,
673 g_param_spec_object ("transient-for",
674 P_("Transient for Window"),
675 P_("The transient parent of the dialog"),
677 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
679 window_signals[SET_FOCUS] =
680 g_signal_new (I_("set_focus"),
681 G_TYPE_FROM_CLASS (gobject_class),
683 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
685 _gtk_marshal_VOID__OBJECT,
689 window_signals[FRAME_EVENT] =
690 g_signal_new (I_("frame_event"),
691 G_TYPE_FROM_CLASS (gobject_class),
693 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
694 _gtk_boolean_handled_accumulator, NULL,
695 _gtk_marshal_BOOLEAN__BOXED,
699 window_signals[ACTIVATE_FOCUS] =
700 g_signal_new (I_("activate_focus"),
701 G_TYPE_FROM_CLASS (gobject_class),
702 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
703 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
705 _gtk_marshal_VOID__VOID,
709 window_signals[ACTIVATE_DEFAULT] =
710 g_signal_new (I_("activate_default"),
711 G_TYPE_FROM_CLASS (gobject_class),
712 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
713 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
715 _gtk_marshal_VOID__VOID,
719 window_signals[MOVE_FOCUS] =
720 g_signal_new (I_("move_focus"),
721 G_TYPE_FROM_CLASS (gobject_class),
722 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
723 G_STRUCT_OFFSET (GtkWindowClass, move_focus),
725 _gtk_marshal_VOID__ENUM,
728 GTK_TYPE_DIRECTION_TYPE);
730 window_signals[KEYS_CHANGED] =
731 g_signal_new (I_("keys_changed"),
732 G_TYPE_FROM_CLASS (gobject_class),
734 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
736 _gtk_marshal_VOID__VOID,
744 binding_set = gtk_binding_set_by_class (klass);
746 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
747 "activate_focus", 0);
748 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
749 "activate_focus", 0);
751 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
752 "activate_default", 0);
754 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
755 "activate_default", 0);
757 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
758 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
759 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
760 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
762 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
763 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
764 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
765 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
769 gtk_window_init (GtkWindow *window)
771 GdkColormap *colormap;
772 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
774 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
775 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
777 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
779 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
781 window->title = NULL;
782 window->wmclass_name = g_strdup (g_get_prgname ());
783 window->wmclass_class = g_strdup (gdk_get_program_class ());
784 window->wm_role = NULL;
785 window->geometry_info = NULL;
786 window->type = GTK_WINDOW_TOPLEVEL;
787 window->focus_widget = NULL;
788 window->default_widget = NULL;
789 window->configure_request_count = 0;
790 window->allow_shrink = FALSE;
791 window->allow_grow = TRUE;
792 window->configure_notify_received = FALSE;
793 window->position = GTK_WIN_POS_NONE;
794 window->need_default_size = TRUE;
795 window->need_default_position = TRUE;
796 window->modal = FALSE;
797 window->frame = NULL;
798 window->has_frame = FALSE;
799 window->frame_left = 0;
800 window->frame_right = 0;
801 window->frame_top = 0;
802 window->frame_bottom = 0;
803 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
804 window->gravity = GDK_GRAVITY_NORTH_WEST;
805 window->decorated = TRUE;
806 window->mnemonic_modifier = GDK_MOD1_MASK;
807 window->screen = gdk_screen_get_default ();
809 priv->accept_focus = TRUE;
810 priv->focus_on_map = TRUE;
811 priv->deletable = TRUE;
812 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
814 colormap = _gtk_widget_peek_colormap ();
816 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
818 g_object_ref_sink (window);
819 window->has_user_ref_count = TRUE;
820 toplevel_list = g_slist_prepend (toplevel_list, window);
822 gtk_decorated_window_init (window);
824 g_signal_connect (window->screen, "composited_changed",
825 G_CALLBACK (gtk_window_on_composited_changed), window);
829 gtk_window_set_property (GObject *object,
836 window = GTK_WINDOW (object);
841 window->type = g_value_get_enum (value);
844 gtk_window_set_title (window, g_value_get_string (value));
847 gtk_window_set_role (window, g_value_get_string (value));
849 case PROP_ALLOW_SHRINK:
850 window->allow_shrink = g_value_get_boolean (value);
851 gtk_widget_queue_resize (GTK_WIDGET (window));
853 case PROP_ALLOW_GROW:
854 window->allow_grow = g_value_get_boolean (value);
855 gtk_widget_queue_resize (GTK_WIDGET (window));
856 g_object_notify (G_OBJECT (window), "resizable");
859 window->allow_grow = g_value_get_boolean (value);
860 gtk_widget_queue_resize (GTK_WIDGET (window));
861 g_object_notify (G_OBJECT (window), "allow-grow");
864 gtk_window_set_modal (window, g_value_get_boolean (value));
867 gtk_window_set_position (window, g_value_get_enum (value));
869 case PROP_DEFAULT_WIDTH:
870 gtk_window_set_default_size_internal (window,
871 TRUE, g_value_get_int (value),
874 case PROP_DEFAULT_HEIGHT:
875 gtk_window_set_default_size_internal (window,
877 TRUE, g_value_get_int (value), FALSE);
879 case PROP_DESTROY_WITH_PARENT:
880 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
883 gtk_window_set_icon (window,
884 g_value_get_object (value));
887 gtk_window_set_icon_name (window, g_value_get_string (value));
890 gtk_window_set_screen (window, g_value_get_object (value));
893 gtk_window_set_type_hint (window,
894 g_value_get_enum (value));
896 case PROP_SKIP_TASKBAR_HINT:
897 gtk_window_set_skip_taskbar_hint (window,
898 g_value_get_boolean (value));
900 case PROP_SKIP_PAGER_HINT:
901 gtk_window_set_skip_pager_hint (window,
902 g_value_get_boolean (value));
904 case PROP_URGENCY_HINT:
905 gtk_window_set_urgency_hint (window,
906 g_value_get_boolean (value));
908 case PROP_ACCEPT_FOCUS:
909 gtk_window_set_accept_focus (window,
910 g_value_get_boolean (value));
912 case PROP_FOCUS_ON_MAP:
913 gtk_window_set_focus_on_map (window,
914 g_value_get_boolean (value));
917 gtk_window_set_decorated (window, g_value_get_boolean (value));
920 gtk_window_set_deletable (window, g_value_get_boolean (value));
923 gtk_window_set_gravity (window, g_value_get_enum (value));
925 case PROP_TRANSIENT_FOR:
926 gtk_window_set_transient_for (window, g_value_get_object (value));
934 gtk_window_get_property (GObject *object,
940 GtkWindowPrivate *priv;
942 window = GTK_WINDOW (object);
943 priv = GTK_WINDOW_GET_PRIVATE (window);
947 GtkWindowGeometryInfo *info;
949 g_value_set_enum (value, window->type);
952 g_value_set_string (value, window->wm_role);
955 g_value_set_string (value, window->title);
957 case PROP_ALLOW_SHRINK:
958 g_value_set_boolean (value, window->allow_shrink);
960 case PROP_ALLOW_GROW:
961 g_value_set_boolean (value, window->allow_grow);
964 g_value_set_boolean (value, window->allow_grow);
967 g_value_set_boolean (value, window->modal);
970 g_value_set_enum (value, window->position);
972 case PROP_DEFAULT_WIDTH:
973 info = gtk_window_get_geometry_info (window, FALSE);
975 g_value_set_int (value, -1);
977 g_value_set_int (value, info->default_width);
979 case PROP_DEFAULT_HEIGHT:
980 info = gtk_window_get_geometry_info (window, FALSE);
982 g_value_set_int (value, -1);
984 g_value_set_int (value, info->default_height);
986 case PROP_DESTROY_WITH_PARENT:
987 g_value_set_boolean (value, window->destroy_with_parent);
990 g_value_set_object (value, gtk_window_get_icon (window));
993 g_value_set_string (value, gtk_window_get_icon_name (window));
996 g_value_set_object (value, window->screen);
999 g_value_set_boolean (value, window->is_active);
1001 case PROP_HAS_TOPLEVEL_FOCUS:
1002 g_value_set_boolean (value, window->has_toplevel_focus);
1004 case PROP_TYPE_HINT:
1005 g_value_set_enum (value, priv->type_hint);
1007 case PROP_SKIP_TASKBAR_HINT:
1008 g_value_set_boolean (value,
1009 gtk_window_get_skip_taskbar_hint (window));
1011 case PROP_SKIP_PAGER_HINT:
1012 g_value_set_boolean (value,
1013 gtk_window_get_skip_pager_hint (window));
1015 case PROP_URGENCY_HINT:
1016 g_value_set_boolean (value,
1017 gtk_window_get_urgency_hint (window));
1019 case PROP_ACCEPT_FOCUS:
1020 g_value_set_boolean (value,
1021 gtk_window_get_accept_focus (window));
1023 case PROP_FOCUS_ON_MAP:
1024 g_value_set_boolean (value,
1025 gtk_window_get_focus_on_map (window));
1027 case PROP_DECORATED:
1028 g_value_set_boolean (value, gtk_window_get_decorated (window));
1030 case PROP_DELETABLE:
1031 g_value_set_boolean (value, gtk_window_get_deletable (window));
1034 g_value_set_enum (value, gtk_window_get_gravity (window));
1036 case PROP_TRANSIENT_FOR:
1037 g_value_set_object (value, gtk_window_get_transient_for (window));
1040 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1047 * @type: type of window
1049 * Creates a new #GtkWindow, which is a toplevel window that can
1050 * contain other widgets. Nearly always, the type of the window should
1051 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1052 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1053 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1054 * dialogs, though in some other toolkits dialogs are called "popups".
1055 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1056 * On X11, popup windows are not controlled by the <link
1057 * linkend="gtk-X11-arch">window manager</link>.
1059 * If you simply want an undecorated window (no window borders), use
1060 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1062 * Return value: a new #GtkWindow.
1065 gtk_window_new (GtkWindowType type)
1069 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1071 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1073 window->type = type;
1075 return GTK_WIDGET (window);
1079 * gtk_window_set_title:
1080 * @window: a #GtkWindow
1081 * @title: title of the window
1083 * Sets the title of the #GtkWindow. The title of a window will be
1084 * displayed in its title bar; on the X Window System, the title bar
1085 * is rendered by the <link linkend="gtk-X11-arch">window
1086 * manager</link>, so exactly how the title appears to users may vary
1087 * according to a user's exact configuration. The title should help a
1088 * user distinguish this window from other windows they may have
1089 * open. A good title might include the application name and current
1090 * document filename, for example.
1094 gtk_window_set_title (GtkWindow *window,
1099 g_return_if_fail (GTK_IS_WINDOW (window));
1101 new_title = g_strdup (title);
1102 g_free (window->title);
1103 window->title = new_title;
1105 if (GTK_WIDGET_REALIZED (window))
1107 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
1109 gtk_decorated_window_set_title (window, title);
1112 g_object_notify (G_OBJECT (window), "title");
1116 * gtk_window_get_title:
1117 * @window: a #GtkWindow
1119 * Retrieves the title of the window. See gtk_window_set_title().
1121 * Return value: the title of the window, or %NULL if none has
1122 * been set explicitely. The returned string is owned by the widget
1123 * and must not be modified or freed.
1125 G_CONST_RETURN gchar *
1126 gtk_window_get_title (GtkWindow *window)
1128 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1130 return window->title;
1134 * gtk_window_set_wmclass:
1135 * @window: a #GtkWindow
1136 * @wmclass_name: window name hint
1137 * @wmclass_class: window class hint
1139 * Don't use this function. It sets the X Window System "class" and
1140 * "name" hints for a window. According to the ICCCM, you should
1141 * always set these to the same value for all windows in an
1142 * application, and GTK+ sets them to that value by default, so calling
1143 * this function is sort of pointless. However, you may want to call
1144 * gtk_window_set_role() on each window in your application, for the
1145 * benefit of the session manager. Setting the role allows the window
1146 * manager to restore window positions when loading a saved session.
1150 gtk_window_set_wmclass (GtkWindow *window,
1151 const gchar *wmclass_name,
1152 const gchar *wmclass_class)
1154 g_return_if_fail (GTK_IS_WINDOW (window));
1156 g_free (window->wmclass_name);
1157 window->wmclass_name = g_strdup (wmclass_name);
1159 g_free (window->wmclass_class);
1160 window->wmclass_class = g_strdup (wmclass_class);
1162 if (GTK_WIDGET_REALIZED (window))
1163 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1167 * gtk_window_set_role:
1168 * @window: a #GtkWindow
1169 * @role: unique identifier for the window to be used when restoring a session
1171 * This function is only useful on X11, not with other GTK+ targets.
1173 * In combination with the window title, the window role allows a
1174 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1175 * same" window when an application is restarted. So for example you
1176 * might set the "toolbox" role on your app's toolbox window, so that
1177 * when the user restarts their session, the window manager can put
1178 * the toolbox back in the same place.
1180 * If a window already has a unique title, you don't need to set the
1181 * role, since the WM can use the title to identify the window when
1182 * restoring the session.
1186 gtk_window_set_role (GtkWindow *window,
1191 g_return_if_fail (GTK_IS_WINDOW (window));
1193 new_role = g_strdup (role);
1194 g_free (window->wm_role);
1195 window->wm_role = new_role;
1197 if (GTK_WIDGET_REALIZED (window))
1198 gdk_window_set_role (GTK_WIDGET (window)->window, window->wm_role);
1200 g_object_notify (G_OBJECT (window), "role");
1204 * gtk_window_get_role:
1205 * @window: a #GtkWindow
1207 * Returns the role of the window. See gtk_window_set_role() for
1208 * further explanation.
1210 * Return value: the role of the window if set, or %NULL. The
1211 * returned is owned by the widget and must not be modified
1214 G_CONST_RETURN gchar *
1215 gtk_window_get_role (GtkWindow *window)
1217 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1219 return window->wm_role;
1223 * gtk_window_set_focus:
1224 * @window: a #GtkWindow
1225 * @focus: widget to be the new focus widget, or %NULL to unset
1226 * any focus widget for the toplevel window.
1228 * If @focus is not the current focus widget, and is focusable, sets
1229 * it as the focus widget for the window. If @focus is %NULL, unsets
1230 * the focus widget for this window. To set the focus to a particular
1231 * widget in the toplevel, it is usually more convenient to use
1232 * gtk_widget_grab_focus() instead of this function.
1235 gtk_window_set_focus (GtkWindow *window,
1238 g_return_if_fail (GTK_IS_WINDOW (window));
1241 g_return_if_fail (GTK_IS_WIDGET (focus));
1242 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1246 gtk_widget_grab_focus (focus);
1249 /* Clear the existing focus chain, so that when we focus into
1250 * the window again, we start at the beginnning.
1252 GtkWidget *widget = window->focus_widget;
1255 while (widget->parent)
1257 widget = widget->parent;
1258 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1262 _gtk_window_internal_set_focus (window, NULL);
1267 _gtk_window_internal_set_focus (GtkWindow *window,
1270 g_return_if_fail (GTK_IS_WINDOW (window));
1272 if ((window->focus_widget != focus) ||
1273 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1274 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1278 * gtk_window_set_default:
1279 * @window: a #GtkWindow
1280 * @default_widget: widget to be the default, or %NULL to unset the
1281 * default widget for the toplevel.
1283 * The default widget is the widget that's activated when the user
1284 * presses Enter in a dialog (for example). This function sets or
1285 * unsets the default widget for a #GtkWindow about. When setting
1286 * (rather than unsetting) the default widget it's generally easier to
1287 * call gtk_widget_grab_focus() on the widget. Before making a widget
1288 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1289 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1292 gtk_window_set_default (GtkWindow *window,
1293 GtkWidget *default_widget)
1295 g_return_if_fail (GTK_IS_WINDOW (window));
1298 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1300 if (window->default_widget != default_widget)
1302 GtkWidget *old_default_widget = NULL;
1305 g_object_ref (default_widget);
1307 if (window->default_widget)
1309 old_default_widget = window->default_widget;
1311 if (window->focus_widget != window->default_widget ||
1312 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1313 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1314 gtk_widget_queue_draw (window->default_widget);
1317 window->default_widget = default_widget;
1319 if (window->default_widget)
1321 if (window->focus_widget == NULL ||
1322 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1323 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1324 gtk_widget_queue_draw (window->default_widget);
1327 if (old_default_widget)
1328 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1332 g_object_notify (G_OBJECT (default_widget), "has-default");
1333 g_object_unref (default_widget);
1339 gtk_window_set_policy (GtkWindow *window,
1340 gboolean allow_shrink,
1341 gboolean allow_grow,
1342 gboolean auto_shrink)
1344 g_return_if_fail (GTK_IS_WINDOW (window));
1346 window->allow_shrink = (allow_shrink != FALSE);
1347 window->allow_grow = (allow_grow != FALSE);
1349 g_object_freeze_notify (G_OBJECT (window));
1350 g_object_notify (G_OBJECT (window), "allow-shrink");
1351 g_object_notify (G_OBJECT (window), "allow-grow");
1352 g_object_notify (G_OBJECT (window), "resizable");
1353 g_object_thaw_notify (G_OBJECT (window));
1355 gtk_widget_queue_resize (GTK_WIDGET (window));
1359 handle_keys_changed (gpointer data)
1363 window = GTK_WINDOW (data);
1365 if (window->keys_changed_handler)
1367 g_source_remove (window->keys_changed_handler);
1368 window->keys_changed_handler = 0;
1371 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1377 gtk_window_notify_keys_changed (GtkWindow *window)
1379 if (!window->keys_changed_handler)
1380 window->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1384 * gtk_window_add_accel_group:
1385 * @window: window to attach accelerator group to
1386 * @accel_group: a #GtkAccelGroup
1388 * Associate @accel_group with @window, such that calling
1389 * gtk_accel_groups_activate() on @window will activate accelerators
1393 gtk_window_add_accel_group (GtkWindow *window,
1394 GtkAccelGroup *accel_group)
1396 g_return_if_fail (GTK_IS_WINDOW (window));
1397 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1399 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1400 g_signal_connect_object (accel_group, "accel_changed",
1401 G_CALLBACK (gtk_window_notify_keys_changed),
1402 window, G_CONNECT_SWAPPED);
1406 * gtk_window_remove_accel_group:
1407 * @window: a #GtkWindow
1408 * @accel_group: a #GtkAccelGroup
1410 * Reverses the effects of gtk_window_add_accel_group().
1413 gtk_window_remove_accel_group (GtkWindow *window,
1414 GtkAccelGroup *accel_group)
1416 g_return_if_fail (GTK_IS_WINDOW (window));
1417 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1419 g_signal_handlers_disconnect_by_func (accel_group,
1420 gtk_window_notify_keys_changed,
1422 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1425 static GtkMnemonicHash *
1426 gtk_window_get_mnemonic_hash (GtkWindow *window,
1429 GtkWindowPrivate *private = GTK_WINDOW_GET_PRIVATE (window);
1430 if (!private->mnemonic_hash && create)
1431 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1433 return private->mnemonic_hash;
1437 * gtk_window_add_mnemonic:
1438 * @window: a #GtkWindow
1439 * @keyval: the mnemonic
1440 * @target: the widget that gets activated by the mnemonic
1442 * Adds a mnemonic to this window.
1445 gtk_window_add_mnemonic (GtkWindow *window,
1449 g_return_if_fail (GTK_IS_WINDOW (window));
1450 g_return_if_fail (GTK_IS_WIDGET (target));
1452 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1454 gtk_window_notify_keys_changed (window);
1458 * gtk_window_remove_mnemonic:
1459 * @window: a #GtkWindow
1460 * @keyval: the mnemonic
1461 * @target: the widget that gets activated by the mnemonic
1463 * Removes a mnemonic from this window.
1466 gtk_window_remove_mnemonic (GtkWindow *window,
1470 g_return_if_fail (GTK_IS_WINDOW (window));
1471 g_return_if_fail (GTK_IS_WIDGET (target));
1473 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
1475 gtk_window_notify_keys_changed (window);
1479 * gtk_window_mnemonic_activate:
1480 * @window: a #GtkWindow
1481 * @keyval: the mnemonic
1482 * @modifier: the modifiers
1483 * @returns: %TRUE if the activation is done.
1485 * Activates the targets associated with the mnemonic.
1488 gtk_window_mnemonic_activate (GtkWindow *window,
1490 GdkModifierType modifier)
1492 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1494 if (window->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
1496 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
1498 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
1505 * gtk_window_set_mnemonic_modifier:
1506 * @window: a #GtkWindow
1507 * @modifier: the modifier mask used to activate
1508 * mnemonics on this window.
1510 * Sets the mnemonic modifier for this window.
1513 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1514 GdkModifierType modifier)
1516 g_return_if_fail (GTK_IS_WINDOW (window));
1517 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1519 window->mnemonic_modifier = modifier;
1520 gtk_window_notify_keys_changed (window);
1524 * gtk_window_get_mnemonic_modifier:
1525 * @window: a #GtkWindow
1527 * Returns the mnemonic modifier for this window. See
1528 * gtk_window_set_mnemonic_modifier().
1530 * Return value: the modifier mask used to activate
1531 * mnemonics on this window.
1534 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1536 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1538 return window->mnemonic_modifier;
1542 * gtk_window_set_position:
1543 * @window: a #GtkWindow.
1544 * @position: a position constraint.
1546 * Sets a position constraint for this window. If the old or new
1547 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1548 * the window to be repositioned to satisfy the new constraint.
1551 gtk_window_set_position (GtkWindow *window,
1552 GtkWindowPosition position)
1554 g_return_if_fail (GTK_IS_WINDOW (window));
1556 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1557 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1559 GtkWindowGeometryInfo *info;
1561 info = gtk_window_get_geometry_info (window, TRUE);
1563 /* this flag causes us to re-request the CENTER_ALWAYS
1564 * constraint in gtk_window_move_resize(), see
1565 * comment in that function.
1567 info->position_constraints_changed = TRUE;
1569 gtk_widget_queue_resize (GTK_WIDGET (window));
1572 window->position = position;
1574 g_object_notify (G_OBJECT (window), "window-position");
1578 * gtk_window_activate_focus:
1579 * @window: a #GtkWindow
1581 * Activates the current focused widget within the window.
1583 * Return value: %TRUE if a widget got activated.
1586 gtk_window_activate_focus (GtkWindow *window)
1588 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1590 if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1591 return gtk_widget_activate (window->focus_widget);
1597 * gtk_window_get_focus:
1598 * @window: a #GtkWindow
1600 * Retrieves the current focused widget within the window.
1601 * Note that this is the widget that would have the focus
1602 * if the toplevel window focused; if the toplevel window
1603 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1604 * not be %TRUE for the widget.
1606 * Return value: the currently focused widget, or %NULL if there is none.
1609 gtk_window_get_focus (GtkWindow *window)
1611 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1613 return window->focus_widget;
1617 * gtk_window_activate_default:
1618 * @window: a #GtkWindow
1620 * Activates the default widget for the window, unless the current
1621 * focused widget has been configured to receive the default action
1622 * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
1623 * focused widget is activated.
1625 * Return value: %TRUE if a widget got activated.
1628 gtk_window_activate_default (GtkWindow *window)
1630 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1632 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1633 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1634 return gtk_widget_activate (window->default_widget);
1635 else if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1636 return gtk_widget_activate (window->focus_widget);
1642 * gtk_window_set_modal:
1643 * @window: a #GtkWindow
1644 * @modal: whether the window is modal
1646 * Sets a window modal or non-modal. Modal windows prevent interaction
1647 * with other windows in the same application. To keep modal dialogs
1648 * on top of main application windows, use
1649 * gtk_window_set_transient_for() to make the dialog transient for the
1650 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1651 * will then disallow lowering the dialog below the parent.
1656 gtk_window_set_modal (GtkWindow *window,
1659 g_return_if_fail (GTK_IS_WINDOW (window));
1661 modal = modal != FALSE;
1662 if (window->modal == modal)
1665 window->modal = modal;
1667 /* adjust desired modality state */
1668 if (GTK_WIDGET_REALIZED (window))
1670 GtkWidget *widget = GTK_WIDGET (window);
1673 gdk_window_set_modal_hint (widget->window, TRUE);
1675 gdk_window_set_modal_hint (widget->window, FALSE);
1678 if (GTK_WIDGET_VISIBLE (window))
1681 gtk_grab_add (GTK_WIDGET (window));
1683 gtk_grab_remove (GTK_WIDGET (window));
1686 g_object_notify (G_OBJECT (window), "modal");
1690 * gtk_window_get_modal:
1691 * @window: a #GtkWindow
1693 * Returns whether the window is modal. See gtk_window_set_modal().
1695 * Return value: %TRUE if the window is set to be modal and
1696 * establishes a grab when shown
1699 gtk_window_get_modal (GtkWindow *window)
1701 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1703 return window->modal;
1707 * gtk_window_list_toplevels:
1709 * Returns a list of all existing toplevel windows. The widgets
1710 * in the list are not individually referenced. If you want
1711 * to iterate through the list and perform actions involving
1712 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1713 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1714 * then unref all the widgets afterwards.
1716 * Return value: list of toplevel widgets
1719 gtk_window_list_toplevels (void)
1724 for (slist = toplevel_list; slist; slist = slist->next)
1725 list = g_list_prepend (list, slist->data);
1731 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1733 GList *embedded_windows;
1735 g_return_if_fail (GTK_IS_WINDOW (window));
1737 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
1738 if (embedded_windows)
1739 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
1740 embedded_windows = g_list_prepend (embedded_windows,
1741 GUINT_TO_POINTER (xid));
1743 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
1746 (GDestroyNotify) g_list_free : NULL);
1750 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1752 GList *embedded_windows;
1755 g_return_if_fail (GTK_IS_WINDOW (window));
1757 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
1758 if (embedded_windows)
1759 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
1761 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1764 embedded_windows = g_list_remove_link (embedded_windows, node);
1765 g_list_free_1 (node);
1768 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
1771 (GDestroyNotify) g_list_free : NULL);
1775 _gtk_window_reposition (GtkWindow *window,
1779 g_return_if_fail (GTK_IS_WINDOW (window));
1781 gtk_window_move (window, x, y);
1785 gtk_window_dispose (GObject *object)
1787 GtkWindow *window = GTK_WINDOW (object);
1789 gtk_window_set_focus (window, NULL);
1790 gtk_window_set_default (window, NULL);
1792 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
1796 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1798 gtk_widget_destroy (GTK_WIDGET (child));
1802 connect_parent_destroyed (GtkWindow *window)
1804 if (window->transient_parent)
1806 g_signal_connect (window->transient_parent,
1808 G_CALLBACK (parent_destroyed_callback),
1814 disconnect_parent_destroyed (GtkWindow *window)
1816 if (window->transient_parent)
1818 g_signal_handlers_disconnect_by_func (window->transient_parent,
1819 parent_destroyed_callback,
1825 gtk_window_transient_parent_realized (GtkWidget *parent,
1828 if (GTK_WIDGET_REALIZED (window))
1829 gdk_window_set_transient_for (window->window, parent->window);
1833 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1836 if (GTK_WIDGET_REALIZED (window))
1837 gdk_property_delete (window->window,
1838 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
1842 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
1846 gtk_window_set_screen (window, parent->screen);
1850 gtk_window_unset_transient_for (GtkWindow *window)
1852 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
1854 if (window->transient_parent)
1856 if (priv->transient_parent_group)
1857 gtk_window_group_remove_window (window->group,
1860 g_signal_handlers_disconnect_by_func (window->transient_parent,
1861 gtk_window_transient_parent_realized,
1863 g_signal_handlers_disconnect_by_func (window->transient_parent,
1864 gtk_window_transient_parent_unrealized,
1866 g_signal_handlers_disconnect_by_func (window->transient_parent,
1867 gtk_window_transient_parent_screen_changed,
1869 g_signal_handlers_disconnect_by_func (window->transient_parent,
1870 gtk_widget_destroyed,
1871 &window->transient_parent);
1873 if (window->destroy_with_parent)
1874 disconnect_parent_destroyed (window);
1876 window->transient_parent = NULL;
1877 priv->transient_parent_group = FALSE;
1882 * gtk_window_set_transient_for:
1883 * @window: a #GtkWindow
1884 * @parent: parent window
1886 * Dialog windows should be set transient for the main application
1887 * window they were spawned from. This allows <link
1888 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1889 * dialog on top of the main window, or center the dialog over the
1890 * main window. gtk_dialog_new_with_buttons() and other convenience
1891 * functions in GTK+ will sometimes call
1892 * gtk_window_set_transient_for() on your behalf.
1894 * On Windows, this function will and put the child window
1895 * on top of the parent, much as the window manager would have
1900 gtk_window_set_transient_for (GtkWindow *window,
1903 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
1905 g_return_if_fail (GTK_IS_WINDOW (window));
1906 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1907 g_return_if_fail (window != parent);
1909 if (window->transient_parent)
1911 if (GTK_WIDGET_REALIZED (window) &&
1912 GTK_WIDGET_REALIZED (window->transient_parent) &&
1913 (!parent || !GTK_WIDGET_REALIZED (parent)))
1914 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1915 GTK_WIDGET (window));
1917 gtk_window_unset_transient_for (window);
1920 window->transient_parent = parent;
1924 g_signal_connect (parent, "destroy",
1925 G_CALLBACK (gtk_widget_destroyed),
1926 &window->transient_parent);
1927 g_signal_connect (parent, "realize",
1928 G_CALLBACK (gtk_window_transient_parent_realized),
1930 g_signal_connect (parent, "unrealize",
1931 G_CALLBACK (gtk_window_transient_parent_unrealized),
1933 g_signal_connect (parent, "notify::screen",
1934 G_CALLBACK (gtk_window_transient_parent_screen_changed),
1937 gtk_window_set_screen (window, parent->screen);
1939 if (window->destroy_with_parent)
1940 connect_parent_destroyed (window);
1942 if (GTK_WIDGET_REALIZED (window) &&
1943 GTK_WIDGET_REALIZED (parent))
1944 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1945 GTK_WIDGET (window));
1949 gtk_window_group_add_window (parent->group, window);
1950 priv->transient_parent_group = TRUE;
1956 * gtk_window_get_transient_for:
1957 * @window: a #GtkWindow
1959 * Fetches the transient parent for this window. See
1960 * gtk_window_set_transient_for().
1962 * Return value: the transient parent for this window, or %NULL
1963 * if no transient parent has been set.
1966 gtk_window_get_transient_for (GtkWindow *window)
1968 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1970 return window->transient_parent;
1974 * gtk_window_set_type_hint:
1975 * @window: a #GtkWindow
1976 * @hint: the window type
1978 * By setting the type hint for the window, you allow the window
1979 * manager to decorate and handle the window in a way which is
1980 * suitable to the function of the window in your application.
1982 * This function should be called before the window becomes visible.
1984 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1985 * will sometimes call gtk_window_set_type_hint() on your behalf.
1989 gtk_window_set_type_hint (GtkWindow *window,
1990 GdkWindowTypeHint hint)
1992 GtkWindowPrivate *priv;
1994 g_return_if_fail (GTK_IS_WINDOW (window));
1995 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1997 priv = GTK_WINDOW_GET_PRIVATE (window);
1999 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2000 window->type_hint = hint;
2002 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2004 priv->reset_type_hint = TRUE;
2005 priv->type_hint = hint;
2009 * gtk_window_get_type_hint:
2010 * @window: a #GtkWindow
2012 * Gets the type hint for this window. See gtk_window_set_type_hint().
2014 * Return value: the type hint for @window.
2017 gtk_window_get_type_hint (GtkWindow *window)
2019 GtkWindowPrivate *priv;
2021 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2023 priv = GTK_WINDOW_GET_PRIVATE (window);
2025 return priv->type_hint;
2029 * gtk_window_set_skip_taskbar_hint:
2030 * @window: a #GtkWindow
2031 * @setting: %TRUE to keep this window from appearing in the task bar
2033 * Windows may set a hint asking the desktop environment not to display
2034 * the window in the task bar. This function sets this hint.
2039 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2042 GtkWindowPrivate *priv;
2044 g_return_if_fail (GTK_IS_WINDOW (window));
2046 priv = GTK_WINDOW_GET_PRIVATE (window);
2048 setting = setting != FALSE;
2050 if (priv->skips_taskbar != setting)
2052 priv->skips_taskbar = setting;
2053 if (GTK_WIDGET_REALIZED (window))
2054 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
2055 priv->skips_taskbar);
2056 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2061 * gtk_window_get_skip_taskbar_hint:
2062 * @window: a #GtkWindow
2064 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2066 * Return value: %TRUE if window shouldn't be in taskbar
2071 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2073 GtkWindowPrivate *priv;
2075 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2077 priv = GTK_WINDOW_GET_PRIVATE (window);
2079 return priv->skips_taskbar;
2083 * gtk_window_set_skip_pager_hint:
2084 * @window: a #GtkWindow
2085 * @setting: %TRUE to keep this window from appearing in the pager
2087 * Windows may set a hint asking the desktop environment not to display
2088 * the window in the pager. This function sets this hint.
2089 * (A "pager" is any desktop navigation tool such as a workspace
2090 * switcher that displays a thumbnail representation of the windows
2096 gtk_window_set_skip_pager_hint (GtkWindow *window,
2099 GtkWindowPrivate *priv;
2101 g_return_if_fail (GTK_IS_WINDOW (window));
2103 priv = GTK_WINDOW_GET_PRIVATE (window);
2105 setting = setting != FALSE;
2107 if (priv->skips_pager != setting)
2109 priv->skips_pager = setting;
2110 if (GTK_WIDGET_REALIZED (window))
2111 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2113 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2118 * gtk_window_get_skip_pager_hint:
2119 * @window: a #GtkWindow
2121 * Gets the value set by gtk_window_set_skip_pager_hint().
2123 * Return value: %TRUE if window shouldn't be in pager
2128 gtk_window_get_skip_pager_hint (GtkWindow *window)
2130 GtkWindowPrivate *priv;
2132 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2134 priv = GTK_WINDOW_GET_PRIVATE (window);
2136 return priv->skips_pager;
2140 * gtk_window_set_urgency_hint:
2141 * @window: a #GtkWindow
2142 * @setting: %TRUE to mark this window as urgent
2144 * Windows may set a hint asking the desktop environment to draw
2145 * the users attention to the window. This function sets this hint.
2150 gtk_window_set_urgency_hint (GtkWindow *window,
2153 GtkWindowPrivate *priv;
2155 g_return_if_fail (GTK_IS_WINDOW (window));
2157 priv = GTK_WINDOW_GET_PRIVATE (window);
2159 setting = setting != FALSE;
2161 if (priv->urgent != setting)
2163 priv->urgent = setting;
2164 if (GTK_WIDGET_REALIZED (window))
2165 gdk_window_set_urgency_hint (GTK_WIDGET (window)->window,
2167 g_object_notify (G_OBJECT (window), "urgency-hint");
2172 * gtk_window_get_urgency_hint:
2173 * @window: a #GtkWindow
2175 * Gets the value set by gtk_window_set_urgency_hint()
2177 * Return value: %TRUE if window is urgent
2182 gtk_window_get_urgency_hint (GtkWindow *window)
2184 GtkWindowPrivate *priv;
2186 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2188 priv = GTK_WINDOW_GET_PRIVATE (window);
2190 return priv->urgent;
2194 * gtk_window_set_accept_focus:
2195 * @window: a #GtkWindow
2196 * @setting: %TRUE to let this window receive input focus
2198 * Windows may set a hint asking the desktop environment not to receive
2199 * the input focus. This function sets this hint.
2204 gtk_window_set_accept_focus (GtkWindow *window,
2207 GtkWindowPrivate *priv;
2209 g_return_if_fail (GTK_IS_WINDOW (window));
2211 priv = GTK_WINDOW_GET_PRIVATE (window);
2213 setting = setting != FALSE;
2215 if (priv->accept_focus != setting)
2217 priv->accept_focus = setting;
2218 if (GTK_WIDGET_REALIZED (window))
2219 gdk_window_set_accept_focus (GTK_WIDGET (window)->window,
2220 priv->accept_focus);
2221 g_object_notify (G_OBJECT (window), "accept-focus");
2226 * gtk_window_get_accept_focus:
2227 * @window: a #GtkWindow
2229 * Gets the value set by gtk_window_set_accept_focus().
2231 * Return value: %TRUE if window should receive the input focus
2236 gtk_window_get_accept_focus (GtkWindow *window)
2238 GtkWindowPrivate *priv;
2240 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2242 priv = GTK_WINDOW_GET_PRIVATE (window);
2244 return priv->accept_focus;
2248 * gtk_window_set_focus_on_map:
2249 * @window: a #GtkWindow
2250 * @setting: %TRUE to let this window receive input focus on map
2252 * Windows may set a hint asking the desktop environment not to receive
2253 * the input focus when the window is mapped. This function sets this
2259 gtk_window_set_focus_on_map (GtkWindow *window,
2262 GtkWindowPrivate *priv;
2264 g_return_if_fail (GTK_IS_WINDOW (window));
2266 priv = GTK_WINDOW_GET_PRIVATE (window);
2268 setting = setting != FALSE;
2270 if (priv->focus_on_map != setting)
2272 priv->focus_on_map = setting;
2273 if (GTK_WIDGET_REALIZED (window))
2274 gdk_window_set_focus_on_map (GTK_WIDGET (window)->window,
2275 priv->focus_on_map);
2276 g_object_notify (G_OBJECT (window), "focus-on-map");
2281 * gtk_window_get_focus_on_map:
2282 * @window: a #GtkWindow
2284 * Gets the value set by gtk_window_set_focus_on_map().
2286 * Return value: %TRUE if window should receive the input focus when
2292 gtk_window_get_focus_on_map (GtkWindow *window)
2294 GtkWindowPrivate *priv;
2296 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2298 priv = GTK_WINDOW_GET_PRIVATE (window);
2300 return priv->focus_on_map;
2304 * gtk_window_set_destroy_with_parent:
2305 * @window: a #GtkWindow
2306 * @setting: whether to destroy @window with its transient parent
2308 * If @setting is %TRUE, then destroying the transient parent of @window
2309 * will also destroy @window itself. This is useful for dialogs that
2310 * shouldn't persist beyond the lifetime of the main window they're
2311 * associated with, for example.
2314 gtk_window_set_destroy_with_parent (GtkWindow *window,
2317 g_return_if_fail (GTK_IS_WINDOW (window));
2319 if (window->destroy_with_parent == (setting != FALSE))
2322 if (window->destroy_with_parent)
2324 disconnect_parent_destroyed (window);
2328 connect_parent_destroyed (window);
2331 window->destroy_with_parent = setting;
2333 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2337 * gtk_window_get_destroy_with_parent:
2338 * @window: a #GtkWindow
2340 * Returns whether the window will be destroyed with its transient parent. See
2341 * gtk_window_set_destroy_with_parent ().
2343 * Return value: %TRUE if the window will be destroyed with its transient parent.
2346 gtk_window_get_destroy_with_parent (GtkWindow *window)
2348 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2350 return window->destroy_with_parent;
2353 static GtkWindowGeometryInfo*
2354 gtk_window_get_geometry_info (GtkWindow *window,
2357 GtkWindowGeometryInfo *info;
2359 info = window->geometry_info;
2360 if (!info && create)
2362 info = g_new0 (GtkWindowGeometryInfo, 1);
2364 info->default_width = -1;
2365 info->default_height = -1;
2366 info->resize_width = -1;
2367 info->resize_height = -1;
2368 info->initial_x = 0;
2369 info->initial_y = 0;
2370 info->initial_pos_set = FALSE;
2371 info->default_is_geometry = FALSE;
2372 info->position_constraints_changed = FALSE;
2373 info->last.configure_request.x = 0;
2374 info->last.configure_request.y = 0;
2375 info->last.configure_request.width = -1;
2376 info->last.configure_request.height = -1;
2377 info->widget = NULL;
2379 window->geometry_info = info;
2386 * gtk_window_set_geometry_hints:
2387 * @window: a #GtkWindow
2388 * @geometry_widget: widget the geometry hints will be applied to
2389 * @geometry: struct containing geometry information
2390 * @geom_mask: mask indicating which struct fields should be paid attention to
2392 * This function sets up hints about how a window can be resized by
2393 * the user. You can set a minimum and maximum size; allowed resize
2394 * increments (e.g. for xterm, you can only resize by the size of a
2395 * character); aspect ratios; and more. See the #GdkGeometry struct.
2399 gtk_window_set_geometry_hints (GtkWindow *window,
2400 GtkWidget *geometry_widget,
2401 GdkGeometry *geometry,
2402 GdkWindowHints geom_mask)
2404 GtkWindowGeometryInfo *info;
2406 g_return_if_fail (GTK_IS_WINDOW (window));
2407 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2409 info = gtk_window_get_geometry_info (window, TRUE);
2412 g_signal_handlers_disconnect_by_func (info->widget,
2413 gtk_widget_destroyed,
2416 info->widget = geometry_widget;
2418 g_signal_connect (geometry_widget, "destroy",
2419 G_CALLBACK (gtk_widget_destroyed),
2423 info->geometry = *geometry;
2425 /* We store gravity in window->gravity not in the hints. */
2426 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2428 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2430 gtk_window_set_gravity (window, geometry->win_gravity);
2433 gtk_widget_queue_resize (GTK_WIDGET (window));
2437 * gtk_window_set_decorated:
2438 * @window: a #GtkWindow
2439 * @setting: %TRUE to decorate the window
2441 * By default, windows are decorated with a title bar, resize
2442 * controls, etc. Some <link linkend="gtk-X11-arch">window
2443 * managers</link> allow GTK+ to disable these decorations, creating a
2444 * borderless window. If you set the decorated property to %FALSE
2445 * using this function, GTK+ will do its best to convince the window
2446 * manager not to decorate the window. Depending on the system, this
2447 * function may not have any effect when called on a window that is
2448 * already visible, so you should call it before calling gtk_window_show().
2450 * On Windows, this function always works, since there's no window manager
2455 gtk_window_set_decorated (GtkWindow *window,
2458 g_return_if_fail (GTK_IS_WINDOW (window));
2460 setting = setting != FALSE;
2462 if (setting == window->decorated)
2465 window->decorated = setting;
2467 if (GTK_WIDGET (window)->window)
2469 if (window->decorated)
2470 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2473 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2477 g_object_notify (G_OBJECT (window), "decorated");
2481 * gtk_window_get_decorated:
2482 * @window: a #GtkWindow
2484 * Returns whether the window has been set to have decorations
2485 * such as a title bar via gtk_window_set_decorated().
2487 * Return value: %TRUE if the window has been set to have decorations
2490 gtk_window_get_decorated (GtkWindow *window)
2492 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2494 return window->decorated;
2498 * gtk_window_set_deletable:
2499 * @window: a #GtkWindow
2500 * @setting: %TRUE to decorate the window as deletable
2502 * By default, windows have a close button in the window frame. Some
2503 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
2504 * disable this button. If you set the deletable property to %FALSE
2505 * using this function, GTK+ will do its best to convince the window
2506 * manager not to show a close button. Depending on the system, this
2507 * function may not have any effect when called on a window that is
2508 * already visible, so you should call it before calling gtk_window_show().
2510 * On Windows, this function always works, since there's no window manager
2516 gtk_window_set_deletable (GtkWindow *window,
2519 GtkWindowPrivate *priv;
2521 g_return_if_fail (GTK_IS_WINDOW (window));
2523 priv = GTK_WINDOW_GET_PRIVATE (window);
2525 setting = setting != FALSE;
2527 if (setting == priv->deletable)
2530 priv->deletable = setting;
2532 if (GTK_WIDGET (window)->window)
2534 if (priv->deletable)
2535 gdk_window_set_functions (GTK_WIDGET (window)->window,
2538 gdk_window_set_functions (GTK_WIDGET (window)->window,
2539 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
2542 g_object_notify (G_OBJECT (window), "deletable");
2546 * gtk_window_get_deletable:
2547 * @window: a #GtkWindow
2549 * Returns whether the window has been set to have a close button
2550 * via gtk_window_set_deletable().
2552 * Return value: %TRUE if the window has been set to have a close button
2557 gtk_window_get_deletable (GtkWindow *window)
2559 GtkWindowPrivate *priv;
2561 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2563 priv = GTK_WINDOW_GET_PRIVATE (window);
2565 return priv->deletable;
2568 static GtkWindowIconInfo*
2569 get_icon_info (GtkWindow *window)
2571 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
2575 free_icon_info (GtkWindowIconInfo *info)
2577 g_free (info->icon_name);
2578 g_slice_free (GtkWindowIconInfo, info);
2582 static GtkWindowIconInfo*
2583 ensure_icon_info (GtkWindow *window)
2585 GtkWindowIconInfo *info;
2587 info = get_icon_info (window);
2591 info = g_slice_new0 (GtkWindowIconInfo);
2592 g_object_set_qdata_full (G_OBJECT (window),
2593 quark_gtk_window_icon_info,
2595 (GDestroyNotify)free_icon_info);
2607 static ScreenIconInfo *
2608 get_screen_icon_info (GdkScreen *screen)
2610 ScreenIconInfo *info = g_object_get_qdata (G_OBJECT (screen),
2611 quark_gtk_window_default_icon_pixmap);
2614 info = g_slice_new0 (ScreenIconInfo);
2615 g_object_set_qdata (G_OBJECT (screen),
2616 quark_gtk_window_default_icon_pixmap, info);
2619 if (info->serial != default_icon_serial)
2623 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2624 info->pixmap = NULL;
2629 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2633 info->serial = default_icon_serial;
2640 get_pixmap_and_mask (GdkWindow *window,
2641 GtkWindowIconInfo *parent_info,
2642 gboolean is_default_list,
2644 GdkPixmap **pmap_return,
2645 GdkBitmap **mask_return)
2647 GdkScreen *screen = gdk_drawable_get_screen (window);
2648 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2649 GdkPixbuf *best_icon;
2653 *pmap_return = NULL;
2654 *mask_return = NULL;
2656 if (is_default_list &&
2657 default_icon_info->pixmap != NULL)
2659 /* Use shared icon pixmap for all windows on this screen.
2661 if (default_icon_info->pixmap)
2662 g_object_ref (default_icon_info->pixmap);
2663 if (default_icon_info->mask)
2664 g_object_ref (default_icon_info->mask);
2666 *pmap_return = default_icon_info->pixmap;
2667 *mask_return = default_icon_info->mask;
2669 else if (parent_info && parent_info->icon_pixmap)
2671 if (parent_info->icon_pixmap)
2672 g_object_ref (parent_info->icon_pixmap);
2673 if (parent_info->icon_mask)
2674 g_object_ref (parent_info->icon_mask);
2676 *pmap_return = parent_info->icon_pixmap;
2677 *mask_return = parent_info->icon_mask;
2681 #define IDEAL_SIZE 48
2683 best_size = G_MAXINT;
2685 tmp_list = icon_list;
2686 while (tmp_list != NULL)
2688 GdkPixbuf *pixbuf = tmp_list->data;
2691 /* average width and height - if someone passes in a rectangular
2692 * icon they deserve what they get.
2694 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2697 if (best_icon == NULL)
2704 /* icon is better if it's 32 pixels or larger, and closer to
2705 * the ideal size than the current best.
2708 (ABS (best_size - IDEAL_SIZE) <
2709 ABS (this - IDEAL_SIZE)))
2716 tmp_list = tmp_list->next;
2720 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2721 gdk_screen_get_system_colormap (screen),
2726 /* Save pmap/mask for others to use if appropriate */
2729 parent_info->icon_pixmap = *pmap_return;
2730 parent_info->icon_mask = *mask_return;
2732 if (parent_info->icon_pixmap)
2733 g_object_ref (parent_info->icon_pixmap);
2734 if (parent_info->icon_mask)
2735 g_object_ref (parent_info->icon_mask);
2737 else if (is_default_list)
2739 default_icon_info->pixmap = *pmap_return;
2740 default_icon_info->mask = *mask_return;
2742 if (default_icon_info->pixmap)
2743 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2744 (gpointer*)&default_icon_info->pixmap);
2745 if (default_icon_info->mask)
2746 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2747 (gpointer*)&default_icon_info->mask);
2753 icon_list_from_theme (GtkWidget *widget,
2758 GtkIconTheme *icon_theme;
2763 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
2765 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
2768 for (i = 0; sizes[i]; i++)
2771 * We need an EWMH extension to handle scalable icons
2772 * by passing their name to the WM. For now just use a
2776 icon = gtk_icon_theme_load_icon (icon_theme, name,
2779 icon = gtk_icon_theme_load_icon (icon_theme, name,
2782 list = g_list_append (list, icon);
2792 gtk_window_realize_icon (GtkWindow *window)
2795 GtkWindowIconInfo *info;
2798 widget = GTK_WIDGET (window);
2800 g_return_if_fail (widget->window != NULL);
2802 /* no point setting an icon on override-redirect */
2803 if (window->type == GTK_WINDOW_POPUP)
2808 info = ensure_icon_info (window);
2813 g_return_if_fail (info->icon_pixmap == NULL);
2814 g_return_if_fail (info->icon_mask == NULL);
2816 info->using_default_icon = FALSE;
2817 info->using_parent_icon = FALSE;
2818 info->using_themed_icon = FALSE;
2820 icon_list = info->icon_list;
2822 /* Look up themed icon */
2823 if (icon_list == NULL && info->icon_name)
2825 icon_list = icon_list_from_theme (widget, info->icon_name);
2827 info->using_themed_icon = TRUE;
2830 /* Inherit from transient parent */
2831 if (icon_list == NULL && window->transient_parent)
2833 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2835 info->using_parent_icon = TRUE;
2838 /* Inherit from default */
2839 if (icon_list == NULL)
2841 icon_list = default_icon_list;
2843 info->using_default_icon = TRUE;
2846 /* Look up themed icon */
2847 if (icon_list == NULL && default_icon_name)
2849 icon_list = icon_list_from_theme (widget, default_icon_name);
2850 info->using_default_icon = TRUE;
2851 info->using_themed_icon = TRUE;
2854 gdk_window_set_icon_list (widget->window, icon_list);
2856 get_pixmap_and_mask (widget->window,
2857 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2858 info->using_default_icon,
2863 /* This is a slight ICCCM violation since it's a color pixmap not
2864 * a bitmap, but everyone does it.
2866 gdk_window_set_icon (widget->window,
2871 info->realized = TRUE;
2873 if (info->using_themed_icon)
2875 GtkIconTheme *icon_theme;
2877 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
2878 g_list_free (icon_list);
2880 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2881 g_signal_connect (icon_theme, "changed",
2882 G_CALLBACK (update_themed_icon), window);
2887 gtk_window_unrealize_icon (GtkWindow *window)
2889 GtkWindowIconInfo *info;
2891 info = get_icon_info (window);
2896 if (info->icon_pixmap)
2897 g_object_unref (info->icon_pixmap);
2899 if (info->icon_mask)
2900 g_object_unref (info->icon_mask);
2902 info->icon_pixmap = NULL;
2903 info->icon_mask = NULL;
2905 if (info->using_themed_icon)
2907 GtkIconTheme *icon_theme;
2909 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2911 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
2914 /* We don't clear the properties on the window, just figure the
2915 * window is going away.
2918 info->realized = FALSE;
2923 * gtk_window_set_icon_list:
2924 * @window: a #GtkWindow
2925 * @list: list of #GdkPixbuf
2927 * Sets up the icon representing a #GtkWindow. The icon is used when
2928 * the window is minimized (also known as iconified). Some window
2929 * managers or desktop environments may also place it in the window
2930 * frame, or display it in other contexts.
2932 * gtk_window_set_icon_list() allows you to pass in the same icon in
2933 * several hand-drawn sizes. The list should contain the natural sizes
2934 * your icon is available in; that is, don't scale the image before
2935 * passing it to GTK+. Scaling is postponed until the last minute,
2936 * when the desired final size is known, to allow best quality.
2938 * By passing several sizes, you may improve the final image quality
2939 * of the icon, by reducing or eliminating automatic image scaling.
2941 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2942 * larger images (64x64, 128x128) if you have them.
2944 * See also gtk_window_set_default_icon_list() to set the icon
2945 * for all windows in your application in one go.
2947 * Note that transient windows (those who have been set transient for another
2948 * window using gtk_window_set_transient_for()) will inherit their
2949 * icon from their transient parent. So there's no need to explicitly
2950 * set the icon on transient windows.
2953 gtk_window_set_icon_list (GtkWindow *window,
2956 GtkWindowIconInfo *info;
2958 g_return_if_fail (GTK_IS_WINDOW (window));
2960 info = ensure_icon_info (window);
2962 if (info->icon_list == list) /* check for NULL mostly */
2965 g_list_foreach (list,
2966 (GFunc) g_object_ref, NULL);
2968 g_list_foreach (info->icon_list,
2969 (GFunc) g_object_unref, NULL);
2971 g_list_free (info->icon_list);
2973 info->icon_list = g_list_copy (list);
2975 g_object_notify (G_OBJECT (window), "icon");
2977 gtk_window_unrealize_icon (window);
2979 if (GTK_WIDGET_REALIZED (window))
2980 gtk_window_realize_icon (window);
2982 /* We could try to update our transient children, but I don't think
2983 * it's really worth it. If we did it, the best way would probably
2984 * be to have children connect to notify::icon-list
2989 * gtk_window_get_icon_list:
2990 * @window: a #GtkWindow
2992 * Retrieves the list of icons set by gtk_window_set_icon_list().
2993 * The list is copied, but the reference count on each
2994 * member won't be incremented.
2996 * Return value: copy of window's icon list
2999 gtk_window_get_icon_list (GtkWindow *window)
3001 GtkWindowIconInfo *info;
3003 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3005 info = get_icon_info (window);
3008 return g_list_copy (info->icon_list);
3014 * gtk_window_set_icon:
3015 * @window: a #GtkWindow
3016 * @icon: icon image, or %NULL
3018 * Sets up the icon representing a #GtkWindow. This icon is used when
3019 * the window is minimized (also known as iconified). Some window
3020 * managers or desktop environments may also place it in the window
3021 * frame, or display it in other contexts.
3023 * The icon should be provided in whatever size it was naturally
3024 * drawn; that is, don't scale the image before passing it to
3025 * GTK+. Scaling is postponed until the last minute, when the desired
3026 * final size is known, to allow best quality.
3028 * If you have your icon hand-drawn in multiple sizes, use
3029 * gtk_window_set_icon_list(). Then the best size will be used.
3031 * This function is equivalent to calling gtk_window_set_icon_list()
3032 * with a 1-element list.
3034 * See also gtk_window_set_default_icon_list() to set the icon
3035 * for all windows in your application in one go.
3038 gtk_window_set_icon (GtkWindow *window,
3043 g_return_if_fail (GTK_IS_WINDOW (window));
3044 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3049 list = g_list_append (list, icon);
3051 gtk_window_set_icon_list (window, list);
3057 update_themed_icon (GtkIconTheme *icon_theme,
3060 g_object_notify (G_OBJECT (window), "icon");
3062 gtk_window_unrealize_icon (window);
3064 if (GTK_WIDGET_REALIZED (window))
3065 gtk_window_realize_icon (window);
3069 * gtk_window_set_icon_name:
3070 * @window: a #GtkWindow
3071 * @name: the name of the themed icon
3073 * Sets the icon for the window from a named themed icon. See
3074 * the docs for #GtkIconTheme for more details.
3076 * Note that this has nothing to do with the WM_ICON_NAME
3077 * property which is mentioned in the ICCCM.
3082 gtk_window_set_icon_name (GtkWindow *window,
3085 GtkWindowIconInfo *info;
3088 g_return_if_fail (GTK_IS_WINDOW (window));
3090 info = ensure_icon_info (window);
3092 tmp = info->icon_name;
3093 info->icon_name = g_strdup (name);
3096 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3097 g_list_free (info->icon_list);
3098 info->icon_list = NULL;
3100 update_themed_icon (NULL, window);
3102 g_object_notify (G_OBJECT (window), "icon-name");
3106 * gtk_window_get_icon_name:
3107 * @window: a #GtkWindow
3109 * Returns the name of the themed icon for the window,
3110 * see gtk_window_set_icon_name().
3112 * Returns: the icon name or %NULL if the window has
3117 G_CONST_RETURN gchar *
3118 gtk_window_get_icon_name (GtkWindow *window)
3120 GtkWindowIconInfo *info;
3122 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3124 info = ensure_icon_info (window);
3126 return info->icon_name;
3130 * gtk_window_get_icon:
3131 * @window: a #GtkWindow
3133 * Gets the value set by gtk_window_set_icon() (or if you've
3134 * called gtk_window_set_icon_list(), gets the first icon in
3137 * Return value: icon for window
3140 gtk_window_get_icon (GtkWindow *window)
3142 GtkWindowIconInfo *info;
3144 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3146 info = get_icon_info (window);
3147 if (info && info->icon_list)
3148 return GDK_PIXBUF (info->icon_list->data);
3153 /* Load pixbuf, printing warning on failure if error == NULL
3156 load_pixbuf_verbosely (const char *filename,
3159 GError *local_err = NULL;
3162 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3170 g_warning ("Error loading icon from file '%s':\n\t%s",
3171 filename, local_err->message);
3172 g_error_free (local_err);
3180 * gtk_window_set_icon_from_file:
3181 * @window: a #GtkWindow
3182 * @filename: location of icon file
3183 * @err: location to store error, or %NULL.
3185 * Sets the icon for @window.
3186 * Warns on failure if @err is %NULL.
3188 * This function is equivalent to calling gtk_window_set_icon()
3189 * with a pixbuf created by loading the image from @filename.
3191 * Returns: %TRUE if setting the icon succeeded.
3196 gtk_window_set_icon_from_file (GtkWindow *window,
3197 const gchar *filename,
3200 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3204 gtk_window_set_icon (window, pixbuf);
3205 g_object_unref (pixbuf);
3214 * gtk_window_set_default_icon_list:
3215 * @list: a list of #GdkPixbuf
3217 * Sets an icon list to be used as fallback for windows that haven't
3218 * had gtk_window_set_icon_list() called on them to set up a
3219 * window-specific icon list. This function allows you to set up the
3220 * icon for all windows in your app at once.
3222 * See gtk_window_set_icon_list() for more details.
3226 gtk_window_set_default_icon_list (GList *list)
3230 if (list == default_icon_list)
3233 /* Update serial so we don't used cached pixmaps/masks
3235 default_icon_serial++;
3237 g_list_foreach (list,
3238 (GFunc) g_object_ref, NULL);
3240 g_list_foreach (default_icon_list,
3241 (GFunc) g_object_unref, NULL);
3243 g_list_free (default_icon_list);
3245 default_icon_list = g_list_copy (list);
3247 /* Update all toplevels */
3248 toplevels = gtk_window_list_toplevels ();
3249 tmp_list = toplevels;
3250 while (tmp_list != NULL)
3252 GtkWindowIconInfo *info;
3253 GtkWindow *w = tmp_list->data;
3255 info = get_icon_info (w);
3256 if (info && info->using_default_icon)
3258 gtk_window_unrealize_icon (w);
3259 if (GTK_WIDGET_REALIZED (w))
3260 gtk_window_realize_icon (w);
3263 tmp_list = tmp_list->next;
3265 g_list_free (toplevels);
3269 * gtk_window_set_default_icon:
3272 * Sets an icon to be used as fallback for windows that haven't
3273 * had gtk_window_set_icon() called on them from a pixbuf.
3278 gtk_window_set_default_icon (GdkPixbuf *icon)
3282 g_return_if_fail (GDK_IS_PIXBUF (icon));
3284 list = g_list_prepend (NULL, icon);
3285 gtk_window_set_default_icon_list (list);
3290 * gtk_window_set_default_icon_name:
3291 * @name: the name of the themed icon
3293 * Sets an icon to be used as fallback for windows that haven't
3294 * had gtk_window_set_icon_list() called on them from a named
3295 * themed icon, see gtk_window_set_icon_name().
3300 gtk_window_set_default_icon_name (const gchar *name)
3305 /* Update serial so we don't used cached pixmaps/masks
3307 default_icon_serial++;
3309 g_free (default_icon_name);
3310 default_icon_name = g_strdup (name);
3312 g_list_foreach (default_icon_list,
3313 (GFunc) g_object_unref, NULL);
3315 g_list_free (default_icon_list);
3316 default_icon_list = NULL;
3318 /* Update all toplevels */
3319 toplevels = gtk_window_list_toplevels ();
3320 tmp_list = toplevels;
3321 while (tmp_list != NULL)
3323 GtkWindowIconInfo *info;
3324 GtkWindow *w = tmp_list->data;
3326 info = get_icon_info (w);
3327 if (info && info->using_default_icon && info->using_themed_icon)
3329 gtk_window_unrealize_icon (w);
3330 if (GTK_WIDGET_REALIZED (w))
3331 gtk_window_realize_icon (w);
3334 tmp_list = tmp_list->next;
3336 g_list_free (toplevels);
3340 * gtk_window_set_default_icon_from_file:
3341 * @filename: location of icon file
3342 * @err: location to store error, or %NULL.
3344 * Sets an icon to be used as fallback for windows that haven't
3345 * had gtk_window_set_icon_list() called on them from a file
3346 * on disk. Warns on failure if @err is %NULL.
3348 * Returns: %TRUE if setting the icon succeeded.
3353 gtk_window_set_default_icon_from_file (const gchar *filename,
3356 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3360 gtk_window_set_default_icon (pixbuf);
3361 g_object_unref (pixbuf);
3370 * gtk_window_get_default_icon_list:
3372 * Gets the value set by gtk_window_set_default_icon_list().
3373 * The list is a copy and should be freed with g_list_free(),
3374 * but the pixbufs in the list have not had their reference count
3377 * Return value: copy of default icon list
3380 gtk_window_get_default_icon_list (void)
3382 return g_list_copy (default_icon_list);
3386 gtk_window_set_default_size_internal (GtkWindow *window,
3387 gboolean change_width,
3389 gboolean change_height,
3391 gboolean is_geometry)
3393 GtkWindowGeometryInfo *info;
3395 g_return_if_fail (change_width == FALSE || width >= -1);
3396 g_return_if_fail (change_height == FALSE || height >= -1);
3398 info = gtk_window_get_geometry_info (window, TRUE);
3400 g_object_freeze_notify (G_OBJECT (window));
3402 info->default_is_geometry = is_geometry != FALSE;
3412 info->default_width = width;
3414 g_object_notify (G_OBJECT (window), "default-width");
3425 info->default_height = height;
3427 g_object_notify (G_OBJECT (window), "default-height");
3430 g_object_thaw_notify (G_OBJECT (window));
3432 gtk_widget_queue_resize (GTK_WIDGET (window));
3436 * gtk_window_set_default_size:
3437 * @window: a #GtkWindow
3438 * @width: width in pixels, or -1 to unset the default width
3439 * @height: height in pixels, or -1 to unset the default height
3441 * Sets the default size of a window. If the window's "natural" size
3442 * (its size request) is larger than the default, the default will be
3443 * ignored. More generally, if the default size does not obey the
3444 * geometry hints for the window (gtk_window_set_geometry_hints() can
3445 * be used to set these explicitly), the default size will be clamped
3446 * to the nearest permitted size.
3448 * Unlike gtk_widget_set_size_request(), which sets a size request for
3449 * a widget and thus would keep users from shrinking the window, this
3450 * function only sets the initial size, just as if the user had
3451 * resized the window themselves. Users can still shrink the window
3452 * again as they normally would. Setting a default size of -1 means to
3453 * use the "natural" default size (the size request of the window).
3455 * For more control over a window's initial size and how resizing works,
3456 * investigate gtk_window_set_geometry_hints().
3458 * For some uses, gtk_window_resize() is a more appropriate function.
3459 * gtk_window_resize() changes the current size of the window, rather
3460 * than the size to be used on initial display. gtk_window_resize() always
3461 * affects the window itself, not the geometry widget.
3463 * The default size of a window only affects the first time a window is
3464 * shown; if a window is hidden and re-shown, it will remember the size
3465 * it had prior to hiding, rather than using the default size.
3467 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3468 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3471 gtk_window_set_default_size (GtkWindow *window,
3475 g_return_if_fail (GTK_IS_WINDOW (window));
3476 g_return_if_fail (width >= -1);
3477 g_return_if_fail (height >= -1);
3479 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3483 * gtk_window_get_default_size:
3484 * @window: a #GtkWindow
3485 * @width: location to store the default width, or %NULL
3486 * @height: location to store the default height, or %NULL
3488 * Gets the default size of the window. A value of -1 for the width or
3489 * height indicates that a default size has not been explicitly set
3490 * for that dimension, so the "natural" size of the window will be
3495 gtk_window_get_default_size (GtkWindow *window,
3499 GtkWindowGeometryInfo *info;
3501 g_return_if_fail (GTK_IS_WINDOW (window));
3503 info = gtk_window_get_geometry_info (window, FALSE);
3506 *width = info ? info->default_width : -1;
3509 *height = info ? info->default_height : -1;
3513 * gtk_window_resize:
3514 * @window: a #GtkWindow
3515 * @width: width in pixels to resize the window to
3516 * @height: height in pixels to resize the window to
3518 * Resizes the window as if the user had done so, obeying geometry
3519 * constraints. The default geometry constraint is that windows may
3520 * not be smaller than their size request; to override this
3521 * constraint, call gtk_widget_set_size_request() to set the window's
3522 * request to a smaller value.
3524 * If gtk_window_resize() is called before showing a window for the
3525 * first time, it overrides any default size set with
3526 * gtk_window_set_default_size().
3528 * Windows may not be resized smaller than 1 by 1 pixels.
3532 gtk_window_resize (GtkWindow *window,
3536 GtkWindowGeometryInfo *info;
3538 g_return_if_fail (GTK_IS_WINDOW (window));
3539 g_return_if_fail (width > 0);
3540 g_return_if_fail (height > 0);
3542 info = gtk_window_get_geometry_info (window, TRUE);
3544 info->resize_width = width;
3545 info->resize_height = height;
3547 gtk_widget_queue_resize (GTK_WIDGET (window));
3551 * gtk_window_get_size:
3552 * @window: a #GtkWindow
3553 * @width: return location for width, or %NULL
3554 * @height: return location for height, or %NULL
3556 * Obtains the current size of @window. If @window is not onscreen,
3557 * it returns the size GTK+ will suggest to the <link
3558 * linkend="gtk-X11-arch">window manager</link> for the initial window
3559 * size (but this is not reliably the same as the size the window
3560 * manager will actually select). The size obtained by
3561 * gtk_window_get_size() is the last size received in a
3562 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
3563 * rather than querying the X server for the size. As a result, if you
3564 * call gtk_window_resize() then immediately call
3565 * gtk_window_get_size(), the size won't have taken effect yet. After
3566 * the window manager processes the resize request, GTK+ receives
3567 * notification that the size has changed via a configure event, and
3568 * the size of the window gets updated.
3570 * Note 1: Nearly any use of this function creates a race condition,
3571 * because the size of the window may change between the time that you
3572 * get the size and the time that you perform some action assuming
3573 * that size is the current size. To avoid race conditions, connect to
3574 * "configure_event" on the window and adjust your size-dependent
3575 * state to match the size delivered in the #GdkEventConfigure.
3577 * Note 2: The returned size does <emphasis>not</emphasis> include the
3578 * size of the window manager decorations (aka the window frame or
3579 * border). Those are not drawn by GTK+ and GTK+ has no reliable
3580 * method of determining their size.
3582 * Note 3: If you are getting a window size in order to position
3583 * the window onscreen, there may be a better way. The preferred
3584 * way is to simply set the window's semantic type with
3585 * gtk_window_set_type_hint(), which allows the window manager to
3586 * e.g. center dialogs. Also, if you set the transient parent of
3587 * dialogs with gtk_window_set_transient_for() window managers
3588 * will often center the dialog over its parent window. It's
3589 * much preferred to let the window manager handle these
3590 * things rather than doing it yourself, because all apps will
3591 * behave consistently and according to user prefs if the window
3592 * manager handles it. Also, the window manager can take the size
3593 * of the window decorations/border into account, while your
3594 * application cannot.
3596 * In any case, if you insist on application-specified window
3597 * positioning, there's <emphasis>still</emphasis> a better way than
3598 * doing it yourself - gtk_window_set_position() will frequently
3599 * handle the details for you.
3603 gtk_window_get_size (GtkWindow *window,
3609 g_return_if_fail (GTK_IS_WINDOW (window));
3611 if (width == NULL && height == NULL)
3614 if (GTK_WIDGET_MAPPED (window))
3616 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3621 GdkRectangle configure_request;
3623 gtk_window_compute_configure_request (window,
3627 w = configure_request.width;
3628 h = configure_request.height;
3639 * @window: a #GtkWindow
3640 * @x: X coordinate to move window to
3641 * @y: Y coordinate to move window to
3643 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3644 * @window to the given position. Window managers are free to ignore
3645 * this; most window managers ignore requests for initial window
3646 * positions (instead using a user-defined placement algorithm) and
3647 * honor requests after the window has already been shown.
3649 * Note: the position is the position of the gravity-determined
3650 * reference point for the window. The gravity determines two things:
3651 * first, the location of the reference point in root window
3652 * coordinates; and second, which point on the window is positioned at
3653 * the reference point.
3655 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3656 * point is simply the @x, @y supplied to gtk_window_move(). The
3657 * top-left corner of the window decorations (aka window frame or
3658 * border) will be placed at @x, @y. Therefore, to position a window
3659 * at the top left of the screen, you want to use the default gravity
3660 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3662 * To position a window at the bottom right corner of the screen, you
3663 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3664 * point is at @x + the window width and @y + the window height, and
3665 * the bottom-right corner of the window border will be placed at that
3666 * reference point. So, to place a window in the bottom right corner
3667 * you would first set gravity to south east, then write:
3668 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3669 * gdk_screen_height () - window_height)</literal> (note that this
3670 * example does not take multi-head scenarios into account).
3672 * The Extended Window Manager Hints specification at <ulink
3673 * url="http://www.freedesktop.org/Standards/wm-spec">
3674 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
3675 * nice table of gravities in the "implementation notes" section.
3677 * The gtk_window_get_position() documentation may also be relevant.
3680 gtk_window_move (GtkWindow *window,
3684 GtkWindowGeometryInfo *info;
3687 g_return_if_fail (GTK_IS_WINDOW (window));
3689 widget = GTK_WIDGET (window);
3691 info = gtk_window_get_geometry_info (window, TRUE);
3693 if (GTK_WIDGET_MAPPED (window))
3695 /* we have now sent a request with this position
3696 * with currently-active constraints, so toggle flag.
3698 info->position_constraints_changed = FALSE;
3700 /* we only constrain if mapped - if not mapped,
3701 * then gtk_window_compute_configure_request()
3702 * will apply the constraints later, and we
3703 * don't want to lose information about
3704 * what position the user set before then.
3705 * i.e. if you do a move() then turn off POS_CENTER
3706 * then show the window, your move() will work.
3708 gtk_window_constrain_position (window,
3709 widget->allocation.width,
3710 widget->allocation.height,
3713 /* Note that this request doesn't go through our standard request
3714 * framework, e.g. doesn't increment configure_request_count,
3715 * doesn't set info->last, etc.; that's because
3716 * we don't save the info needed to arrive at this same request
3719 * To gtk_window_move_resize(), this will end up looking exactly
3720 * the same as the position being changed by the window
3724 /* FIXME are we handling gravity properly for framed windows? */
3726 gdk_window_move (window->frame,
3727 x - window->frame_left,
3728 y - window->frame_top);
3730 gdk_window_move (GTK_WIDGET (window)->window,
3735 /* Save this position to apply on mapping */
3736 info->initial_x = x;
3737 info->initial_y = y;
3738 info->initial_pos_set = TRUE;
3743 * gtk_window_get_position:
3744 * @window: a #GtkWindow
3745 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3746 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3748 * This function returns the position you need to pass to
3749 * gtk_window_move() to keep @window in its current position. This
3750 * means that the meaning of the returned value varies with window
3751 * gravity. See gtk_window_move() for more details.
3753 * If you haven't changed the window gravity, its gravity will be
3754 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3755 * gets the position of the top-left corner of the window manager
3756 * frame for the window. gtk_window_move() sets the position of this
3757 * same top-left corner.
3759 * gtk_window_get_position() is not 100% reliable because the X Window System
3760 * does not specify a way to obtain the geometry of the
3761 * decorations placed on a window by the window manager.
3762 * Thus GTK+ is using a "best guess" that works with most
3765 * Moreover, nearly all window managers are historically broken with
3766 * respect to their handling of window gravity. So moving a window to
3767 * its current position as returned by gtk_window_get_position() tends
3768 * to result in moving the window slightly. Window managers are
3769 * slowly getting better over time.
3771 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3772 * frame is not relevant, and thus gtk_window_get_position() will
3773 * always produce accurate results. However you can't use static
3774 * gravity to do things like place a window in a corner of the screen,
3775 * because static gravity ignores the window manager decorations.
3777 * If you are saving and restoring your application's window
3778 * positions, you should know that it's impossible for applications to
3779 * do this without getting it somewhat wrong because applications do
3780 * not have sufficient knowledge of window manager state. The Correct
3781 * Mechanism is to support the session management protocol (see the
3782 * "GnomeClient" object in the GNOME libraries for example) and allow
3783 * the window manager to save your window sizes and positions.
3788 gtk_window_get_position (GtkWindow *window,
3794 g_return_if_fail (GTK_IS_WINDOW (window));
3796 widget = GTK_WIDGET (window);
3798 if (window->gravity == GDK_GRAVITY_STATIC)
3800 if (GTK_WIDGET_MAPPED (widget))
3802 /* This does a server round-trip, which is sort of wrong;
3803 * but a server round-trip is inevitable for
3804 * gdk_window_get_frame_extents() in the usual
3805 * NorthWestGravity case below, so not sure what else to
3806 * do. We should likely be consistent about whether we get
3807 * the client-side info or the server-side info.
3809 gdk_window_get_origin (widget->window, root_x, root_y);
3813 GdkRectangle configure_request;
3815 gtk_window_compute_configure_request (window,
3819 *root_x = configure_request.x;
3820 *root_y = configure_request.y;
3825 GdkRectangle frame_extents;
3830 if (GTK_WIDGET_MAPPED (widget))
3833 gdk_window_get_frame_extents (window->frame, &frame_extents);
3835 gdk_window_get_frame_extents (widget->window, &frame_extents);
3836 x = frame_extents.x;
3837 y = frame_extents.y;
3838 gtk_window_get_size (window, &w, &h);
3842 /* We just say the frame has 0 size on all sides.
3843 * Not sure what else to do.
3845 gtk_window_compute_configure_request (window,
3848 x = frame_extents.x;
3849 y = frame_extents.y;
3850 w = frame_extents.width;
3851 h = frame_extents.height;
3854 switch (window->gravity)
3856 case GDK_GRAVITY_NORTH:
3857 case GDK_GRAVITY_CENTER:
3858 case GDK_GRAVITY_SOUTH:
3859 /* Find center of frame. */
3860 x += frame_extents.width / 2;
3861 /* Center client window on that point. */
3865 case GDK_GRAVITY_SOUTH_EAST:
3866 case GDK_GRAVITY_EAST:
3867 case GDK_GRAVITY_NORTH_EAST:
3868 /* Find right edge of frame */
3869 x += frame_extents.width;
3870 /* Align left edge of client at that point. */
3877 switch (window->gravity)
3879 case GDK_GRAVITY_WEST:
3880 case GDK_GRAVITY_CENTER:
3881 case GDK_GRAVITY_EAST:
3882 /* Find center of frame. */
3883 y += frame_extents.height / 2;
3884 /* Center client window there. */
3887 case GDK_GRAVITY_SOUTH_WEST:
3888 case GDK_GRAVITY_SOUTH:
3889 case GDK_GRAVITY_SOUTH_EAST:
3890 /* Find south edge of frame */
3891 y += frame_extents.height;
3892 /* Place bottom edge of client there */
3907 * gtk_window_reshow_with_initial_size:
3908 * @window: a #GtkWindow
3910 * Hides @window, then reshows it, resetting the
3911 * default size and position of the window. Used
3912 * by GUI builders only.
3915 gtk_window_reshow_with_initial_size (GtkWindow *window)
3919 g_return_if_fail (GTK_IS_WINDOW (window));
3921 widget = GTK_WIDGET (window);
3923 gtk_widget_hide (widget);
3924 gtk_widget_unrealize (widget);
3925 gtk_widget_show (widget);
3929 gtk_window_destroy (GtkObject *object)
3931 GtkWindow *window = GTK_WINDOW (object);
3933 toplevel_list = g_slist_remove (toplevel_list, window);
3935 if (window->transient_parent)
3936 gtk_window_set_transient_for (window, NULL);
3938 /* frees the icons */
3939 gtk_window_set_icon_list (window, NULL);
3941 if (window->has_user_ref_count)
3943 window->has_user_ref_count = FALSE;
3944 g_object_unref (window);
3948 gtk_window_group_remove_window (window->group, window);
3950 gtk_window_free_key_hash (window);
3952 GTK_OBJECT_CLASS (gtk_window_parent_class)->destroy (object);
3956 gtk_window_finalize (GObject *object)
3958 GtkWindow *window = GTK_WINDOW (object);
3959 GtkMnemonicHash *mnemonic_hash;
3961 g_free (window->title);
3962 g_free (window->wmclass_name);
3963 g_free (window->wmclass_class);
3964 g_free (window->wm_role);
3966 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
3968 _gtk_mnemonic_hash_free (mnemonic_hash);
3970 if (window->geometry_info)
3972 if (window->geometry_info->widget)
3973 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3974 gtk_widget_destroyed,
3975 &window->geometry_info->widget);
3976 g_free (window->geometry_info);
3979 if (window->keys_changed_handler)
3981 g_source_remove (window->keys_changed_handler);
3982 window->keys_changed_handler = 0;
3987 g_signal_handlers_disconnect_by_func (window->screen,
3988 gtk_window_on_composited_changed, window);
3991 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
3995 gtk_window_show (GtkWidget *widget)
3997 GtkWindow *window = GTK_WINDOW (widget);
3998 GtkContainer *container = GTK_CONTAINER (window);
3999 gboolean need_resize;
4001 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
4003 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
4004 container->need_resize = FALSE;
4008 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4009 GtkAllocation allocation = { 0, 0 };
4010 GdkRectangle configure_request;
4011 GdkGeometry new_geometry;
4013 gboolean was_realized;
4015 /* We are going to go ahead and perform this configure request
4016 * and then emulate a configure notify by going ahead and
4017 * doing a size allocate. Sort of a synchronous
4018 * mini-copy of gtk_window_move_resize() here.
4020 gtk_window_compute_configure_request (window,
4025 /* We update this because we are going to go ahead
4026 * and gdk_window_resize() below, rather than
4029 info->last.configure_request.width = configure_request.width;
4030 info->last.configure_request.height = configure_request.height;
4032 /* and allocate the window - this is normally done
4033 * in move_resize in response to configure notify
4035 allocation.width = configure_request.width;
4036 allocation.height = configure_request.height;
4037 gtk_widget_size_allocate (widget, &allocation);
4039 /* Then we guarantee we have a realize */
4040 was_realized = FALSE;
4041 if (!GTK_WIDGET_REALIZED (widget))
4043 gtk_widget_realize (widget);
4044 was_realized = TRUE;
4047 /* Must be done after the windows are realized,
4048 * so that the decorations can be read
4050 gtk_decorated_window_calculate_frame_size (window);
4052 /* We only send configure request if we didn't just finish
4053 * creating the window; if we just created the window
4054 * then we created it with widget->allocation anyhow.
4057 gdk_window_move_resize (widget->window,
4058 configure_request.x,
4059 configure_request.y,
4060 configure_request.width,
4061 configure_request.height);
4064 gtk_container_check_resize (container);
4066 gtk_widget_map (widget);
4068 /* Try to make sure that we have some focused widget
4070 if (!window->focus_widget && !GTK_IS_PLUG (window))
4071 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4074 gtk_grab_add (widget);
4078 gtk_window_hide (GtkWidget *widget)
4080 GtkWindow *window = GTK_WINDOW (widget);
4082 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4083 gtk_widget_unmap (widget);
4086 gtk_grab_remove (widget);
4090 gtk_window_map (GtkWidget *widget)
4092 GtkWindow *window = GTK_WINDOW (widget);
4093 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4094 GdkWindow *toplevel;
4096 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4098 if (window->bin.child &&
4099 GTK_WIDGET_VISIBLE (window->bin.child) &&
4100 !GTK_WIDGET_MAPPED (window->bin.child))
4101 gtk_widget_map (window->bin.child);
4104 toplevel = window->frame;
4106 toplevel = widget->window;
4108 if (window->maximize_initially)
4109 gdk_window_maximize (toplevel);
4111 gdk_window_unmaximize (toplevel);
4113 if (window->stick_initially)
4114 gdk_window_stick (toplevel);
4116 gdk_window_unstick (toplevel);
4118 if (window->iconify_initially)
4119 gdk_window_iconify (toplevel);
4121 gdk_window_deiconify (toplevel);
4123 if (priv->fullscreen_initially)
4124 gdk_window_fullscreen (toplevel);
4126 gdk_window_unfullscreen (toplevel);
4128 gdk_window_set_keep_above (toplevel, priv->above_initially);
4130 gdk_window_set_keep_below (toplevel, priv->below_initially);
4132 /* No longer use the default settings */
4133 window->need_default_size = FALSE;
4134 window->need_default_position = FALSE;
4136 if (priv->reset_type_hint)
4138 /* We should only reset the type hint when the application
4139 * used gtk_window_set_type_hint() to change the hint.
4140 * Some applications use X directly to change the properties;
4141 * in that case, we shouldn't overwrite what they did.
4143 gdk_window_set_type_hint (widget->window, priv->type_hint);
4144 priv->reset_type_hint = FALSE;
4147 gdk_window_show (widget->window);
4150 gdk_window_show (window->frame);
4152 if (!disable_startup_notification &&
4153 !sent_startup_notification)
4155 sent_startup_notification = TRUE;
4156 gdk_notify_startup_complete ();
4161 gtk_window_map_event (GtkWidget *widget,
4164 if (!GTK_WIDGET_MAPPED (widget))
4166 /* we should be be unmapped, but are getting a MapEvent, this may happen
4167 * to toplevel XWindows if mapping was intercepted by a window manager
4168 * and an unmap request occoured while the MapRequestEvent was still
4169 * being handled. we work around this situaiton here by re-requesting
4170 * the window being unmapped. more details can be found in:
4171 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4173 gdk_window_hide (widget->window);
4179 gtk_window_unmap (GtkWidget *widget)
4181 GtkWindow *window = GTK_WINDOW (widget);
4182 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
4183 GtkWindowGeometryInfo *info;
4184 GdkWindowState state;
4186 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4188 gdk_window_withdraw (window->frame);
4190 gdk_window_withdraw (widget->window);
4192 window->configure_request_count = 0;
4193 window->configure_notify_received = FALSE;
4195 /* on unmap, we reset the default positioning of the window,
4196 * so it's placed again, but we don't reset the default
4197 * size of the window, so it's remembered.
4199 window->need_default_position = TRUE;
4201 info = gtk_window_get_geometry_info (window, FALSE);
4204 info->initial_pos_set = FALSE;
4205 info->position_constraints_changed = FALSE;
4208 state = gdk_window_get_state (widget->window);
4209 window->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4210 window->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4211 window->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4212 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4213 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4217 gtk_window_realize (GtkWidget *widget)
4220 GdkWindow *parent_window;
4221 GdkWindowAttr attributes;
4222 gint attributes_mask;
4223 GtkWindowPrivate *priv;
4225 window = GTK_WINDOW (widget);
4227 priv = GTK_WINDOW_GET_PRIVATE (window);
4229 /* ensure widget tree is properly size allocated */
4230 if (widget->allocation.x == -1 &&
4231 widget->allocation.y == -1 &&
4232 widget->allocation.width == 1 &&
4233 widget->allocation.height == 1)
4235 GtkRequisition requisition;
4236 GtkAllocation allocation = { 0, 0, 200, 200 };
4238 gtk_widget_size_request (widget, &requisition);
4239 if (requisition.width || requisition.height)
4241 /* non-empty window */
4242 allocation.width = requisition.width;
4243 allocation.height = requisition.height;
4245 gtk_widget_size_allocate (widget, &allocation);
4247 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4249 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
4252 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4254 switch (window->type)
4256 case GTK_WINDOW_TOPLEVEL:
4257 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4259 case GTK_WINDOW_POPUP:
4260 attributes.window_type = GDK_WINDOW_TEMP;
4263 g_warning (G_STRLOC": Unknown window type %d!", window->type);
4267 attributes.title = window->title;
4268 attributes.wmclass_name = window->wmclass_name;
4269 attributes.wmclass_class = window->wmclass_class;
4270 attributes.wclass = GDK_INPUT_OUTPUT;
4271 attributes.visual = gtk_widget_get_visual (widget);
4272 attributes.colormap = gtk_widget_get_colormap (widget);
4274 if (window->has_frame)
4276 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
4277 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
4278 attributes.event_mask = (GDK_EXPOSURE_MASK |
4279 GDK_KEY_PRESS_MASK |
4280 GDK_ENTER_NOTIFY_MASK |
4281 GDK_LEAVE_NOTIFY_MASK |
4282 GDK_FOCUS_CHANGE_MASK |
4283 GDK_STRUCTURE_MASK |
4284 GDK_BUTTON_MOTION_MASK |
4285 GDK_POINTER_MOTION_HINT_MASK |
4286 GDK_BUTTON_PRESS_MASK |
4287 GDK_BUTTON_RELEASE_MASK);
4289 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4291 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4292 &attributes, attributes_mask);
4294 gdk_window_set_user_data (window->frame, widget);
4296 attributes.window_type = GDK_WINDOW_CHILD;
4297 attributes.x = window->frame_left;
4298 attributes.y = window->frame_top;
4300 attributes_mask = GDK_WA_X | GDK_WA_Y;
4302 parent_window = window->frame;
4304 g_signal_connect (window,
4306 G_CALLBACK (gtk_window_event),
4311 attributes_mask = 0;
4312 parent_window = gtk_widget_get_root_window (widget);
4315 attributes.width = widget->allocation.width;
4316 attributes.height = widget->allocation.height;
4317 attributes.event_mask = gtk_widget_get_events (widget);
4318 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4319 GDK_KEY_PRESS_MASK |
4320 GDK_KEY_RELEASE_MASK |
4321 GDK_ENTER_NOTIFY_MASK |
4322 GDK_LEAVE_NOTIFY_MASK |
4323 GDK_FOCUS_CHANGE_MASK |
4324 GDK_STRUCTURE_MASK);
4326 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
4327 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
4328 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
4330 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
4332 gdk_window_enable_synchronized_configure (widget->window);
4334 gdk_window_set_user_data (widget->window, window);
4336 widget->style = gtk_style_attach (widget->style, widget->window);
4337 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4339 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
4341 /* This is a bad hack to set the window background. */
4342 gtk_window_paint (widget, NULL);
4344 if (window->transient_parent &&
4345 GTK_WIDGET_REALIZED (window->transient_parent))
4346 gdk_window_set_transient_for (widget->window,
4347 GTK_WIDGET (window->transient_parent)->window);
4349 if (window->wm_role)
4350 gdk_window_set_role (widget->window, window->wm_role);
4352 if (!window->decorated)
4353 gdk_window_set_decorations (widget->window, 0);
4355 if (!priv->deletable)
4356 gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4358 gdk_window_set_type_hint (widget->window, priv->type_hint);
4360 if (gtk_window_get_skip_pager_hint (window))
4361 gdk_window_set_skip_pager_hint (widget->window, TRUE);
4363 if (gtk_window_get_skip_taskbar_hint (window))
4364 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
4366 if (gtk_window_get_accept_focus (window))
4367 gdk_window_set_accept_focus (widget->window, TRUE);
4369 gdk_window_set_accept_focus (widget->window, FALSE);
4371 if (gtk_window_get_focus_on_map (window))
4372 gdk_window_set_focus_on_map (widget->window, TRUE);
4374 gdk_window_set_focus_on_map (widget->window, FALSE);
4377 gdk_window_set_modal_hint (widget->window, TRUE);
4379 gdk_window_set_modal_hint (widget->window, FALSE);
4382 gtk_window_realize_icon (window);
4386 gtk_window_unrealize (GtkWidget *widget)
4389 GtkWindowGeometryInfo *info;
4391 window = GTK_WINDOW (widget);
4393 /* On unrealize, we reset the size of the window such
4394 * that we will re-apply the default sizing stuff
4395 * next time we show the window.
4397 * Default positioning is reset on unmap, instead of unrealize.
4399 window->need_default_size = TRUE;
4400 info = gtk_window_get_geometry_info (window, FALSE);
4403 info->resize_width = -1;
4404 info->resize_height = -1;
4405 info->last.configure_request.x = 0;
4406 info->last.configure_request.y = 0;
4407 info->last.configure_request.width = -1;
4408 info->last.configure_request.height = -1;
4409 /* be sure we reset geom hints on re-realize */
4410 info->last.flags = 0;
4415 gdk_window_set_user_data (window->frame, NULL);
4416 gdk_window_destroy (window->frame);
4417 window->frame = NULL;
4421 gtk_window_unrealize_icon (window);
4423 (* GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize) (widget);
4427 gtk_window_size_request (GtkWidget *widget,
4428 GtkRequisition *requisition)
4433 window = GTK_WINDOW (widget);
4434 bin = GTK_BIN (window);
4436 requisition->width = GTK_CONTAINER (window)->border_width * 2;
4437 requisition->height = GTK_CONTAINER (window)->border_width * 2;
4439 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
4441 GtkRequisition child_requisition;
4443 gtk_widget_size_request (bin->child, &child_requisition);
4445 requisition->width += child_requisition.width;
4446 requisition->height += child_requisition.height;
4451 gtk_window_size_allocate (GtkWidget *widget,
4452 GtkAllocation *allocation)
4455 GtkAllocation child_allocation;
4457 window = GTK_WINDOW (widget);
4458 widget->allocation = *allocation;
4460 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
4462 child_allocation.x = GTK_CONTAINER (window)->border_width;
4463 child_allocation.y = GTK_CONTAINER (window)->border_width;
4464 child_allocation.width =
4465 MAX (1, (gint)allocation->width - child_allocation.x * 2);
4466 child_allocation.height =
4467 MAX (1, (gint)allocation->height - child_allocation.y * 2);
4469 gtk_widget_size_allocate (window->bin.child, &child_allocation);
4472 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4474 gdk_window_resize (window->frame,
4475 allocation->width + window->frame_left + window->frame_right,
4476 allocation->height + window->frame_top + window->frame_bottom);
4481 gtk_window_event (GtkWidget *widget, GdkEvent *event)
4484 gboolean return_val;
4486 window = GTK_WINDOW (widget);
4488 if (window->frame && (event->any.window == window->frame))
4490 if ((event->type != GDK_KEY_PRESS) &&
4491 (event->type != GDK_KEY_RELEASE) &&
4492 (event->type != GDK_FOCUS_CHANGE))
4494 g_signal_stop_emission_by_name (widget, "event");
4496 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
4501 g_object_unref (event->any.window);
4502 event->any.window = g_object_ref (widget->window);
4510 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
4512 GdkEventConfigure *configure_event;
4515 switch (event->type)
4518 configure_event = (GdkEventConfigure *)event;
4520 /* Invalidate the decorations */
4523 rect.width = configure_event->width;
4524 rect.height = configure_event->height;
4526 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
4528 /* Pass on the (modified) configure event */
4529 configure_event->width -= window->frame_left + window->frame_right;
4530 configure_event->height -= window->frame_top + window->frame_bottom;
4531 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
4540 gtk_window_configure_event (GtkWidget *widget,
4541 GdkEventConfigure *event)
4543 GtkWindow *window = GTK_WINDOW (widget);
4544 gboolean expected_reply = window->configure_request_count > 0;
4546 /* window->configure_request_count incremented for each
4547 * configure request, and decremented to a min of 0 for
4548 * each configure notify.
4550 * All it means is that we know we will get at least
4551 * window->configure_request_count more configure notifies.
4552 * We could get more configure notifies than that; some
4553 * of the configure notifies we get may be unrelated to
4554 * the configure requests. But we will get at least
4555 * window->configure_request_count notifies.
4558 if (window->configure_request_count > 0)
4559 window->configure_request_count -= 1;
4561 /* As an optimization, we avoid a resize when possible.
4563 * The only times we can avoid a resize are:
4564 * - we know only the position changed, not the size
4565 * - we know we have made more requests and so will get more
4566 * notifies and can wait to resize when we get them
4569 if (!expected_reply &&
4570 (widget->allocation.width == event->width &&
4571 widget->allocation.height == event->height))
4573 gdk_window_configure_finished (widget->window);
4578 * If we do need to resize, we do that by:
4579 * - filling in widget->allocation with the new size
4580 * - setting configure_notify_received to TRUE
4581 * for use in gtk_window_move_resize()
4582 * - queueing a resize, leading to invocation of
4583 * gtk_window_move_resize() in an idle handler
4587 window->configure_notify_received = TRUE;
4589 widget->allocation.width = event->width;
4590 widget->allocation.height = event->height;
4592 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4597 /* the accel_key and accel_mods fields of the key have to be setup
4598 * upon calling this function. it'll then return whether that key
4599 * is at all used as accelerator, and if so will OR in the
4600 * accel_flags member of the key.
4603 _gtk_window_query_nonaccels (GtkWindow *window,
4605 GdkModifierType accel_mods)
4607 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4609 /* movement keys are considered locked accels */
4612 static const guint bindings[] = {
4613 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
4614 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
4618 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
4619 if (bindings[i] == accel_key)
4623 /* mnemonics are considered locked accels */
4624 if (accel_mods == window->mnemonic_modifier)
4626 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4627 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
4635 * gtk_window_propagate_key_event:
4636 * @window: a #GtkWindow
4637 * @event: a #GdkEventKey
4639 * Propagate a key press or release event to the focus widget and
4640 * up the focus container chain until a widget handles @event.
4641 * This is normally called by the default ::key_press_event and
4642 * ::key_release_event handlers for toplevel windows,
4643 * however in some cases it may be useful to call this directly when
4644 * overriding the standard key handling for a toplevel window.
4646 * Return value: %TRUE if a widget in the focus chain handled the event.
4649 gtk_window_propagate_key_event (GtkWindow *window,
4652 gboolean handled = FALSE;
4653 GtkWidget *widget, *focus;
4655 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4657 widget = GTK_WIDGET (window);
4658 focus = window->focus_widget;
4660 g_object_ref (focus);
4663 focus && focus != widget &&
4664 gtk_widget_get_toplevel (focus) == widget)
4668 if (GTK_WIDGET_IS_SENSITIVE (focus))
4669 handled = gtk_widget_event (focus, (GdkEvent*) event);
4671 parent = focus->parent;
4673 g_object_ref (parent);
4675 g_object_unref (focus);
4681 g_object_unref (focus);
4687 gtk_window_key_press_event (GtkWidget *widget,
4690 GtkWindow *window = GTK_WINDOW (widget);
4691 gboolean handled = FALSE;
4693 /* handle mnemonics and accelerators */
4695 handled = gtk_window_activate_key (window, event);
4697 /* handle focus widget key events */
4699 handled = gtk_window_propagate_key_event (window, event);
4701 /* Chain up, invokes binding set */
4703 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
4709 gtk_window_key_release_event (GtkWidget *widget,
4712 GtkWindow *window = GTK_WINDOW (widget);
4713 gboolean handled = FALSE;
4715 /* handle focus widget key events */
4717 handled = gtk_window_propagate_key_event (window, event);
4719 /* Chain up, invokes binding set */
4721 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
4727 gtk_window_real_activate_default (GtkWindow *window)
4729 gtk_window_activate_default (window);
4733 gtk_window_real_activate_focus (GtkWindow *window)
4735 gtk_window_activate_focus (window);
4739 gtk_window_move_focus (GtkWindow *window,
4740 GtkDirectionType dir)
4742 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4744 if (!GTK_CONTAINER (window)->focus_child)
4745 gtk_window_set_focus (window, NULL);
4749 gtk_window_enter_notify_event (GtkWidget *widget,
4750 GdkEventCrossing *event)
4756 gtk_window_leave_notify_event (GtkWidget *widget,
4757 GdkEventCrossing *event)
4763 do_focus_change (GtkWidget *widget,
4766 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4768 g_object_ref (widget);
4771 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4773 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4775 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4776 fevent->focus_change.window = widget->window;
4778 g_object_ref (widget->window);
4779 fevent->focus_change.in = in;
4781 gtk_widget_event (widget, fevent);
4783 g_object_notify (G_OBJECT (widget), "has-focus");
4785 g_object_unref (widget);
4786 gdk_event_free (fevent);
4790 gtk_window_focus_in_event (GtkWidget *widget,
4791 GdkEventFocus *event)
4793 GtkWindow *window = GTK_WINDOW (widget);
4795 /* It appears spurious focus in events can occur when
4796 * the window is hidden. So we'll just check to see if
4797 * the window is visible before actually handling the
4800 if (GTK_WIDGET_VISIBLE (widget))
4802 _gtk_window_set_has_toplevel_focus (window, TRUE);
4803 _gtk_window_set_is_active (window, TRUE);
4810 gtk_window_focus_out_event (GtkWidget *widget,
4811 GdkEventFocus *event)
4813 GtkWindow *window = GTK_WINDOW (widget);
4815 _gtk_window_set_has_toplevel_focus (window, FALSE);
4816 _gtk_window_set_is_active (window, FALSE);
4821 static GdkAtom atom_rcfiles = GDK_NONE;
4822 static GdkAtom atom_iconthemes = GDK_NONE;
4825 send_client_message_to_embedded_windows (GtkWidget *widget,
4826 GdkAtom message_type)
4828 GList *embedded_windows;
4830 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
4831 if (embedded_windows)
4833 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4836 for (i = 0; i < 5; i++)
4837 send_event->client.data.l[i] = 0;
4838 send_event->client.data_format = 32;
4839 send_event->client.message_type = message_type;
4841 while (embedded_windows)
4843 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4844 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4845 embedded_windows = embedded_windows->next;
4848 gdk_event_free (send_event);
4853 gtk_window_client_event (GtkWidget *widget,
4854 GdkEventClient *event)
4858 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
4859 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
4862 if (event->message_type == atom_rcfiles)
4864 send_client_message_to_embedded_windows (widget, atom_rcfiles);
4865 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4868 if (event->message_type == atom_iconthemes)
4870 send_client_message_to_embedded_windows (widget, atom_iconthemes);
4871 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
4878 gtk_window_check_resize (GtkContainer *container)
4880 GtkWindow *window = GTK_WINDOW (container);
4882 if (GTK_WIDGET_VISIBLE (container))
4883 gtk_window_move_resize (window);
4887 gtk_window_focus (GtkWidget *widget,
4888 GtkDirectionType direction)
4892 GtkContainer *container;
4893 GtkWidget *old_focus_child;
4896 container = GTK_CONTAINER (widget);
4897 window = GTK_WINDOW (widget);
4898 bin = GTK_BIN (widget);
4900 old_focus_child = container->focus_child;
4902 /* We need a special implementation here to deal properly with wrapping
4903 * around in the tab chain without the danger of going into an
4906 if (old_focus_child)
4908 if (gtk_widget_child_focus (old_focus_child, direction))
4912 if (window->focus_widget)
4914 if (direction == GTK_DIR_LEFT ||
4915 direction == GTK_DIR_RIGHT ||
4916 direction == GTK_DIR_UP ||
4917 direction == GTK_DIR_DOWN)
4922 /* Wrapped off the end, clear the focus setting for the toplpevel */
4923 parent = window->focus_widget->parent;
4926 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4927 parent = GTK_WIDGET (parent)->parent;
4930 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4933 /* Now try to focus the first widget in the window */
4936 if (gtk_widget_child_focus (bin->child, direction))
4944 gtk_window_real_set_focus (GtkWindow *window,
4947 GtkWidget *old_focus = window->focus_widget;
4948 gboolean had_default = FALSE;
4949 gboolean focus_had_default = FALSE;
4950 gboolean old_focus_had_default = FALSE;
4954 g_object_ref (old_focus);
4955 g_object_freeze_notify (G_OBJECT (old_focus));
4956 old_focus_had_default = GTK_WIDGET_HAS_DEFAULT (old_focus);
4960 g_object_ref (focus);
4961 g_object_freeze_notify (G_OBJECT (focus));
4962 focus_had_default = GTK_WIDGET_HAS_DEFAULT (focus);
4965 if (window->default_widget)
4966 had_default = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4968 if (window->focus_widget)
4970 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4971 (window->focus_widget != window->default_widget))
4973 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4974 gtk_widget_queue_draw (window->focus_widget);
4976 if (window->default_widget)
4977 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4980 window->focus_widget = NULL;
4982 if (window->has_focus)
4983 do_focus_change (old_focus, FALSE);
4985 g_object_notify (G_OBJECT (old_focus), "is-focus");
4988 /* The above notifications may have set a new focus widget,
4989 * if so, we don't want to override it.
4991 if (focus && !window->focus_widget)
4993 window->focus_widget = focus;
4995 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4996 (window->focus_widget != window->default_widget))
4998 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4999 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
5001 if (window->default_widget)
5002 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
5005 if (window->has_focus)
5006 do_focus_change (window->focus_widget, TRUE);
5008 g_object_notify (G_OBJECT (window->focus_widget), "is-focus");
5011 /* If the default widget changed, a redraw will have been queued
5012 * on the old and new default widgets by gtk_window_set_default(), so
5013 * we only have to worry about the case where it didn't change.
5014 * We'll sometimes queue a draw twice on the new widget but that
5017 if (window->default_widget &&
5018 (had_default != GTK_WIDGET_HAS_DEFAULT (window->default_widget)))
5019 gtk_widget_queue_draw (window->default_widget);
5023 if (old_focus_had_default != GTK_WIDGET_HAS_DEFAULT (old_focus))
5024 gtk_widget_queue_draw (old_focus);
5026 g_object_thaw_notify (G_OBJECT (old_focus));
5027 g_object_unref (old_focus);
5031 if (focus_had_default != GTK_WIDGET_HAS_DEFAULT (focus))
5032 gtk_widget_queue_draw (focus);
5034 g_object_thaw_notify (G_OBJECT (focus));
5035 g_object_unref (focus);
5040 * _gtk_window_unset_focus_and_default:
5041 * @window: a #GtkWindow
5042 * @widget: a widget inside of @window
5044 * Checks whether the focus and default widgets of @window are
5045 * @widget or a descendent of @widget, and if so, unset them.
5048 _gtk_window_unset_focus_and_default (GtkWindow *window,
5054 g_object_ref (window);
5055 g_object_ref (widget);
5057 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
5059 child = window->focus_widget;
5061 while (child && child != widget)
5062 child = child->parent;
5064 if (child == widget)
5065 gtk_window_set_focus (GTK_WINDOW (window), NULL);
5068 child = window->default_widget;
5070 while (child && child != widget)
5071 child = child->parent;
5073 if (child == widget)
5074 gtk_window_set_default (window, NULL);
5076 g_object_unref (widget);
5077 g_object_unref (window);
5080 /*********************************
5081 * Functions related to resizing *
5082 *********************************/
5084 /* This function doesn't constrain to geometry hints */
5086 gtk_window_compute_configure_request_size (GtkWindow *window,
5090 GtkRequisition requisition;
5091 GtkWindowGeometryInfo *info;
5095 * - we've done a size request
5098 widget = GTK_WIDGET (window);
5100 info = gtk_window_get_geometry_info (window, FALSE);
5102 if (window->need_default_size)
5104 gtk_widget_get_child_requisition (widget, &requisition);
5106 /* Default to requisition */
5107 *width = requisition.width;
5108 *height = requisition.height;
5110 /* If window is empty so requests 0, default to random nonzero size */
5111 if (*width == 0 && *height == 0)
5117 /* Override requisition with default size */
5121 gint base_width = 0;
5122 gint base_height = 0;
5124 gint height_inc = 1;
5126 if (info->default_is_geometry &&
5127 (info->default_width > 0 || info->default_height > 0))
5129 GdkGeometry geometry;
5132 gtk_window_compute_hints (window, &geometry, &flags);
5134 if (flags & GDK_HINT_BASE_SIZE)
5136 base_width = geometry.base_width;
5137 base_height = geometry.base_height;
5139 else if (flags & GDK_HINT_MIN_SIZE)
5141 base_width = geometry.min_width;
5142 base_height = geometry.min_height;
5144 if (flags & GDK_HINT_RESIZE_INC)
5146 width_inc = geometry.width_inc;
5147 height_inc = geometry.height_inc;
5151 if (info->default_width > 0)
5152 *width = info->default_width * width_inc + base_width;
5154 if (info->default_height > 0)
5155 *height = info->default_height * height_inc + base_height;
5160 /* Default to keeping current size */
5161 *width = widget->allocation.width;
5162 *height = widget->allocation.height;
5165 /* Override any size with gtk_window_resize() values */
5168 if (info->resize_width > 0)
5169 *width = info->resize_width;
5171 if (info->resize_height > 0)
5172 *height = info->resize_height;
5176 static GtkWindowPosition
5177 get_effective_position (GtkWindow *window)
5179 GtkWindowPosition pos = window->position;
5180 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5181 (window->transient_parent == NULL ||
5182 !GTK_WIDGET_MAPPED (window->transient_parent)))
5183 pos = GTK_WIN_POS_NONE;
5189 get_center_monitor_of_window (GtkWindow *window)
5191 /* We could try to sort out the relative positions of the monitors and
5192 * stuff, or we could just be losers and assume you have a row
5193 * or column of monitors.
5195 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5199 get_monitor_containing_pointer (GtkWindow *window)
5203 GdkScreen *window_screen;
5204 GdkScreen *pointer_screen;
5206 window_screen = gtk_window_check_screen (window);
5207 gdk_display_get_pointer (gdk_screen_get_display (window_screen),
5211 if (pointer_screen == window_screen)
5212 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5220 center_window_on_monitor (GtkWindow *window,
5226 GdkRectangle monitor;
5229 monitor_num = get_monitor_containing_pointer (window);
5231 if (monitor_num == -1)
5232 monitor_num = get_center_monitor_of_window (window);
5234 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5235 monitor_num, &monitor);
5237 *x = (monitor.width - w) / 2 + monitor.x;
5238 *y = (monitor.height - h) / 2 + monitor.y;
5240 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5241 * and WM decorations.
5250 clamp_window_to_rectangle (gint *x,
5254 const GdkRectangle *rect)
5256 gint outside_w, outside_h;
5258 outside_w = (*x + w) - (rect->x + rect->width);
5262 outside_h = (*y + h) - (rect->y + rect->height);
5266 /* if larger than the screen, center on the screen. */
5268 *x += (rect->x - *x) / 2;
5270 *y += (rect->y - *y) / 2;
5275 gtk_window_compute_configure_request (GtkWindow *window,
5276 GdkRectangle *request,
5277 GdkGeometry *geometry,
5280 GdkGeometry new_geometry;
5284 GtkWindowPosition pos;
5285 GtkWidget *parent_widget;
5286 GtkWindowGeometryInfo *info;
5290 widget = GTK_WIDGET (window);
5292 screen = gtk_window_check_screen (window);
5294 gtk_widget_size_request (widget, NULL);
5295 gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
5297 gtk_window_compute_hints (window, &new_geometry, &new_flags);
5298 gtk_window_constrain_size (window,
5299 &new_geometry, new_flags,
5303 parent_widget = (GtkWidget*) window->transient_parent;
5305 pos = get_effective_position (window);
5306 info = gtk_window_get_geometry_info (window, FALSE);
5308 /* by default, don't change position requested */
5311 x = info->last.configure_request.x;
5312 y = info->last.configure_request.y;
5321 if (window->need_default_position)
5324 /* FIXME this all interrelates with window gravity.
5325 * For most of them I think we want to set GRAVITY_CENTER.
5327 * Not sure how to go about that.
5332 /* here we are only handling CENTER_ALWAYS
5333 * as it relates to default positioning,
5334 * where it's equivalent to simply CENTER
5336 case GTK_WIN_POS_CENTER_ALWAYS:
5337 case GTK_WIN_POS_CENTER:
5338 center_window_on_monitor (window, w, h, &x, &y);
5341 case GTK_WIN_POS_CENTER_ON_PARENT:
5344 GdkRectangle monitor;
5347 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
5349 if (parent_widget->window != NULL)
5350 monitor_num = gdk_screen_get_monitor_at_window (screen,
5351 parent_widget->window);
5355 gdk_window_get_origin (parent_widget->window,
5358 x = ox + (parent_widget->allocation.width - w) / 2;
5359 y = oy + (parent_widget->allocation.height - h) / 2;
5361 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5362 * WM decorations. If parent wasn't on a monitor, just
5365 if (monitor_num >= 0)
5367 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5368 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5373 case GTK_WIN_POS_MOUSE:
5375 gint screen_width = gdk_screen_get_width (screen);
5376 gint screen_height = gdk_screen_get_height (screen);
5378 GdkRectangle monitor;
5379 GdkScreen *pointer_screen;
5382 gdk_display_get_pointer (gdk_screen_get_display (screen),
5386 if (pointer_screen == screen)
5387 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
5393 x = CLAMP (x, 0, screen_width - w);
5394 y = CLAMP (y, 0, screen_height - h);
5396 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5397 * WM decorations. Don't try to figure out what's going
5398 * on if the mouse wasn't inside a monitor.
5400 if (monitor_num >= 0)
5402 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5403 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5411 } /* if (window->need_default_position) */
5413 if (window->need_default_position && info &&
5414 info->initial_pos_set)
5416 x = info->initial_x;
5417 y = info->initial_y;
5418 gtk_window_constrain_position (window, w, h, &x, &y);
5424 request->height = h;
5427 *geometry = new_geometry;
5433 gtk_window_constrain_position (GtkWindow *window,
5439 /* See long comments in gtk_window_move_resize()
5440 * on when it's safe to call this function.
5442 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
5444 gint center_x, center_y;
5446 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
5454 gtk_window_move_resize (GtkWindow *window)
5458 * First we determine whether any information has changed that would
5459 * cause us to revise our last configure request. If we would send
5460 * a different configure request from last time, then
5461 * configure_request_size_changed = TRUE or
5462 * configure_request_pos_changed = TRUE. configure_request_size_changed
5463 * may be true due to new hints, a gtk_window_resize(), or whatever.
5464 * configure_request_pos_changed may be true due to gtk_window_set_position()
5465 * or gtk_window_move().
5467 * If the configure request has changed, we send off a new one. To
5468 * ensure GTK+ invariants are maintained (resize queue does what it
5469 * should), we go ahead and size_allocate the requested size in this
5472 * If the configure request has not changed, we don't ever resend
5473 * it, because it could mean fighting the user or window manager.
5476 * To prepare the configure request, we come up with a base size/pos:
5477 * - the one from gtk_window_move()/gtk_window_resize()
5478 * - else default_width, default_height if we haven't ever
5480 * - else the size request if we haven't ever been mapped,
5481 * as a substitute default size
5482 * - else the current size of the window, as received from
5483 * configure notifies (i.e. the current allocation)
5485 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
5486 * the position request to be centered.
5489 GtkContainer *container;
5490 GtkWindowGeometryInfo *info;
5491 GdkGeometry new_geometry;
5493 GdkRectangle new_request;
5494 gboolean configure_request_size_changed;
5495 gboolean configure_request_pos_changed;
5496 gboolean hints_changed; /* do we need to send these again */
5497 GtkWindowLastGeometryInfo saved_last_info;
5499 widget = GTK_WIDGET (window);
5500 container = GTK_CONTAINER (widget);
5501 info = gtk_window_get_geometry_info (window, TRUE);
5503 configure_request_size_changed = FALSE;
5504 configure_request_pos_changed = FALSE;
5506 gtk_window_compute_configure_request (window, &new_request,
5507 &new_geometry, &new_flags);
5509 /* This check implies the invariant that we never set info->last
5510 * without setting the hints and sending off a configure request.
5512 * If we change info->last without sending the request, we may
5515 if (info->last.configure_request.x != new_request.x ||
5516 info->last.configure_request.y != new_request.y)
5517 configure_request_pos_changed = TRUE;
5519 if ((info->last.configure_request.width != new_request.width ||
5520 info->last.configure_request.height != new_request.height))
5521 configure_request_size_changed = TRUE;
5523 hints_changed = FALSE;
5525 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
5526 &new_geometry, new_flags))
5528 hints_changed = TRUE;
5531 /* Position Constraints
5532 * ====================
5534 * POS_CENTER_ALWAYS is conceptually a constraint rather than
5535 * a default. The other POS_ values are used only when the
5536 * window is shown, not after that.
5538 * However, we can't implement a position constraint as
5539 * "anytime the window size changes, center the window"
5540 * because this may well end up fighting the WM or user. In
5541 * fact it gets in an infinite loop with at least one WM.
5543 * Basically, applications are in no way in a position to
5544 * constrain the position of a window, with one exception:
5545 * override redirect windows. (Really the intended purpose
5546 * of CENTER_ALWAYS anyhow, I would think.)
5548 * So the way we implement this "constraint" is to say that when WE
5549 * cause a move or resize, i.e. we make a configure request changing
5550 * window size, we recompute the CENTER_ALWAYS position to reflect
5551 * the new window size, and include it in our request. Also, if we
5552 * just turned on CENTER_ALWAYS we snap to center with a new
5553 * request. Otherwise, if we are just NOTIFIED of a move or resize
5554 * done by someone else e.g. the window manager, we do NOT send a
5555 * new configure request.
5557 * For override redirect windows, this works fine; all window
5558 * sizes are from our configure requests. For managed windows,
5559 * it is at least semi-sane, though who knows what the
5560 * app author is thinking.
5563 /* This condition should be kept in sync with the condition later on
5564 * that determines whether we send a configure request. i.e. we
5565 * should do this position constraining anytime we were going to
5566 * send a configure request anyhow, plus when constraints have
5569 if (configure_request_pos_changed ||
5570 configure_request_size_changed ||
5572 info->position_constraints_changed)
5574 /* We request the constrained position if:
5575 * - we were changing position, and need to clamp
5576 * the change to the constraint
5577 * - we're changing the size anyway
5578 * - set_position() was called to toggle CENTER_ALWAYS on
5581 gtk_window_constrain_position (window,
5587 /* Update whether we need to request a move */
5588 if (info->last.configure_request.x != new_request.x ||
5589 info->last.configure_request.y != new_request.y)
5590 configure_request_pos_changed = TRUE;
5592 configure_request_pos_changed = FALSE;
5596 if (window->type == GTK_WINDOW_TOPLEVEL)
5598 int notify_x, notify_y;
5600 /* this is the position from the last configure notify */
5601 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
5603 g_message ("--- %s ---\n"
5604 "last : %d,%d\t%d x %d\n"
5605 "this : %d,%d\t%d x %d\n"
5606 "alloc : %d,%d\t%d x %d\n"
5608 "resize: \t%d x %d\n"
5609 "size_changed: %d pos_changed: %d hints_changed: %d\n"
5610 "configure_notify_received: %d\n"
5611 "configure_request_count: %d\n"
5612 "position_constraints_changed: %d\n",
5613 window->title ? window->title : "(no title)",
5614 info->last.configure_request.x,
5615 info->last.configure_request.y,
5616 info->last.configure_request.width,
5617 info->last.configure_request.height,
5623 widget->allocation.width,
5624 widget->allocation.height,
5625 widget->requisition.width,
5626 widget->requisition.height,
5628 info->resize_height,
5629 configure_request_pos_changed,
5630 configure_request_size_changed,
5632 window->configure_notify_received,
5633 window->configure_request_count,
5634 info->position_constraints_changed);
5638 saved_last_info = info->last;
5639 info->last.geometry = new_geometry;
5640 info->last.flags = new_flags;
5641 info->last.configure_request = new_request;
5643 /* need to set PPosition so the WM will look at our position,
5644 * but we don't want to count PPosition coming and going as a hints
5645 * change for future iterations. So we saved info->last prior to
5649 /* Also, if the initial position was explicitly set, then we always
5650 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
5654 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
5655 * this is an initial map
5658 if ((configure_request_pos_changed ||
5659 info->initial_pos_set ||
5660 (window->need_default_position &&
5661 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
5662 (new_flags & GDK_HINT_POS) == 0)
5664 new_flags |= GDK_HINT_POS;
5665 hints_changed = TRUE;
5668 /* Set hints if necessary
5671 gdk_window_set_geometry_hints (widget->window,
5675 /* handle resizing/moving and widget tree allocation
5677 if (window->configure_notify_received)
5679 GtkAllocation allocation;
5681 /* If we have received a configure event since
5682 * the last time in this function, we need to
5683 * accept our new size and size_allocate child widgets.
5684 * (see gtk_window_configure_event() for more details).
5686 * 1 or more configure notifies may have been received.
5687 * Also, configure_notify_received will only be TRUE
5688 * if all expected configure notifies have been received
5689 * (one per configure request), as an optimization.
5692 window->configure_notify_received = FALSE;
5694 /* gtk_window_configure_event() filled in widget->allocation */
5695 allocation = widget->allocation;
5696 gtk_widget_size_allocate (widget, &allocation);
5698 gdk_window_process_all_updates ();
5700 gdk_window_configure_finished (widget->window);
5702 /* If the configure request changed, it means that
5704 * 1) coincidentally changed hints or widget properties
5705 * impacting the configure request before getting
5706 * a configure notify, or
5707 * 2) some broken widget is changing its size request
5708 * during size allocation, resulting in
5709 * a false appearance of changed configure request.
5711 * For 1), we could just go ahead and ask for the
5712 * new size right now, but doing that for 2)
5713 * might well be fighting the user (and can even
5714 * trigger a loop). Since we really don't want to
5715 * do that, we requeue a resize in hopes that
5716 * by the time it gets handled, the child has seen
5717 * the light and is willing to go along with the
5718 * new size. (this happens for the zvt widget, since
5719 * the size_allocate() above will have stored the
5720 * requisition corresponding to the new size in the
5723 * This doesn't buy us anything for 1), but it shouldn't
5724 * hurt us too badly, since it is what would have
5725 * happened if we had gotten the configure event before
5726 * the new size had been set.
5729 if (configure_request_size_changed ||
5730 configure_request_pos_changed)
5732 /* Don't change the recorded last info after all, because we
5733 * haven't actually updated to the new info yet - we decided
5734 * to postpone our configure request until later.
5736 info->last = saved_last_info;
5738 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
5741 return; /* Bail out, we didn't really process the move/resize */
5743 else if ((configure_request_size_changed || hints_changed) &&
5744 (widget->allocation.width != new_request.width ||
5745 widget->allocation.height != new_request.height))
5748 /* We are in one of the following situations:
5749 * A. configure_request_size_changed
5750 * our requisition has changed and we need a different window size,
5751 * so we request it from the window manager.
5752 * B. !configure_request_size_changed && hints_changed
5753 * the window manager rejects our size, but we have just changed the
5754 * window manager hints, so there's a chance our request will
5755 * be honoured this time, so we try again.
5757 * However, if the new requisition is the same as the current allocation,
5758 * we don't request it again, since we won't get a ConfigureNotify back from
5759 * the window manager unless it decides to change our requisition. If
5760 * we don't get the ConfigureNotify back, the resize queue will never be run.
5763 /* Now send the configure request */
5764 if (configure_request_pos_changed)
5768 gdk_window_move_resize (window->frame,
5769 new_request.x - window->frame_left,
5770 new_request.y - window->frame_top,
5771 new_request.width + window->frame_left + window->frame_right,
5772 new_request.height + window->frame_top + window->frame_bottom);
5773 gdk_window_resize (widget->window,
5774 new_request.width, new_request.height);
5777 gdk_window_move_resize (widget->window,
5778 new_request.x, new_request.y,
5779 new_request.width, new_request.height);
5781 else /* only size changed */
5784 gdk_window_resize (window->frame,
5785 new_request.width + window->frame_left + window->frame_right,
5786 new_request.height + window->frame_top + window->frame_bottom);
5787 gdk_window_resize (widget->window,
5788 new_request.width, new_request.height);
5791 /* Increment the number of have-not-yet-received-notify requests */
5792 window->configure_request_count += 1;
5794 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5795 * configure event in response to our resizing request.
5796 * the configure event will cause a new resize with
5797 * ->configure_notify_received=TRUE.
5798 * until then, we want to
5799 * - discard expose events
5800 * - coalesce resizes for our children
5801 * - defer any window resizes until the configure event arrived
5802 * to achieve this, we queue a resize for the window, but remove its
5803 * resizing handler, so resizing will not be handled from the next
5804 * idle handler but when the configure event arrives.
5806 * FIXME: we should also dequeue the pending redraws here, since
5807 * we handle those ourselves upon ->configure_notify_received==TRUE.
5809 if (container->resize_mode == GTK_RESIZE_QUEUE)
5811 gtk_widget_queue_resize (widget);
5812 _gtk_container_dequeue_resize_handler (container);
5817 /* Handle any position changes.
5819 if (configure_request_pos_changed)
5823 gdk_window_move (window->frame,
5824 new_request.x - window->frame_left,
5825 new_request.y - window->frame_top);
5828 gdk_window_move (widget->window,
5829 new_request.x, new_request.y);
5832 /* And run the resize queue.
5834 gtk_container_resize_children (container);
5837 /* We have now processed a move/resize since the last position
5838 * constraint change, setting of the initial position, or resize.
5839 * (Not resetting these flags here can lead to infinite loops for
5840 * GTK_RESIZE_IMMEDIATE containers)
5842 info->position_constraints_changed = FALSE;
5843 info->initial_pos_set = FALSE;
5844 info->resize_width = -1;
5845 info->resize_height = -1;
5848 /* Compare two sets of Geometry hints for equality.
5851 gtk_window_compare_hints (GdkGeometry *geometry_a,
5853 GdkGeometry *geometry_b,
5856 if (flags_a != flags_b)
5859 if ((flags_a & GDK_HINT_MIN_SIZE) &&
5860 (geometry_a->min_width != geometry_b->min_width ||
5861 geometry_a->min_height != geometry_b->min_height))
5864 if ((flags_a & GDK_HINT_MAX_SIZE) &&
5865 (geometry_a->max_width != geometry_b->max_width ||
5866 geometry_a->max_height != geometry_b->max_height))
5869 if ((flags_a & GDK_HINT_BASE_SIZE) &&
5870 (geometry_a->base_width != geometry_b->base_width ||
5871 geometry_a->base_height != geometry_b->base_height))
5874 if ((flags_a & GDK_HINT_ASPECT) &&
5875 (geometry_a->min_aspect != geometry_b->min_aspect ||
5876 geometry_a->max_aspect != geometry_b->max_aspect))
5879 if ((flags_a & GDK_HINT_RESIZE_INC) &&
5880 (geometry_a->width_inc != geometry_b->width_inc ||
5881 geometry_a->height_inc != geometry_b->height_inc))
5884 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5885 geometry_a->win_gravity != geometry_b->win_gravity)
5892 _gtk_window_constrain_size (GtkWindow *window,
5898 GtkWindowGeometryInfo *info;
5900 g_return_if_fail (GTK_IS_WINDOW (window));
5902 info = window->geometry_info;
5905 GdkWindowHints flags = info->last.flags;
5906 GdkGeometry *geometry = &info->last.geometry;
5908 gtk_window_constrain_size (window,
5919 gtk_window_constrain_size (GtkWindow *window,
5920 GdkGeometry *geometry,
5927 gdk_window_constrain_size (geometry, flags, width, height,
5928 new_width, new_height);
5931 /* Compute the set of geometry hints and flags for a window
5932 * based on the application set geometry, and requisiition
5933 * of the window. gtk_widget_size_request() must have been
5937 gtk_window_compute_hints (GtkWindow *window,
5938 GdkGeometry *new_geometry,
5942 gint extra_width = 0;
5943 gint extra_height = 0;
5944 GtkWindowGeometryInfo *geometry_info;
5945 GtkRequisition requisition;
5947 widget = GTK_WIDGET (window);
5949 gtk_widget_get_child_requisition (widget, &requisition);
5950 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5954 *new_flags = geometry_info->mask;
5955 *new_geometry = geometry_info->geometry;
5962 if (geometry_info && geometry_info->widget)
5964 GtkRequisition child_requisition;
5966 /* FIXME: This really isn't right. It gets the min size wrong and forces
5967 * callers to do horrible hacks like set a huge usize on the child requisition
5968 * to get the base size right. We really want to find the answers to:
5970 * - If the geometry widget was infinitely big, how much extra space
5971 * would be needed for the stuff around it.
5973 * - If the geometry widget was infinitely small, how big would the
5974 * window still have to be.
5976 * Finding these answers would be a bit of a mess here. (Bug #68668)
5978 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5980 extra_width = widget->requisition.width - child_requisition.width;
5981 extra_height = widget->requisition.height - child_requisition.height;
5984 /* We don't want to set GDK_HINT_POS in here, we just set it
5985 * in gtk_window_move_resize() when we want the position
5989 if (*new_flags & GDK_HINT_BASE_SIZE)
5991 new_geometry->base_width += extra_width;
5992 new_geometry->base_height += extra_height;
5994 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5995 (*new_flags & GDK_HINT_RESIZE_INC) &&
5996 ((extra_width != 0) || (extra_height != 0)))
5998 *new_flags |= GDK_HINT_BASE_SIZE;
6000 new_geometry->base_width = extra_width;
6001 new_geometry->base_height = extra_height;
6004 if (*new_flags & GDK_HINT_MIN_SIZE)
6006 if (new_geometry->min_width < 0)
6007 new_geometry->min_width = requisition.width;
6009 new_geometry->min_width += extra_width;
6011 if (new_geometry->min_height < 0)
6012 new_geometry->min_height = requisition.height;
6014 new_geometry->min_height += extra_height;
6016 else if (!window->allow_shrink)
6018 *new_flags |= GDK_HINT_MIN_SIZE;
6020 new_geometry->min_width = requisition.width;
6021 new_geometry->min_height = requisition.height;
6024 if (*new_flags & GDK_HINT_MAX_SIZE)
6026 if (new_geometry->max_width < 0)
6027 new_geometry->max_width = requisition.width;
6029 new_geometry->max_width += extra_width;
6031 if (new_geometry->max_height < 0)
6032 new_geometry->max_height = requisition.height;
6034 new_geometry->max_height += extra_height;
6036 else if (!window->allow_grow)
6038 *new_flags |= GDK_HINT_MAX_SIZE;
6040 new_geometry->max_width = requisition.width;
6041 new_geometry->max_height = requisition.height;
6044 *new_flags |= GDK_HINT_WIN_GRAVITY;
6045 new_geometry->win_gravity = window->gravity;
6048 /***********************
6049 * Redrawing functions *
6050 ***********************/
6053 gtk_window_paint (GtkWidget *widget,
6056 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
6057 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
6061 gtk_window_expose (GtkWidget *widget,
6062 GdkEventExpose *event)
6064 if (!GTK_WIDGET_APP_PAINTABLE (widget))
6065 gtk_window_paint (widget, &event->area);
6067 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event)
6068 return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event);
6074 * gtk_window_set_has_frame:
6075 * @window: a #GtkWindow
6076 * @setting: a boolean
6078 * (Note: this is a special-purpose function for the framebuffer port,
6079 * that causes GTK+ to draw its own window border. For most applications,
6080 * you want gtk_window_set_decorated() instead, which tells the window
6081 * manager whether to draw the window border.)
6083 * If this function is called on a window with setting of %TRUE, before
6084 * it is realized or showed, it will have a "frame" window around
6085 * @window->window, accessible in @window->frame. Using the signal
6086 * frame_event you can receive all events targeted at the frame.
6088 * This function is used by the linux-fb port to implement managed
6089 * windows, but it could conceivably be used by X-programs that
6090 * want to do their own window decorations.
6094 gtk_window_set_has_frame (GtkWindow *window,
6097 g_return_if_fail (GTK_IS_WINDOW (window));
6098 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
6100 window->has_frame = setting != FALSE;
6104 * gtk_window_get_has_frame:
6105 * @window: a #GtkWindow
6107 * Accessor for whether the window has a frame window exterior to
6108 * @window->window. Gets the value set by gtk_window_set_has_frame ().
6110 * Return value: %TRUE if a frame has been added to the window
6111 * via gtk_window_set_has_frame().
6114 gtk_window_get_has_frame (GtkWindow *window)
6116 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6118 return window->has_frame;
6122 * gtk_window_set_frame_dimensions:
6123 * @window: a #GtkWindow that has a frame
6124 * @left: The width of the left border
6125 * @top: The height of the top border
6126 * @right: The width of the right border
6127 * @bottom: The height of the bottom border
6129 * (Note: this is a special-purpose function intended for the framebuffer
6130 * port; see gtk_window_set_has_frame(). It will have no effect on the
6131 * window border drawn by the window manager, which is the normal
6132 * case when using the X Window system.)
6134 * For windows with frames (see gtk_window_set_has_frame()) this function
6135 * can be used to change the size of the frame border.
6138 gtk_window_set_frame_dimensions (GtkWindow *window,
6146 g_return_if_fail (GTK_IS_WINDOW (window));
6148 widget = GTK_WIDGET (window);
6150 if (window->frame_left == left &&
6151 window->frame_top == top &&
6152 window->frame_right == right &&
6153 window->frame_bottom == bottom)
6156 window->frame_left = left;
6157 window->frame_top = top;
6158 window->frame_right = right;
6159 window->frame_bottom = bottom;
6161 if (GTK_WIDGET_REALIZED (widget) && window->frame)
6163 gint width = widget->allocation.width + left + right;
6164 gint height = widget->allocation.height + top + bottom;
6165 gdk_window_resize (window->frame, width, height);
6166 gtk_decorated_window_move_resize_window (window,
6168 widget->allocation.width,
6169 widget->allocation.height);
6174 * gtk_window_present:
6175 * @window: a #GtkWindow
6177 * Presents a window to the user. This may mean raising the window
6178 * in the stacking order, deiconifying it, moving it to the current
6179 * desktop, and/or giving it the keyboard focus, possibly dependent
6180 * on the user's platform, window manager, and preferences.
6182 * If @window is hidden, this function calls gtk_widget_show()
6185 * This function should be used when the user tries to open a window
6186 * that's already open. Say for example the preferences dialog is
6187 * currently open, and the user chooses Preferences from the menu
6188 * a second time; use gtk_window_present() to move the already-open dialog
6189 * where the user can see it.
6191 * If you are calling this function in response to a user interaction,
6192 * it is preferable to use gtk_window_present_with_time().
6196 gtk_window_present (GtkWindow *window)
6198 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6202 * gtk_window_present_with_time:
6203 * @window: a #GtkWindow
6204 * @timestamp: the timestamp of the user interaction (typically a
6205 * button or key press event) which triggered this call
6207 * Presents a window to the user in response to a user interaction.
6208 * If you need to present a window without a timestamp, use
6209 * gtk_window_present(). See gtk_window_present() for details.
6214 gtk_window_present_with_time (GtkWindow *window,
6219 g_return_if_fail (GTK_IS_WINDOW (window));
6221 widget = GTK_WIDGET (window);
6223 if (GTK_WIDGET_VISIBLE (window))
6225 g_assert (widget->window != NULL);
6227 gdk_window_show (widget->window);
6229 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
6230 if (timestamp == GDK_CURRENT_TIME)
6232 #ifdef GDK_WINDOWING_X11
6233 GdkDisplay *display;
6235 display = gtk_widget_get_display (GTK_WIDGET (window));
6236 timestamp = gdk_x11_display_get_user_time (display);
6238 timestamp = gtk_get_current_event_time ();
6242 gdk_window_focus (widget->window, timestamp);
6246 gtk_widget_show (widget);
6251 * gtk_window_iconify:
6252 * @window: a #GtkWindow
6254 * Asks to iconify (i.e. minimize) the specified @window. Note that
6255 * you shouldn't assume the window is definitely iconified afterward,
6256 * because other entities (e.g. the user or <link
6257 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
6258 * again, or there may not be a window manager in which case
6259 * iconification isn't possible, etc. But normally the window will end
6260 * up iconified. Just don't write code that crashes if not.
6262 * It's permitted to call this function before showing a window,
6263 * in which case the window will be iconified before it ever appears
6266 * You can track iconification via the "window_state_event" signal
6271 gtk_window_iconify (GtkWindow *window)
6274 GdkWindow *toplevel;
6276 g_return_if_fail (GTK_IS_WINDOW (window));
6278 widget = GTK_WIDGET (window);
6280 window->iconify_initially = TRUE;
6283 toplevel = window->frame;
6285 toplevel = widget->window;
6287 if (toplevel != NULL)
6288 gdk_window_iconify (toplevel);
6292 * gtk_window_deiconify:
6293 * @window: a #GtkWindow
6295 * Asks to deiconify (i.e. unminimize) the specified @window. Note
6296 * that you shouldn't assume the window is definitely deiconified
6297 * afterward, because other entities (e.g. the user or <link
6298 * linkend="gtk-X11-arch">window manager</link>) could iconify it
6299 * again before your code which assumes deiconification gets to run.
6301 * You can track iconification via the "window_state_event" signal
6305 gtk_window_deiconify (GtkWindow *window)
6308 GdkWindow *toplevel;
6310 g_return_if_fail (GTK_IS_WINDOW (window));
6312 widget = GTK_WIDGET (window);
6314 window->iconify_initially = FALSE;
6317 toplevel = window->frame;
6319 toplevel = widget->window;
6321 if (toplevel != NULL)
6322 gdk_window_deiconify (toplevel);
6327 * @window: a #GtkWindow
6329 * Asks to stick @window, which means that it will appear on all user
6330 * desktops. Note that you shouldn't assume the window is definitely
6331 * stuck afterward, because other entities (e.g. the user or <link
6332 * linkend="gtk-X11-arch">window manager</link>) could unstick it
6333 * again, and some window managers do not support sticking
6334 * windows. But normally the window will end up stuck. Just don't
6335 * write code that crashes if not.
6337 * It's permitted to call this function before showing a window.
6339 * You can track stickiness via the "window_state_event" signal
6344 gtk_window_stick (GtkWindow *window)
6347 GdkWindow *toplevel;
6349 g_return_if_fail (GTK_IS_WINDOW (window));
6351 widget = GTK_WIDGET (window);
6353 window->stick_initially = TRUE;
6356 toplevel = window->frame;
6358 toplevel = widget->window;
6360 if (toplevel != NULL)
6361 gdk_window_stick (toplevel);
6365 * gtk_window_unstick:
6366 * @window: a #GtkWindow
6368 * Asks to unstick @window, which means that it will appear on only
6369 * one of the user's desktops. Note that you shouldn't assume the
6370 * window is definitely unstuck afterward, because other entities
6371 * (e.g. the user or <link linkend="gtk-X11-arch">window
6372 * manager</link>) could stick it again. But normally the window will
6373 * end up stuck. Just don't write code that crashes if not.
6375 * You can track stickiness via the "window_state_event" signal
6380 gtk_window_unstick (GtkWindow *window)
6383 GdkWindow *toplevel;
6385 g_return_if_fail (GTK_IS_WINDOW (window));
6387 widget = GTK_WIDGET (window);
6389 window->stick_initially = FALSE;
6392 toplevel = window->frame;
6394 toplevel = widget->window;
6396 if (toplevel != NULL)
6397 gdk_window_unstick (toplevel);
6401 * gtk_window_maximize:
6402 * @window: a #GtkWindow
6404 * Asks to maximize @window, so that it becomes full-screen. Note that
6405 * you shouldn't assume the window is definitely maximized afterward,
6406 * because other entities (e.g. the user or <link
6407 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
6408 * again, and not all window managers support maximization. But
6409 * normally the window will end up maximized. Just don't write code
6410 * that crashes if not.
6412 * It's permitted to call this function before showing a window,
6413 * in which case the window will be maximized when it appears onscreen
6416 * You can track maximization via the "window_state_event" signal
6421 gtk_window_maximize (GtkWindow *window)
6424 GdkWindow *toplevel;
6426 g_return_if_fail (GTK_IS_WINDOW (window));
6428 widget = GTK_WIDGET (window);
6430 window->maximize_initially = TRUE;
6433 toplevel = window->frame;
6435 toplevel = widget->window;
6437 if (toplevel != NULL)
6438 gdk_window_maximize (toplevel);
6442 * gtk_window_unmaximize:
6443 * @window: a #GtkWindow
6445 * Asks to unmaximize @window. Note that you shouldn't assume the
6446 * window is definitely unmaximized afterward, because other entities
6447 * (e.g. the user or <link linkend="gtk-X11-arch">window
6448 * manager</link>) could maximize it again, and not all window
6449 * managers honor requests to unmaximize. But normally the window will
6450 * end up unmaximized. Just don't write code that crashes if not.
6452 * You can track maximization via the "window_state_event" signal
6457 gtk_window_unmaximize (GtkWindow *window)
6460 GdkWindow *toplevel;
6462 g_return_if_fail (GTK_IS_WINDOW (window));
6464 widget = GTK_WIDGET (window);
6466 window->maximize_initially = FALSE;
6469 toplevel = window->frame;
6471 toplevel = widget->window;
6473 if (toplevel != NULL)
6474 gdk_window_unmaximize (toplevel);
6478 * gtk_window_fullscreen:
6479 * @window: a #GtkWindow
6481 * Asks to place @window in the fullscreen state. Note that you
6482 * shouldn't assume the window is definitely full screen afterward,
6483 * because other entities (e.g. the user or <link
6484 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
6485 * again, and not all window managers honor requests to fullscreen
6486 * windows. But normally the window will end up fullscreen. Just
6487 * don't write code that crashes if not.
6489 * You can track the fullscreen state via the "window_state_event" signal
6495 gtk_window_fullscreen (GtkWindow *window)
6498 GdkWindow *toplevel;
6499 GtkWindowPrivate *priv;
6501 g_return_if_fail (GTK_IS_WINDOW (window));
6503 widget = GTK_WIDGET (window);
6504 priv = GTK_WINDOW_GET_PRIVATE (window);
6506 priv->fullscreen_initially = TRUE;
6509 toplevel = window->frame;
6511 toplevel = widget->window;
6513 if (toplevel != NULL)
6514 gdk_window_fullscreen (toplevel);
6518 * gtk_window_unfullscreen:
6519 * @window: a #GtkWindow
6521 * Asks to toggle off the fullscreen state for @window. Note that you
6522 * shouldn't assume the window is definitely not full screen
6523 * afterward, because other entities (e.g. the user or <link
6524 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
6525 * again, and not all window managers honor requests to unfullscreen
6526 * windows. But normally the window will end up restored to its normal
6527 * state. Just don't write code that crashes if not.
6529 * You can track the fullscreen state via the "window_state_event" signal
6535 gtk_window_unfullscreen (GtkWindow *window)
6538 GdkWindow *toplevel;
6539 GtkWindowPrivate *priv;
6541 g_return_if_fail (GTK_IS_WINDOW (window));
6543 widget = GTK_WIDGET (window);
6544 priv = GTK_WINDOW_GET_PRIVATE (window);
6546 priv->fullscreen_initially = FALSE;
6549 toplevel = window->frame;
6551 toplevel = widget->window;
6553 if (toplevel != NULL)
6554 gdk_window_unfullscreen (toplevel);
6558 * gtk_window_set_keep_above:
6559 * @window: a #GtkWindow
6560 * @setting: whether to keep @window above other windows
6562 * Asks to keep @window above, so that it stays on top. Note that
6563 * you shouldn't assume the window is definitely above afterward,
6564 * because other entities (e.g. the user or <link
6565 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
6566 * and not all window managers support keeping windows above. But
6567 * normally the window will end kept above. Just don't write code
6568 * that crashes if not.
6570 * It's permitted to call this function before showing a window,
6571 * in which case the window will be kept above when it appears onscreen
6574 * You can track the above state via the "window_state_event" signal
6577 * Note that, according to the <ulink
6578 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
6579 * Manager Hints</ulink> specification, the above state is mainly meant
6580 * for user preferences and should not be used by applications e.g. for
6581 * drawing attention to their dialogs.
6586 gtk_window_set_keep_above (GtkWindow *window,
6590 GtkWindowPrivate *priv;
6591 GdkWindow *toplevel;
6593 g_return_if_fail (GTK_IS_WINDOW (window));
6595 widget = GTK_WIDGET (window);
6596 priv = GTK_WINDOW_GET_PRIVATE (window);
6598 priv->above_initially = setting != FALSE;
6600 priv->below_initially = FALSE;
6603 toplevel = window->frame;
6605 toplevel = widget->window;
6607 if (toplevel != NULL)
6608 gdk_window_set_keep_above (toplevel, setting);
6612 * gtk_window_set_keep_below:
6613 * @window: a #GtkWindow
6614 * @setting: whether to keep @window below other windows
6616 * Asks to keep @window below, so that it stays in bottom. Note that
6617 * you shouldn't assume the window is definitely below afterward,
6618 * because other entities (e.g. the user or <link
6619 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
6620 * and not all window managers support putting windows below. But
6621 * normally the window will be kept below. Just don't write code
6622 * that crashes if not.
6624 * It's permitted to call this function before showing a window,
6625 * in which case the window will be kept below when it appears onscreen
6628 * You can track the below state via the "window_state_event" signal
6631 * Note that, according to the <ulink
6632 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
6633 * Manager Hints</ulink> specification, the above state is mainly meant
6634 * for user preferences and should not be used by applications e.g. for
6635 * drawing attention to their dialogs.
6640 gtk_window_set_keep_below (GtkWindow *window,
6644 GtkWindowPrivate *priv;
6645 GdkWindow *toplevel;
6647 g_return_if_fail (GTK_IS_WINDOW (window));
6649 widget = GTK_WIDGET (window);
6650 priv = GTK_WINDOW_GET_PRIVATE (window);
6652 priv->below_initially = setting != FALSE;
6654 priv->above_initially = FALSE;
6657 toplevel = window->frame;
6659 toplevel = widget->window;
6661 if (toplevel != NULL)
6662 gdk_window_set_keep_below (toplevel, setting);
6666 * gtk_window_set_resizable:
6667 * @window: a #GtkWindow
6668 * @resizable: %TRUE if the user can resize this window
6670 * Sets whether the user can resize a window. Windows are user resizable
6674 gtk_window_set_resizable (GtkWindow *window,
6677 g_return_if_fail (GTK_IS_WINDOW (window));
6679 gtk_window_set_policy (window, FALSE, resizable, FALSE);
6683 * gtk_window_get_resizable:
6684 * @window: a #GtkWindow
6686 * Gets the value set by gtk_window_set_resizable().
6688 * Return value: %TRUE if the user can resize the window
6691 gtk_window_get_resizable (GtkWindow *window)
6693 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6695 /* allow_grow is most likely to indicate the semantic concept we
6696 * mean by "resizable" (and will be a reliable indicator if
6697 * set_policy() hasn't been called)
6699 return window->allow_grow;
6703 * gtk_window_set_gravity:
6704 * @window: a #GtkWindow
6705 * @gravity: window gravity
6707 * Window gravity defines the meaning of coordinates passed to
6708 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
6711 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
6712 * typically "do what you mean."
6716 gtk_window_set_gravity (GtkWindow *window,
6719 g_return_if_fail (GTK_IS_WINDOW (window));
6721 if (gravity != window->gravity)
6723 window->gravity = gravity;
6725 /* gtk_window_move_resize() will adapt gravity
6727 gtk_widget_queue_resize (GTK_WIDGET (window));
6729 g_object_notify (G_OBJECT (window), "gravity");
6734 * gtk_window_get_gravity:
6735 * @window: a #GtkWindow
6737 * Gets the value set by gtk_window_set_gravity().
6739 * Return value: window gravity
6742 gtk_window_get_gravity (GtkWindow *window)
6744 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
6746 return window->gravity;
6750 * gtk_window_begin_resize_drag:
6751 * @window: a #GtkWindow
6752 * @button: mouse button that initiated the drag
6753 * @edge: position of the resize control
6754 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6755 * @root_y: Y position where the user clicked to initiate the drag
6756 * @timestamp: timestamp from the click event that initiated the drag
6758 * Starts resizing a window. This function is used if an application
6759 * has window resizing controls. When GDK can support it, the resize
6760 * will be done using the standard mechanism for the <link
6761 * linkend="gtk-X11-arch">window manager</link> or windowing
6762 * system. Otherwise, GDK will try to emulate window resizing,
6763 * potentially not all that well, depending on the windowing system.
6767 gtk_window_begin_resize_drag (GtkWindow *window,
6775 GdkWindow *toplevel;
6777 g_return_if_fail (GTK_IS_WINDOW (window));
6778 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6780 widget = GTK_WIDGET (window);
6783 toplevel = window->frame;
6785 toplevel = widget->window;
6787 gdk_window_begin_resize_drag (toplevel,
6794 * gtk_window_get_frame_dimensions:
6795 * @window: a #GtkWindow
6796 * @left: location to store the width of the frame at the left, or %NULL
6797 * @top: location to store the height of the frame at the top, or %NULL
6798 * @right: location to store the width of the frame at the returns, or %NULL
6799 * @bottom: location to store the height of the frame at the bottom, or %NULL
6801 * (Note: this is a special-purpose function intended for the
6802 * framebuffer port; see gtk_window_set_has_frame(). It will not
6803 * return the size of the window border drawn by the <link
6804 * linkend="gtk-X11-arch">window manager</link>, which is the normal
6805 * case when using a windowing system. See
6806 * gdk_window_get_frame_extents() to get the standard window border
6809 * Retrieves the dimensions of the frame window for this toplevel.
6810 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
6813 gtk_window_get_frame_dimensions (GtkWindow *window,
6819 g_return_if_fail (GTK_IS_WINDOW (window));
6822 *left = window->frame_left;
6824 *top = window->frame_top;
6826 *right = window->frame_right;
6828 *bottom = window->frame_bottom;
6832 * gtk_window_begin_move_drag:
6833 * @window: a #GtkWindow
6834 * @button: mouse button that initiated the drag
6835 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6836 * @root_y: Y position where the user clicked to initiate the drag
6837 * @timestamp: timestamp from the click event that initiated the drag
6839 * Starts moving a window. This function is used if an application has
6840 * window movement grips. When GDK can support it, the window movement
6841 * will be done using the standard mechanism for the <link
6842 * linkend="gtk-X11-arch">window manager</link> or windowing
6843 * system. Otherwise, GDK will try to emulate window movement,
6844 * potentially not all that well, depending on the windowing system.
6848 gtk_window_begin_move_drag (GtkWindow *window,
6855 GdkWindow *toplevel;
6857 g_return_if_fail (GTK_IS_WINDOW (window));
6858 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6860 widget = GTK_WIDGET (window);
6863 toplevel = window->frame;
6865 toplevel = widget->window;
6867 gdk_window_begin_move_drag (toplevel,
6874 * gtk_window_set_screen:
6875 * @window: a #GtkWindow.
6876 * @screen: a #GdkScreen.
6878 * Sets the #GdkScreen where the @window is displayed; if
6879 * the window is already mapped, it will be unmapped, and
6880 * then remapped on the new screen.
6885 gtk_window_set_screen (GtkWindow *window,
6889 GdkScreen *previous_screen;
6890 gboolean was_mapped;
6892 g_return_if_fail (GTK_IS_WINDOW (window));
6893 g_return_if_fail (GDK_IS_SCREEN (screen));
6895 if (screen == window->screen)
6898 widget = GTK_WIDGET (window);
6900 previous_screen = window->screen;
6901 was_mapped = GTK_WIDGET_MAPPED (widget);
6904 gtk_widget_unmap (widget);
6905 if (GTK_WIDGET_REALIZED (widget))
6906 gtk_widget_unrealize (widget);
6908 gtk_window_free_key_hash (window);
6909 window->screen = screen;
6910 gtk_widget_reset_rc_styles (widget);
6911 if (screen != previous_screen)
6913 g_signal_handlers_disconnect_by_func (previous_screen,
6914 gtk_window_on_composited_changed, window);
6915 g_signal_connect (screen, "composited_changed",
6916 G_CALLBACK (gtk_window_on_composited_changed), window);
6918 _gtk_widget_propagate_screen_changed (widget, previous_screen);
6919 _gtk_widget_propagate_composited_changed (widget);
6921 g_object_notify (G_OBJECT (window), "screen");
6924 gtk_widget_map (widget);
6928 gtk_window_on_composited_changed (GdkScreen *screen,
6931 gtk_widget_queue_draw (GTK_WIDGET (window));
6933 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
6937 gtk_window_check_screen (GtkWindow *window)
6940 return window->screen;
6943 g_warning ("Screen for GtkWindow not set; you must always set\n"
6944 "a screen for a GtkWindow before using the window");
6950 * gtk_window_get_screen:
6951 * @window: a #GtkWindow.
6953 * Returns the #GdkScreen associated with @window.
6955 * Return value: a #GdkScreen.
6960 gtk_window_get_screen (GtkWindow *window)
6962 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6964 return window->screen;
6968 * gtk_window_is_active:
6969 * @window: a #GtkWindow
6971 * Returns whether the window is part of the current active toplevel.
6972 * (That is, the toplevel window receiving keystrokes.)
6973 * The return value is %TRUE if the window is active toplevel
6974 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
6975 * You might use this function if you wanted to draw a widget
6976 * differently in an active window from a widget in an inactive window.
6977 * See gtk_window_has_toplevel_focus()
6979 * Return value: %TRUE if the window part of the current active window.
6984 gtk_window_is_active (GtkWindow *window)
6986 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6988 return window->is_active;
6992 * gtk_window_has_toplevel_focus:
6993 * @window: a #GtkWindow
6995 * Returns whether the input focus is within this GtkWindow.
6996 * For real toplevel windows, this is identical to gtk_window_is_active(),
6997 * but for embedded windows, like #GtkPlug, the results will differ.
6999 * Return value: %TRUE if the input focus is within this GtkWindow
7004 gtk_window_has_toplevel_focus (GtkWindow *window)
7006 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7008 return window->has_toplevel_focus;
7012 gtk_window_group_class_init (GtkWindowGroupClass *klass)
7017 gtk_window_group_get_type (void)
7019 static GType window_group_type = 0;
7021 if (!window_group_type)
7023 const GTypeInfo window_group_info =
7025 sizeof (GtkWindowGroupClass),
7026 NULL, /* base_init */
7027 NULL, /* base_finalize */
7028 (GClassInitFunc) gtk_window_group_class_init,
7029 NULL, /* class_finalize */
7030 NULL, /* class_data */
7031 sizeof (GtkWindowGroup),
7032 0, /* n_preallocs */
7033 (GInstanceInitFunc) NULL,
7036 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
7037 &window_group_info, 0);
7040 return window_group_type;
7044 * gtk_window_group_new:
7046 * Creates a new #GtkWindowGroup object. Grabs added with
7047 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
7049 * Return value: a new #GtkWindowGroup.
7052 gtk_window_group_new (void)
7054 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
7058 window_group_cleanup_grabs (GtkWindowGroup *group,
7062 GSList *to_remove = NULL;
7064 tmp_list = group->grabs;
7067 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
7068 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
7069 tmp_list = tmp_list->next;
7074 gtk_grab_remove (to_remove->data);
7075 g_object_unref (to_remove->data);
7076 to_remove = g_slist_delete_link (to_remove, to_remove);
7081 * gtk_window_group_add_window:
7082 * @window_group: a #GtkWindowGroup
7083 * @window: the #GtkWindow to add
7085 * Adds a window to a #GtkWindowGroup.
7088 gtk_window_group_add_window (GtkWindowGroup *window_group,
7091 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7092 g_return_if_fail (GTK_IS_WINDOW (window));
7094 if (window->group != window_group)
7096 g_object_ref (window);
7097 g_object_ref (window_group);
7100 gtk_window_group_remove_window (window->group, window);
7102 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
7104 window->group = window_group;
7106 g_object_unref (window);
7111 * gtk_window_group_remove_window:
7112 * @window_group: a #GtkWindowGroup
7113 * @window: the #GtkWindow to remove
7115 * Removes a window from a #GtkWindowGroup.
7118 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7121 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7122 g_return_if_fail (GTK_IS_WIDGET (window));
7123 g_return_if_fail (window->group == window_group);
7125 g_object_ref (window);
7127 window_group_cleanup_grabs (window_group, window);
7128 window->group = NULL;
7130 g_object_unref (window_group);
7131 g_object_unref (window);
7135 * gtk_window_get_group:
7136 * @window: a #GtkWindow, or %NULL
7138 * Returns the group for @window or the default group, if
7139 * @window is %NULL or if @window does not have an explicit
7142 * Returns: the #GtkWindowGroup for a window or the default group
7147 gtk_window_get_group (GtkWindow *window)
7149 if (window && window->group)
7150 return window->group;
7153 static GtkWindowGroup *default_group = NULL;
7156 default_group = gtk_window_group_new ();
7158 return default_group;
7162 /* Return the current grab widget of the given group
7165 _gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
7167 if (window_group->grabs)
7168 return GTK_WIDGET (window_group->grabs->data);
7173 Derived from XParseGeometry() in XFree86
7175 Copyright 1985, 1986, 1987,1998 The Open Group
7177 All Rights Reserved.
7179 The above copyright notice and this permission notice shall be included
7180 in all copies or substantial portions of the Software.
7182 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
7183 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7184 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7185 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
7186 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7187 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
7188 OTHER DEALINGS IN THE SOFTWARE.
7190 Except as contained in this notice, the name of The Open Group shall
7191 not be used in advertising or otherwise to promote the sale, use or
7192 other dealings in this Software without prior written authorization
7193 from The Open Group.
7198 * XParseGeometry parses strings of the form
7199 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
7200 * width, height, xoffset, and yoffset are unsigned integers.
7201 * Example: "=80x24+300-49"
7202 * The equal sign is optional.
7203 * It returns a bitmask that indicates which of the four values
7204 * were actually found in the string. For each value found,
7205 * the corresponding argument is updated; for each value
7206 * not found, the corresponding argument is left unchanged.
7209 /* The following code is from Xlib, and is minimally modified, so we
7210 * can track any upstream changes if required. Don't change this
7211 * code. Or if you do, put in a huge comment marking which thing
7216 read_int (gchar *string,
7224 else if (*string == '-')
7230 for (; (*string >= '0') && (*string <= '9'); string++)
7232 result = (result * 10) + (*string - '0');
7244 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
7245 * value (x, y, width, height) was found in the parsed string.
7247 #define NoValue 0x0000
7248 #define XValue 0x0001
7249 #define YValue 0x0002
7250 #define WidthValue 0x0004
7251 #define HeightValue 0x0008
7252 #define AllValues 0x000F
7253 #define XNegative 0x0010
7254 #define YNegative 0x0020
7256 /* Try not to reformat/modify, so we can compare/sync with X sources */
7258 gtk_XParseGeometry (const char *string,
7261 unsigned int *width,
7262 unsigned int *height)
7266 unsigned int tempWidth, tempHeight;
7268 char *nextCharacter;
7270 /* These initializations are just to silence gcc */
7276 if ( (string == NULL) || (*string == '\0')) return(mask);
7278 string++; /* ignore possible '=' at beg of geometry spec */
7280 strind = (char *)string;
7281 if (*strind != '+' && *strind != '-' && *strind != 'x') {
7282 tempWidth = read_int(strind, &nextCharacter);
7283 if (strind == nextCharacter)
7285 strind = nextCharacter;
7289 if (*strind == 'x' || *strind == 'X') {
7291 tempHeight = read_int(strind, &nextCharacter);
7292 if (strind == nextCharacter)
7294 strind = nextCharacter;
7295 mask |= HeightValue;
7298 if ((*strind == '+') || (*strind == '-')) {
7299 if (*strind == '-') {
7301 tempX = -read_int(strind, &nextCharacter);
7302 if (strind == nextCharacter)
7304 strind = nextCharacter;
7310 tempX = read_int(strind, &nextCharacter);
7311 if (strind == nextCharacter)
7313 strind = nextCharacter;
7316 if ((*strind == '+') || (*strind == '-')) {
7317 if (*strind == '-') {
7319 tempY = -read_int(strind, &nextCharacter);
7320 if (strind == nextCharacter)
7322 strind = nextCharacter;
7329 tempY = read_int(strind, &nextCharacter);
7330 if (strind == nextCharacter)
7332 strind = nextCharacter;
7338 /* If strind isn't at the end of the string the it's an invalid
7339 geometry specification. */
7341 if (*strind != '\0') return (0);
7347 if (mask & WidthValue)
7349 if (mask & HeightValue)
7350 *height = tempHeight;
7355 * gtk_window_parse_geometry:
7356 * @window: a #GtkWindow
7357 * @geometry: geometry string
7359 * Parses a standard X Window System geometry string - see the
7360 * manual page for X (type 'man X') for details on this.
7361 * gtk_window_parse_geometry() does work on all GTK+ ports
7362 * including Win32 but is primarily intended for an X environment.
7364 * If either a size or a position can be extracted from the
7365 * geometry string, gtk_window_parse_geometry() returns %TRUE
7366 * and calls gtk_window_set_default_size() and/or gtk_window_move()
7367 * to resize/move the window.
7369 * If gtk_window_parse_geometry() returns %TRUE, it will also
7370 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
7371 * indicating to the window manager that the size/position of
7372 * the window was user-specified. This causes most window
7373 * managers to honor the geometry.
7375 * Note that for gtk_window_parse_geometry() to work as expected, it has
7376 * to be called when the window has its "final" size, i.e. after calling
7377 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
7380 * <informalexample><programlisting>
7381 * #include <gtk/gtk.h>
7384 * fill_with_content (GtkWidget *vbox)
7386 * /<!-- -->* fill with content... *<!-- -->/
7390 * main (int argc, char *argv[])
7392 * GtkWidget *window, *vbox;
7393 * GdkGeometry size_hints = {
7394 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
7397 * gtk_init (&argc, &argv);
7399 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7400 * vbox = gtk_vbox_new (FALSE, 0);
7402 * gtk_container_add (GTK_CONTAINER (window), vbox);
7403 * fill_with_content (vbox);
7404 * gtk_widget_show_all (vbox);
7406 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
7409 * GDK_HINT_MIN_SIZE |
7410 * GDK_HINT_BASE_SIZE |
7411 * GDK_HINT_RESIZE_INC);
7415 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
7416 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
7419 * gtk_widget_show_all (window);
7424 * </programlisting></informalexample>
7426 * Return value: %TRUE if string was parsed successfully
7429 gtk_window_parse_geometry (GtkWindow *window,
7430 const gchar *geometry)
7432 gint result, x = 0, y = 0;
7435 gboolean size_set, pos_set;
7438 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7439 g_return_val_if_fail (geometry != NULL, FALSE);
7441 screen = gtk_window_check_screen (window);
7443 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
7446 if ((result & WidthValue) || (result & HeightValue))
7448 gtk_window_set_default_size_internal (window,
7449 TRUE, result & WidthValue ? w : -1,
7450 TRUE, result & HeightValue ? h : -1,
7455 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
7457 grav = GDK_GRAVITY_NORTH_WEST;
7459 if ((result & XNegative) && (result & YNegative))
7460 grav = GDK_GRAVITY_SOUTH_EAST;
7461 else if (result & XNegative)
7462 grav = GDK_GRAVITY_NORTH_EAST;
7463 else if (result & YNegative)
7464 grav = GDK_GRAVITY_SOUTH_WEST;
7466 if ((result & XValue) == 0)
7469 if ((result & YValue) == 0)
7472 if (grav == GDK_GRAVITY_SOUTH_WEST ||
7473 grav == GDK_GRAVITY_SOUTH_EAST)
7474 y = gdk_screen_get_height (screen) - h + y;
7476 if (grav == GDK_GRAVITY_SOUTH_EAST ||
7477 grav == GDK_GRAVITY_NORTH_EAST)
7478 x = gdk_screen_get_width (screen) - w + x;
7480 /* we don't let you put a window offscreen; maybe some people would
7481 * prefer to be able to, but it's kind of a bogus thing to do.
7490 if ((result & XValue) || (result & YValue))
7492 gtk_window_set_gravity (window, grav);
7493 gtk_window_move (window, x, y);
7497 if (size_set || pos_set)
7499 /* Set USSize, USPosition hints */
7500 GtkWindowGeometryInfo *info;
7502 info = gtk_window_get_geometry_info (window, TRUE);
7505 info->mask |= GDK_HINT_USER_POS;
7507 info->mask |= GDK_HINT_USER_SIZE;
7514 gtk_window_mnemonic_hash_foreach (guint keyval,
7520 GtkWindowKeysForeachFunc func;
7524 (*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
7528 _gtk_window_keys_foreach (GtkWindow *window,
7529 GtkWindowKeysForeachFunc func,
7533 GtkMnemonicHash *mnemonic_hash;
7537 GtkWindowKeysForeachFunc func;
7541 info.window = window;
7543 info.func_data = func_data;
7545 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
7547 _gtk_mnemonic_hash_foreach (mnemonic_hash,
7548 gtk_window_mnemonic_hash_foreach, &info);
7550 groups = gtk_accel_groups_from_object (G_OBJECT (window));
7553 GtkAccelGroup *group = groups->data;
7556 for (i = 0; i < group->n_accels; i++)
7558 GtkAccelKey *key = &group->priv_accels[i].key;
7561 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
7564 groups = groups->next;
7569 gtk_window_keys_changed (GtkWindow *window)
7571 gtk_window_free_key_hash (window);
7572 gtk_window_get_key_hash (window);
7575 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
7577 struct _GtkWindowKeyEntry
7581 guint is_mnemonic : 1;
7585 window_key_entry_destroy (gpointer data)
7587 g_slice_free (GtkWindowKeyEntry, data);
7591 add_to_key_hash (GtkWindow *window,
7593 GdkModifierType modifiers,
7594 gboolean is_mnemonic,
7597 GtkKeyHash *key_hash = data;
7599 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
7601 entry->keyval = keyval;
7602 entry->modifiers = modifiers;
7603 entry->is_mnemonic = is_mnemonic;
7605 /* GtkAccelGroup stores lowercased accelerators. To deal
7606 * with this, if <Shift> was specified, uppercase.
7608 if (modifiers & GDK_SHIFT_MASK)
7610 if (keyval == GDK_Tab)
7611 keyval = GDK_ISO_Left_Tab;
7613 keyval = gdk_keyval_to_upper (keyval);
7616 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
7620 gtk_window_get_key_hash (GtkWindow *window)
7622 GdkScreen *screen = gtk_window_check_screen (window);
7623 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7628 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
7629 (GDestroyNotify)window_key_entry_destroy);
7630 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
7631 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
7637 gtk_window_free_key_hash (GtkWindow *window)
7639 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7642 _gtk_key_hash_free (key_hash);
7643 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
7648 * gtk_window_activate_key:
7649 * @window: a #GtkWindow
7650 * @event: a #GdkEventKey
7652 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
7653 * called by the default ::key_press_event handler for toplevel windows,
7654 * however in some cases it may be useful to call this directly when
7655 * overriding the standard key handling for a toplevel window.
7657 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
7660 gtk_window_activate_key (GtkWindow *window,
7663 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7664 GtkWindowKeyEntry *found_entry = NULL;
7668 gtk_window_keys_changed (window);
7669 key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7674 GSList *entries = _gtk_key_hash_lookup (key_hash,
7675 event->hardware_keycode,
7677 gtk_accelerator_get_default_mod_mask (),
7681 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
7683 GtkWindowKeyEntry *entry = tmp_list->data;
7684 if (entry->is_mnemonic)
7686 found_entry = entry;
7691 if (!found_entry && entries)
7692 found_entry = entries->data;
7694 g_slist_free (entries);
7699 if (found_entry->is_mnemonic)
7700 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
7702 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
7709 window_update_has_focus (GtkWindow *window)
7711 GtkWidget *widget = GTK_WIDGET (window);
7712 gboolean has_focus = window->has_toplevel_focus && window->is_active;
7714 if (has_focus != window->has_focus)
7716 window->has_focus = has_focus;
7720 if (window->focus_widget &&
7721 window->focus_widget != widget &&
7722 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7723 do_focus_change (window->focus_widget, TRUE);
7727 if (window->focus_widget &&
7728 window->focus_widget != widget &&
7729 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7730 do_focus_change (window->focus_widget, FALSE);
7736 * _gtk_window_set_is_active:
7737 * @window: a #GtkWindow
7738 * @is_active: %TRUE if the window is in the currently active toplevel
7740 * Internal function that sets whether the #GtkWindow is part
7741 * of the currently active toplevel window (taking into account inter-process
7745 _gtk_window_set_is_active (GtkWindow *window,
7748 g_return_if_fail (GTK_IS_WINDOW (window));
7750 is_active = is_active != FALSE;
7752 if (is_active != window->is_active)
7754 window->is_active = is_active;
7755 window_update_has_focus (window);
7757 g_object_notify (G_OBJECT (window), "is-active");
7762 * _gtk_window_set_has_toplevel_focus:
7763 * @window: a #GtkWindow
7764 * @has_toplevel_focus: %TRUE if the in
7766 * Internal function that sets whether the keyboard focus for the
7767 * toplevel window (taking into account inter-process embedding.)
7770 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
7771 gboolean has_toplevel_focus)
7773 g_return_if_fail (GTK_IS_WINDOW (window));
7775 has_toplevel_focus = has_toplevel_focus != FALSE;
7777 if (has_toplevel_focus != window->has_toplevel_focus)
7779 window->has_toplevel_focus = has_toplevel_focus;
7780 window_update_has_focus (window);
7782 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
7787 * gtk_window_set_auto_startup_notification:
7788 * @setting: %TRUE to automatically do startup notification
7790 * By default, after showing the first #GtkWindow, GTK+ calls
7791 * gdk_notify_startup_complete(). Call this function to disable
7792 * the automatic startup notification. You might do this if your
7793 * first window is a splash screen, and you want to delay notification
7794 * until after your real main window has been shown, for example.
7796 * In that example, you would disable startup notification
7797 * temporarily, show your splash screen, then re-enable it so that
7798 * showing the main window would automatically result in notification.
7803 gtk_window_set_auto_startup_notification (gboolean setting)
7805 disable_startup_notification = !setting;
7810 #undef gtk_window_set_icon_from_file
7813 gtk_window_set_icon_from_file (GtkWindow *window,
7814 const gchar *filename,
7817 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
7820 if (utf8_filename == NULL)
7823 retval = gtk_window_set_icon_from_file_utf8 (window, utf8_filename, err);
7825 g_free (utf8_filename);
7830 #undef gtk_window_set_default_icon_from_file
7833 gtk_window_set_default_icon_from_file (const gchar *filename,
7836 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
7839 if (utf8_filename == NULL)
7842 retval = gtk_window_set_default_icon_from_file_utf8 (utf8_filename, err);
7844 g_free (utf8_filename);
7851 #define __GTK_WINDOW_C__
7852 #include "gtkaliasdef.c"