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 GDK_THREADS_ENTER ();
1364 window = GTK_WINDOW (data);
1366 if (window->keys_changed_handler)
1368 g_source_remove (window->keys_changed_handler);
1369 window->keys_changed_handler = 0;
1372 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1373 GDK_THREADS_LEAVE ();
1379 gtk_window_notify_keys_changed (GtkWindow *window)
1381 if (!window->keys_changed_handler)
1382 window->keys_changed_handler = g_idle_add (handle_keys_changed, window);
1386 * gtk_window_add_accel_group:
1387 * @window: window to attach accelerator group to
1388 * @accel_group: a #GtkAccelGroup
1390 * Associate @accel_group with @window, such that calling
1391 * gtk_accel_groups_activate() on @window will activate accelerators
1395 gtk_window_add_accel_group (GtkWindow *window,
1396 GtkAccelGroup *accel_group)
1398 g_return_if_fail (GTK_IS_WINDOW (window));
1399 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1401 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1402 g_signal_connect_object (accel_group, "accel_changed",
1403 G_CALLBACK (gtk_window_notify_keys_changed),
1404 window, G_CONNECT_SWAPPED);
1408 * gtk_window_remove_accel_group:
1409 * @window: a #GtkWindow
1410 * @accel_group: a #GtkAccelGroup
1412 * Reverses the effects of gtk_window_add_accel_group().
1415 gtk_window_remove_accel_group (GtkWindow *window,
1416 GtkAccelGroup *accel_group)
1418 g_return_if_fail (GTK_IS_WINDOW (window));
1419 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1421 g_signal_handlers_disconnect_by_func (accel_group,
1422 gtk_window_notify_keys_changed,
1424 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1427 static GtkMnemonicHash *
1428 gtk_window_get_mnemonic_hash (GtkWindow *window,
1431 GtkWindowPrivate *private = GTK_WINDOW_GET_PRIVATE (window);
1432 if (!private->mnemonic_hash && create)
1433 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1435 return private->mnemonic_hash;
1439 * gtk_window_add_mnemonic:
1440 * @window: a #GtkWindow
1441 * @keyval: the mnemonic
1442 * @target: the widget that gets activated by the mnemonic
1444 * Adds a mnemonic to this window.
1447 gtk_window_add_mnemonic (GtkWindow *window,
1451 g_return_if_fail (GTK_IS_WINDOW (window));
1452 g_return_if_fail (GTK_IS_WIDGET (target));
1454 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1456 gtk_window_notify_keys_changed (window);
1460 * gtk_window_remove_mnemonic:
1461 * @window: a #GtkWindow
1462 * @keyval: the mnemonic
1463 * @target: the widget that gets activated by the mnemonic
1465 * Removes a mnemonic from this window.
1468 gtk_window_remove_mnemonic (GtkWindow *window,
1472 g_return_if_fail (GTK_IS_WINDOW (window));
1473 g_return_if_fail (GTK_IS_WIDGET (target));
1475 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
1477 gtk_window_notify_keys_changed (window);
1481 * gtk_window_mnemonic_activate:
1482 * @window: a #GtkWindow
1483 * @keyval: the mnemonic
1484 * @modifier: the modifiers
1485 * @returns: %TRUE if the activation is done.
1487 * Activates the targets associated with the mnemonic.
1490 gtk_window_mnemonic_activate (GtkWindow *window,
1492 GdkModifierType modifier)
1494 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1496 if (window->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
1498 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
1500 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
1507 * gtk_window_set_mnemonic_modifier:
1508 * @window: a #GtkWindow
1509 * @modifier: the modifier mask used to activate
1510 * mnemonics on this window.
1512 * Sets the mnemonic modifier for this window.
1515 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1516 GdkModifierType modifier)
1518 g_return_if_fail (GTK_IS_WINDOW (window));
1519 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1521 window->mnemonic_modifier = modifier;
1522 gtk_window_notify_keys_changed (window);
1526 * gtk_window_get_mnemonic_modifier:
1527 * @window: a #GtkWindow
1529 * Returns the mnemonic modifier for this window. See
1530 * gtk_window_set_mnemonic_modifier().
1532 * Return value: the modifier mask used to activate
1533 * mnemonics on this window.
1536 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1538 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1540 return window->mnemonic_modifier;
1544 * gtk_window_set_position:
1545 * @window: a #GtkWindow.
1546 * @position: a position constraint.
1548 * Sets a position constraint for this window. If the old or new
1549 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1550 * the window to be repositioned to satisfy the new constraint.
1553 gtk_window_set_position (GtkWindow *window,
1554 GtkWindowPosition position)
1556 g_return_if_fail (GTK_IS_WINDOW (window));
1558 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1559 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1561 GtkWindowGeometryInfo *info;
1563 info = gtk_window_get_geometry_info (window, TRUE);
1565 /* this flag causes us to re-request the CENTER_ALWAYS
1566 * constraint in gtk_window_move_resize(), see
1567 * comment in that function.
1569 info->position_constraints_changed = TRUE;
1571 gtk_widget_queue_resize (GTK_WIDGET (window));
1574 window->position = position;
1576 g_object_notify (G_OBJECT (window), "window-position");
1580 * gtk_window_activate_focus:
1581 * @window: a #GtkWindow
1583 * Activates the current focused widget within the window.
1585 * Return value: %TRUE if a widget got activated.
1588 gtk_window_activate_focus (GtkWindow *window)
1590 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1592 if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1593 return gtk_widget_activate (window->focus_widget);
1599 * gtk_window_get_focus:
1600 * @window: a #GtkWindow
1602 * Retrieves the current focused widget within the window.
1603 * Note that this is the widget that would have the focus
1604 * if the toplevel window focused; if the toplevel window
1605 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1606 * not be %TRUE for the widget.
1608 * Return value: the currently focused widget, or %NULL if there is none.
1611 gtk_window_get_focus (GtkWindow *window)
1613 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1615 return window->focus_widget;
1619 * gtk_window_activate_default:
1620 * @window: a #GtkWindow
1622 * Activates the default widget for the window, unless the current
1623 * focused widget has been configured to receive the default action
1624 * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
1625 * focused widget is activated.
1627 * Return value: %TRUE if a widget got activated.
1630 gtk_window_activate_default (GtkWindow *window)
1632 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1634 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1635 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1636 return gtk_widget_activate (window->default_widget);
1637 else if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1638 return gtk_widget_activate (window->focus_widget);
1644 * gtk_window_set_modal:
1645 * @window: a #GtkWindow
1646 * @modal: whether the window is modal
1648 * Sets a window modal or non-modal. Modal windows prevent interaction
1649 * with other windows in the same application. To keep modal dialogs
1650 * on top of main application windows, use
1651 * gtk_window_set_transient_for() to make the dialog transient for the
1652 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1653 * will then disallow lowering the dialog below the parent.
1658 gtk_window_set_modal (GtkWindow *window,
1661 g_return_if_fail (GTK_IS_WINDOW (window));
1663 modal = modal != FALSE;
1664 if (window->modal == modal)
1667 window->modal = modal;
1669 /* adjust desired modality state */
1670 if (GTK_WIDGET_REALIZED (window))
1672 GtkWidget *widget = GTK_WIDGET (window);
1675 gdk_window_set_modal_hint (widget->window, TRUE);
1677 gdk_window_set_modal_hint (widget->window, FALSE);
1680 if (GTK_WIDGET_VISIBLE (window))
1683 gtk_grab_add (GTK_WIDGET (window));
1685 gtk_grab_remove (GTK_WIDGET (window));
1688 g_object_notify (G_OBJECT (window), "modal");
1692 * gtk_window_get_modal:
1693 * @window: a #GtkWindow
1695 * Returns whether the window is modal. See gtk_window_set_modal().
1697 * Return value: %TRUE if the window is set to be modal and
1698 * establishes a grab when shown
1701 gtk_window_get_modal (GtkWindow *window)
1703 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1705 return window->modal;
1709 * gtk_window_list_toplevels:
1711 * Returns a list of all existing toplevel windows. The widgets
1712 * in the list are not individually referenced. If you want
1713 * to iterate through the list and perform actions involving
1714 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1715 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1716 * then unref all the widgets afterwards.
1718 * Return value: list of toplevel widgets
1721 gtk_window_list_toplevels (void)
1726 for (slist = toplevel_list; slist; slist = slist->next)
1727 list = g_list_prepend (list, slist->data);
1733 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1735 GList *embedded_windows;
1737 g_return_if_fail (GTK_IS_WINDOW (window));
1739 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
1740 if (embedded_windows)
1741 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
1742 embedded_windows = g_list_prepend (embedded_windows,
1743 GUINT_TO_POINTER (xid));
1745 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
1748 (GDestroyNotify) g_list_free : NULL);
1752 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1754 GList *embedded_windows;
1757 g_return_if_fail (GTK_IS_WINDOW (window));
1759 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
1760 if (embedded_windows)
1761 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
1763 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1766 embedded_windows = g_list_remove_link (embedded_windows, node);
1767 g_list_free_1 (node);
1770 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
1773 (GDestroyNotify) g_list_free : NULL);
1777 _gtk_window_reposition (GtkWindow *window,
1781 g_return_if_fail (GTK_IS_WINDOW (window));
1783 gtk_window_move (window, x, y);
1787 gtk_window_dispose (GObject *object)
1789 GtkWindow *window = GTK_WINDOW (object);
1791 gtk_window_set_focus (window, NULL);
1792 gtk_window_set_default (window, NULL);
1794 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
1798 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1800 gtk_widget_destroy (GTK_WIDGET (child));
1804 connect_parent_destroyed (GtkWindow *window)
1806 if (window->transient_parent)
1808 g_signal_connect (window->transient_parent,
1810 G_CALLBACK (parent_destroyed_callback),
1816 disconnect_parent_destroyed (GtkWindow *window)
1818 if (window->transient_parent)
1820 g_signal_handlers_disconnect_by_func (window->transient_parent,
1821 parent_destroyed_callback,
1827 gtk_window_transient_parent_realized (GtkWidget *parent,
1830 if (GTK_WIDGET_REALIZED (window))
1831 gdk_window_set_transient_for (window->window, parent->window);
1835 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1838 if (GTK_WIDGET_REALIZED (window))
1839 gdk_property_delete (window->window,
1840 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
1844 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
1848 gtk_window_set_screen (window, parent->screen);
1852 gtk_window_unset_transient_for (GtkWindow *window)
1854 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
1856 if (window->transient_parent)
1858 if (priv->transient_parent_group)
1859 gtk_window_group_remove_window (window->group,
1862 g_signal_handlers_disconnect_by_func (window->transient_parent,
1863 gtk_window_transient_parent_realized,
1865 g_signal_handlers_disconnect_by_func (window->transient_parent,
1866 gtk_window_transient_parent_unrealized,
1868 g_signal_handlers_disconnect_by_func (window->transient_parent,
1869 gtk_window_transient_parent_screen_changed,
1871 g_signal_handlers_disconnect_by_func (window->transient_parent,
1872 gtk_widget_destroyed,
1873 &window->transient_parent);
1875 if (window->destroy_with_parent)
1876 disconnect_parent_destroyed (window);
1878 window->transient_parent = NULL;
1879 priv->transient_parent_group = FALSE;
1884 * gtk_window_set_transient_for:
1885 * @window: a #GtkWindow
1886 * @parent: parent window
1888 * Dialog windows should be set transient for the main application
1889 * window they were spawned from. This allows <link
1890 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1891 * dialog on top of the main window, or center the dialog over the
1892 * main window. gtk_dialog_new_with_buttons() and other convenience
1893 * functions in GTK+ will sometimes call
1894 * gtk_window_set_transient_for() on your behalf.
1896 * On Windows, this function will and put the child window
1897 * on top of the parent, much as the window manager would have
1902 gtk_window_set_transient_for (GtkWindow *window,
1905 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
1907 g_return_if_fail (GTK_IS_WINDOW (window));
1908 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1909 g_return_if_fail (window != parent);
1911 if (window->transient_parent)
1913 if (GTK_WIDGET_REALIZED (window) &&
1914 GTK_WIDGET_REALIZED (window->transient_parent) &&
1915 (!parent || !GTK_WIDGET_REALIZED (parent)))
1916 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1917 GTK_WIDGET (window));
1919 gtk_window_unset_transient_for (window);
1922 window->transient_parent = parent;
1926 g_signal_connect (parent, "destroy",
1927 G_CALLBACK (gtk_widget_destroyed),
1928 &window->transient_parent);
1929 g_signal_connect (parent, "realize",
1930 G_CALLBACK (gtk_window_transient_parent_realized),
1932 g_signal_connect (parent, "unrealize",
1933 G_CALLBACK (gtk_window_transient_parent_unrealized),
1935 g_signal_connect (parent, "notify::screen",
1936 G_CALLBACK (gtk_window_transient_parent_screen_changed),
1939 gtk_window_set_screen (window, parent->screen);
1941 if (window->destroy_with_parent)
1942 connect_parent_destroyed (window);
1944 if (GTK_WIDGET_REALIZED (window) &&
1945 GTK_WIDGET_REALIZED (parent))
1946 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1947 GTK_WIDGET (window));
1951 gtk_window_group_add_window (parent->group, window);
1952 priv->transient_parent_group = TRUE;
1958 * gtk_window_get_transient_for:
1959 * @window: a #GtkWindow
1961 * Fetches the transient parent for this window. See
1962 * gtk_window_set_transient_for().
1964 * Return value: the transient parent for this window, or %NULL
1965 * if no transient parent has been set.
1968 gtk_window_get_transient_for (GtkWindow *window)
1970 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1972 return window->transient_parent;
1976 * gtk_window_set_type_hint:
1977 * @window: a #GtkWindow
1978 * @hint: the window type
1980 * By setting the type hint for the window, you allow the window
1981 * manager to decorate and handle the window in a way which is
1982 * suitable to the function of the window in your application.
1984 * This function should be called before the window becomes visible.
1986 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1987 * will sometimes call gtk_window_set_type_hint() on your behalf.
1991 gtk_window_set_type_hint (GtkWindow *window,
1992 GdkWindowTypeHint hint)
1994 GtkWindowPrivate *priv;
1996 g_return_if_fail (GTK_IS_WINDOW (window));
1997 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1999 priv = GTK_WINDOW_GET_PRIVATE (window);
2001 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2002 window->type_hint = hint;
2004 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2006 priv->reset_type_hint = TRUE;
2007 priv->type_hint = hint;
2011 * gtk_window_get_type_hint:
2012 * @window: a #GtkWindow
2014 * Gets the type hint for this window. See gtk_window_set_type_hint().
2016 * Return value: the type hint for @window.
2019 gtk_window_get_type_hint (GtkWindow *window)
2021 GtkWindowPrivate *priv;
2023 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2025 priv = GTK_WINDOW_GET_PRIVATE (window);
2027 return priv->type_hint;
2031 * gtk_window_set_skip_taskbar_hint:
2032 * @window: a #GtkWindow
2033 * @setting: %TRUE to keep this window from appearing in the task bar
2035 * Windows may set a hint asking the desktop environment not to display
2036 * the window in the task bar. This function sets this hint.
2041 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2044 GtkWindowPrivate *priv;
2046 g_return_if_fail (GTK_IS_WINDOW (window));
2048 priv = GTK_WINDOW_GET_PRIVATE (window);
2050 setting = setting != FALSE;
2052 if (priv->skips_taskbar != setting)
2054 priv->skips_taskbar = setting;
2055 if (GTK_WIDGET_REALIZED (window))
2056 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
2057 priv->skips_taskbar);
2058 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2063 * gtk_window_get_skip_taskbar_hint:
2064 * @window: a #GtkWindow
2066 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2068 * Return value: %TRUE if window shouldn't be in taskbar
2073 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2075 GtkWindowPrivate *priv;
2077 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2079 priv = GTK_WINDOW_GET_PRIVATE (window);
2081 return priv->skips_taskbar;
2085 * gtk_window_set_skip_pager_hint:
2086 * @window: a #GtkWindow
2087 * @setting: %TRUE to keep this window from appearing in the pager
2089 * Windows may set a hint asking the desktop environment not to display
2090 * the window in the pager. This function sets this hint.
2091 * (A "pager" is any desktop navigation tool such as a workspace
2092 * switcher that displays a thumbnail representation of the windows
2098 gtk_window_set_skip_pager_hint (GtkWindow *window,
2101 GtkWindowPrivate *priv;
2103 g_return_if_fail (GTK_IS_WINDOW (window));
2105 priv = GTK_WINDOW_GET_PRIVATE (window);
2107 setting = setting != FALSE;
2109 if (priv->skips_pager != setting)
2111 priv->skips_pager = setting;
2112 if (GTK_WIDGET_REALIZED (window))
2113 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2115 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2120 * gtk_window_get_skip_pager_hint:
2121 * @window: a #GtkWindow
2123 * Gets the value set by gtk_window_set_skip_pager_hint().
2125 * Return value: %TRUE if window shouldn't be in pager
2130 gtk_window_get_skip_pager_hint (GtkWindow *window)
2132 GtkWindowPrivate *priv;
2134 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2136 priv = GTK_WINDOW_GET_PRIVATE (window);
2138 return priv->skips_pager;
2142 * gtk_window_set_urgency_hint:
2143 * @window: a #GtkWindow
2144 * @setting: %TRUE to mark this window as urgent
2146 * Windows may set a hint asking the desktop environment to draw
2147 * the users attention to the window. This function sets this hint.
2152 gtk_window_set_urgency_hint (GtkWindow *window,
2155 GtkWindowPrivate *priv;
2157 g_return_if_fail (GTK_IS_WINDOW (window));
2159 priv = GTK_WINDOW_GET_PRIVATE (window);
2161 setting = setting != FALSE;
2163 if (priv->urgent != setting)
2165 priv->urgent = setting;
2166 if (GTK_WIDGET_REALIZED (window))
2167 gdk_window_set_urgency_hint (GTK_WIDGET (window)->window,
2169 g_object_notify (G_OBJECT (window), "urgency-hint");
2174 * gtk_window_get_urgency_hint:
2175 * @window: a #GtkWindow
2177 * Gets the value set by gtk_window_set_urgency_hint()
2179 * Return value: %TRUE if window is urgent
2184 gtk_window_get_urgency_hint (GtkWindow *window)
2186 GtkWindowPrivate *priv;
2188 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2190 priv = GTK_WINDOW_GET_PRIVATE (window);
2192 return priv->urgent;
2196 * gtk_window_set_accept_focus:
2197 * @window: a #GtkWindow
2198 * @setting: %TRUE to let this window receive input focus
2200 * Windows may set a hint asking the desktop environment not to receive
2201 * the input focus. This function sets this hint.
2206 gtk_window_set_accept_focus (GtkWindow *window,
2209 GtkWindowPrivate *priv;
2211 g_return_if_fail (GTK_IS_WINDOW (window));
2213 priv = GTK_WINDOW_GET_PRIVATE (window);
2215 setting = setting != FALSE;
2217 if (priv->accept_focus != setting)
2219 priv->accept_focus = setting;
2220 if (GTK_WIDGET_REALIZED (window))
2221 gdk_window_set_accept_focus (GTK_WIDGET (window)->window,
2222 priv->accept_focus);
2223 g_object_notify (G_OBJECT (window), "accept-focus");
2228 * gtk_window_get_accept_focus:
2229 * @window: a #GtkWindow
2231 * Gets the value set by gtk_window_set_accept_focus().
2233 * Return value: %TRUE if window should receive the input focus
2238 gtk_window_get_accept_focus (GtkWindow *window)
2240 GtkWindowPrivate *priv;
2242 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2244 priv = GTK_WINDOW_GET_PRIVATE (window);
2246 return priv->accept_focus;
2250 * gtk_window_set_focus_on_map:
2251 * @window: a #GtkWindow
2252 * @setting: %TRUE to let this window receive input focus on map
2254 * Windows may set a hint asking the desktop environment not to receive
2255 * the input focus when the window is mapped. This function sets this
2261 gtk_window_set_focus_on_map (GtkWindow *window,
2264 GtkWindowPrivate *priv;
2266 g_return_if_fail (GTK_IS_WINDOW (window));
2268 priv = GTK_WINDOW_GET_PRIVATE (window);
2270 setting = setting != FALSE;
2272 if (priv->focus_on_map != setting)
2274 priv->focus_on_map = setting;
2275 if (GTK_WIDGET_REALIZED (window))
2276 gdk_window_set_focus_on_map (GTK_WIDGET (window)->window,
2277 priv->focus_on_map);
2278 g_object_notify (G_OBJECT (window), "focus-on-map");
2283 * gtk_window_get_focus_on_map:
2284 * @window: a #GtkWindow
2286 * Gets the value set by gtk_window_set_focus_on_map().
2288 * Return value: %TRUE if window should receive the input focus when
2294 gtk_window_get_focus_on_map (GtkWindow *window)
2296 GtkWindowPrivate *priv;
2298 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2300 priv = GTK_WINDOW_GET_PRIVATE (window);
2302 return priv->focus_on_map;
2306 * gtk_window_set_destroy_with_parent:
2307 * @window: a #GtkWindow
2308 * @setting: whether to destroy @window with its transient parent
2310 * If @setting is %TRUE, then destroying the transient parent of @window
2311 * will also destroy @window itself. This is useful for dialogs that
2312 * shouldn't persist beyond the lifetime of the main window they're
2313 * associated with, for example.
2316 gtk_window_set_destroy_with_parent (GtkWindow *window,
2319 g_return_if_fail (GTK_IS_WINDOW (window));
2321 if (window->destroy_with_parent == (setting != FALSE))
2324 if (window->destroy_with_parent)
2326 disconnect_parent_destroyed (window);
2330 connect_parent_destroyed (window);
2333 window->destroy_with_parent = setting;
2335 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2339 * gtk_window_get_destroy_with_parent:
2340 * @window: a #GtkWindow
2342 * Returns whether the window will be destroyed with its transient parent. See
2343 * gtk_window_set_destroy_with_parent ().
2345 * Return value: %TRUE if the window will be destroyed with its transient parent.
2348 gtk_window_get_destroy_with_parent (GtkWindow *window)
2350 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2352 return window->destroy_with_parent;
2355 static GtkWindowGeometryInfo*
2356 gtk_window_get_geometry_info (GtkWindow *window,
2359 GtkWindowGeometryInfo *info;
2361 info = window->geometry_info;
2362 if (!info && create)
2364 info = g_new0 (GtkWindowGeometryInfo, 1);
2366 info->default_width = -1;
2367 info->default_height = -1;
2368 info->resize_width = -1;
2369 info->resize_height = -1;
2370 info->initial_x = 0;
2371 info->initial_y = 0;
2372 info->initial_pos_set = FALSE;
2373 info->default_is_geometry = FALSE;
2374 info->position_constraints_changed = FALSE;
2375 info->last.configure_request.x = 0;
2376 info->last.configure_request.y = 0;
2377 info->last.configure_request.width = -1;
2378 info->last.configure_request.height = -1;
2379 info->widget = NULL;
2381 window->geometry_info = info;
2388 * gtk_window_set_geometry_hints:
2389 * @window: a #GtkWindow
2390 * @geometry_widget: widget the geometry hints will be applied to
2391 * @geometry: struct containing geometry information
2392 * @geom_mask: mask indicating which struct fields should be paid attention to
2394 * This function sets up hints about how a window can be resized by
2395 * the user. You can set a minimum and maximum size; allowed resize
2396 * increments (e.g. for xterm, you can only resize by the size of a
2397 * character); aspect ratios; and more. See the #GdkGeometry struct.
2401 gtk_window_set_geometry_hints (GtkWindow *window,
2402 GtkWidget *geometry_widget,
2403 GdkGeometry *geometry,
2404 GdkWindowHints geom_mask)
2406 GtkWindowGeometryInfo *info;
2408 g_return_if_fail (GTK_IS_WINDOW (window));
2409 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2411 info = gtk_window_get_geometry_info (window, TRUE);
2414 g_signal_handlers_disconnect_by_func (info->widget,
2415 gtk_widget_destroyed,
2418 info->widget = geometry_widget;
2420 g_signal_connect (geometry_widget, "destroy",
2421 G_CALLBACK (gtk_widget_destroyed),
2425 info->geometry = *geometry;
2427 /* We store gravity in window->gravity not in the hints. */
2428 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2430 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2432 gtk_window_set_gravity (window, geometry->win_gravity);
2435 gtk_widget_queue_resize (GTK_WIDGET (window));
2439 * gtk_window_set_decorated:
2440 * @window: a #GtkWindow
2441 * @setting: %TRUE to decorate the window
2443 * By default, windows are decorated with a title bar, resize
2444 * controls, etc. Some <link linkend="gtk-X11-arch">window
2445 * managers</link> allow GTK+ to disable these decorations, creating a
2446 * borderless window. If you set the decorated property to %FALSE
2447 * using this function, GTK+ will do its best to convince the window
2448 * manager not to decorate the window. Depending on the system, this
2449 * function may not have any effect when called on a window that is
2450 * already visible, so you should call it before calling gtk_window_show().
2452 * On Windows, this function always works, since there's no window manager
2457 gtk_window_set_decorated (GtkWindow *window,
2460 g_return_if_fail (GTK_IS_WINDOW (window));
2462 setting = setting != FALSE;
2464 if (setting == window->decorated)
2467 window->decorated = setting;
2469 if (GTK_WIDGET (window)->window)
2471 if (window->decorated)
2472 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2475 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2479 g_object_notify (G_OBJECT (window), "decorated");
2483 * gtk_window_get_decorated:
2484 * @window: a #GtkWindow
2486 * Returns whether the window has been set to have decorations
2487 * such as a title bar via gtk_window_set_decorated().
2489 * Return value: %TRUE if the window has been set to have decorations
2492 gtk_window_get_decorated (GtkWindow *window)
2494 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2496 return window->decorated;
2500 * gtk_window_set_deletable:
2501 * @window: a #GtkWindow
2502 * @setting: %TRUE to decorate the window as deletable
2504 * By default, windows have a close button in the window frame. Some
2505 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
2506 * disable this button. If you set the deletable property to %FALSE
2507 * using this function, GTK+ will do its best to convince the window
2508 * manager not to show a close button. Depending on the system, this
2509 * function may not have any effect when called on a window that is
2510 * already visible, so you should call it before calling gtk_window_show().
2512 * On Windows, this function always works, since there's no window manager
2518 gtk_window_set_deletable (GtkWindow *window,
2521 GtkWindowPrivate *priv;
2523 g_return_if_fail (GTK_IS_WINDOW (window));
2525 priv = GTK_WINDOW_GET_PRIVATE (window);
2527 setting = setting != FALSE;
2529 if (setting == priv->deletable)
2532 priv->deletable = setting;
2534 if (GTK_WIDGET (window)->window)
2536 if (priv->deletable)
2537 gdk_window_set_functions (GTK_WIDGET (window)->window,
2540 gdk_window_set_functions (GTK_WIDGET (window)->window,
2541 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
2544 g_object_notify (G_OBJECT (window), "deletable");
2548 * gtk_window_get_deletable:
2549 * @window: a #GtkWindow
2551 * Returns whether the window has been set to have a close button
2552 * via gtk_window_set_deletable().
2554 * Return value: %TRUE if the window has been set to have a close button
2559 gtk_window_get_deletable (GtkWindow *window)
2561 GtkWindowPrivate *priv;
2563 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2565 priv = GTK_WINDOW_GET_PRIVATE (window);
2567 return priv->deletable;
2570 static GtkWindowIconInfo*
2571 get_icon_info (GtkWindow *window)
2573 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
2577 free_icon_info (GtkWindowIconInfo *info)
2579 g_free (info->icon_name);
2580 g_slice_free (GtkWindowIconInfo, info);
2584 static GtkWindowIconInfo*
2585 ensure_icon_info (GtkWindow *window)
2587 GtkWindowIconInfo *info;
2589 info = get_icon_info (window);
2593 info = g_slice_new0 (GtkWindowIconInfo);
2594 g_object_set_qdata_full (G_OBJECT (window),
2595 quark_gtk_window_icon_info,
2597 (GDestroyNotify)free_icon_info);
2609 static ScreenIconInfo *
2610 get_screen_icon_info (GdkScreen *screen)
2612 ScreenIconInfo *info = g_object_get_qdata (G_OBJECT (screen),
2613 quark_gtk_window_default_icon_pixmap);
2616 info = g_slice_new0 (ScreenIconInfo);
2617 g_object_set_qdata (G_OBJECT (screen),
2618 quark_gtk_window_default_icon_pixmap, info);
2621 if (info->serial != default_icon_serial)
2625 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2626 info->pixmap = NULL;
2631 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2635 info->serial = default_icon_serial;
2642 get_pixmap_and_mask (GdkWindow *window,
2643 GtkWindowIconInfo *parent_info,
2644 gboolean is_default_list,
2646 GdkPixmap **pmap_return,
2647 GdkBitmap **mask_return)
2649 GdkScreen *screen = gdk_drawable_get_screen (window);
2650 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2651 GdkPixbuf *best_icon;
2655 *pmap_return = NULL;
2656 *mask_return = NULL;
2658 if (is_default_list &&
2659 default_icon_info->pixmap != NULL)
2661 /* Use shared icon pixmap for all windows on this screen.
2663 if (default_icon_info->pixmap)
2664 g_object_ref (default_icon_info->pixmap);
2665 if (default_icon_info->mask)
2666 g_object_ref (default_icon_info->mask);
2668 *pmap_return = default_icon_info->pixmap;
2669 *mask_return = default_icon_info->mask;
2671 else if (parent_info && parent_info->icon_pixmap)
2673 if (parent_info->icon_pixmap)
2674 g_object_ref (parent_info->icon_pixmap);
2675 if (parent_info->icon_mask)
2676 g_object_ref (parent_info->icon_mask);
2678 *pmap_return = parent_info->icon_pixmap;
2679 *mask_return = parent_info->icon_mask;
2683 #define IDEAL_SIZE 48
2685 best_size = G_MAXINT;
2687 tmp_list = icon_list;
2688 while (tmp_list != NULL)
2690 GdkPixbuf *pixbuf = tmp_list->data;
2693 /* average width and height - if someone passes in a rectangular
2694 * icon they deserve what they get.
2696 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2699 if (best_icon == NULL)
2706 /* icon is better if it's 32 pixels or larger, and closer to
2707 * the ideal size than the current best.
2710 (ABS (best_size - IDEAL_SIZE) <
2711 ABS (this - IDEAL_SIZE)))
2718 tmp_list = tmp_list->next;
2722 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2723 gdk_screen_get_system_colormap (screen),
2728 /* Save pmap/mask for others to use if appropriate */
2731 parent_info->icon_pixmap = *pmap_return;
2732 parent_info->icon_mask = *mask_return;
2734 if (parent_info->icon_pixmap)
2735 g_object_ref (parent_info->icon_pixmap);
2736 if (parent_info->icon_mask)
2737 g_object_ref (parent_info->icon_mask);
2739 else if (is_default_list)
2741 default_icon_info->pixmap = *pmap_return;
2742 default_icon_info->mask = *mask_return;
2744 if (default_icon_info->pixmap)
2745 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2746 (gpointer*)&default_icon_info->pixmap);
2747 if (default_icon_info->mask)
2748 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2749 (gpointer*)&default_icon_info->mask);
2755 icon_list_from_theme (GtkWidget *widget,
2760 GtkIconTheme *icon_theme;
2765 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
2767 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
2770 for (i = 0; sizes[i]; i++)
2773 * We need an EWMH extension to handle scalable icons
2774 * by passing their name to the WM. For now just use a
2778 icon = gtk_icon_theme_load_icon (icon_theme, name,
2781 icon = gtk_icon_theme_load_icon (icon_theme, name,
2784 list = g_list_append (list, icon);
2794 gtk_window_realize_icon (GtkWindow *window)
2797 GtkWindowIconInfo *info;
2800 widget = GTK_WIDGET (window);
2802 g_return_if_fail (widget->window != NULL);
2804 /* no point setting an icon on override-redirect */
2805 if (window->type == GTK_WINDOW_POPUP)
2810 info = ensure_icon_info (window);
2815 g_return_if_fail (info->icon_pixmap == NULL);
2816 g_return_if_fail (info->icon_mask == NULL);
2818 info->using_default_icon = FALSE;
2819 info->using_parent_icon = FALSE;
2820 info->using_themed_icon = FALSE;
2822 icon_list = info->icon_list;
2824 /* Look up themed icon */
2825 if (icon_list == NULL && info->icon_name)
2827 icon_list = icon_list_from_theme (widget, info->icon_name);
2829 info->using_themed_icon = TRUE;
2832 /* Inherit from transient parent */
2833 if (icon_list == NULL && window->transient_parent)
2835 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2837 info->using_parent_icon = TRUE;
2840 /* Inherit from default */
2841 if (icon_list == NULL)
2843 icon_list = default_icon_list;
2845 info->using_default_icon = TRUE;
2848 /* Look up themed icon */
2849 if (icon_list == NULL && default_icon_name)
2851 icon_list = icon_list_from_theme (widget, default_icon_name);
2852 info->using_default_icon = TRUE;
2853 info->using_themed_icon = TRUE;
2856 gdk_window_set_icon_list (widget->window, icon_list);
2858 get_pixmap_and_mask (widget->window,
2859 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2860 info->using_default_icon,
2865 /* This is a slight ICCCM violation since it's a color pixmap not
2866 * a bitmap, but everyone does it.
2868 gdk_window_set_icon (widget->window,
2873 info->realized = TRUE;
2875 if (info->using_themed_icon)
2877 GtkIconTheme *icon_theme;
2879 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
2880 g_list_free (icon_list);
2882 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2883 g_signal_connect (icon_theme, "changed",
2884 G_CALLBACK (update_themed_icon), window);
2889 gtk_window_unrealize_icon (GtkWindow *window)
2891 GtkWindowIconInfo *info;
2893 info = get_icon_info (window);
2898 if (info->icon_pixmap)
2899 g_object_unref (info->icon_pixmap);
2901 if (info->icon_mask)
2902 g_object_unref (info->icon_mask);
2904 info->icon_pixmap = NULL;
2905 info->icon_mask = NULL;
2907 if (info->using_themed_icon)
2909 GtkIconTheme *icon_theme;
2911 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2913 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
2916 /* We don't clear the properties on the window, just figure the
2917 * window is going away.
2920 info->realized = FALSE;
2925 * gtk_window_set_icon_list:
2926 * @window: a #GtkWindow
2927 * @list: list of #GdkPixbuf
2929 * Sets up the icon representing a #GtkWindow. The icon is used when
2930 * the window is minimized (also known as iconified). Some window
2931 * managers or desktop environments may also place it in the window
2932 * frame, or display it in other contexts.
2934 * gtk_window_set_icon_list() allows you to pass in the same icon in
2935 * several hand-drawn sizes. The list should contain the natural sizes
2936 * your icon is available in; that is, don't scale the image before
2937 * passing it to GTK+. Scaling is postponed until the last minute,
2938 * when the desired final size is known, to allow best quality.
2940 * By passing several sizes, you may improve the final image quality
2941 * of the icon, by reducing or eliminating automatic image scaling.
2943 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2944 * larger images (64x64, 128x128) if you have them.
2946 * See also gtk_window_set_default_icon_list() to set the icon
2947 * for all windows in your application in one go.
2949 * Note that transient windows (those who have been set transient for another
2950 * window using gtk_window_set_transient_for()) will inherit their
2951 * icon from their transient parent. So there's no need to explicitly
2952 * set the icon on transient windows.
2955 gtk_window_set_icon_list (GtkWindow *window,
2958 GtkWindowIconInfo *info;
2960 g_return_if_fail (GTK_IS_WINDOW (window));
2962 info = ensure_icon_info (window);
2964 if (info->icon_list == list) /* check for NULL mostly */
2967 g_list_foreach (list,
2968 (GFunc) g_object_ref, NULL);
2970 g_list_foreach (info->icon_list,
2971 (GFunc) g_object_unref, NULL);
2973 g_list_free (info->icon_list);
2975 info->icon_list = g_list_copy (list);
2977 g_object_notify (G_OBJECT (window), "icon");
2979 gtk_window_unrealize_icon (window);
2981 if (GTK_WIDGET_REALIZED (window))
2982 gtk_window_realize_icon (window);
2984 /* We could try to update our transient children, but I don't think
2985 * it's really worth it. If we did it, the best way would probably
2986 * be to have children connect to notify::icon-list
2991 * gtk_window_get_icon_list:
2992 * @window: a #GtkWindow
2994 * Retrieves the list of icons set by gtk_window_set_icon_list().
2995 * The list is copied, but the reference count on each
2996 * member won't be incremented.
2998 * Return value: copy of window's icon list
3001 gtk_window_get_icon_list (GtkWindow *window)
3003 GtkWindowIconInfo *info;
3005 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3007 info = get_icon_info (window);
3010 return g_list_copy (info->icon_list);
3016 * gtk_window_set_icon:
3017 * @window: a #GtkWindow
3018 * @icon: icon image, or %NULL
3020 * Sets up the icon representing a #GtkWindow. This icon is used when
3021 * the window is minimized (also known as iconified). Some window
3022 * managers or desktop environments may also place it in the window
3023 * frame, or display it in other contexts.
3025 * The icon should be provided in whatever size it was naturally
3026 * drawn; that is, don't scale the image before passing it to
3027 * GTK+. Scaling is postponed until the last minute, when the desired
3028 * final size is known, to allow best quality.
3030 * If you have your icon hand-drawn in multiple sizes, use
3031 * gtk_window_set_icon_list(). Then the best size will be used.
3033 * This function is equivalent to calling gtk_window_set_icon_list()
3034 * with a 1-element list.
3036 * See also gtk_window_set_default_icon_list() to set the icon
3037 * for all windows in your application in one go.
3040 gtk_window_set_icon (GtkWindow *window,
3045 g_return_if_fail (GTK_IS_WINDOW (window));
3046 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3051 list = g_list_append (list, icon);
3053 gtk_window_set_icon_list (window, list);
3059 update_themed_icon (GtkIconTheme *icon_theme,
3062 g_object_notify (G_OBJECT (window), "icon");
3064 gtk_window_unrealize_icon (window);
3066 if (GTK_WIDGET_REALIZED (window))
3067 gtk_window_realize_icon (window);
3071 * gtk_window_set_icon_name:
3072 * @window: a #GtkWindow
3073 * @name: the name of the themed icon
3075 * Sets the icon for the window from a named themed icon. See
3076 * the docs for #GtkIconTheme for more details.
3078 * Note that this has nothing to do with the WM_ICON_NAME
3079 * property which is mentioned in the ICCCM.
3084 gtk_window_set_icon_name (GtkWindow *window,
3087 GtkWindowIconInfo *info;
3090 g_return_if_fail (GTK_IS_WINDOW (window));
3092 info = ensure_icon_info (window);
3094 tmp = info->icon_name;
3095 info->icon_name = g_strdup (name);
3098 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3099 g_list_free (info->icon_list);
3100 info->icon_list = NULL;
3102 update_themed_icon (NULL, window);
3104 g_object_notify (G_OBJECT (window), "icon-name");
3108 * gtk_window_get_icon_name:
3109 * @window: a #GtkWindow
3111 * Returns the name of the themed icon for the window,
3112 * see gtk_window_set_icon_name().
3114 * Returns: the icon name or %NULL if the window has
3119 G_CONST_RETURN gchar *
3120 gtk_window_get_icon_name (GtkWindow *window)
3122 GtkWindowIconInfo *info;
3124 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3126 info = ensure_icon_info (window);
3128 return info->icon_name;
3132 * gtk_window_get_icon:
3133 * @window: a #GtkWindow
3135 * Gets the value set by gtk_window_set_icon() (or if you've
3136 * called gtk_window_set_icon_list(), gets the first icon in
3139 * Return value: icon for window
3142 gtk_window_get_icon (GtkWindow *window)
3144 GtkWindowIconInfo *info;
3146 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3148 info = get_icon_info (window);
3149 if (info && info->icon_list)
3150 return GDK_PIXBUF (info->icon_list->data);
3155 /* Load pixbuf, printing warning on failure if error == NULL
3158 load_pixbuf_verbosely (const char *filename,
3161 GError *local_err = NULL;
3164 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3172 g_warning ("Error loading icon from file '%s':\n\t%s",
3173 filename, local_err->message);
3174 g_error_free (local_err);
3182 * gtk_window_set_icon_from_file:
3183 * @window: a #GtkWindow
3184 * @filename: location of icon file
3185 * @err: location to store error, or %NULL.
3187 * Sets the icon for @window.
3188 * Warns on failure if @err is %NULL.
3190 * This function is equivalent to calling gtk_window_set_icon()
3191 * with a pixbuf created by loading the image from @filename.
3193 * Returns: %TRUE if setting the icon succeeded.
3198 gtk_window_set_icon_from_file (GtkWindow *window,
3199 const gchar *filename,
3202 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3206 gtk_window_set_icon (window, pixbuf);
3207 g_object_unref (pixbuf);
3216 * gtk_window_set_default_icon_list:
3217 * @list: a list of #GdkPixbuf
3219 * Sets an icon list to be used as fallback for windows that haven't
3220 * had gtk_window_set_icon_list() called on them to set up a
3221 * window-specific icon list. This function allows you to set up the
3222 * icon for all windows in your app at once.
3224 * See gtk_window_set_icon_list() for more details.
3228 gtk_window_set_default_icon_list (GList *list)
3232 if (list == default_icon_list)
3235 /* Update serial so we don't used cached pixmaps/masks
3237 default_icon_serial++;
3239 g_list_foreach (list,
3240 (GFunc) g_object_ref, NULL);
3242 g_list_foreach (default_icon_list,
3243 (GFunc) g_object_unref, NULL);
3245 g_list_free (default_icon_list);
3247 default_icon_list = g_list_copy (list);
3249 /* Update all toplevels */
3250 toplevels = gtk_window_list_toplevels ();
3251 tmp_list = toplevels;
3252 while (tmp_list != NULL)
3254 GtkWindowIconInfo *info;
3255 GtkWindow *w = tmp_list->data;
3257 info = get_icon_info (w);
3258 if (info && info->using_default_icon)
3260 gtk_window_unrealize_icon (w);
3261 if (GTK_WIDGET_REALIZED (w))
3262 gtk_window_realize_icon (w);
3265 tmp_list = tmp_list->next;
3267 g_list_free (toplevels);
3271 * gtk_window_set_default_icon:
3274 * Sets an icon to be used as fallback for windows that haven't
3275 * had gtk_window_set_icon() called on them from a pixbuf.
3280 gtk_window_set_default_icon (GdkPixbuf *icon)
3284 g_return_if_fail (GDK_IS_PIXBUF (icon));
3286 list = g_list_prepend (NULL, icon);
3287 gtk_window_set_default_icon_list (list);
3292 * gtk_window_set_default_icon_name:
3293 * @name: the name of the themed icon
3295 * Sets an icon to be used as fallback for windows that haven't
3296 * had gtk_window_set_icon_list() called on them from a named
3297 * themed icon, see gtk_window_set_icon_name().
3302 gtk_window_set_default_icon_name (const gchar *name)
3307 /* Update serial so we don't used cached pixmaps/masks
3309 default_icon_serial++;
3311 g_free (default_icon_name);
3312 default_icon_name = g_strdup (name);
3314 g_list_foreach (default_icon_list,
3315 (GFunc) g_object_unref, NULL);
3317 g_list_free (default_icon_list);
3318 default_icon_list = NULL;
3320 /* Update all toplevels */
3321 toplevels = gtk_window_list_toplevels ();
3322 tmp_list = toplevels;
3323 while (tmp_list != NULL)
3325 GtkWindowIconInfo *info;
3326 GtkWindow *w = tmp_list->data;
3328 info = get_icon_info (w);
3329 if (info && info->using_default_icon && info->using_themed_icon)
3331 gtk_window_unrealize_icon (w);
3332 if (GTK_WIDGET_REALIZED (w))
3333 gtk_window_realize_icon (w);
3336 tmp_list = tmp_list->next;
3338 g_list_free (toplevels);
3342 * gtk_window_set_default_icon_from_file:
3343 * @filename: location of icon file
3344 * @err: location to store error, or %NULL.
3346 * Sets an icon to be used as fallback for windows that haven't
3347 * had gtk_window_set_icon_list() called on them from a file
3348 * on disk. Warns on failure if @err is %NULL.
3350 * Returns: %TRUE if setting the icon succeeded.
3355 gtk_window_set_default_icon_from_file (const gchar *filename,
3358 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3362 gtk_window_set_default_icon (pixbuf);
3363 g_object_unref (pixbuf);
3372 * gtk_window_get_default_icon_list:
3374 * Gets the value set by gtk_window_set_default_icon_list().
3375 * The list is a copy and should be freed with g_list_free(),
3376 * but the pixbufs in the list have not had their reference count
3379 * Return value: copy of default icon list
3382 gtk_window_get_default_icon_list (void)
3384 return g_list_copy (default_icon_list);
3388 gtk_window_set_default_size_internal (GtkWindow *window,
3389 gboolean change_width,
3391 gboolean change_height,
3393 gboolean is_geometry)
3395 GtkWindowGeometryInfo *info;
3397 g_return_if_fail (change_width == FALSE || width >= -1);
3398 g_return_if_fail (change_height == FALSE || height >= -1);
3400 info = gtk_window_get_geometry_info (window, TRUE);
3402 g_object_freeze_notify (G_OBJECT (window));
3404 info->default_is_geometry = is_geometry != FALSE;
3414 info->default_width = width;
3416 g_object_notify (G_OBJECT (window), "default-width");
3427 info->default_height = height;
3429 g_object_notify (G_OBJECT (window), "default-height");
3432 g_object_thaw_notify (G_OBJECT (window));
3434 gtk_widget_queue_resize (GTK_WIDGET (window));
3438 * gtk_window_set_default_size:
3439 * @window: a #GtkWindow
3440 * @width: width in pixels, or -1 to unset the default width
3441 * @height: height in pixels, or -1 to unset the default height
3443 * Sets the default size of a window. If the window's "natural" size
3444 * (its size request) is larger than the default, the default will be
3445 * ignored. More generally, if the default size does not obey the
3446 * geometry hints for the window (gtk_window_set_geometry_hints() can
3447 * be used to set these explicitly), the default size will be clamped
3448 * to the nearest permitted size.
3450 * Unlike gtk_widget_set_size_request(), which sets a size request for
3451 * a widget and thus would keep users from shrinking the window, this
3452 * function only sets the initial size, just as if the user had
3453 * resized the window themselves. Users can still shrink the window
3454 * again as they normally would. Setting a default size of -1 means to
3455 * use the "natural" default size (the size request of the window).
3457 * For more control over a window's initial size and how resizing works,
3458 * investigate gtk_window_set_geometry_hints().
3460 * For some uses, gtk_window_resize() is a more appropriate function.
3461 * gtk_window_resize() changes the current size of the window, rather
3462 * than the size to be used on initial display. gtk_window_resize() always
3463 * affects the window itself, not the geometry widget.
3465 * The default size of a window only affects the first time a window is
3466 * shown; if a window is hidden and re-shown, it will remember the size
3467 * it had prior to hiding, rather than using the default size.
3469 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3470 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3473 gtk_window_set_default_size (GtkWindow *window,
3477 g_return_if_fail (GTK_IS_WINDOW (window));
3478 g_return_if_fail (width >= -1);
3479 g_return_if_fail (height >= -1);
3481 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3485 * gtk_window_get_default_size:
3486 * @window: a #GtkWindow
3487 * @width: location to store the default width, or %NULL
3488 * @height: location to store the default height, or %NULL
3490 * Gets the default size of the window. A value of -1 for the width or
3491 * height indicates that a default size has not been explicitly set
3492 * for that dimension, so the "natural" size of the window will be
3497 gtk_window_get_default_size (GtkWindow *window,
3501 GtkWindowGeometryInfo *info;
3503 g_return_if_fail (GTK_IS_WINDOW (window));
3505 info = gtk_window_get_geometry_info (window, FALSE);
3508 *width = info ? info->default_width : -1;
3511 *height = info ? info->default_height : -1;
3515 * gtk_window_resize:
3516 * @window: a #GtkWindow
3517 * @width: width in pixels to resize the window to
3518 * @height: height in pixels to resize the window to
3520 * Resizes the window as if the user had done so, obeying geometry
3521 * constraints. The default geometry constraint is that windows may
3522 * not be smaller than their size request; to override this
3523 * constraint, call gtk_widget_set_size_request() to set the window's
3524 * request to a smaller value.
3526 * If gtk_window_resize() is called before showing a window for the
3527 * first time, it overrides any default size set with
3528 * gtk_window_set_default_size().
3530 * Windows may not be resized smaller than 1 by 1 pixels.
3534 gtk_window_resize (GtkWindow *window,
3538 GtkWindowGeometryInfo *info;
3540 g_return_if_fail (GTK_IS_WINDOW (window));
3541 g_return_if_fail (width > 0);
3542 g_return_if_fail (height > 0);
3544 info = gtk_window_get_geometry_info (window, TRUE);
3546 info->resize_width = width;
3547 info->resize_height = height;
3549 gtk_widget_queue_resize (GTK_WIDGET (window));
3553 * gtk_window_get_size:
3554 * @window: a #GtkWindow
3555 * @width: return location for width, or %NULL
3556 * @height: return location for height, or %NULL
3558 * Obtains the current size of @window. If @window is not onscreen,
3559 * it returns the size GTK+ will suggest to the <link
3560 * linkend="gtk-X11-arch">window manager</link> for the initial window
3561 * size (but this is not reliably the same as the size the window
3562 * manager will actually select). The size obtained by
3563 * gtk_window_get_size() is the last size received in a
3564 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
3565 * rather than querying the X server for the size. As a result, if you
3566 * call gtk_window_resize() then immediately call
3567 * gtk_window_get_size(), the size won't have taken effect yet. After
3568 * the window manager processes the resize request, GTK+ receives
3569 * notification that the size has changed via a configure event, and
3570 * the size of the window gets updated.
3572 * Note 1: Nearly any use of this function creates a race condition,
3573 * because the size of the window may change between the time that you
3574 * get the size and the time that you perform some action assuming
3575 * that size is the current size. To avoid race conditions, connect to
3576 * "configure_event" on the window and adjust your size-dependent
3577 * state to match the size delivered in the #GdkEventConfigure.
3579 * Note 2: The returned size does <emphasis>not</emphasis> include the
3580 * size of the window manager decorations (aka the window frame or
3581 * border). Those are not drawn by GTK+ and GTK+ has no reliable
3582 * method of determining their size.
3584 * Note 3: If you are getting a window size in order to position
3585 * the window onscreen, there may be a better way. The preferred
3586 * way is to simply set the window's semantic type with
3587 * gtk_window_set_type_hint(), which allows the window manager to
3588 * e.g. center dialogs. Also, if you set the transient parent of
3589 * dialogs with gtk_window_set_transient_for() window managers
3590 * will often center the dialog over its parent window. It's
3591 * much preferred to let the window manager handle these
3592 * things rather than doing it yourself, because all apps will
3593 * behave consistently and according to user prefs if the window
3594 * manager handles it. Also, the window manager can take the size
3595 * of the window decorations/border into account, while your
3596 * application cannot.
3598 * In any case, if you insist on application-specified window
3599 * positioning, there's <emphasis>still</emphasis> a better way than
3600 * doing it yourself - gtk_window_set_position() will frequently
3601 * handle the details for you.
3605 gtk_window_get_size (GtkWindow *window,
3611 g_return_if_fail (GTK_IS_WINDOW (window));
3613 if (width == NULL && height == NULL)
3616 if (GTK_WIDGET_MAPPED (window))
3618 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3623 GdkRectangle configure_request;
3625 gtk_window_compute_configure_request (window,
3629 w = configure_request.width;
3630 h = configure_request.height;
3641 * @window: a #GtkWindow
3642 * @x: X coordinate to move window to
3643 * @y: Y coordinate to move window to
3645 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3646 * @window to the given position. Window managers are free to ignore
3647 * this; most window managers ignore requests for initial window
3648 * positions (instead using a user-defined placement algorithm) and
3649 * honor requests after the window has already been shown.
3651 * Note: the position is the position of the gravity-determined
3652 * reference point for the window. The gravity determines two things:
3653 * first, the location of the reference point in root window
3654 * coordinates; and second, which point on the window is positioned at
3655 * the reference point.
3657 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3658 * point is simply the @x, @y supplied to gtk_window_move(). The
3659 * top-left corner of the window decorations (aka window frame or
3660 * border) will be placed at @x, @y. Therefore, to position a window
3661 * at the top left of the screen, you want to use the default gravity
3662 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3664 * To position a window at the bottom right corner of the screen, you
3665 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3666 * point is at @x + the window width and @y + the window height, and
3667 * the bottom-right corner of the window border will be placed at that
3668 * reference point. So, to place a window in the bottom right corner
3669 * you would first set gravity to south east, then write:
3670 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3671 * gdk_screen_height () - window_height)</literal> (note that this
3672 * example does not take multi-head scenarios into account).
3674 * The Extended Window Manager Hints specification at <ulink
3675 * url="http://www.freedesktop.org/Standards/wm-spec">
3676 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
3677 * nice table of gravities in the "implementation notes" section.
3679 * The gtk_window_get_position() documentation may also be relevant.
3682 gtk_window_move (GtkWindow *window,
3686 GtkWindowGeometryInfo *info;
3689 g_return_if_fail (GTK_IS_WINDOW (window));
3691 widget = GTK_WIDGET (window);
3693 info = gtk_window_get_geometry_info (window, TRUE);
3695 if (GTK_WIDGET_MAPPED (window))
3697 /* we have now sent a request with this position
3698 * with currently-active constraints, so toggle flag.
3700 info->position_constraints_changed = FALSE;
3702 /* we only constrain if mapped - if not mapped,
3703 * then gtk_window_compute_configure_request()
3704 * will apply the constraints later, and we
3705 * don't want to lose information about
3706 * what position the user set before then.
3707 * i.e. if you do a move() then turn off POS_CENTER
3708 * then show the window, your move() will work.
3710 gtk_window_constrain_position (window,
3711 widget->allocation.width,
3712 widget->allocation.height,
3715 /* Note that this request doesn't go through our standard request
3716 * framework, e.g. doesn't increment configure_request_count,
3717 * doesn't set info->last, etc.; that's because
3718 * we don't save the info needed to arrive at this same request
3721 * To gtk_window_move_resize(), this will end up looking exactly
3722 * the same as the position being changed by the window
3726 /* FIXME are we handling gravity properly for framed windows? */
3728 gdk_window_move (window->frame,
3729 x - window->frame_left,
3730 y - window->frame_top);
3732 gdk_window_move (GTK_WIDGET (window)->window,
3737 /* Save this position to apply on mapping */
3738 info->initial_x = x;
3739 info->initial_y = y;
3740 info->initial_pos_set = TRUE;
3745 * gtk_window_get_position:
3746 * @window: a #GtkWindow
3747 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3748 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3750 * This function returns the position you need to pass to
3751 * gtk_window_move() to keep @window in its current position. This
3752 * means that the meaning of the returned value varies with window
3753 * gravity. See gtk_window_move() for more details.
3755 * If you haven't changed the window gravity, its gravity will be
3756 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3757 * gets the position of the top-left corner of the window manager
3758 * frame for the window. gtk_window_move() sets the position of this
3759 * same top-left corner.
3761 * gtk_window_get_position() is not 100% reliable because the X Window System
3762 * does not specify a way to obtain the geometry of the
3763 * decorations placed on a window by the window manager.
3764 * Thus GTK+ is using a "best guess" that works with most
3767 * Moreover, nearly all window managers are historically broken with
3768 * respect to their handling of window gravity. So moving a window to
3769 * its current position as returned by gtk_window_get_position() tends
3770 * to result in moving the window slightly. Window managers are
3771 * slowly getting better over time.
3773 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3774 * frame is not relevant, and thus gtk_window_get_position() will
3775 * always produce accurate results. However you can't use static
3776 * gravity to do things like place a window in a corner of the screen,
3777 * because static gravity ignores the window manager decorations.
3779 * If you are saving and restoring your application's window
3780 * positions, you should know that it's impossible for applications to
3781 * do this without getting it somewhat wrong because applications do
3782 * not have sufficient knowledge of window manager state. The Correct
3783 * Mechanism is to support the session management protocol (see the
3784 * "GnomeClient" object in the GNOME libraries for example) and allow
3785 * the window manager to save your window sizes and positions.
3790 gtk_window_get_position (GtkWindow *window,
3796 g_return_if_fail (GTK_IS_WINDOW (window));
3798 widget = GTK_WIDGET (window);
3800 if (window->gravity == GDK_GRAVITY_STATIC)
3802 if (GTK_WIDGET_MAPPED (widget))
3804 /* This does a server round-trip, which is sort of wrong;
3805 * but a server round-trip is inevitable for
3806 * gdk_window_get_frame_extents() in the usual
3807 * NorthWestGravity case below, so not sure what else to
3808 * do. We should likely be consistent about whether we get
3809 * the client-side info or the server-side info.
3811 gdk_window_get_origin (widget->window, root_x, root_y);
3815 GdkRectangle configure_request;
3817 gtk_window_compute_configure_request (window,
3821 *root_x = configure_request.x;
3822 *root_y = configure_request.y;
3827 GdkRectangle frame_extents;
3832 if (GTK_WIDGET_MAPPED (widget))
3835 gdk_window_get_frame_extents (window->frame, &frame_extents);
3837 gdk_window_get_frame_extents (widget->window, &frame_extents);
3838 x = frame_extents.x;
3839 y = frame_extents.y;
3840 gtk_window_get_size (window, &w, &h);
3844 /* We just say the frame has 0 size on all sides.
3845 * Not sure what else to do.
3847 gtk_window_compute_configure_request (window,
3850 x = frame_extents.x;
3851 y = frame_extents.y;
3852 w = frame_extents.width;
3853 h = frame_extents.height;
3856 switch (window->gravity)
3858 case GDK_GRAVITY_NORTH:
3859 case GDK_GRAVITY_CENTER:
3860 case GDK_GRAVITY_SOUTH:
3861 /* Find center of frame. */
3862 x += frame_extents.width / 2;
3863 /* Center client window on that point. */
3867 case GDK_GRAVITY_SOUTH_EAST:
3868 case GDK_GRAVITY_EAST:
3869 case GDK_GRAVITY_NORTH_EAST:
3870 /* Find right edge of frame */
3871 x += frame_extents.width;
3872 /* Align left edge of client at that point. */
3879 switch (window->gravity)
3881 case GDK_GRAVITY_WEST:
3882 case GDK_GRAVITY_CENTER:
3883 case GDK_GRAVITY_EAST:
3884 /* Find center of frame. */
3885 y += frame_extents.height / 2;
3886 /* Center client window there. */
3889 case GDK_GRAVITY_SOUTH_WEST:
3890 case GDK_GRAVITY_SOUTH:
3891 case GDK_GRAVITY_SOUTH_EAST:
3892 /* Find south edge of frame */
3893 y += frame_extents.height;
3894 /* Place bottom edge of client there */
3909 * gtk_window_reshow_with_initial_size:
3910 * @window: a #GtkWindow
3912 * Hides @window, then reshows it, resetting the
3913 * default size and position of the window. Used
3914 * by GUI builders only.
3917 gtk_window_reshow_with_initial_size (GtkWindow *window)
3921 g_return_if_fail (GTK_IS_WINDOW (window));
3923 widget = GTK_WIDGET (window);
3925 gtk_widget_hide (widget);
3926 gtk_widget_unrealize (widget);
3927 gtk_widget_show (widget);
3931 gtk_window_destroy (GtkObject *object)
3933 GtkWindow *window = GTK_WINDOW (object);
3935 toplevel_list = g_slist_remove (toplevel_list, window);
3937 if (window->transient_parent)
3938 gtk_window_set_transient_for (window, NULL);
3940 /* frees the icons */
3941 gtk_window_set_icon_list (window, NULL);
3943 if (window->has_user_ref_count)
3945 window->has_user_ref_count = FALSE;
3946 g_object_unref (window);
3950 gtk_window_group_remove_window (window->group, window);
3952 gtk_window_free_key_hash (window);
3954 GTK_OBJECT_CLASS (gtk_window_parent_class)->destroy (object);
3958 gtk_window_finalize (GObject *object)
3960 GtkWindow *window = GTK_WINDOW (object);
3961 GtkMnemonicHash *mnemonic_hash;
3963 g_free (window->title);
3964 g_free (window->wmclass_name);
3965 g_free (window->wmclass_class);
3966 g_free (window->wm_role);
3968 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
3970 _gtk_mnemonic_hash_free (mnemonic_hash);
3972 if (window->geometry_info)
3974 if (window->geometry_info->widget)
3975 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3976 gtk_widget_destroyed,
3977 &window->geometry_info->widget);
3978 g_free (window->geometry_info);
3981 if (window->keys_changed_handler)
3983 g_source_remove (window->keys_changed_handler);
3984 window->keys_changed_handler = 0;
3989 g_signal_handlers_disconnect_by_func (window->screen,
3990 gtk_window_on_composited_changed, window);
3993 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
3997 gtk_window_show (GtkWidget *widget)
3999 GtkWindow *window = GTK_WINDOW (widget);
4000 GtkContainer *container = GTK_CONTAINER (window);
4001 gboolean need_resize;
4003 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
4005 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
4006 container->need_resize = FALSE;
4010 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4011 GtkAllocation allocation = { 0, 0 };
4012 GdkRectangle configure_request;
4013 GdkGeometry new_geometry;
4015 gboolean was_realized;
4017 /* We are going to go ahead and perform this configure request
4018 * and then emulate a configure notify by going ahead and
4019 * doing a size allocate. Sort of a synchronous
4020 * mini-copy of gtk_window_move_resize() here.
4022 gtk_window_compute_configure_request (window,
4027 /* We update this because we are going to go ahead
4028 * and gdk_window_resize() below, rather than
4031 info->last.configure_request.width = configure_request.width;
4032 info->last.configure_request.height = configure_request.height;
4034 /* and allocate the window - this is normally done
4035 * in move_resize in response to configure notify
4037 allocation.width = configure_request.width;
4038 allocation.height = configure_request.height;
4039 gtk_widget_size_allocate (widget, &allocation);
4041 /* Then we guarantee we have a realize */
4042 was_realized = FALSE;
4043 if (!GTK_WIDGET_REALIZED (widget))
4045 gtk_widget_realize (widget);
4046 was_realized = TRUE;
4049 /* Must be done after the windows are realized,
4050 * so that the decorations can be read
4052 gtk_decorated_window_calculate_frame_size (window);
4054 /* We only send configure request if we didn't just finish
4055 * creating the window; if we just created the window
4056 * then we created it with widget->allocation anyhow.
4059 gdk_window_move_resize (widget->window,
4060 configure_request.x,
4061 configure_request.y,
4062 configure_request.width,
4063 configure_request.height);
4066 gtk_container_check_resize (container);
4068 gtk_widget_map (widget);
4070 /* Try to make sure that we have some focused widget
4072 if (!window->focus_widget && !GTK_IS_PLUG (window))
4073 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4076 gtk_grab_add (widget);
4080 gtk_window_hide (GtkWidget *widget)
4082 GtkWindow *window = GTK_WINDOW (widget);
4084 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4085 gtk_widget_unmap (widget);
4088 gtk_grab_remove (widget);
4092 gtk_window_map (GtkWidget *widget)
4094 GtkWindow *window = GTK_WINDOW (widget);
4095 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4096 GdkWindow *toplevel;
4098 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4100 if (window->bin.child &&
4101 GTK_WIDGET_VISIBLE (window->bin.child) &&
4102 !GTK_WIDGET_MAPPED (window->bin.child))
4103 gtk_widget_map (window->bin.child);
4106 toplevel = window->frame;
4108 toplevel = widget->window;
4110 if (window->maximize_initially)
4111 gdk_window_maximize (toplevel);
4113 gdk_window_unmaximize (toplevel);
4115 if (window->stick_initially)
4116 gdk_window_stick (toplevel);
4118 gdk_window_unstick (toplevel);
4120 if (window->iconify_initially)
4121 gdk_window_iconify (toplevel);
4123 gdk_window_deiconify (toplevel);
4125 if (priv->fullscreen_initially)
4126 gdk_window_fullscreen (toplevel);
4128 gdk_window_unfullscreen (toplevel);
4130 gdk_window_set_keep_above (toplevel, priv->above_initially);
4132 gdk_window_set_keep_below (toplevel, priv->below_initially);
4134 /* No longer use the default settings */
4135 window->need_default_size = FALSE;
4136 window->need_default_position = FALSE;
4138 if (priv->reset_type_hint)
4140 /* We should only reset the type hint when the application
4141 * used gtk_window_set_type_hint() to change the hint.
4142 * Some applications use X directly to change the properties;
4143 * in that case, we shouldn't overwrite what they did.
4145 gdk_window_set_type_hint (widget->window, priv->type_hint);
4146 priv->reset_type_hint = FALSE;
4149 gdk_window_show (widget->window);
4152 gdk_window_show (window->frame);
4154 if (!disable_startup_notification &&
4155 !sent_startup_notification)
4157 sent_startup_notification = TRUE;
4158 gdk_notify_startup_complete ();
4163 gtk_window_map_event (GtkWidget *widget,
4166 if (!GTK_WIDGET_MAPPED (widget))
4168 /* we should be be unmapped, but are getting a MapEvent, this may happen
4169 * to toplevel XWindows if mapping was intercepted by a window manager
4170 * and an unmap request occoured while the MapRequestEvent was still
4171 * being handled. we work around this situaiton here by re-requesting
4172 * the window being unmapped. more details can be found in:
4173 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4175 gdk_window_hide (widget->window);
4181 gtk_window_unmap (GtkWidget *widget)
4183 GtkWindow *window = GTK_WINDOW (widget);
4184 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
4185 GtkWindowGeometryInfo *info;
4186 GdkWindowState state;
4188 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4190 gdk_window_withdraw (window->frame);
4192 gdk_window_withdraw (widget->window);
4194 window->configure_request_count = 0;
4195 window->configure_notify_received = FALSE;
4197 /* on unmap, we reset the default positioning of the window,
4198 * so it's placed again, but we don't reset the default
4199 * size of the window, so it's remembered.
4201 window->need_default_position = TRUE;
4203 info = gtk_window_get_geometry_info (window, FALSE);
4206 info->initial_pos_set = FALSE;
4207 info->position_constraints_changed = FALSE;
4210 state = gdk_window_get_state (widget->window);
4211 window->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4212 window->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4213 window->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4214 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4215 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4219 gtk_window_realize (GtkWidget *widget)
4222 GdkWindow *parent_window;
4223 GdkWindowAttr attributes;
4224 gint attributes_mask;
4225 GtkWindowPrivate *priv;
4227 window = GTK_WINDOW (widget);
4229 priv = GTK_WINDOW_GET_PRIVATE (window);
4231 /* ensure widget tree is properly size allocated */
4232 if (widget->allocation.x == -1 &&
4233 widget->allocation.y == -1 &&
4234 widget->allocation.width == 1 &&
4235 widget->allocation.height == 1)
4237 GtkRequisition requisition;
4238 GtkAllocation allocation = { 0, 0, 200, 200 };
4240 gtk_widget_size_request (widget, &requisition);
4241 if (requisition.width || requisition.height)
4243 /* non-empty window */
4244 allocation.width = requisition.width;
4245 allocation.height = requisition.height;
4247 gtk_widget_size_allocate (widget, &allocation);
4249 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4251 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
4254 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4256 switch (window->type)
4258 case GTK_WINDOW_TOPLEVEL:
4259 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4261 case GTK_WINDOW_POPUP:
4262 attributes.window_type = GDK_WINDOW_TEMP;
4265 g_warning (G_STRLOC": Unknown window type %d!", window->type);
4269 attributes.title = window->title;
4270 attributes.wmclass_name = window->wmclass_name;
4271 attributes.wmclass_class = window->wmclass_class;
4272 attributes.wclass = GDK_INPUT_OUTPUT;
4273 attributes.visual = gtk_widget_get_visual (widget);
4274 attributes.colormap = gtk_widget_get_colormap (widget);
4276 if (window->has_frame)
4278 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
4279 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
4280 attributes.event_mask = (GDK_EXPOSURE_MASK |
4281 GDK_KEY_PRESS_MASK |
4282 GDK_ENTER_NOTIFY_MASK |
4283 GDK_LEAVE_NOTIFY_MASK |
4284 GDK_FOCUS_CHANGE_MASK |
4285 GDK_STRUCTURE_MASK |
4286 GDK_BUTTON_MOTION_MASK |
4287 GDK_POINTER_MOTION_HINT_MASK |
4288 GDK_BUTTON_PRESS_MASK |
4289 GDK_BUTTON_RELEASE_MASK);
4291 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4293 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4294 &attributes, attributes_mask);
4296 gdk_window_set_user_data (window->frame, widget);
4298 attributes.window_type = GDK_WINDOW_CHILD;
4299 attributes.x = window->frame_left;
4300 attributes.y = window->frame_top;
4302 attributes_mask = GDK_WA_X | GDK_WA_Y;
4304 parent_window = window->frame;
4306 g_signal_connect (window,
4308 G_CALLBACK (gtk_window_event),
4313 attributes_mask = 0;
4314 parent_window = gtk_widget_get_root_window (widget);
4317 attributes.width = widget->allocation.width;
4318 attributes.height = widget->allocation.height;
4319 attributes.event_mask = gtk_widget_get_events (widget);
4320 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4321 GDK_KEY_PRESS_MASK |
4322 GDK_KEY_RELEASE_MASK |
4323 GDK_ENTER_NOTIFY_MASK |
4324 GDK_LEAVE_NOTIFY_MASK |
4325 GDK_FOCUS_CHANGE_MASK |
4326 GDK_STRUCTURE_MASK);
4328 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
4329 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
4330 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
4332 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
4334 gdk_window_enable_synchronized_configure (widget->window);
4336 gdk_window_set_user_data (widget->window, window);
4338 widget->style = gtk_style_attach (widget->style, widget->window);
4339 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4341 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
4343 /* This is a bad hack to set the window background. */
4344 gtk_window_paint (widget, NULL);
4346 if (window->transient_parent &&
4347 GTK_WIDGET_REALIZED (window->transient_parent))
4348 gdk_window_set_transient_for (widget->window,
4349 GTK_WIDGET (window->transient_parent)->window);
4351 if (window->wm_role)
4352 gdk_window_set_role (widget->window, window->wm_role);
4354 if (!window->decorated)
4355 gdk_window_set_decorations (widget->window, 0);
4357 if (!priv->deletable)
4358 gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4360 gdk_window_set_type_hint (widget->window, priv->type_hint);
4362 if (gtk_window_get_skip_pager_hint (window))
4363 gdk_window_set_skip_pager_hint (widget->window, TRUE);
4365 if (gtk_window_get_skip_taskbar_hint (window))
4366 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
4368 if (gtk_window_get_accept_focus (window))
4369 gdk_window_set_accept_focus (widget->window, TRUE);
4371 gdk_window_set_accept_focus (widget->window, FALSE);
4373 if (gtk_window_get_focus_on_map (window))
4374 gdk_window_set_focus_on_map (widget->window, TRUE);
4376 gdk_window_set_focus_on_map (widget->window, FALSE);
4379 gdk_window_set_modal_hint (widget->window, TRUE);
4381 gdk_window_set_modal_hint (widget->window, FALSE);
4384 gtk_window_realize_icon (window);
4388 gtk_window_unrealize (GtkWidget *widget)
4391 GtkWindowGeometryInfo *info;
4393 window = GTK_WINDOW (widget);
4395 /* On unrealize, we reset the size of the window such
4396 * that we will re-apply the default sizing stuff
4397 * next time we show the window.
4399 * Default positioning is reset on unmap, instead of unrealize.
4401 window->need_default_size = TRUE;
4402 info = gtk_window_get_geometry_info (window, FALSE);
4405 info->resize_width = -1;
4406 info->resize_height = -1;
4407 info->last.configure_request.x = 0;
4408 info->last.configure_request.y = 0;
4409 info->last.configure_request.width = -1;
4410 info->last.configure_request.height = -1;
4411 /* be sure we reset geom hints on re-realize */
4412 info->last.flags = 0;
4417 gdk_window_set_user_data (window->frame, NULL);
4418 gdk_window_destroy (window->frame);
4419 window->frame = NULL;
4423 gtk_window_unrealize_icon (window);
4425 (* GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize) (widget);
4429 gtk_window_size_request (GtkWidget *widget,
4430 GtkRequisition *requisition)
4435 window = GTK_WINDOW (widget);
4436 bin = GTK_BIN (window);
4438 requisition->width = GTK_CONTAINER (window)->border_width * 2;
4439 requisition->height = GTK_CONTAINER (window)->border_width * 2;
4441 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
4443 GtkRequisition child_requisition;
4445 gtk_widget_size_request (bin->child, &child_requisition);
4447 requisition->width += child_requisition.width;
4448 requisition->height += child_requisition.height;
4453 gtk_window_size_allocate (GtkWidget *widget,
4454 GtkAllocation *allocation)
4457 GtkAllocation child_allocation;
4459 window = GTK_WINDOW (widget);
4460 widget->allocation = *allocation;
4462 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
4464 child_allocation.x = GTK_CONTAINER (window)->border_width;
4465 child_allocation.y = GTK_CONTAINER (window)->border_width;
4466 child_allocation.width =
4467 MAX (1, (gint)allocation->width - child_allocation.x * 2);
4468 child_allocation.height =
4469 MAX (1, (gint)allocation->height - child_allocation.y * 2);
4471 gtk_widget_size_allocate (window->bin.child, &child_allocation);
4474 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4476 gdk_window_resize (window->frame,
4477 allocation->width + window->frame_left + window->frame_right,
4478 allocation->height + window->frame_top + window->frame_bottom);
4483 gtk_window_event (GtkWidget *widget, GdkEvent *event)
4486 gboolean return_val;
4488 window = GTK_WINDOW (widget);
4490 if (window->frame && (event->any.window == window->frame))
4492 if ((event->type != GDK_KEY_PRESS) &&
4493 (event->type != GDK_KEY_RELEASE) &&
4494 (event->type != GDK_FOCUS_CHANGE))
4496 g_signal_stop_emission_by_name (widget, "event");
4498 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
4503 g_object_unref (event->any.window);
4504 event->any.window = g_object_ref (widget->window);
4512 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
4514 GdkEventConfigure *configure_event;
4517 switch (event->type)
4520 configure_event = (GdkEventConfigure *)event;
4522 /* Invalidate the decorations */
4525 rect.width = configure_event->width;
4526 rect.height = configure_event->height;
4528 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
4530 /* Pass on the (modified) configure event */
4531 configure_event->width -= window->frame_left + window->frame_right;
4532 configure_event->height -= window->frame_top + window->frame_bottom;
4533 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
4542 gtk_window_configure_event (GtkWidget *widget,
4543 GdkEventConfigure *event)
4545 GtkWindow *window = GTK_WINDOW (widget);
4546 gboolean expected_reply = window->configure_request_count > 0;
4548 /* window->configure_request_count incremented for each
4549 * configure request, and decremented to a min of 0 for
4550 * each configure notify.
4552 * All it means is that we know we will get at least
4553 * window->configure_request_count more configure notifies.
4554 * We could get more configure notifies than that; some
4555 * of the configure notifies we get may be unrelated to
4556 * the configure requests. But we will get at least
4557 * window->configure_request_count notifies.
4560 if (window->configure_request_count > 0)
4561 window->configure_request_count -= 1;
4563 /* As an optimization, we avoid a resize when possible.
4565 * The only times we can avoid a resize are:
4566 * - we know only the position changed, not the size
4567 * - we know we have made more requests and so will get more
4568 * notifies and can wait to resize when we get them
4571 if (!expected_reply &&
4572 (widget->allocation.width == event->width &&
4573 widget->allocation.height == event->height))
4575 gdk_window_configure_finished (widget->window);
4580 * If we do need to resize, we do that by:
4581 * - filling in widget->allocation with the new size
4582 * - setting configure_notify_received to TRUE
4583 * for use in gtk_window_move_resize()
4584 * - queueing a resize, leading to invocation of
4585 * gtk_window_move_resize() in an idle handler
4589 window->configure_notify_received = TRUE;
4591 widget->allocation.width = event->width;
4592 widget->allocation.height = event->height;
4594 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4599 /* the accel_key and accel_mods fields of the key have to be setup
4600 * upon calling this function. it'll then return whether that key
4601 * is at all used as accelerator, and if so will OR in the
4602 * accel_flags member of the key.
4605 _gtk_window_query_nonaccels (GtkWindow *window,
4607 GdkModifierType accel_mods)
4609 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4611 /* movement keys are considered locked accels */
4614 static const guint bindings[] = {
4615 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
4616 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
4620 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
4621 if (bindings[i] == accel_key)
4625 /* mnemonics are considered locked accels */
4626 if (accel_mods == window->mnemonic_modifier)
4628 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4629 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
4637 * gtk_window_propagate_key_event:
4638 * @window: a #GtkWindow
4639 * @event: a #GdkEventKey
4641 * Propagate a key press or release event to the focus widget and
4642 * up the focus container chain until a widget handles @event.
4643 * This is normally called by the default ::key_press_event and
4644 * ::key_release_event handlers for toplevel windows,
4645 * however in some cases it may be useful to call this directly when
4646 * overriding the standard key handling for a toplevel window.
4648 * Return value: %TRUE if a widget in the focus chain handled the event.
4651 gtk_window_propagate_key_event (GtkWindow *window,
4654 gboolean handled = FALSE;
4655 GtkWidget *widget, *focus;
4657 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4659 widget = GTK_WIDGET (window);
4660 focus = window->focus_widget;
4662 g_object_ref (focus);
4665 focus && focus != widget &&
4666 gtk_widget_get_toplevel (focus) == widget)
4670 if (GTK_WIDGET_IS_SENSITIVE (focus))
4671 handled = gtk_widget_event (focus, (GdkEvent*) event);
4673 parent = focus->parent;
4675 g_object_ref (parent);
4677 g_object_unref (focus);
4683 g_object_unref (focus);
4689 gtk_window_key_press_event (GtkWidget *widget,
4692 GtkWindow *window = GTK_WINDOW (widget);
4693 gboolean handled = FALSE;
4695 /* handle mnemonics and accelerators */
4697 handled = gtk_window_activate_key (window, event);
4699 /* handle focus widget key events */
4701 handled = gtk_window_propagate_key_event (window, event);
4703 /* Chain up, invokes binding set */
4705 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
4711 gtk_window_key_release_event (GtkWidget *widget,
4714 GtkWindow *window = GTK_WINDOW (widget);
4715 gboolean handled = FALSE;
4717 /* handle focus widget key events */
4719 handled = gtk_window_propagate_key_event (window, event);
4721 /* Chain up, invokes binding set */
4723 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
4729 gtk_window_real_activate_default (GtkWindow *window)
4731 gtk_window_activate_default (window);
4735 gtk_window_real_activate_focus (GtkWindow *window)
4737 gtk_window_activate_focus (window);
4741 gtk_window_move_focus (GtkWindow *window,
4742 GtkDirectionType dir)
4744 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4746 if (!GTK_CONTAINER (window)->focus_child)
4747 gtk_window_set_focus (window, NULL);
4751 gtk_window_enter_notify_event (GtkWidget *widget,
4752 GdkEventCrossing *event)
4758 gtk_window_leave_notify_event (GtkWidget *widget,
4759 GdkEventCrossing *event)
4765 do_focus_change (GtkWidget *widget,
4768 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4770 g_object_ref (widget);
4773 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4775 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4777 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4778 fevent->focus_change.window = widget->window;
4780 g_object_ref (widget->window);
4781 fevent->focus_change.in = in;
4783 gtk_widget_event (widget, fevent);
4785 g_object_notify (G_OBJECT (widget), "has-focus");
4787 g_object_unref (widget);
4788 gdk_event_free (fevent);
4792 gtk_window_focus_in_event (GtkWidget *widget,
4793 GdkEventFocus *event)
4795 GtkWindow *window = GTK_WINDOW (widget);
4797 /* It appears spurious focus in events can occur when
4798 * the window is hidden. So we'll just check to see if
4799 * the window is visible before actually handling the
4802 if (GTK_WIDGET_VISIBLE (widget))
4804 _gtk_window_set_has_toplevel_focus (window, TRUE);
4805 _gtk_window_set_is_active (window, TRUE);
4812 gtk_window_focus_out_event (GtkWidget *widget,
4813 GdkEventFocus *event)
4815 GtkWindow *window = GTK_WINDOW (widget);
4817 _gtk_window_set_has_toplevel_focus (window, FALSE);
4818 _gtk_window_set_is_active (window, FALSE);
4823 static GdkAtom atom_rcfiles = GDK_NONE;
4824 static GdkAtom atom_iconthemes = GDK_NONE;
4827 send_client_message_to_embedded_windows (GtkWidget *widget,
4828 GdkAtom message_type)
4830 GList *embedded_windows;
4832 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
4833 if (embedded_windows)
4835 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4838 for (i = 0; i < 5; i++)
4839 send_event->client.data.l[i] = 0;
4840 send_event->client.data_format = 32;
4841 send_event->client.message_type = message_type;
4843 while (embedded_windows)
4845 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4846 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4847 embedded_windows = embedded_windows->next;
4850 gdk_event_free (send_event);
4855 gtk_window_client_event (GtkWidget *widget,
4856 GdkEventClient *event)
4860 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
4861 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
4864 if (event->message_type == atom_rcfiles)
4866 send_client_message_to_embedded_windows (widget, atom_rcfiles);
4867 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4870 if (event->message_type == atom_iconthemes)
4872 send_client_message_to_embedded_windows (widget, atom_iconthemes);
4873 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
4880 gtk_window_check_resize (GtkContainer *container)
4882 GtkWindow *window = GTK_WINDOW (container);
4884 if (GTK_WIDGET_VISIBLE (container))
4885 gtk_window_move_resize (window);
4889 gtk_window_focus (GtkWidget *widget,
4890 GtkDirectionType direction)
4894 GtkContainer *container;
4895 GtkWidget *old_focus_child;
4898 container = GTK_CONTAINER (widget);
4899 window = GTK_WINDOW (widget);
4900 bin = GTK_BIN (widget);
4902 old_focus_child = container->focus_child;
4904 /* We need a special implementation here to deal properly with wrapping
4905 * around in the tab chain without the danger of going into an
4908 if (old_focus_child)
4910 if (gtk_widget_child_focus (old_focus_child, direction))
4914 if (window->focus_widget)
4916 if (direction == GTK_DIR_LEFT ||
4917 direction == GTK_DIR_RIGHT ||
4918 direction == GTK_DIR_UP ||
4919 direction == GTK_DIR_DOWN)
4924 /* Wrapped off the end, clear the focus setting for the toplpevel */
4925 parent = window->focus_widget->parent;
4928 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4929 parent = GTK_WIDGET (parent)->parent;
4932 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4935 /* Now try to focus the first widget in the window */
4938 if (gtk_widget_child_focus (bin->child, direction))
4946 gtk_window_real_set_focus (GtkWindow *window,
4949 GtkWidget *old_focus = window->focus_widget;
4950 gboolean had_default = FALSE;
4951 gboolean focus_had_default = FALSE;
4952 gboolean old_focus_had_default = FALSE;
4956 g_object_ref (old_focus);
4957 g_object_freeze_notify (G_OBJECT (old_focus));
4958 old_focus_had_default = GTK_WIDGET_HAS_DEFAULT (old_focus);
4962 g_object_ref (focus);
4963 g_object_freeze_notify (G_OBJECT (focus));
4964 focus_had_default = GTK_WIDGET_HAS_DEFAULT (focus);
4967 if (window->default_widget)
4968 had_default = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4970 if (window->focus_widget)
4972 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4973 (window->focus_widget != window->default_widget))
4975 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4976 gtk_widget_queue_draw (window->focus_widget);
4978 if (window->default_widget)
4979 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4982 window->focus_widget = NULL;
4984 if (window->has_focus)
4985 do_focus_change (old_focus, FALSE);
4987 g_object_notify (G_OBJECT (old_focus), "is-focus");
4990 /* The above notifications may have set a new focus widget,
4991 * if so, we don't want to override it.
4993 if (focus && !window->focus_widget)
4995 window->focus_widget = focus;
4997 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4998 (window->focus_widget != window->default_widget))
5000 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
5001 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
5003 if (window->default_widget)
5004 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
5007 if (window->has_focus)
5008 do_focus_change (window->focus_widget, TRUE);
5010 g_object_notify (G_OBJECT (window->focus_widget), "is-focus");
5013 /* If the default widget changed, a redraw will have been queued
5014 * on the old and new default widgets by gtk_window_set_default(), so
5015 * we only have to worry about the case where it didn't change.
5016 * We'll sometimes queue a draw twice on the new widget but that
5019 if (window->default_widget &&
5020 (had_default != GTK_WIDGET_HAS_DEFAULT (window->default_widget)))
5021 gtk_widget_queue_draw (window->default_widget);
5025 if (old_focus_had_default != GTK_WIDGET_HAS_DEFAULT (old_focus))
5026 gtk_widget_queue_draw (old_focus);
5028 g_object_thaw_notify (G_OBJECT (old_focus));
5029 g_object_unref (old_focus);
5033 if (focus_had_default != GTK_WIDGET_HAS_DEFAULT (focus))
5034 gtk_widget_queue_draw (focus);
5036 g_object_thaw_notify (G_OBJECT (focus));
5037 g_object_unref (focus);
5042 * _gtk_window_unset_focus_and_default:
5043 * @window: a #GtkWindow
5044 * @widget: a widget inside of @window
5046 * Checks whether the focus and default widgets of @window are
5047 * @widget or a descendent of @widget, and if so, unset them.
5050 _gtk_window_unset_focus_and_default (GtkWindow *window,
5056 g_object_ref (window);
5057 g_object_ref (widget);
5059 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
5061 child = window->focus_widget;
5063 while (child && child != widget)
5064 child = child->parent;
5066 if (child == widget)
5067 gtk_window_set_focus (GTK_WINDOW (window), NULL);
5070 child = window->default_widget;
5072 while (child && child != widget)
5073 child = child->parent;
5075 if (child == widget)
5076 gtk_window_set_default (window, NULL);
5078 g_object_unref (widget);
5079 g_object_unref (window);
5082 /*********************************
5083 * Functions related to resizing *
5084 *********************************/
5086 /* This function doesn't constrain to geometry hints */
5088 gtk_window_compute_configure_request_size (GtkWindow *window,
5092 GtkRequisition requisition;
5093 GtkWindowGeometryInfo *info;
5097 * - we've done a size request
5100 widget = GTK_WIDGET (window);
5102 info = gtk_window_get_geometry_info (window, FALSE);
5104 if (window->need_default_size)
5106 gtk_widget_get_child_requisition (widget, &requisition);
5108 /* Default to requisition */
5109 *width = requisition.width;
5110 *height = requisition.height;
5112 /* If window is empty so requests 0, default to random nonzero size */
5113 if (*width == 0 && *height == 0)
5119 /* Override requisition with default size */
5123 gint base_width = 0;
5124 gint base_height = 0;
5126 gint height_inc = 1;
5128 if (info->default_is_geometry &&
5129 (info->default_width > 0 || info->default_height > 0))
5131 GdkGeometry geometry;
5134 gtk_window_compute_hints (window, &geometry, &flags);
5136 if (flags & GDK_HINT_BASE_SIZE)
5138 base_width = geometry.base_width;
5139 base_height = geometry.base_height;
5141 else if (flags & GDK_HINT_MIN_SIZE)
5143 base_width = geometry.min_width;
5144 base_height = geometry.min_height;
5146 if (flags & GDK_HINT_RESIZE_INC)
5148 width_inc = geometry.width_inc;
5149 height_inc = geometry.height_inc;
5153 if (info->default_width > 0)
5154 *width = info->default_width * width_inc + base_width;
5156 if (info->default_height > 0)
5157 *height = info->default_height * height_inc + base_height;
5162 /* Default to keeping current size */
5163 *width = widget->allocation.width;
5164 *height = widget->allocation.height;
5167 /* Override any size with gtk_window_resize() values */
5170 if (info->resize_width > 0)
5171 *width = info->resize_width;
5173 if (info->resize_height > 0)
5174 *height = info->resize_height;
5178 static GtkWindowPosition
5179 get_effective_position (GtkWindow *window)
5181 GtkWindowPosition pos = window->position;
5182 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5183 (window->transient_parent == NULL ||
5184 !GTK_WIDGET_MAPPED (window->transient_parent)))
5185 pos = GTK_WIN_POS_NONE;
5191 get_center_monitor_of_window (GtkWindow *window)
5193 /* We could try to sort out the relative positions of the monitors and
5194 * stuff, or we could just be losers and assume you have a row
5195 * or column of monitors.
5197 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5201 get_monitor_containing_pointer (GtkWindow *window)
5205 GdkScreen *window_screen;
5206 GdkScreen *pointer_screen;
5208 window_screen = gtk_window_check_screen (window);
5209 gdk_display_get_pointer (gdk_screen_get_display (window_screen),
5213 if (pointer_screen == window_screen)
5214 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5222 center_window_on_monitor (GtkWindow *window,
5228 GdkRectangle monitor;
5231 monitor_num = get_monitor_containing_pointer (window);
5233 if (monitor_num == -1)
5234 monitor_num = get_center_monitor_of_window (window);
5236 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5237 monitor_num, &monitor);
5239 *x = (monitor.width - w) / 2 + monitor.x;
5240 *y = (monitor.height - h) / 2 + monitor.y;
5242 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5243 * and WM decorations.
5252 clamp_window_to_rectangle (gint *x,
5256 const GdkRectangle *rect)
5258 gint outside_w, outside_h;
5260 outside_w = (*x + w) - (rect->x + rect->width);
5264 outside_h = (*y + h) - (rect->y + rect->height);
5268 /* if larger than the screen, center on the screen. */
5270 *x += (rect->x - *x) / 2;
5272 *y += (rect->y - *y) / 2;
5277 gtk_window_compute_configure_request (GtkWindow *window,
5278 GdkRectangle *request,
5279 GdkGeometry *geometry,
5282 GdkGeometry new_geometry;
5286 GtkWindowPosition pos;
5287 GtkWidget *parent_widget;
5288 GtkWindowGeometryInfo *info;
5292 widget = GTK_WIDGET (window);
5294 screen = gtk_window_check_screen (window);
5296 gtk_widget_size_request (widget, NULL);
5297 gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
5299 gtk_window_compute_hints (window, &new_geometry, &new_flags);
5300 gtk_window_constrain_size (window,
5301 &new_geometry, new_flags,
5305 parent_widget = (GtkWidget*) window->transient_parent;
5307 pos = get_effective_position (window);
5308 info = gtk_window_get_geometry_info (window, FALSE);
5310 /* by default, don't change position requested */
5313 x = info->last.configure_request.x;
5314 y = info->last.configure_request.y;
5323 if (window->need_default_position)
5326 /* FIXME this all interrelates with window gravity.
5327 * For most of them I think we want to set GRAVITY_CENTER.
5329 * Not sure how to go about that.
5334 /* here we are only handling CENTER_ALWAYS
5335 * as it relates to default positioning,
5336 * where it's equivalent to simply CENTER
5338 case GTK_WIN_POS_CENTER_ALWAYS:
5339 case GTK_WIN_POS_CENTER:
5340 center_window_on_monitor (window, w, h, &x, &y);
5343 case GTK_WIN_POS_CENTER_ON_PARENT:
5346 GdkRectangle monitor;
5349 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
5351 if (parent_widget->window != NULL)
5352 monitor_num = gdk_screen_get_monitor_at_window (screen,
5353 parent_widget->window);
5357 gdk_window_get_origin (parent_widget->window,
5360 x = ox + (parent_widget->allocation.width - w) / 2;
5361 y = oy + (parent_widget->allocation.height - h) / 2;
5363 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5364 * WM decorations. If parent wasn't on a monitor, just
5367 if (monitor_num >= 0)
5369 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5370 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5375 case GTK_WIN_POS_MOUSE:
5377 gint screen_width = gdk_screen_get_width (screen);
5378 gint screen_height = gdk_screen_get_height (screen);
5380 GdkRectangle monitor;
5381 GdkScreen *pointer_screen;
5384 gdk_display_get_pointer (gdk_screen_get_display (screen),
5388 if (pointer_screen == screen)
5389 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
5395 x = CLAMP (x, 0, screen_width - w);
5396 y = CLAMP (y, 0, screen_height - h);
5398 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5399 * WM decorations. Don't try to figure out what's going
5400 * on if the mouse wasn't inside a monitor.
5402 if (monitor_num >= 0)
5404 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5405 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5413 } /* if (window->need_default_position) */
5415 if (window->need_default_position && info &&
5416 info->initial_pos_set)
5418 x = info->initial_x;
5419 y = info->initial_y;
5420 gtk_window_constrain_position (window, w, h, &x, &y);
5426 request->height = h;
5429 *geometry = new_geometry;
5435 gtk_window_constrain_position (GtkWindow *window,
5441 /* See long comments in gtk_window_move_resize()
5442 * on when it's safe to call this function.
5444 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
5446 gint center_x, center_y;
5448 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
5456 gtk_window_move_resize (GtkWindow *window)
5460 * First we determine whether any information has changed that would
5461 * cause us to revise our last configure request. If we would send
5462 * a different configure request from last time, then
5463 * configure_request_size_changed = TRUE or
5464 * configure_request_pos_changed = TRUE. configure_request_size_changed
5465 * may be true due to new hints, a gtk_window_resize(), or whatever.
5466 * configure_request_pos_changed may be true due to gtk_window_set_position()
5467 * or gtk_window_move().
5469 * If the configure request has changed, we send off a new one. To
5470 * ensure GTK+ invariants are maintained (resize queue does what it
5471 * should), we go ahead and size_allocate the requested size in this
5474 * If the configure request has not changed, we don't ever resend
5475 * it, because it could mean fighting the user or window manager.
5478 * To prepare the configure request, we come up with a base size/pos:
5479 * - the one from gtk_window_move()/gtk_window_resize()
5480 * - else default_width, default_height if we haven't ever
5482 * - else the size request if we haven't ever been mapped,
5483 * as a substitute default size
5484 * - else the current size of the window, as received from
5485 * configure notifies (i.e. the current allocation)
5487 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
5488 * the position request to be centered.
5491 GtkContainer *container;
5492 GtkWindowGeometryInfo *info;
5493 GdkGeometry new_geometry;
5495 GdkRectangle new_request;
5496 gboolean configure_request_size_changed;
5497 gboolean configure_request_pos_changed;
5498 gboolean hints_changed; /* do we need to send these again */
5499 GtkWindowLastGeometryInfo saved_last_info;
5501 widget = GTK_WIDGET (window);
5502 container = GTK_CONTAINER (widget);
5503 info = gtk_window_get_geometry_info (window, TRUE);
5505 configure_request_size_changed = FALSE;
5506 configure_request_pos_changed = FALSE;
5508 gtk_window_compute_configure_request (window, &new_request,
5509 &new_geometry, &new_flags);
5511 /* This check implies the invariant that we never set info->last
5512 * without setting the hints and sending off a configure request.
5514 * If we change info->last without sending the request, we may
5517 if (info->last.configure_request.x != new_request.x ||
5518 info->last.configure_request.y != new_request.y)
5519 configure_request_pos_changed = TRUE;
5521 if ((info->last.configure_request.width != new_request.width ||
5522 info->last.configure_request.height != new_request.height))
5523 configure_request_size_changed = TRUE;
5525 hints_changed = FALSE;
5527 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
5528 &new_geometry, new_flags))
5530 hints_changed = TRUE;
5533 /* Position Constraints
5534 * ====================
5536 * POS_CENTER_ALWAYS is conceptually a constraint rather than
5537 * a default. The other POS_ values are used only when the
5538 * window is shown, not after that.
5540 * However, we can't implement a position constraint as
5541 * "anytime the window size changes, center the window"
5542 * because this may well end up fighting the WM or user. In
5543 * fact it gets in an infinite loop with at least one WM.
5545 * Basically, applications are in no way in a position to
5546 * constrain the position of a window, with one exception:
5547 * override redirect windows. (Really the intended purpose
5548 * of CENTER_ALWAYS anyhow, I would think.)
5550 * So the way we implement this "constraint" is to say that when WE
5551 * cause a move or resize, i.e. we make a configure request changing
5552 * window size, we recompute the CENTER_ALWAYS position to reflect
5553 * the new window size, and include it in our request. Also, if we
5554 * just turned on CENTER_ALWAYS we snap to center with a new
5555 * request. Otherwise, if we are just NOTIFIED of a move or resize
5556 * done by someone else e.g. the window manager, we do NOT send a
5557 * new configure request.
5559 * For override redirect windows, this works fine; all window
5560 * sizes are from our configure requests. For managed windows,
5561 * it is at least semi-sane, though who knows what the
5562 * app author is thinking.
5565 /* This condition should be kept in sync with the condition later on
5566 * that determines whether we send a configure request. i.e. we
5567 * should do this position constraining anytime we were going to
5568 * send a configure request anyhow, plus when constraints have
5571 if (configure_request_pos_changed ||
5572 configure_request_size_changed ||
5574 info->position_constraints_changed)
5576 /* We request the constrained position if:
5577 * - we were changing position, and need to clamp
5578 * the change to the constraint
5579 * - we're changing the size anyway
5580 * - set_position() was called to toggle CENTER_ALWAYS on
5583 gtk_window_constrain_position (window,
5589 /* Update whether we need to request a move */
5590 if (info->last.configure_request.x != new_request.x ||
5591 info->last.configure_request.y != new_request.y)
5592 configure_request_pos_changed = TRUE;
5594 configure_request_pos_changed = FALSE;
5598 if (window->type == GTK_WINDOW_TOPLEVEL)
5600 int notify_x, notify_y;
5602 /* this is the position from the last configure notify */
5603 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
5605 g_message ("--- %s ---\n"
5606 "last : %d,%d\t%d x %d\n"
5607 "this : %d,%d\t%d x %d\n"
5608 "alloc : %d,%d\t%d x %d\n"
5610 "resize: \t%d x %d\n"
5611 "size_changed: %d pos_changed: %d hints_changed: %d\n"
5612 "configure_notify_received: %d\n"
5613 "configure_request_count: %d\n"
5614 "position_constraints_changed: %d\n",
5615 window->title ? window->title : "(no title)",
5616 info->last.configure_request.x,
5617 info->last.configure_request.y,
5618 info->last.configure_request.width,
5619 info->last.configure_request.height,
5625 widget->allocation.width,
5626 widget->allocation.height,
5627 widget->requisition.width,
5628 widget->requisition.height,
5630 info->resize_height,
5631 configure_request_pos_changed,
5632 configure_request_size_changed,
5634 window->configure_notify_received,
5635 window->configure_request_count,
5636 info->position_constraints_changed);
5640 saved_last_info = info->last;
5641 info->last.geometry = new_geometry;
5642 info->last.flags = new_flags;
5643 info->last.configure_request = new_request;
5645 /* need to set PPosition so the WM will look at our position,
5646 * but we don't want to count PPosition coming and going as a hints
5647 * change for future iterations. So we saved info->last prior to
5651 /* Also, if the initial position was explicitly set, then we always
5652 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
5656 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
5657 * this is an initial map
5660 if ((configure_request_pos_changed ||
5661 info->initial_pos_set ||
5662 (window->need_default_position &&
5663 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
5664 (new_flags & GDK_HINT_POS) == 0)
5666 new_flags |= GDK_HINT_POS;
5667 hints_changed = TRUE;
5670 /* Set hints if necessary
5673 gdk_window_set_geometry_hints (widget->window,
5677 /* handle resizing/moving and widget tree allocation
5679 if (window->configure_notify_received)
5681 GtkAllocation allocation;
5683 /* If we have received a configure event since
5684 * the last time in this function, we need to
5685 * accept our new size and size_allocate child widgets.
5686 * (see gtk_window_configure_event() for more details).
5688 * 1 or more configure notifies may have been received.
5689 * Also, configure_notify_received will only be TRUE
5690 * if all expected configure notifies have been received
5691 * (one per configure request), as an optimization.
5694 window->configure_notify_received = FALSE;
5696 /* gtk_window_configure_event() filled in widget->allocation */
5697 allocation = widget->allocation;
5698 gtk_widget_size_allocate (widget, &allocation);
5700 gdk_window_process_all_updates ();
5702 gdk_window_configure_finished (widget->window);
5704 /* If the configure request changed, it means that
5706 * 1) coincidentally changed hints or widget properties
5707 * impacting the configure request before getting
5708 * a configure notify, or
5709 * 2) some broken widget is changing its size request
5710 * during size allocation, resulting in
5711 * a false appearance of changed configure request.
5713 * For 1), we could just go ahead and ask for the
5714 * new size right now, but doing that for 2)
5715 * might well be fighting the user (and can even
5716 * trigger a loop). Since we really don't want to
5717 * do that, we requeue a resize in hopes that
5718 * by the time it gets handled, the child has seen
5719 * the light and is willing to go along with the
5720 * new size. (this happens for the zvt widget, since
5721 * the size_allocate() above will have stored the
5722 * requisition corresponding to the new size in the
5725 * This doesn't buy us anything for 1), but it shouldn't
5726 * hurt us too badly, since it is what would have
5727 * happened if we had gotten the configure event before
5728 * the new size had been set.
5731 if (configure_request_size_changed ||
5732 configure_request_pos_changed)
5734 /* Don't change the recorded last info after all, because we
5735 * haven't actually updated to the new info yet - we decided
5736 * to postpone our configure request until later.
5738 info->last = saved_last_info;
5740 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
5743 return; /* Bail out, we didn't really process the move/resize */
5745 else if ((configure_request_size_changed || hints_changed) &&
5746 (widget->allocation.width != new_request.width ||
5747 widget->allocation.height != new_request.height))
5750 /* We are in one of the following situations:
5751 * A. configure_request_size_changed
5752 * our requisition has changed and we need a different window size,
5753 * so we request it from the window manager.
5754 * B. !configure_request_size_changed && hints_changed
5755 * the window manager rejects our size, but we have just changed the
5756 * window manager hints, so there's a chance our request will
5757 * be honoured this time, so we try again.
5759 * However, if the new requisition is the same as the current allocation,
5760 * we don't request it again, since we won't get a ConfigureNotify back from
5761 * the window manager unless it decides to change our requisition. If
5762 * we don't get the ConfigureNotify back, the resize queue will never be run.
5765 /* Now send the configure request */
5766 if (configure_request_pos_changed)
5770 gdk_window_move_resize (window->frame,
5771 new_request.x - window->frame_left,
5772 new_request.y - window->frame_top,
5773 new_request.width + window->frame_left + window->frame_right,
5774 new_request.height + window->frame_top + window->frame_bottom);
5775 gdk_window_resize (widget->window,
5776 new_request.width, new_request.height);
5779 gdk_window_move_resize (widget->window,
5780 new_request.x, new_request.y,
5781 new_request.width, new_request.height);
5783 else /* only size changed */
5786 gdk_window_resize (window->frame,
5787 new_request.width + window->frame_left + window->frame_right,
5788 new_request.height + window->frame_top + window->frame_bottom);
5789 gdk_window_resize (widget->window,
5790 new_request.width, new_request.height);
5793 /* Increment the number of have-not-yet-received-notify requests */
5794 window->configure_request_count += 1;
5796 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5797 * configure event in response to our resizing request.
5798 * the configure event will cause a new resize with
5799 * ->configure_notify_received=TRUE.
5800 * until then, we want to
5801 * - discard expose events
5802 * - coalesce resizes for our children
5803 * - defer any window resizes until the configure event arrived
5804 * to achieve this, we queue a resize for the window, but remove its
5805 * resizing handler, so resizing will not be handled from the next
5806 * idle handler but when the configure event arrives.
5808 * FIXME: we should also dequeue the pending redraws here, since
5809 * we handle those ourselves upon ->configure_notify_received==TRUE.
5811 if (container->resize_mode == GTK_RESIZE_QUEUE)
5813 gtk_widget_queue_resize (widget);
5814 _gtk_container_dequeue_resize_handler (container);
5819 /* Handle any position changes.
5821 if (configure_request_pos_changed)
5825 gdk_window_move (window->frame,
5826 new_request.x - window->frame_left,
5827 new_request.y - window->frame_top);
5830 gdk_window_move (widget->window,
5831 new_request.x, new_request.y);
5834 /* And run the resize queue.
5836 gtk_container_resize_children (container);
5839 /* We have now processed a move/resize since the last position
5840 * constraint change, setting of the initial position, or resize.
5841 * (Not resetting these flags here can lead to infinite loops for
5842 * GTK_RESIZE_IMMEDIATE containers)
5844 info->position_constraints_changed = FALSE;
5845 info->initial_pos_set = FALSE;
5846 info->resize_width = -1;
5847 info->resize_height = -1;
5850 /* Compare two sets of Geometry hints for equality.
5853 gtk_window_compare_hints (GdkGeometry *geometry_a,
5855 GdkGeometry *geometry_b,
5858 if (flags_a != flags_b)
5861 if ((flags_a & GDK_HINT_MIN_SIZE) &&
5862 (geometry_a->min_width != geometry_b->min_width ||
5863 geometry_a->min_height != geometry_b->min_height))
5866 if ((flags_a & GDK_HINT_MAX_SIZE) &&
5867 (geometry_a->max_width != geometry_b->max_width ||
5868 geometry_a->max_height != geometry_b->max_height))
5871 if ((flags_a & GDK_HINT_BASE_SIZE) &&
5872 (geometry_a->base_width != geometry_b->base_width ||
5873 geometry_a->base_height != geometry_b->base_height))
5876 if ((flags_a & GDK_HINT_ASPECT) &&
5877 (geometry_a->min_aspect != geometry_b->min_aspect ||
5878 geometry_a->max_aspect != geometry_b->max_aspect))
5881 if ((flags_a & GDK_HINT_RESIZE_INC) &&
5882 (geometry_a->width_inc != geometry_b->width_inc ||
5883 geometry_a->height_inc != geometry_b->height_inc))
5886 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5887 geometry_a->win_gravity != geometry_b->win_gravity)
5894 _gtk_window_constrain_size (GtkWindow *window,
5900 GtkWindowGeometryInfo *info;
5902 g_return_if_fail (GTK_IS_WINDOW (window));
5904 info = window->geometry_info;
5907 GdkWindowHints flags = info->last.flags;
5908 GdkGeometry *geometry = &info->last.geometry;
5910 gtk_window_constrain_size (window,
5921 gtk_window_constrain_size (GtkWindow *window,
5922 GdkGeometry *geometry,
5929 gdk_window_constrain_size (geometry, flags, width, height,
5930 new_width, new_height);
5933 /* Compute the set of geometry hints and flags for a window
5934 * based on the application set geometry, and requisiition
5935 * of the window. gtk_widget_size_request() must have been
5939 gtk_window_compute_hints (GtkWindow *window,
5940 GdkGeometry *new_geometry,
5944 gint extra_width = 0;
5945 gint extra_height = 0;
5946 GtkWindowGeometryInfo *geometry_info;
5947 GtkRequisition requisition;
5949 widget = GTK_WIDGET (window);
5951 gtk_widget_get_child_requisition (widget, &requisition);
5952 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5956 *new_flags = geometry_info->mask;
5957 *new_geometry = geometry_info->geometry;
5964 if (geometry_info && geometry_info->widget)
5966 GtkRequisition child_requisition;
5968 /* FIXME: This really isn't right. It gets the min size wrong and forces
5969 * callers to do horrible hacks like set a huge usize on the child requisition
5970 * to get the base size right. We really want to find the answers to:
5972 * - If the geometry widget was infinitely big, how much extra space
5973 * would be needed for the stuff around it.
5975 * - If the geometry widget was infinitely small, how big would the
5976 * window still have to be.
5978 * Finding these answers would be a bit of a mess here. (Bug #68668)
5980 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5982 extra_width = widget->requisition.width - child_requisition.width;
5983 extra_height = widget->requisition.height - child_requisition.height;
5986 /* We don't want to set GDK_HINT_POS in here, we just set it
5987 * in gtk_window_move_resize() when we want the position
5991 if (*new_flags & GDK_HINT_BASE_SIZE)
5993 new_geometry->base_width += extra_width;
5994 new_geometry->base_height += extra_height;
5996 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5997 (*new_flags & GDK_HINT_RESIZE_INC) &&
5998 ((extra_width != 0) || (extra_height != 0)))
6000 *new_flags |= GDK_HINT_BASE_SIZE;
6002 new_geometry->base_width = extra_width;
6003 new_geometry->base_height = extra_height;
6006 if (*new_flags & GDK_HINT_MIN_SIZE)
6008 if (new_geometry->min_width < 0)
6009 new_geometry->min_width = requisition.width;
6011 new_geometry->min_width += extra_width;
6013 if (new_geometry->min_height < 0)
6014 new_geometry->min_height = requisition.height;
6016 new_geometry->min_height += extra_height;
6018 else if (!window->allow_shrink)
6020 *new_flags |= GDK_HINT_MIN_SIZE;
6022 new_geometry->min_width = requisition.width;
6023 new_geometry->min_height = requisition.height;
6026 if (*new_flags & GDK_HINT_MAX_SIZE)
6028 if (new_geometry->max_width < 0)
6029 new_geometry->max_width = requisition.width;
6031 new_geometry->max_width += extra_width;
6033 if (new_geometry->max_height < 0)
6034 new_geometry->max_height = requisition.height;
6036 new_geometry->max_height += extra_height;
6038 else if (!window->allow_grow)
6040 *new_flags |= GDK_HINT_MAX_SIZE;
6042 new_geometry->max_width = requisition.width;
6043 new_geometry->max_height = requisition.height;
6046 *new_flags |= GDK_HINT_WIN_GRAVITY;
6047 new_geometry->win_gravity = window->gravity;
6050 /***********************
6051 * Redrawing functions *
6052 ***********************/
6055 gtk_window_paint (GtkWidget *widget,
6058 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
6059 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
6063 gtk_window_expose (GtkWidget *widget,
6064 GdkEventExpose *event)
6066 if (!GTK_WIDGET_APP_PAINTABLE (widget))
6067 gtk_window_paint (widget, &event->area);
6069 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event)
6070 return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event);
6076 * gtk_window_set_has_frame:
6077 * @window: a #GtkWindow
6078 * @setting: a boolean
6080 * (Note: this is a special-purpose function for the framebuffer port,
6081 * that causes GTK+ to draw its own window border. For most applications,
6082 * you want gtk_window_set_decorated() instead, which tells the window
6083 * manager whether to draw the window border.)
6085 * If this function is called on a window with setting of %TRUE, before
6086 * it is realized or showed, it will have a "frame" window around
6087 * @window->window, accessible in @window->frame. Using the signal
6088 * frame_event you can receive all events targeted at the frame.
6090 * This function is used by the linux-fb port to implement managed
6091 * windows, but it could conceivably be used by X-programs that
6092 * want to do their own window decorations.
6096 gtk_window_set_has_frame (GtkWindow *window,
6099 g_return_if_fail (GTK_IS_WINDOW (window));
6100 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
6102 window->has_frame = setting != FALSE;
6106 * gtk_window_get_has_frame:
6107 * @window: a #GtkWindow
6109 * Accessor for whether the window has a frame window exterior to
6110 * @window->window. Gets the value set by gtk_window_set_has_frame ().
6112 * Return value: %TRUE if a frame has been added to the window
6113 * via gtk_window_set_has_frame().
6116 gtk_window_get_has_frame (GtkWindow *window)
6118 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6120 return window->has_frame;
6124 * gtk_window_set_frame_dimensions:
6125 * @window: a #GtkWindow that has a frame
6126 * @left: The width of the left border
6127 * @top: The height of the top border
6128 * @right: The width of the right border
6129 * @bottom: The height of the bottom border
6131 * (Note: this is a special-purpose function intended for the framebuffer
6132 * port; see gtk_window_set_has_frame(). It will have no effect on the
6133 * window border drawn by the window manager, which is the normal
6134 * case when using the X Window system.)
6136 * For windows with frames (see gtk_window_set_has_frame()) this function
6137 * can be used to change the size of the frame border.
6140 gtk_window_set_frame_dimensions (GtkWindow *window,
6148 g_return_if_fail (GTK_IS_WINDOW (window));
6150 widget = GTK_WIDGET (window);
6152 if (window->frame_left == left &&
6153 window->frame_top == top &&
6154 window->frame_right == right &&
6155 window->frame_bottom == bottom)
6158 window->frame_left = left;
6159 window->frame_top = top;
6160 window->frame_right = right;
6161 window->frame_bottom = bottom;
6163 if (GTK_WIDGET_REALIZED (widget) && window->frame)
6165 gint width = widget->allocation.width + left + right;
6166 gint height = widget->allocation.height + top + bottom;
6167 gdk_window_resize (window->frame, width, height);
6168 gtk_decorated_window_move_resize_window (window,
6170 widget->allocation.width,
6171 widget->allocation.height);
6176 * gtk_window_present:
6177 * @window: a #GtkWindow
6179 * Presents a window to the user. This may mean raising the window
6180 * in the stacking order, deiconifying it, moving it to the current
6181 * desktop, and/or giving it the keyboard focus, possibly dependent
6182 * on the user's platform, window manager, and preferences.
6184 * If @window is hidden, this function calls gtk_widget_show()
6187 * This function should be used when the user tries to open a window
6188 * that's already open. Say for example the preferences dialog is
6189 * currently open, and the user chooses Preferences from the menu
6190 * a second time; use gtk_window_present() to move the already-open dialog
6191 * where the user can see it.
6193 * If you are calling this function in response to a user interaction,
6194 * it is preferable to use gtk_window_present_with_time().
6198 gtk_window_present (GtkWindow *window)
6200 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6204 * gtk_window_present_with_time:
6205 * @window: a #GtkWindow
6206 * @timestamp: the timestamp of the user interaction (typically a
6207 * button or key press event) which triggered this call
6209 * Presents a window to the user in response to a user interaction.
6210 * If you need to present a window without a timestamp, use
6211 * gtk_window_present(). See gtk_window_present() for details.
6216 gtk_window_present_with_time (GtkWindow *window,
6221 g_return_if_fail (GTK_IS_WINDOW (window));
6223 widget = GTK_WIDGET (window);
6225 if (GTK_WIDGET_VISIBLE (window))
6227 g_assert (widget->window != NULL);
6229 gdk_window_show (widget->window);
6231 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
6232 if (timestamp == GDK_CURRENT_TIME)
6234 #ifdef GDK_WINDOWING_X11
6235 GdkDisplay *display;
6237 display = gtk_widget_get_display (GTK_WIDGET (window));
6238 timestamp = gdk_x11_display_get_user_time (display);
6240 timestamp = gtk_get_current_event_time ();
6244 gdk_window_focus (widget->window, timestamp);
6248 gtk_widget_show (widget);
6253 * gtk_window_iconify:
6254 * @window: a #GtkWindow
6256 * Asks to iconify (i.e. minimize) the specified @window. Note that
6257 * you shouldn't assume the window is definitely iconified afterward,
6258 * because other entities (e.g. the user or <link
6259 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
6260 * again, or there may not be a window manager in which case
6261 * iconification isn't possible, etc. But normally the window will end
6262 * up iconified. Just don't write code that crashes if not.
6264 * It's permitted to call this function before showing a window,
6265 * in which case the window will be iconified before it ever appears
6268 * You can track iconification via the "window_state_event" signal
6273 gtk_window_iconify (GtkWindow *window)
6276 GdkWindow *toplevel;
6278 g_return_if_fail (GTK_IS_WINDOW (window));
6280 widget = GTK_WIDGET (window);
6282 window->iconify_initially = TRUE;
6285 toplevel = window->frame;
6287 toplevel = widget->window;
6289 if (toplevel != NULL)
6290 gdk_window_iconify (toplevel);
6294 * gtk_window_deiconify:
6295 * @window: a #GtkWindow
6297 * Asks to deiconify (i.e. unminimize) the specified @window. Note
6298 * that you shouldn't assume the window is definitely deiconified
6299 * afterward, because other entities (e.g. the user or <link
6300 * linkend="gtk-X11-arch">window manager</link>) could iconify it
6301 * again before your code which assumes deiconification gets to run.
6303 * You can track iconification via the "window_state_event" signal
6307 gtk_window_deiconify (GtkWindow *window)
6310 GdkWindow *toplevel;
6312 g_return_if_fail (GTK_IS_WINDOW (window));
6314 widget = GTK_WIDGET (window);
6316 window->iconify_initially = FALSE;
6319 toplevel = window->frame;
6321 toplevel = widget->window;
6323 if (toplevel != NULL)
6324 gdk_window_deiconify (toplevel);
6329 * @window: a #GtkWindow
6331 * Asks to stick @window, which means that it will appear on all user
6332 * desktops. Note that you shouldn't assume the window is definitely
6333 * stuck afterward, because other entities (e.g. the user or <link
6334 * linkend="gtk-X11-arch">window manager</link>) could unstick it
6335 * again, and some window managers do not support sticking
6336 * windows. But normally the window will end up stuck. Just don't
6337 * write code that crashes if not.
6339 * It's permitted to call this function before showing a window.
6341 * You can track stickiness via the "window_state_event" signal
6346 gtk_window_stick (GtkWindow *window)
6349 GdkWindow *toplevel;
6351 g_return_if_fail (GTK_IS_WINDOW (window));
6353 widget = GTK_WIDGET (window);
6355 window->stick_initially = TRUE;
6358 toplevel = window->frame;
6360 toplevel = widget->window;
6362 if (toplevel != NULL)
6363 gdk_window_stick (toplevel);
6367 * gtk_window_unstick:
6368 * @window: a #GtkWindow
6370 * Asks to unstick @window, which means that it will appear on only
6371 * one of the user's desktops. Note that you shouldn't assume the
6372 * window is definitely unstuck afterward, because other entities
6373 * (e.g. the user or <link linkend="gtk-X11-arch">window
6374 * manager</link>) could stick it again. But normally the window will
6375 * end up stuck. Just don't write code that crashes if not.
6377 * You can track stickiness via the "window_state_event" signal
6382 gtk_window_unstick (GtkWindow *window)
6385 GdkWindow *toplevel;
6387 g_return_if_fail (GTK_IS_WINDOW (window));
6389 widget = GTK_WIDGET (window);
6391 window->stick_initially = FALSE;
6394 toplevel = window->frame;
6396 toplevel = widget->window;
6398 if (toplevel != NULL)
6399 gdk_window_unstick (toplevel);
6403 * gtk_window_maximize:
6404 * @window: a #GtkWindow
6406 * Asks to maximize @window, so that it becomes full-screen. Note that
6407 * you shouldn't assume the window is definitely maximized afterward,
6408 * because other entities (e.g. the user or <link
6409 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
6410 * again, and not all window managers support maximization. But
6411 * normally the window will end up maximized. Just don't write code
6412 * that crashes if not.
6414 * It's permitted to call this function before showing a window,
6415 * in which case the window will be maximized when it appears onscreen
6418 * You can track maximization via the "window_state_event" signal
6423 gtk_window_maximize (GtkWindow *window)
6426 GdkWindow *toplevel;
6428 g_return_if_fail (GTK_IS_WINDOW (window));
6430 widget = GTK_WIDGET (window);
6432 window->maximize_initially = TRUE;
6435 toplevel = window->frame;
6437 toplevel = widget->window;
6439 if (toplevel != NULL)
6440 gdk_window_maximize (toplevel);
6444 * gtk_window_unmaximize:
6445 * @window: a #GtkWindow
6447 * Asks to unmaximize @window. Note that you shouldn't assume the
6448 * window is definitely unmaximized afterward, because other entities
6449 * (e.g. the user or <link linkend="gtk-X11-arch">window
6450 * manager</link>) could maximize it again, and not all window
6451 * managers honor requests to unmaximize. But normally the window will
6452 * end up unmaximized. Just don't write code that crashes if not.
6454 * You can track maximization via the "window_state_event" signal
6459 gtk_window_unmaximize (GtkWindow *window)
6462 GdkWindow *toplevel;
6464 g_return_if_fail (GTK_IS_WINDOW (window));
6466 widget = GTK_WIDGET (window);
6468 window->maximize_initially = FALSE;
6471 toplevel = window->frame;
6473 toplevel = widget->window;
6475 if (toplevel != NULL)
6476 gdk_window_unmaximize (toplevel);
6480 * gtk_window_fullscreen:
6481 * @window: a #GtkWindow
6483 * Asks to place @window in the fullscreen state. Note that you
6484 * shouldn't assume the window is definitely full screen afterward,
6485 * because other entities (e.g. the user or <link
6486 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
6487 * again, and not all window managers honor requests to fullscreen
6488 * windows. But normally the window will end up fullscreen. Just
6489 * don't write code that crashes if not.
6491 * You can track the fullscreen state via the "window_state_event" signal
6497 gtk_window_fullscreen (GtkWindow *window)
6500 GdkWindow *toplevel;
6501 GtkWindowPrivate *priv;
6503 g_return_if_fail (GTK_IS_WINDOW (window));
6505 widget = GTK_WIDGET (window);
6506 priv = GTK_WINDOW_GET_PRIVATE (window);
6508 priv->fullscreen_initially = TRUE;
6511 toplevel = window->frame;
6513 toplevel = widget->window;
6515 if (toplevel != NULL)
6516 gdk_window_fullscreen (toplevel);
6520 * gtk_window_unfullscreen:
6521 * @window: a #GtkWindow
6523 * Asks to toggle off the fullscreen state for @window. Note that you
6524 * shouldn't assume the window is definitely not full screen
6525 * afterward, because other entities (e.g. the user or <link
6526 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
6527 * again, and not all window managers honor requests to unfullscreen
6528 * windows. But normally the window will end up restored to its normal
6529 * state. Just don't write code that crashes if not.
6531 * You can track the fullscreen state via the "window_state_event" signal
6537 gtk_window_unfullscreen (GtkWindow *window)
6540 GdkWindow *toplevel;
6541 GtkWindowPrivate *priv;
6543 g_return_if_fail (GTK_IS_WINDOW (window));
6545 widget = GTK_WIDGET (window);
6546 priv = GTK_WINDOW_GET_PRIVATE (window);
6548 priv->fullscreen_initially = FALSE;
6551 toplevel = window->frame;
6553 toplevel = widget->window;
6555 if (toplevel != NULL)
6556 gdk_window_unfullscreen (toplevel);
6560 * gtk_window_set_keep_above:
6561 * @window: a #GtkWindow
6562 * @setting: whether to keep @window above other windows
6564 * Asks to keep @window above, so that it stays on top. Note that
6565 * you shouldn't assume the window is definitely above afterward,
6566 * because other entities (e.g. the user or <link
6567 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
6568 * and not all window managers support keeping windows above. But
6569 * normally the window will end kept above. Just don't write code
6570 * that crashes if not.
6572 * It's permitted to call this function before showing a window,
6573 * in which case the window will be kept above when it appears onscreen
6576 * You can track the above state via the "window_state_event" signal
6579 * Note that, according to the <ulink
6580 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
6581 * Manager Hints</ulink> specification, the above state is mainly meant
6582 * for user preferences and should not be used by applications e.g. for
6583 * drawing attention to their dialogs.
6588 gtk_window_set_keep_above (GtkWindow *window,
6592 GtkWindowPrivate *priv;
6593 GdkWindow *toplevel;
6595 g_return_if_fail (GTK_IS_WINDOW (window));
6597 widget = GTK_WIDGET (window);
6598 priv = GTK_WINDOW_GET_PRIVATE (window);
6600 priv->above_initially = setting != FALSE;
6602 priv->below_initially = FALSE;
6605 toplevel = window->frame;
6607 toplevel = widget->window;
6609 if (toplevel != NULL)
6610 gdk_window_set_keep_above (toplevel, setting);
6614 * gtk_window_set_keep_below:
6615 * @window: a #GtkWindow
6616 * @setting: whether to keep @window below other windows
6618 * Asks to keep @window below, so that it stays in bottom. Note that
6619 * you shouldn't assume the window is definitely below afterward,
6620 * because other entities (e.g. the user or <link
6621 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
6622 * and not all window managers support putting windows below. But
6623 * normally the window will be kept below. Just don't write code
6624 * that crashes if not.
6626 * It's permitted to call this function before showing a window,
6627 * in which case the window will be kept below when it appears onscreen
6630 * You can track the below state via the "window_state_event" signal
6633 * Note that, according to the <ulink
6634 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
6635 * Manager Hints</ulink> specification, the above state is mainly meant
6636 * for user preferences and should not be used by applications e.g. for
6637 * drawing attention to their dialogs.
6642 gtk_window_set_keep_below (GtkWindow *window,
6646 GtkWindowPrivate *priv;
6647 GdkWindow *toplevel;
6649 g_return_if_fail (GTK_IS_WINDOW (window));
6651 widget = GTK_WIDGET (window);
6652 priv = GTK_WINDOW_GET_PRIVATE (window);
6654 priv->below_initially = setting != FALSE;
6656 priv->above_initially = FALSE;
6659 toplevel = window->frame;
6661 toplevel = widget->window;
6663 if (toplevel != NULL)
6664 gdk_window_set_keep_below (toplevel, setting);
6668 * gtk_window_set_resizable:
6669 * @window: a #GtkWindow
6670 * @resizable: %TRUE if the user can resize this window
6672 * Sets whether the user can resize a window. Windows are user resizable
6676 gtk_window_set_resizable (GtkWindow *window,
6679 g_return_if_fail (GTK_IS_WINDOW (window));
6681 gtk_window_set_policy (window, FALSE, resizable, FALSE);
6685 * gtk_window_get_resizable:
6686 * @window: a #GtkWindow
6688 * Gets the value set by gtk_window_set_resizable().
6690 * Return value: %TRUE if the user can resize the window
6693 gtk_window_get_resizable (GtkWindow *window)
6695 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6697 /* allow_grow is most likely to indicate the semantic concept we
6698 * mean by "resizable" (and will be a reliable indicator if
6699 * set_policy() hasn't been called)
6701 return window->allow_grow;
6705 * gtk_window_set_gravity:
6706 * @window: a #GtkWindow
6707 * @gravity: window gravity
6709 * Window gravity defines the meaning of coordinates passed to
6710 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
6713 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
6714 * typically "do what you mean."
6718 gtk_window_set_gravity (GtkWindow *window,
6721 g_return_if_fail (GTK_IS_WINDOW (window));
6723 if (gravity != window->gravity)
6725 window->gravity = gravity;
6727 /* gtk_window_move_resize() will adapt gravity
6729 gtk_widget_queue_resize (GTK_WIDGET (window));
6731 g_object_notify (G_OBJECT (window), "gravity");
6736 * gtk_window_get_gravity:
6737 * @window: a #GtkWindow
6739 * Gets the value set by gtk_window_set_gravity().
6741 * Return value: window gravity
6744 gtk_window_get_gravity (GtkWindow *window)
6746 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
6748 return window->gravity;
6752 * gtk_window_begin_resize_drag:
6753 * @window: a #GtkWindow
6754 * @button: mouse button that initiated the drag
6755 * @edge: position of the resize control
6756 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6757 * @root_y: Y position where the user clicked to initiate the drag
6758 * @timestamp: timestamp from the click event that initiated the drag
6760 * Starts resizing a window. This function is used if an application
6761 * has window resizing controls. When GDK can support it, the resize
6762 * will be done using the standard mechanism for the <link
6763 * linkend="gtk-X11-arch">window manager</link> or windowing
6764 * system. Otherwise, GDK will try to emulate window resizing,
6765 * potentially not all that well, depending on the windowing system.
6769 gtk_window_begin_resize_drag (GtkWindow *window,
6777 GdkWindow *toplevel;
6779 g_return_if_fail (GTK_IS_WINDOW (window));
6780 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6782 widget = GTK_WIDGET (window);
6785 toplevel = window->frame;
6787 toplevel = widget->window;
6789 gdk_window_begin_resize_drag (toplevel,
6796 * gtk_window_get_frame_dimensions:
6797 * @window: a #GtkWindow
6798 * @left: location to store the width of the frame at the left, or %NULL
6799 * @top: location to store the height of the frame at the top, or %NULL
6800 * @right: location to store the width of the frame at the returns, or %NULL
6801 * @bottom: location to store the height of the frame at the bottom, or %NULL
6803 * (Note: this is a special-purpose function intended for the
6804 * framebuffer port; see gtk_window_set_has_frame(). It will not
6805 * return the size of the window border drawn by the <link
6806 * linkend="gtk-X11-arch">window manager</link>, which is the normal
6807 * case when using a windowing system. See
6808 * gdk_window_get_frame_extents() to get the standard window border
6811 * Retrieves the dimensions of the frame window for this toplevel.
6812 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
6815 gtk_window_get_frame_dimensions (GtkWindow *window,
6821 g_return_if_fail (GTK_IS_WINDOW (window));
6824 *left = window->frame_left;
6826 *top = window->frame_top;
6828 *right = window->frame_right;
6830 *bottom = window->frame_bottom;
6834 * gtk_window_begin_move_drag:
6835 * @window: a #GtkWindow
6836 * @button: mouse button that initiated the drag
6837 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6838 * @root_y: Y position where the user clicked to initiate the drag
6839 * @timestamp: timestamp from the click event that initiated the drag
6841 * Starts moving a window. This function is used if an application has
6842 * window movement grips. When GDK can support it, the window movement
6843 * will be done using the standard mechanism for the <link
6844 * linkend="gtk-X11-arch">window manager</link> or windowing
6845 * system. Otherwise, GDK will try to emulate window movement,
6846 * potentially not all that well, depending on the windowing system.
6850 gtk_window_begin_move_drag (GtkWindow *window,
6857 GdkWindow *toplevel;
6859 g_return_if_fail (GTK_IS_WINDOW (window));
6860 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6862 widget = GTK_WIDGET (window);
6865 toplevel = window->frame;
6867 toplevel = widget->window;
6869 gdk_window_begin_move_drag (toplevel,
6876 * gtk_window_set_screen:
6877 * @window: a #GtkWindow.
6878 * @screen: a #GdkScreen.
6880 * Sets the #GdkScreen where the @window is displayed; if
6881 * the window is already mapped, it will be unmapped, and
6882 * then remapped on the new screen.
6887 gtk_window_set_screen (GtkWindow *window,
6891 GdkScreen *previous_screen;
6892 gboolean was_mapped;
6894 g_return_if_fail (GTK_IS_WINDOW (window));
6895 g_return_if_fail (GDK_IS_SCREEN (screen));
6897 if (screen == window->screen)
6900 widget = GTK_WIDGET (window);
6902 previous_screen = window->screen;
6903 was_mapped = GTK_WIDGET_MAPPED (widget);
6906 gtk_widget_unmap (widget);
6907 if (GTK_WIDGET_REALIZED (widget))
6908 gtk_widget_unrealize (widget);
6910 gtk_window_free_key_hash (window);
6911 window->screen = screen;
6912 gtk_widget_reset_rc_styles (widget);
6913 if (screen != previous_screen)
6915 g_signal_handlers_disconnect_by_func (previous_screen,
6916 gtk_window_on_composited_changed, window);
6917 g_signal_connect (screen, "composited_changed",
6918 G_CALLBACK (gtk_window_on_composited_changed), window);
6920 _gtk_widget_propagate_screen_changed (widget, previous_screen);
6921 _gtk_widget_propagate_composited_changed (widget);
6923 g_object_notify (G_OBJECT (window), "screen");
6926 gtk_widget_map (widget);
6930 gtk_window_on_composited_changed (GdkScreen *screen,
6933 gtk_widget_queue_draw (GTK_WIDGET (window));
6935 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
6939 gtk_window_check_screen (GtkWindow *window)
6942 return window->screen;
6945 g_warning ("Screen for GtkWindow not set; you must always set\n"
6946 "a screen for a GtkWindow before using the window");
6952 * gtk_window_get_screen:
6953 * @window: a #GtkWindow.
6955 * Returns the #GdkScreen associated with @window.
6957 * Return value: a #GdkScreen.
6962 gtk_window_get_screen (GtkWindow *window)
6964 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6966 return window->screen;
6970 * gtk_window_is_active:
6971 * @window: a #GtkWindow
6973 * Returns whether the window is part of the current active toplevel.
6974 * (That is, the toplevel window receiving keystrokes.)
6975 * The return value is %TRUE if the window is active toplevel
6976 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
6977 * You might use this function if you wanted to draw a widget
6978 * differently in an active window from a widget in an inactive window.
6979 * See gtk_window_has_toplevel_focus()
6981 * Return value: %TRUE if the window part of the current active window.
6986 gtk_window_is_active (GtkWindow *window)
6988 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6990 return window->is_active;
6994 * gtk_window_has_toplevel_focus:
6995 * @window: a #GtkWindow
6997 * Returns whether the input focus is within this GtkWindow.
6998 * For real toplevel windows, this is identical to gtk_window_is_active(),
6999 * but for embedded windows, like #GtkPlug, the results will differ.
7001 * Return value: %TRUE if the input focus is within this GtkWindow
7006 gtk_window_has_toplevel_focus (GtkWindow *window)
7008 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7010 return window->has_toplevel_focus;
7014 gtk_window_group_class_init (GtkWindowGroupClass *klass)
7019 gtk_window_group_get_type (void)
7021 static GType window_group_type = 0;
7023 if (!window_group_type)
7025 const GTypeInfo window_group_info =
7027 sizeof (GtkWindowGroupClass),
7028 NULL, /* base_init */
7029 NULL, /* base_finalize */
7030 (GClassInitFunc) gtk_window_group_class_init,
7031 NULL, /* class_finalize */
7032 NULL, /* class_data */
7033 sizeof (GtkWindowGroup),
7034 0, /* n_preallocs */
7035 (GInstanceInitFunc) NULL,
7038 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
7039 &window_group_info, 0);
7042 return window_group_type;
7046 * gtk_window_group_new:
7048 * Creates a new #GtkWindowGroup object. Grabs added with
7049 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
7051 * Return value: a new #GtkWindowGroup.
7054 gtk_window_group_new (void)
7056 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
7060 window_group_cleanup_grabs (GtkWindowGroup *group,
7064 GSList *to_remove = NULL;
7066 tmp_list = group->grabs;
7069 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
7070 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
7071 tmp_list = tmp_list->next;
7076 gtk_grab_remove (to_remove->data);
7077 g_object_unref (to_remove->data);
7078 to_remove = g_slist_delete_link (to_remove, to_remove);
7083 * gtk_window_group_add_window:
7084 * @window_group: a #GtkWindowGroup
7085 * @window: the #GtkWindow to add
7087 * Adds a window to a #GtkWindowGroup.
7090 gtk_window_group_add_window (GtkWindowGroup *window_group,
7093 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7094 g_return_if_fail (GTK_IS_WINDOW (window));
7096 if (window->group != window_group)
7098 g_object_ref (window);
7099 g_object_ref (window_group);
7102 gtk_window_group_remove_window (window->group, window);
7104 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
7106 window->group = window_group;
7108 g_object_unref (window);
7113 * gtk_window_group_remove_window:
7114 * @window_group: a #GtkWindowGroup
7115 * @window: the #GtkWindow to remove
7117 * Removes a window from a #GtkWindowGroup.
7120 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7123 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7124 g_return_if_fail (GTK_IS_WIDGET (window));
7125 g_return_if_fail (window->group == window_group);
7127 g_object_ref (window);
7129 window_group_cleanup_grabs (window_group, window);
7130 window->group = NULL;
7132 g_object_unref (window_group);
7133 g_object_unref (window);
7137 * gtk_window_get_group:
7138 * @window: a #GtkWindow, or %NULL
7140 * Returns the group for @window or the default group, if
7141 * @window is %NULL or if @window does not have an explicit
7144 * Returns: the #GtkWindowGroup for a window or the default group
7149 gtk_window_get_group (GtkWindow *window)
7151 if (window && window->group)
7152 return window->group;
7155 static GtkWindowGroup *default_group = NULL;
7158 default_group = gtk_window_group_new ();
7160 return default_group;
7164 /* Return the current grab widget of the given group
7167 _gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
7169 if (window_group->grabs)
7170 return GTK_WIDGET (window_group->grabs->data);
7175 Derived from XParseGeometry() in XFree86
7177 Copyright 1985, 1986, 1987,1998 The Open Group
7179 All Rights Reserved.
7181 The above copyright notice and this permission notice shall be included
7182 in all copies or substantial portions of the Software.
7184 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
7185 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7186 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7187 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
7188 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7189 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
7190 OTHER DEALINGS IN THE SOFTWARE.
7192 Except as contained in this notice, the name of The Open Group shall
7193 not be used in advertising or otherwise to promote the sale, use or
7194 other dealings in this Software without prior written authorization
7195 from The Open Group.
7200 * XParseGeometry parses strings of the form
7201 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
7202 * width, height, xoffset, and yoffset are unsigned integers.
7203 * Example: "=80x24+300-49"
7204 * The equal sign is optional.
7205 * It returns a bitmask that indicates which of the four values
7206 * were actually found in the string. For each value found,
7207 * the corresponding argument is updated; for each value
7208 * not found, the corresponding argument is left unchanged.
7211 /* The following code is from Xlib, and is minimally modified, so we
7212 * can track any upstream changes if required. Don't change this
7213 * code. Or if you do, put in a huge comment marking which thing
7218 read_int (gchar *string,
7226 else if (*string == '-')
7232 for (; (*string >= '0') && (*string <= '9'); string++)
7234 result = (result * 10) + (*string - '0');
7246 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
7247 * value (x, y, width, height) was found in the parsed string.
7249 #define NoValue 0x0000
7250 #define XValue 0x0001
7251 #define YValue 0x0002
7252 #define WidthValue 0x0004
7253 #define HeightValue 0x0008
7254 #define AllValues 0x000F
7255 #define XNegative 0x0010
7256 #define YNegative 0x0020
7258 /* Try not to reformat/modify, so we can compare/sync with X sources */
7260 gtk_XParseGeometry (const char *string,
7263 unsigned int *width,
7264 unsigned int *height)
7268 unsigned int tempWidth, tempHeight;
7270 char *nextCharacter;
7272 /* These initializations are just to silence gcc */
7278 if ( (string == NULL) || (*string == '\0')) return(mask);
7280 string++; /* ignore possible '=' at beg of geometry spec */
7282 strind = (char *)string;
7283 if (*strind != '+' && *strind != '-' && *strind != 'x') {
7284 tempWidth = read_int(strind, &nextCharacter);
7285 if (strind == nextCharacter)
7287 strind = nextCharacter;
7291 if (*strind == 'x' || *strind == 'X') {
7293 tempHeight = read_int(strind, &nextCharacter);
7294 if (strind == nextCharacter)
7296 strind = nextCharacter;
7297 mask |= HeightValue;
7300 if ((*strind == '+') || (*strind == '-')) {
7301 if (*strind == '-') {
7303 tempX = -read_int(strind, &nextCharacter);
7304 if (strind == nextCharacter)
7306 strind = nextCharacter;
7312 tempX = read_int(strind, &nextCharacter);
7313 if (strind == nextCharacter)
7315 strind = nextCharacter;
7318 if ((*strind == '+') || (*strind == '-')) {
7319 if (*strind == '-') {
7321 tempY = -read_int(strind, &nextCharacter);
7322 if (strind == nextCharacter)
7324 strind = nextCharacter;
7331 tempY = read_int(strind, &nextCharacter);
7332 if (strind == nextCharacter)
7334 strind = nextCharacter;
7340 /* If strind isn't at the end of the string the it's an invalid
7341 geometry specification. */
7343 if (*strind != '\0') return (0);
7349 if (mask & WidthValue)
7351 if (mask & HeightValue)
7352 *height = tempHeight;
7357 * gtk_window_parse_geometry:
7358 * @window: a #GtkWindow
7359 * @geometry: geometry string
7361 * Parses a standard X Window System geometry string - see the
7362 * manual page for X (type 'man X') for details on this.
7363 * gtk_window_parse_geometry() does work on all GTK+ ports
7364 * including Win32 but is primarily intended for an X environment.
7366 * If either a size or a position can be extracted from the
7367 * geometry string, gtk_window_parse_geometry() returns %TRUE
7368 * and calls gtk_window_set_default_size() and/or gtk_window_move()
7369 * to resize/move the window.
7371 * If gtk_window_parse_geometry() returns %TRUE, it will also
7372 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
7373 * indicating to the window manager that the size/position of
7374 * the window was user-specified. This causes most window
7375 * managers to honor the geometry.
7377 * Note that for gtk_window_parse_geometry() to work as expected, it has
7378 * to be called when the window has its "final" size, i.e. after calling
7379 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
7382 * <informalexample><programlisting>
7383 * #include <gtk/gtk.h>
7386 * fill_with_content (GtkWidget *vbox)
7388 * /<!-- -->* fill with content... *<!-- -->/
7392 * main (int argc, char *argv[])
7394 * GtkWidget *window, *vbox;
7395 * GdkGeometry size_hints = {
7396 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
7399 * gtk_init (&argc, &argv);
7401 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7402 * vbox = gtk_vbox_new (FALSE, 0);
7404 * gtk_container_add (GTK_CONTAINER (window), vbox);
7405 * fill_with_content (vbox);
7406 * gtk_widget_show_all (vbox);
7408 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
7411 * GDK_HINT_MIN_SIZE |
7412 * GDK_HINT_BASE_SIZE |
7413 * GDK_HINT_RESIZE_INC);
7417 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
7418 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
7421 * gtk_widget_show_all (window);
7426 * </programlisting></informalexample>
7428 * Return value: %TRUE if string was parsed successfully
7431 gtk_window_parse_geometry (GtkWindow *window,
7432 const gchar *geometry)
7434 gint result, x = 0, y = 0;
7437 gboolean size_set, pos_set;
7440 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7441 g_return_val_if_fail (geometry != NULL, FALSE);
7443 screen = gtk_window_check_screen (window);
7445 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
7448 if ((result & WidthValue) || (result & HeightValue))
7450 gtk_window_set_default_size_internal (window,
7451 TRUE, result & WidthValue ? w : -1,
7452 TRUE, result & HeightValue ? h : -1,
7457 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
7459 grav = GDK_GRAVITY_NORTH_WEST;
7461 if ((result & XNegative) && (result & YNegative))
7462 grav = GDK_GRAVITY_SOUTH_EAST;
7463 else if (result & XNegative)
7464 grav = GDK_GRAVITY_NORTH_EAST;
7465 else if (result & YNegative)
7466 grav = GDK_GRAVITY_SOUTH_WEST;
7468 if ((result & XValue) == 0)
7471 if ((result & YValue) == 0)
7474 if (grav == GDK_GRAVITY_SOUTH_WEST ||
7475 grav == GDK_GRAVITY_SOUTH_EAST)
7476 y = gdk_screen_get_height (screen) - h + y;
7478 if (grav == GDK_GRAVITY_SOUTH_EAST ||
7479 grav == GDK_GRAVITY_NORTH_EAST)
7480 x = gdk_screen_get_width (screen) - w + x;
7482 /* we don't let you put a window offscreen; maybe some people would
7483 * prefer to be able to, but it's kind of a bogus thing to do.
7492 if ((result & XValue) || (result & YValue))
7494 gtk_window_set_gravity (window, grav);
7495 gtk_window_move (window, x, y);
7499 if (size_set || pos_set)
7501 /* Set USSize, USPosition hints */
7502 GtkWindowGeometryInfo *info;
7504 info = gtk_window_get_geometry_info (window, TRUE);
7507 info->mask |= GDK_HINT_USER_POS;
7509 info->mask |= GDK_HINT_USER_SIZE;
7516 gtk_window_mnemonic_hash_foreach (guint keyval,
7522 GtkWindowKeysForeachFunc func;
7526 (*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
7530 _gtk_window_keys_foreach (GtkWindow *window,
7531 GtkWindowKeysForeachFunc func,
7535 GtkMnemonicHash *mnemonic_hash;
7539 GtkWindowKeysForeachFunc func;
7543 info.window = window;
7545 info.func_data = func_data;
7547 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
7549 _gtk_mnemonic_hash_foreach (mnemonic_hash,
7550 gtk_window_mnemonic_hash_foreach, &info);
7552 groups = gtk_accel_groups_from_object (G_OBJECT (window));
7555 GtkAccelGroup *group = groups->data;
7558 for (i = 0; i < group->n_accels; i++)
7560 GtkAccelKey *key = &group->priv_accels[i].key;
7563 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
7566 groups = groups->next;
7571 gtk_window_keys_changed (GtkWindow *window)
7573 gtk_window_free_key_hash (window);
7574 gtk_window_get_key_hash (window);
7577 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
7579 struct _GtkWindowKeyEntry
7583 guint is_mnemonic : 1;
7587 window_key_entry_destroy (gpointer data)
7589 g_slice_free (GtkWindowKeyEntry, data);
7593 add_to_key_hash (GtkWindow *window,
7595 GdkModifierType modifiers,
7596 gboolean is_mnemonic,
7599 GtkKeyHash *key_hash = data;
7601 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
7603 entry->keyval = keyval;
7604 entry->modifiers = modifiers;
7605 entry->is_mnemonic = is_mnemonic;
7607 /* GtkAccelGroup stores lowercased accelerators. To deal
7608 * with this, if <Shift> was specified, uppercase.
7610 if (modifiers & GDK_SHIFT_MASK)
7612 if (keyval == GDK_Tab)
7613 keyval = GDK_ISO_Left_Tab;
7615 keyval = gdk_keyval_to_upper (keyval);
7618 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
7622 gtk_window_get_key_hash (GtkWindow *window)
7624 GdkScreen *screen = gtk_window_check_screen (window);
7625 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7630 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
7631 (GDestroyNotify)window_key_entry_destroy);
7632 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
7633 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
7639 gtk_window_free_key_hash (GtkWindow *window)
7641 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7644 _gtk_key_hash_free (key_hash);
7645 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
7650 * gtk_window_activate_key:
7651 * @window: a #GtkWindow
7652 * @event: a #GdkEventKey
7654 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
7655 * called by the default ::key_press_event handler for toplevel windows,
7656 * however in some cases it may be useful to call this directly when
7657 * overriding the standard key handling for a toplevel window.
7659 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
7662 gtk_window_activate_key (GtkWindow *window,
7665 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7666 GtkWindowKeyEntry *found_entry = NULL;
7670 gtk_window_keys_changed (window);
7671 key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7676 GSList *entries = _gtk_key_hash_lookup (key_hash,
7677 event->hardware_keycode,
7679 gtk_accelerator_get_default_mod_mask (),
7683 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
7685 GtkWindowKeyEntry *entry = tmp_list->data;
7686 if (entry->is_mnemonic)
7688 found_entry = entry;
7693 if (!found_entry && entries)
7694 found_entry = entries->data;
7696 g_slist_free (entries);
7701 if (found_entry->is_mnemonic)
7702 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
7704 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
7711 window_update_has_focus (GtkWindow *window)
7713 GtkWidget *widget = GTK_WIDGET (window);
7714 gboolean has_focus = window->has_toplevel_focus && window->is_active;
7716 if (has_focus != window->has_focus)
7718 window->has_focus = has_focus;
7722 if (window->focus_widget &&
7723 window->focus_widget != widget &&
7724 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7725 do_focus_change (window->focus_widget, TRUE);
7729 if (window->focus_widget &&
7730 window->focus_widget != widget &&
7731 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7732 do_focus_change (window->focus_widget, FALSE);
7738 * _gtk_window_set_is_active:
7739 * @window: a #GtkWindow
7740 * @is_active: %TRUE if the window is in the currently active toplevel
7742 * Internal function that sets whether the #GtkWindow is part
7743 * of the currently active toplevel window (taking into account inter-process
7747 _gtk_window_set_is_active (GtkWindow *window,
7750 g_return_if_fail (GTK_IS_WINDOW (window));
7752 is_active = is_active != FALSE;
7754 if (is_active != window->is_active)
7756 window->is_active = is_active;
7757 window_update_has_focus (window);
7759 g_object_notify (G_OBJECT (window), "is-active");
7764 * _gtk_window_set_has_toplevel_focus:
7765 * @window: a #GtkWindow
7766 * @has_toplevel_focus: %TRUE if the in
7768 * Internal function that sets whether the keyboard focus for the
7769 * toplevel window (taking into account inter-process embedding.)
7772 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
7773 gboolean has_toplevel_focus)
7775 g_return_if_fail (GTK_IS_WINDOW (window));
7777 has_toplevel_focus = has_toplevel_focus != FALSE;
7779 if (has_toplevel_focus != window->has_toplevel_focus)
7781 window->has_toplevel_focus = has_toplevel_focus;
7782 window_update_has_focus (window);
7784 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
7789 * gtk_window_set_auto_startup_notification:
7790 * @setting: %TRUE to automatically do startup notification
7792 * By default, after showing the first #GtkWindow, GTK+ calls
7793 * gdk_notify_startup_complete(). Call this function to disable
7794 * the automatic startup notification. You might do this if your
7795 * first window is a splash screen, and you want to delay notification
7796 * until after your real main window has been shown, for example.
7798 * In that example, you would disable startup notification
7799 * temporarily, show your splash screen, then re-enable it so that
7800 * showing the main window would automatically result in notification.
7805 gtk_window_set_auto_startup_notification (gboolean setting)
7807 disable_startup_notification = !setting;
7812 #undef gtk_window_set_icon_from_file
7815 gtk_window_set_icon_from_file (GtkWindow *window,
7816 const gchar *filename,
7819 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
7822 if (utf8_filename == NULL)
7825 retval = gtk_window_set_icon_from_file_utf8 (window, utf8_filename, err);
7827 g_free (utf8_filename);
7832 #undef gtk_window_set_default_icon_from_file
7835 gtk_window_set_default_icon_from_file (const gchar *filename,
7838 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
7841 if (utf8_filename == NULL)
7844 retval = gtk_window_set_default_icon_from_file_utf8 (utf8_filename, err);
7846 g_free (utf8_filename);
7853 #define __GTK_WINDOW_C__
7854 #include "gtkaliasdef.c"