1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
31 #include "gdk/gdkkeysyms.h"
35 #include "gtkprivate.h"
37 #include "gtkwindow.h"
38 #include "gtkwindow-decorate.h"
39 #include "gtkbindings.h"
40 #include "gtkkeyhash.h"
42 #include "gtkmnemonichash.h"
43 #include "gtkiconfactory.h"
44 #include "gtkicontheme.h"
45 #include "gtkmarshalers.h"
49 #ifdef GDK_WINDOWING_X11
79 PROP_DESTROY_WITH_PARENT,
84 PROP_SKIP_TASKBAR_HINT,
94 /* Readonly properties */
96 PROP_HAS_TOPLEVEL_FOCUS,
104 GdkPixmap *icon_pixmap;
105 GdkPixmap *icon_mask;
108 guint using_default_icon : 1;
109 guint using_parent_icon : 1;
110 guint using_themed_icon : 1;
114 GdkGeometry geometry; /* Last set of geometry hints we set */
115 GdkWindowHints flags;
116 GdkRectangle configure_request;
117 } GtkWindowLastGeometryInfo;
119 struct _GtkWindowGeometryInfo
121 /* Properties that the app has set on the window
123 GdkGeometry geometry; /* Geometry hints */
125 GtkWidget *widget; /* subwidget to which hints apply */
126 /* from last gtk_window_resize () - if > 0, indicates that
127 * we should resize to this size.
132 /* From last gtk_window_move () prior to mapping -
133 * only used if initial_pos_set
138 /* Default size - used only the FIRST time we map a window,
143 /* whether to use initial_x, initial_y */
144 guint initial_pos_set : 1;
145 /* CENTER_ALWAYS or other position constraint changed since
146 * we sent the last configure request.
148 guint position_constraints_changed : 1;
150 /* if true, default_width, height come from gtk_window_parse_geometry,
151 * and thus should be multiplied by the increments and affect the
152 * geometry widget only
154 guint default_is_geometry : 1;
156 GtkWindowLastGeometryInfo last;
159 #define GTK_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW, GtkWindowPrivate))
161 typedef struct _GtkWindowPrivate GtkWindowPrivate;
163 struct _GtkWindowPrivate
165 GtkMnemonicHash *mnemonic_hash;
167 guint above_initially : 1;
168 guint below_initially : 1;
169 guint fullscreen_initially : 1;
170 guint skips_taskbar : 1;
171 guint skips_pager : 1;
173 guint accept_focus : 1;
174 guint focus_on_map : 1;
176 guint transient_parent_group : 1;
178 guint reset_type_hint : 1;
179 GdkWindowTypeHint type_hint;
182 static void gtk_window_dispose (GObject *object);
183 static void gtk_window_destroy (GtkObject *object);
184 static void gtk_window_finalize (GObject *object);
185 static void gtk_window_show (GtkWidget *widget);
186 static void gtk_window_hide (GtkWidget *widget);
187 static void gtk_window_map (GtkWidget *widget);
188 static void gtk_window_unmap (GtkWidget *widget);
189 static void gtk_window_realize (GtkWidget *widget);
190 static void gtk_window_unrealize (GtkWidget *widget);
191 static void gtk_window_size_request (GtkWidget *widget,
192 GtkRequisition *requisition);
193 static void gtk_window_size_allocate (GtkWidget *widget,
194 GtkAllocation *allocation);
195 static gint gtk_window_event (GtkWidget *widget,
197 static gboolean gtk_window_map_event (GtkWidget *widget,
199 static gboolean gtk_window_frame_event (GtkWindow *window,
201 static gint gtk_window_configure_event (GtkWidget *widget,
202 GdkEventConfigure *event);
203 static gint gtk_window_key_press_event (GtkWidget *widget,
205 static gint gtk_window_key_release_event (GtkWidget *widget,
207 static gint gtk_window_enter_notify_event (GtkWidget *widget,
208 GdkEventCrossing *event);
209 static gint gtk_window_leave_notify_event (GtkWidget *widget,
210 GdkEventCrossing *event);
211 static gint gtk_window_focus_in_event (GtkWidget *widget,
212 GdkEventFocus *event);
213 static gint gtk_window_focus_out_event (GtkWidget *widget,
214 GdkEventFocus *event);
215 static gint gtk_window_client_event (GtkWidget *widget,
216 GdkEventClient *event);
217 static void gtk_window_check_resize (GtkContainer *container);
218 static gint gtk_window_focus (GtkWidget *widget,
219 GtkDirectionType direction);
220 static void gtk_window_real_set_focus (GtkWindow *window,
223 static void gtk_window_real_activate_default (GtkWindow *window);
224 static void gtk_window_real_activate_focus (GtkWindow *window);
225 static void gtk_window_move_focus (GtkWindow *window,
226 GtkDirectionType dir);
227 static void gtk_window_keys_changed (GtkWindow *window);
228 static void gtk_window_paint (GtkWidget *widget,
230 static gint gtk_window_expose (GtkWidget *widget,
231 GdkEventExpose *event);
232 static void gtk_window_unset_transient_for (GtkWindow *window);
233 static void gtk_window_transient_parent_realized (GtkWidget *parent,
235 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
238 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
240 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
243 static void gtk_window_move_resize (GtkWindow *window);
244 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
246 GdkGeometry *geometry_b,
248 static void gtk_window_constrain_size (GtkWindow *window,
249 GdkGeometry *geometry,
255 static void gtk_window_constrain_position (GtkWindow *window,
260 static void gtk_window_compute_hints (GtkWindow *window,
261 GdkGeometry *new_geometry,
263 static void gtk_window_compute_configure_request (GtkWindow *window,
264 GdkRectangle *request,
265 GdkGeometry *geometry,
268 static void gtk_window_set_default_size_internal (GtkWindow *window,
269 gboolean change_width,
271 gboolean change_height,
273 gboolean is_geometry);
275 static void update_themed_icon (GtkIconTheme *theme,
277 static GList *icon_list_from_theme (GtkWidget *widget,
279 static void gtk_window_realize_icon (GtkWindow *window);
280 static void gtk_window_unrealize_icon (GtkWindow *window);
282 static void gtk_window_notify_keys_changed (GtkWindow *window);
283 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
284 static void gtk_window_free_key_hash (GtkWindow *window);
285 static void gtk_window_on_composited_changed (GdkScreen *screen,
288 static GSList *toplevel_list = NULL;
289 static guint window_signals[LAST_SIGNAL] = { 0 };
290 static GList *default_icon_list = NULL;
291 static gchar *default_icon_name = NULL;
292 static guint default_icon_serial = 0;
293 static gboolean disable_startup_notification = FALSE;
294 static gboolean sent_startup_notification = FALSE;
296 static GQuark quark_gtk_embedded = 0;
297 static GQuark quark_gtk_window_key_hash = 0;
298 static GQuark quark_gtk_window_default_icon_pixmap = 0;
299 static GQuark quark_gtk_window_icon_info = 0;
301 static void gtk_window_set_property (GObject *object,
305 static void gtk_window_get_property (GObject *object,
311 G_DEFINE_TYPE (GtkWindow, gtk_window, GTK_TYPE_BIN)
314 add_tab_bindings (GtkBindingSet *binding_set,
315 GdkModifierType modifiers,
316 GtkDirectionType direction)
318 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
320 GTK_TYPE_DIRECTION_TYPE, direction);
321 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
323 GTK_TYPE_DIRECTION_TYPE, direction);
327 add_arrow_bindings (GtkBindingSet *binding_set,
329 GtkDirectionType direction)
331 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
333 gtk_binding_entry_add_signal (binding_set, keysym, 0,
335 GTK_TYPE_DIRECTION_TYPE, direction);
336 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
338 GTK_TYPE_DIRECTION_TYPE, direction);
339 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
341 GTK_TYPE_DIRECTION_TYPE, direction);
342 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
344 GTK_TYPE_DIRECTION_TYPE, direction);
349 gtk_window_class_init (GtkWindowClass *klass)
351 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
352 GtkObjectClass *object_class;
353 GtkWidgetClass *widget_class;
354 GtkContainerClass *container_class;
355 GtkBindingSet *binding_set;
357 object_class = (GtkObjectClass*) klass;
358 widget_class = (GtkWidgetClass*) klass;
359 container_class = (GtkContainerClass*) klass;
361 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
362 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
363 quark_gtk_window_default_icon_pixmap = g_quark_from_static_string ("gtk-window-default-icon-pixmap");
364 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
366 gobject_class->dispose = gtk_window_dispose;
367 gobject_class->finalize = gtk_window_finalize;
369 gobject_class->set_property = gtk_window_set_property;
370 gobject_class->get_property = gtk_window_get_property;
372 object_class->destroy = gtk_window_destroy;
374 widget_class->show = gtk_window_show;
375 widget_class->hide = gtk_window_hide;
376 widget_class->map = gtk_window_map;
377 widget_class->map_event = gtk_window_map_event;
378 widget_class->unmap = gtk_window_unmap;
379 widget_class->realize = gtk_window_realize;
380 widget_class->unrealize = gtk_window_unrealize;
381 widget_class->size_request = gtk_window_size_request;
382 widget_class->size_allocate = gtk_window_size_allocate;
383 widget_class->configure_event = gtk_window_configure_event;
384 widget_class->key_press_event = gtk_window_key_press_event;
385 widget_class->key_release_event = gtk_window_key_release_event;
386 widget_class->enter_notify_event = gtk_window_enter_notify_event;
387 widget_class->leave_notify_event = gtk_window_leave_notify_event;
388 widget_class->focus_in_event = gtk_window_focus_in_event;
389 widget_class->focus_out_event = gtk_window_focus_out_event;
390 widget_class->client_event = gtk_window_client_event;
391 widget_class->focus = gtk_window_focus;
393 widget_class->expose_event = gtk_window_expose;
395 container_class->check_resize = gtk_window_check_resize;
397 klass->set_focus = gtk_window_real_set_focus;
398 klass->frame_event = gtk_window_frame_event;
400 klass->activate_default = gtk_window_real_activate_default;
401 klass->activate_focus = gtk_window_real_activate_focus;
402 klass->move_focus = gtk_window_move_focus;
403 klass->keys_changed = gtk_window_keys_changed;
405 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
408 g_object_class_install_property (gobject_class,
410 g_param_spec_enum ("type",
412 P_("The type of the window"),
413 GTK_TYPE_WINDOW_TYPE,
415 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
417 g_object_class_install_property (gobject_class,
419 g_param_spec_string ("title",
421 P_("The title of the window"),
423 GTK_PARAM_READWRITE));
425 g_object_class_install_property (gobject_class,
427 g_param_spec_string ("role",
429 P_("Unique identifier for the window to be used when restoring a session"),
431 GTK_PARAM_READWRITE));
433 g_object_class_install_property (gobject_class,
435 g_param_spec_boolean ("allow-shrink",
437 /* xgettext:no-c-format */
438 P_("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
440 GTK_PARAM_READWRITE));
442 g_object_class_install_property (gobject_class,
444 g_param_spec_boolean ("allow-grow",
446 P_("If TRUE, users can expand the window beyond its minimum size"),
448 GTK_PARAM_READWRITE));
450 g_object_class_install_property (gobject_class,
452 g_param_spec_boolean ("resizable",
454 P_("If TRUE, users can resize the window"),
456 GTK_PARAM_READWRITE));
458 g_object_class_install_property (gobject_class,
460 g_param_spec_boolean ("modal",
462 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
464 GTK_PARAM_READWRITE));
466 g_object_class_install_property (gobject_class,
468 g_param_spec_enum ("window-position",
469 P_("Window Position"),
470 P_("The initial position of the window"),
471 GTK_TYPE_WINDOW_POSITION,
473 GTK_PARAM_READWRITE));
475 g_object_class_install_property (gobject_class,
477 g_param_spec_int ("default-width",
479 P_("The default width of the window, used when initially showing the window"),
483 GTK_PARAM_READWRITE));
485 g_object_class_install_property (gobject_class,
487 g_param_spec_int ("default-height",
488 P_("Default Height"),
489 P_("The default height of the window, used when initially showing the window"),
493 GTK_PARAM_READWRITE));
495 g_object_class_install_property (gobject_class,
496 PROP_DESTROY_WITH_PARENT,
497 g_param_spec_boolean ("destroy-with-parent",
498 P_("Destroy with Parent"),
499 P_("If this window should be destroyed when the parent is destroyed"),
501 GTK_PARAM_READWRITE));
503 g_object_class_install_property (gobject_class,
505 g_param_spec_object ("icon",
507 P_("Icon for this window"),
509 GTK_PARAM_READWRITE));
512 * GtkWindow:icon-name:
514 * The :icon-name property specifies the name of the themed icon to
515 * use as the window icon. See #GtkIconTheme for more details.
519 g_object_class_install_property (gobject_class,
521 g_param_spec_string ("icon-name",
523 P_("Name of the themed icon for this window"),
525 GTK_PARAM_READWRITE));
527 g_object_class_install_property (gobject_class,
529 g_param_spec_object ("screen",
531 P_("The screen where this window will be displayed"),
533 GTK_PARAM_READWRITE));
535 g_object_class_install_property (gobject_class,
537 g_param_spec_boolean ("is-active",
539 P_("Whether the toplevel is the current active window"),
541 GTK_PARAM_READABLE));
543 g_object_class_install_property (gobject_class,
544 PROP_HAS_TOPLEVEL_FOCUS,
545 g_param_spec_boolean ("has-toplevel-focus",
546 P_("Focus in Toplevel"),
547 P_("Whether the input focus is within this GtkWindow"),
549 GTK_PARAM_READABLE));
551 g_object_class_install_property (gobject_class,
553 g_param_spec_enum ("type-hint",
555 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
556 GDK_TYPE_WINDOW_TYPE_HINT,
557 GDK_WINDOW_TYPE_HINT_NORMAL,
558 GTK_PARAM_READWRITE));
560 g_object_class_install_property (gobject_class,
561 PROP_SKIP_TASKBAR_HINT,
562 g_param_spec_boolean ("skip-taskbar-hint",
564 P_("TRUE if the window should not be in the task bar."),
566 GTK_PARAM_READWRITE));
568 g_object_class_install_property (gobject_class,
569 PROP_SKIP_PAGER_HINT,
570 g_param_spec_boolean ("skip-pager-hint",
572 P_("TRUE if the window should not be in the pager."),
574 GTK_PARAM_READWRITE));
576 g_object_class_install_property (gobject_class,
578 g_param_spec_boolean ("urgency-hint",
580 P_("TRUE if the window should be brought to the user's attention."),
582 GTK_PARAM_READWRITE));
585 * GtkWindow:accept-focus-hint:
587 * Whether the window should receive the input focus.
591 g_object_class_install_property (gobject_class,
593 g_param_spec_boolean ("accept-focus",
595 P_("TRUE if the window should receive the input focus."),
597 GTK_PARAM_READWRITE));
600 * GtkWindow:focus-on-map-hint:
602 * Whether the window should receive the input focus when mapped.
606 g_object_class_install_property (gobject_class,
608 g_param_spec_boolean ("focus-on-map",
610 P_("TRUE if the window should receive the input focus when mapped."),
612 GTK_PARAM_READWRITE));
615 * GtkWindow:decorated:
617 * Whether the window should be decorated by the window manager.
621 g_object_class_install_property (gobject_class,
623 g_param_spec_boolean ("decorated",
625 P_("Whether the window should be decorated by the window manager"),
627 GTK_PARAM_READWRITE));
630 * GtkWindow:deletable:
632 * Whether the window frame should have a close button.
636 g_object_class_install_property (gobject_class,
638 g_param_spec_boolean ("deletable",
640 P_("Whether the window frame should have a close button"),
642 GTK_PARAM_READWRITE));
648 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
649 * more details about window gravity.
653 g_object_class_install_property (gobject_class,
655 g_param_spec_enum ("gravity",
657 P_("The window gravity of the window"),
659 GDK_GRAVITY_NORTH_WEST,
660 GTK_PARAM_READWRITE));
664 * GtkWindow:transient-for:
666 * The transient parent of the window. See gtk_window_set_transient_for() for
667 * more details about transient windows.
671 g_object_class_install_property (gobject_class,
673 g_param_spec_object ("transient-for",
674 P_("Transient for Window"),
675 P_("The transient parent of the dialog"),
677 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
679 window_signals[SET_FOCUS] =
680 g_signal_new (I_("set_focus"),
681 G_TYPE_FROM_CLASS (gobject_class),
683 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
685 _gtk_marshal_VOID__OBJECT,
689 window_signals[FRAME_EVENT] =
690 g_signal_new (I_("frame_event"),
691 G_TYPE_FROM_CLASS (gobject_class),
693 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
694 _gtk_boolean_handled_accumulator, NULL,
695 _gtk_marshal_BOOLEAN__BOXED,
699 window_signals[ACTIVATE_FOCUS] =
700 g_signal_new (I_("activate_focus"),
701 G_TYPE_FROM_CLASS (gobject_class),
702 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
703 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
705 _gtk_marshal_VOID__VOID,
709 window_signals[ACTIVATE_DEFAULT] =
710 g_signal_new (I_("activate_default"),
711 G_TYPE_FROM_CLASS (gobject_class),
712 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
713 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
715 _gtk_marshal_VOID__VOID,
719 window_signals[MOVE_FOCUS] =
720 g_signal_new (I_("move_focus"),
721 G_TYPE_FROM_CLASS (gobject_class),
722 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
723 G_STRUCT_OFFSET (GtkWindowClass, move_focus),
725 _gtk_marshal_VOID__ENUM,
728 GTK_TYPE_DIRECTION_TYPE);
730 window_signals[KEYS_CHANGED] =
731 g_signal_new (I_("keys_changed"),
732 G_TYPE_FROM_CLASS (gobject_class),
734 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
736 _gtk_marshal_VOID__VOID,
744 binding_set = gtk_binding_set_by_class (klass);
746 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
747 "activate_focus", 0);
748 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
749 "activate_focus", 0);
751 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
752 "activate_default", 0);
754 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
755 "activate_default", 0);
757 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
758 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
759 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
760 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
762 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
763 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
764 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
765 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
769 gtk_window_init (GtkWindow *window)
771 GdkColormap *colormap;
772 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
774 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
775 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
777 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
779 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
781 window->title = NULL;
782 window->wmclass_name = g_strdup (g_get_prgname ());
783 window->wmclass_class = g_strdup (gdk_get_program_class ());
784 window->wm_role = NULL;
785 window->geometry_info = NULL;
786 window->type = GTK_WINDOW_TOPLEVEL;
787 window->focus_widget = NULL;
788 window->default_widget = NULL;
789 window->configure_request_count = 0;
790 window->allow_shrink = FALSE;
791 window->allow_grow = TRUE;
792 window->configure_notify_received = FALSE;
793 window->position = GTK_WIN_POS_NONE;
794 window->need_default_size = TRUE;
795 window->need_default_position = TRUE;
796 window->modal = FALSE;
797 window->frame = NULL;
798 window->has_frame = FALSE;
799 window->frame_left = 0;
800 window->frame_right = 0;
801 window->frame_top = 0;
802 window->frame_bottom = 0;
803 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
804 window->gravity = GDK_GRAVITY_NORTH_WEST;
805 window->decorated = TRUE;
806 window->mnemonic_modifier = GDK_MOD1_MASK;
807 window->screen = gdk_screen_get_default ();
809 priv->accept_focus = TRUE;
810 priv->focus_on_map = TRUE;
811 priv->deletable = TRUE;
812 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
814 colormap = _gtk_widget_peek_colormap ();
816 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
818 g_object_ref_sink (window);
819 window->has_user_ref_count = TRUE;
820 toplevel_list = g_slist_prepend (toplevel_list, window);
822 gtk_decorated_window_init (window);
824 g_signal_connect (window->screen, "composited_changed",
825 G_CALLBACK (gtk_window_on_composited_changed), window);
829 gtk_window_set_property (GObject *object,
836 window = GTK_WINDOW (object);
841 window->type = g_value_get_enum (value);
844 gtk_window_set_title (window, g_value_get_string (value));
847 gtk_window_set_role (window, g_value_get_string (value));
849 case PROP_ALLOW_SHRINK:
850 window->allow_shrink = g_value_get_boolean (value);
851 gtk_widget_queue_resize (GTK_WIDGET (window));
853 case PROP_ALLOW_GROW:
854 window->allow_grow = g_value_get_boolean (value);
855 gtk_widget_queue_resize (GTK_WIDGET (window));
856 g_object_notify (G_OBJECT (window), "resizable");
859 window->allow_grow = g_value_get_boolean (value);
860 gtk_widget_queue_resize (GTK_WIDGET (window));
861 g_object_notify (G_OBJECT (window), "allow-grow");
864 gtk_window_set_modal (window, g_value_get_boolean (value));
867 gtk_window_set_position (window, g_value_get_enum (value));
869 case PROP_DEFAULT_WIDTH:
870 gtk_window_set_default_size_internal (window,
871 TRUE, g_value_get_int (value),
874 case PROP_DEFAULT_HEIGHT:
875 gtk_window_set_default_size_internal (window,
877 TRUE, g_value_get_int (value), FALSE);
879 case PROP_DESTROY_WITH_PARENT:
880 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
883 gtk_window_set_icon (window,
884 g_value_get_object (value));
887 gtk_window_set_icon_name (window, g_value_get_string (value));
890 gtk_window_set_screen (window, g_value_get_object (value));
893 gtk_window_set_type_hint (window,
894 g_value_get_enum (value));
896 case PROP_SKIP_TASKBAR_HINT:
897 gtk_window_set_skip_taskbar_hint (window,
898 g_value_get_boolean (value));
900 case PROP_SKIP_PAGER_HINT:
901 gtk_window_set_skip_pager_hint (window,
902 g_value_get_boolean (value));
904 case PROP_URGENCY_HINT:
905 gtk_window_set_urgency_hint (window,
906 g_value_get_boolean (value));
908 case PROP_ACCEPT_FOCUS:
909 gtk_window_set_accept_focus (window,
910 g_value_get_boolean (value));
912 case PROP_FOCUS_ON_MAP:
913 gtk_window_set_focus_on_map (window,
914 g_value_get_boolean (value));
917 gtk_window_set_decorated (window, g_value_get_boolean (value));
920 gtk_window_set_deletable (window, g_value_get_boolean (value));
923 gtk_window_set_gravity (window, g_value_get_enum (value));
925 case PROP_TRANSIENT_FOR:
926 gtk_window_set_transient_for (window, g_value_get_object (value));
934 gtk_window_get_property (GObject *object,
940 GtkWindowPrivate *priv;
942 window = GTK_WINDOW (object);
943 priv = GTK_WINDOW_GET_PRIVATE (window);
947 GtkWindowGeometryInfo *info;
949 g_value_set_enum (value, window->type);
952 g_value_set_string (value, window->wm_role);
955 g_value_set_string (value, window->title);
957 case PROP_ALLOW_SHRINK:
958 g_value_set_boolean (value, window->allow_shrink);
960 case PROP_ALLOW_GROW:
961 g_value_set_boolean (value, window->allow_grow);
964 g_value_set_boolean (value, window->allow_grow);
967 g_value_set_boolean (value, window->modal);
970 g_value_set_enum (value, window->position);
972 case PROP_DEFAULT_WIDTH:
973 info = gtk_window_get_geometry_info (window, FALSE);
975 g_value_set_int (value, -1);
977 g_value_set_int (value, info->default_width);
979 case PROP_DEFAULT_HEIGHT:
980 info = gtk_window_get_geometry_info (window, FALSE);
982 g_value_set_int (value, -1);
984 g_value_set_int (value, info->default_height);
986 case PROP_DESTROY_WITH_PARENT:
987 g_value_set_boolean (value, window->destroy_with_parent);
990 g_value_set_object (value, gtk_window_get_icon (window));
993 g_value_set_string (value, gtk_window_get_icon_name (window));
996 g_value_set_object (value, window->screen);
999 g_value_set_boolean (value, window->is_active);
1001 case PROP_HAS_TOPLEVEL_FOCUS:
1002 g_value_set_boolean (value, window->has_toplevel_focus);
1004 case PROP_TYPE_HINT:
1005 g_value_set_enum (value, priv->type_hint);
1007 case PROP_SKIP_TASKBAR_HINT:
1008 g_value_set_boolean (value,
1009 gtk_window_get_skip_taskbar_hint (window));
1011 case PROP_SKIP_PAGER_HINT:
1012 g_value_set_boolean (value,
1013 gtk_window_get_skip_pager_hint (window));
1015 case PROP_URGENCY_HINT:
1016 g_value_set_boolean (value,
1017 gtk_window_get_urgency_hint (window));
1019 case PROP_ACCEPT_FOCUS:
1020 g_value_set_boolean (value,
1021 gtk_window_get_accept_focus (window));
1023 case PROP_FOCUS_ON_MAP:
1024 g_value_set_boolean (value,
1025 gtk_window_get_focus_on_map (window));
1027 case PROP_DECORATED:
1028 g_value_set_boolean (value, gtk_window_get_decorated (window));
1030 case PROP_DELETABLE:
1031 g_value_set_boolean (value, gtk_window_get_deletable (window));
1034 g_value_set_enum (value, gtk_window_get_gravity (window));
1036 case PROP_TRANSIENT_FOR:
1037 g_value_set_object (value, gtk_window_get_transient_for (window));
1040 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1047 * @type: type of window
1049 * Creates a new #GtkWindow, which is a toplevel window that can
1050 * contain other widgets. Nearly always, the type of the window should
1051 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1052 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1053 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1054 * dialogs, though in some other toolkits dialogs are called "popups".
1055 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1056 * On X11, popup windows are not controlled by the <link
1057 * linkend="gtk-X11-arch">window manager</link>.
1059 * If you simply want an undecorated window (no window borders), use
1060 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1062 * Return value: a new #GtkWindow.
1065 gtk_window_new (GtkWindowType type)
1069 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1071 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1073 window->type = type;
1075 return GTK_WIDGET (window);
1079 * gtk_window_set_title:
1080 * @window: a #GtkWindow
1081 * @title: title of the window
1083 * Sets the title of the #GtkWindow. The title of a window will be
1084 * displayed in its title bar; on the X Window System, the title bar
1085 * is rendered by the <link linkend="gtk-X11-arch">window
1086 * manager</link>, so exactly how the title appears to users may vary
1087 * according to a user's exact configuration. The title should help a
1088 * user distinguish this window from other windows they may have
1089 * open. A good title might include the application name and current
1090 * document filename, for example.
1094 gtk_window_set_title (GtkWindow *window,
1099 g_return_if_fail (GTK_IS_WINDOW (window));
1101 new_title = g_strdup (title);
1102 g_free (window->title);
1103 window->title = new_title;
1105 if (GTK_WIDGET_REALIZED (window))
1107 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
1109 gtk_decorated_window_set_title (window, title);
1112 g_object_notify (G_OBJECT (window), "title");
1116 * gtk_window_get_title:
1117 * @window: a #GtkWindow
1119 * Retrieves the title of the window. See gtk_window_set_title().
1121 * Return value: the title of the window, or %NULL if none has
1122 * been set explicitely. The returned string is owned by the widget
1123 * and must not be modified or freed.
1125 G_CONST_RETURN gchar *
1126 gtk_window_get_title (GtkWindow *window)
1128 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1130 return window->title;
1134 * gtk_window_set_wmclass:
1135 * @window: a #GtkWindow
1136 * @wmclass_name: window name hint
1137 * @wmclass_class: window class hint
1139 * Don't use this function. It sets the X Window System "class" and
1140 * "name" hints for a window. According to the ICCCM, you should
1141 * always set these to the same value for all windows in an
1142 * application, and GTK+ sets them to that value by default, so calling
1143 * this function is sort of pointless. However, you may want to call
1144 * gtk_window_set_role() on each window in your application, for the
1145 * benefit of the session manager. Setting the role allows the window
1146 * manager to restore window positions when loading a saved session.
1150 gtk_window_set_wmclass (GtkWindow *window,
1151 const gchar *wmclass_name,
1152 const gchar *wmclass_class)
1154 g_return_if_fail (GTK_IS_WINDOW (window));
1156 g_free (window->wmclass_name);
1157 window->wmclass_name = g_strdup (wmclass_name);
1159 g_free (window->wmclass_class);
1160 window->wmclass_class = g_strdup (wmclass_class);
1162 if (GTK_WIDGET_REALIZED (window))
1163 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1167 * gtk_window_set_role:
1168 * @window: a #GtkWindow
1169 * @role: unique identifier for the window to be used when restoring a session
1171 * This function is only useful on X11, not with other GTK+ targets.
1173 * In combination with the window title, the window role allows a
1174 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1175 * same" window when an application is restarted. So for example you
1176 * might set the "toolbox" role on your app's toolbox window, so that
1177 * when the user restarts their session, the window manager can put
1178 * the toolbox back in the same place.
1180 * If a window already has a unique title, you don't need to set the
1181 * role, since the WM can use the title to identify the window when
1182 * restoring the session.
1186 gtk_window_set_role (GtkWindow *window,
1191 g_return_if_fail (GTK_IS_WINDOW (window));
1193 new_role = g_strdup (role);
1194 g_free (window->wm_role);
1195 window->wm_role = new_role;
1197 if (GTK_WIDGET_REALIZED (window))
1198 gdk_window_set_role (GTK_WIDGET (window)->window, window->wm_role);
1200 g_object_notify (G_OBJECT (window), "role");
1204 * gtk_window_get_role:
1205 * @window: a #GtkWindow
1207 * Returns the role of the window. See gtk_window_set_role() for
1208 * further explanation.
1210 * Return value: the role of the window if set, or %NULL. The
1211 * returned is owned by the widget and must not be modified
1214 G_CONST_RETURN gchar *
1215 gtk_window_get_role (GtkWindow *window)
1217 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1219 return window->wm_role;
1223 * gtk_window_set_focus:
1224 * @window: a #GtkWindow
1225 * @focus: widget to be the new focus widget, or %NULL to unset
1226 * any focus widget for the toplevel window.
1228 * If @focus is not the current focus widget, and is focusable, sets
1229 * it as the focus widget for the window. If @focus is %NULL, unsets
1230 * the focus widget for this window. To set the focus to a particular
1231 * widget in the toplevel, it is usually more convenient to use
1232 * gtk_widget_grab_focus() instead of this function.
1235 gtk_window_set_focus (GtkWindow *window,
1238 g_return_if_fail (GTK_IS_WINDOW (window));
1241 g_return_if_fail (GTK_IS_WIDGET (focus));
1242 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1246 gtk_widget_grab_focus (focus);
1249 /* Clear the existing focus chain, so that when we focus into
1250 * the window again, we start at the beginnning.
1252 GtkWidget *widget = window->focus_widget;
1255 while (widget->parent)
1257 widget = widget->parent;
1258 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1262 _gtk_window_internal_set_focus (window, NULL);
1267 _gtk_window_internal_set_focus (GtkWindow *window,
1270 g_return_if_fail (GTK_IS_WINDOW (window));
1272 if ((window->focus_widget != focus) ||
1273 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1274 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1278 * gtk_window_set_default:
1279 * @window: a #GtkWindow
1280 * @default_widget: widget to be the default, or %NULL to unset the
1281 * default widget for the toplevel.
1283 * The default widget is the widget that's activated when the user
1284 * presses Enter in a dialog (for example). This function sets or
1285 * unsets the default widget for a #GtkWindow about. When setting
1286 * (rather than unsetting) the default widget it's generally easier to
1287 * call gtk_widget_grab_focus() on the widget. Before making a widget
1288 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1289 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1292 gtk_window_set_default (GtkWindow *window,
1293 GtkWidget *default_widget)
1295 g_return_if_fail (GTK_IS_WINDOW (window));
1298 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1300 if (window->default_widget != default_widget)
1302 GtkWidget *old_default_widget = NULL;
1305 g_object_ref (default_widget);
1307 if (window->default_widget)
1309 old_default_widget = window->default_widget;
1311 if (window->focus_widget != window->default_widget ||
1312 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1313 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1314 gtk_widget_queue_draw (window->default_widget);
1317 window->default_widget = default_widget;
1319 if (window->default_widget)
1321 if (window->focus_widget == NULL ||
1322 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1323 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1324 gtk_widget_queue_draw (window->default_widget);
1327 if (old_default_widget)
1328 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1332 g_object_notify (G_OBJECT (default_widget), "has-default");
1333 g_object_unref (default_widget);
1339 gtk_window_set_policy (GtkWindow *window,
1340 gboolean allow_shrink,
1341 gboolean allow_grow,
1342 gboolean auto_shrink)
1344 g_return_if_fail (GTK_IS_WINDOW (window));
1346 window->allow_shrink = (allow_shrink != FALSE);
1347 window->allow_grow = (allow_grow != FALSE);
1349 g_object_freeze_notify (G_OBJECT (window));
1350 g_object_notify (G_OBJECT (window), "allow-shrink");
1351 g_object_notify (G_OBJECT (window), "allow-grow");
1352 g_object_notify (G_OBJECT (window), "resizable");
1353 g_object_thaw_notify (G_OBJECT (window));
1355 gtk_widget_queue_resize (GTK_WIDGET (window));
1359 handle_keys_changed (gpointer data)
1363 window = GTK_WINDOW (data);
1365 if (window->keys_changed_handler)
1367 g_source_remove (window->keys_changed_handler);
1368 window->keys_changed_handler = 0;
1371 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1377 gtk_window_notify_keys_changed (GtkWindow *window)
1379 if (!window->keys_changed_handler)
1380 window->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1384 * gtk_window_add_accel_group:
1385 * @window: window to attach accelerator group to
1386 * @accel_group: a #GtkAccelGroup
1388 * Associate @accel_group with @window, such that calling
1389 * gtk_accel_groups_activate() on @window will activate accelerators
1393 gtk_window_add_accel_group (GtkWindow *window,
1394 GtkAccelGroup *accel_group)
1396 g_return_if_fail (GTK_IS_WINDOW (window));
1397 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1399 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1400 g_signal_connect_object (accel_group, "accel_changed",
1401 G_CALLBACK (gtk_window_notify_keys_changed),
1402 window, G_CONNECT_SWAPPED);
1406 * gtk_window_remove_accel_group:
1407 * @window: a #GtkWindow
1408 * @accel_group: a #GtkAccelGroup
1410 * Reverses the effects of gtk_window_add_accel_group().
1413 gtk_window_remove_accel_group (GtkWindow *window,
1414 GtkAccelGroup *accel_group)
1416 g_return_if_fail (GTK_IS_WINDOW (window));
1417 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1419 g_signal_handlers_disconnect_by_func (accel_group,
1420 gtk_window_notify_keys_changed,
1422 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1425 static GtkMnemonicHash *
1426 gtk_window_get_mnemonic_hash (GtkWindow *window,
1429 GtkWindowPrivate *private = GTK_WINDOW_GET_PRIVATE (window);
1430 if (!private->mnemonic_hash && create)
1431 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1433 return private->mnemonic_hash;
1437 * gtk_window_add_mnemonic:
1438 * @window: a #GtkWindow
1439 * @keyval: the mnemonic
1440 * @target: the widget that gets activated by the mnemonic
1442 * Adds a mnemonic to this window.
1445 gtk_window_add_mnemonic (GtkWindow *window,
1449 g_return_if_fail (GTK_IS_WINDOW (window));
1450 g_return_if_fail (GTK_IS_WIDGET (target));
1452 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1454 gtk_window_notify_keys_changed (window);
1458 * gtk_window_remove_mnemonic:
1459 * @window: a #GtkWindow
1460 * @keyval: the mnemonic
1461 * @target: the widget that gets activated by the mnemonic
1463 * Removes a mnemonic from this window.
1466 gtk_window_remove_mnemonic (GtkWindow *window,
1470 g_return_if_fail (GTK_IS_WINDOW (window));
1471 g_return_if_fail (GTK_IS_WIDGET (target));
1473 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
1475 gtk_window_notify_keys_changed (window);
1479 * gtk_window_mnemonic_activate:
1480 * @window: a #GtkWindow
1481 * @keyval: the mnemonic
1482 * @modifier: the modifiers
1483 * @returns: %TRUE if the activation is done.
1485 * Activates the targets associated with the mnemonic.
1488 gtk_window_mnemonic_activate (GtkWindow *window,
1490 GdkModifierType modifier)
1492 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1494 if (window->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
1496 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
1498 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
1505 * gtk_window_set_mnemonic_modifier:
1506 * @window: a #GtkWindow
1507 * @modifier: the modifier mask used to activate
1508 * mnemonics on this window.
1510 * Sets the mnemonic modifier for this window.
1513 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1514 GdkModifierType modifier)
1516 g_return_if_fail (GTK_IS_WINDOW (window));
1517 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1519 window->mnemonic_modifier = modifier;
1520 gtk_window_notify_keys_changed (window);
1524 * gtk_window_get_mnemonic_modifier:
1525 * @window: a #GtkWindow
1527 * Returns the mnemonic modifier for this window. See
1528 * gtk_window_set_mnemonic_modifier().
1530 * Return value: the modifier mask used to activate
1531 * mnemonics on this window.
1534 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1536 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1538 return window->mnemonic_modifier;
1542 * gtk_window_set_position:
1543 * @window: a #GtkWindow.
1544 * @position: a position constraint.
1546 * Sets a position constraint for this window. If the old or new
1547 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1548 * the window to be repositioned to satisfy the new constraint.
1551 gtk_window_set_position (GtkWindow *window,
1552 GtkWindowPosition position)
1554 g_return_if_fail (GTK_IS_WINDOW (window));
1556 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1557 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1559 GtkWindowGeometryInfo *info;
1561 info = gtk_window_get_geometry_info (window, TRUE);
1563 /* this flag causes us to re-request the CENTER_ALWAYS
1564 * constraint in gtk_window_move_resize(), see
1565 * comment in that function.
1567 info->position_constraints_changed = TRUE;
1569 gtk_widget_queue_resize (GTK_WIDGET (window));
1572 window->position = position;
1574 g_object_notify (G_OBJECT (window), "window-position");
1578 * gtk_window_activate_focus:
1579 * @window: a #GtkWindow
1581 * Activates the current focused widget within the window.
1583 * Return value: %TRUE if a widget got activated.
1586 gtk_window_activate_focus (GtkWindow *window)
1588 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1590 if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1591 return gtk_widget_activate (window->focus_widget);
1597 * gtk_window_get_focus:
1598 * @window: a #GtkWindow
1600 * Retrieves the current focused widget within the window.
1601 * Note that this is the widget that would have the focus
1602 * if the toplevel window focused; if the toplevel window
1603 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1604 * not be %TRUE for the widget.
1606 * Return value: the currently focused widget, or %NULL if there is none.
1609 gtk_window_get_focus (GtkWindow *window)
1611 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1613 return window->focus_widget;
1617 * gtk_window_activate_default:
1618 * @window: a #GtkWindow
1620 * Activates the default widget for the window, unless the current
1621 * focused widget has been configured to receive the default action
1622 * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
1623 * focused widget is activated.
1625 * Return value: %TRUE if a widget got activated.
1628 gtk_window_activate_default (GtkWindow *window)
1630 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1632 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1633 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1634 return gtk_widget_activate (window->default_widget);
1635 else if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1636 return gtk_widget_activate (window->focus_widget);
1642 * gtk_window_set_modal:
1643 * @window: a #GtkWindow
1644 * @modal: whether the window is modal
1646 * Sets a window modal or non-modal. Modal windows prevent interaction
1647 * with other windows in the same application. To keep modal dialogs
1648 * on top of main application windows, use
1649 * gtk_window_set_transient_for() to make the dialog transient for the
1650 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1651 * will then disallow lowering the dialog below the parent.
1656 gtk_window_set_modal (GtkWindow *window,
1659 g_return_if_fail (GTK_IS_WINDOW (window));
1661 modal = modal != FALSE;
1662 if (window->modal == modal)
1665 window->modal = modal;
1667 /* adjust desired modality state */
1668 if (GTK_WIDGET_REALIZED (window))
1670 GtkWidget *widget = GTK_WIDGET (window);
1673 gdk_window_set_modal_hint (widget->window, TRUE);
1675 gdk_window_set_modal_hint (widget->window, FALSE);
1678 if (GTK_WIDGET_VISIBLE (window))
1681 gtk_grab_add (GTK_WIDGET (window));
1683 gtk_grab_remove (GTK_WIDGET (window));
1686 g_object_notify (G_OBJECT (window), "modal");
1690 * gtk_window_get_modal:
1691 * @window: a #GtkWindow
1693 * Returns whether the window is modal. See gtk_window_set_modal().
1695 * Return value: %TRUE if the window is set to be modal and
1696 * establishes a grab when shown
1699 gtk_window_get_modal (GtkWindow *window)
1701 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1703 return window->modal;
1707 * gtk_window_list_toplevels:
1709 * Returns a list of all existing toplevel windows. The widgets
1710 * in the list are not individually referenced. If you want
1711 * to iterate through the list and perform actions involving
1712 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1713 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1714 * then unref all the widgets afterwards.
1716 * Return value: list of toplevel widgets
1719 gtk_window_list_toplevels (void)
1724 for (slist = toplevel_list; slist; slist = slist->next)
1725 list = g_list_prepend (list, slist->data);
1731 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1733 GList *embedded_windows;
1735 g_return_if_fail (GTK_IS_WINDOW (window));
1737 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
1738 if (embedded_windows)
1739 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
1740 embedded_windows = g_list_prepend (embedded_windows,
1741 GUINT_TO_POINTER (xid));
1743 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
1746 (GDestroyNotify) g_list_free : NULL);
1750 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1752 GList *embedded_windows;
1755 g_return_if_fail (GTK_IS_WINDOW (window));
1757 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
1758 if (embedded_windows)
1759 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
1761 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1764 embedded_windows = g_list_remove_link (embedded_windows, node);
1765 g_list_free_1 (node);
1768 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
1771 (GDestroyNotify) g_list_free : NULL);
1775 _gtk_window_reposition (GtkWindow *window,
1779 g_return_if_fail (GTK_IS_WINDOW (window));
1781 gtk_window_move (window, x, y);
1785 gtk_window_dispose (GObject *object)
1787 GtkWindow *window = GTK_WINDOW (object);
1789 gtk_window_set_focus (window, NULL);
1790 gtk_window_set_default (window, NULL);
1792 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
1796 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1798 gtk_widget_destroy (GTK_WIDGET (child));
1802 connect_parent_destroyed (GtkWindow *window)
1804 if (window->transient_parent)
1806 g_signal_connect (window->transient_parent,
1808 G_CALLBACK (parent_destroyed_callback),
1814 disconnect_parent_destroyed (GtkWindow *window)
1816 if (window->transient_parent)
1818 g_signal_handlers_disconnect_by_func (window->transient_parent,
1819 parent_destroyed_callback,
1825 gtk_window_transient_parent_realized (GtkWidget *parent,
1828 if (GTK_WIDGET_REALIZED (window))
1829 gdk_window_set_transient_for (window->window, parent->window);
1833 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1836 if (GTK_WIDGET_REALIZED (window))
1837 gdk_property_delete (window->window,
1838 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
1842 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
1846 gtk_window_set_screen (window, parent->screen);
1850 gtk_window_unset_transient_for (GtkWindow *window)
1852 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
1854 if (window->transient_parent)
1856 if (priv->transient_parent_group)
1857 gtk_window_group_remove_window (window->group,
1860 g_signal_handlers_disconnect_by_func (window->transient_parent,
1861 gtk_window_transient_parent_realized,
1863 g_signal_handlers_disconnect_by_func (window->transient_parent,
1864 gtk_window_transient_parent_unrealized,
1866 g_signal_handlers_disconnect_by_func (window->transient_parent,
1867 gtk_window_transient_parent_screen_changed,
1869 g_signal_handlers_disconnect_by_func (window->transient_parent,
1870 gtk_widget_destroyed,
1871 &window->transient_parent);
1873 if (window->destroy_with_parent)
1874 disconnect_parent_destroyed (window);
1876 window->transient_parent = NULL;
1877 priv->transient_parent_group = FALSE;
1882 * gtk_window_set_transient_for:
1883 * @window: a #GtkWindow
1884 * @parent: parent window
1886 * Dialog windows should be set transient for the main application
1887 * window they were spawned from. This allows <link
1888 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1889 * dialog on top of the main window, or center the dialog over the
1890 * main window. gtk_dialog_new_with_buttons() and other convenience
1891 * functions in GTK+ will sometimes call
1892 * gtk_window_set_transient_for() on your behalf.
1894 * On Windows, this function will and put the child window
1895 * on top of the parent, much as the window manager would have
1900 gtk_window_set_transient_for (GtkWindow *window,
1903 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
1905 g_return_if_fail (GTK_IS_WINDOW (window));
1906 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1907 g_return_if_fail (window != parent);
1909 if (window->transient_parent)
1911 if (GTK_WIDGET_REALIZED (window) &&
1912 GTK_WIDGET_REALIZED (window->transient_parent) &&
1913 (!parent || !GTK_WIDGET_REALIZED (parent)))
1914 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1915 GTK_WIDGET (window));
1917 gtk_window_unset_transient_for (window);
1920 window->transient_parent = parent;
1924 g_signal_connect (parent, "destroy",
1925 G_CALLBACK (gtk_widget_destroyed),
1926 &window->transient_parent);
1927 g_signal_connect (parent, "realize",
1928 G_CALLBACK (gtk_window_transient_parent_realized),
1930 g_signal_connect (parent, "unrealize",
1931 G_CALLBACK (gtk_window_transient_parent_unrealized),
1933 g_signal_connect (parent, "notify::screen",
1934 G_CALLBACK (gtk_window_transient_parent_screen_changed),
1937 gtk_window_set_screen (window, parent->screen);
1939 if (window->destroy_with_parent)
1940 connect_parent_destroyed (window);
1942 if (GTK_WIDGET_REALIZED (window) &&
1943 GTK_WIDGET_REALIZED (parent))
1944 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1945 GTK_WIDGET (window));
1949 gtk_window_group_add_window (parent->group, window);
1950 priv->transient_parent_group = TRUE;
1956 * gtk_window_get_transient_for:
1957 * @window: a #GtkWindow
1959 * Fetches the transient parent for this window. See
1960 * gtk_window_set_transient_for().
1962 * Return value: the transient parent for this window, or %NULL
1963 * if no transient parent has been set.
1966 gtk_window_get_transient_for (GtkWindow *window)
1968 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1970 return window->transient_parent;
1974 * gtk_window_set_type_hint:
1975 * @window: a #GtkWindow
1976 * @hint: the window type
1978 * By setting the type hint for the window, you allow the window
1979 * manager to decorate and handle the window in a way which is
1980 * suitable to the function of the window in your application.
1982 * This function should be called before the window becomes visible.
1984 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1985 * will sometimes call gtk_window_set_type_hint() on your behalf.
1989 gtk_window_set_type_hint (GtkWindow *window,
1990 GdkWindowTypeHint hint)
1992 GtkWindowPrivate *priv;
1994 g_return_if_fail (GTK_IS_WINDOW (window));
1995 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1997 priv = GTK_WINDOW_GET_PRIVATE (window);
1999 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2000 window->type_hint = hint;
2002 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2004 priv->reset_type_hint = TRUE;
2005 priv->type_hint = hint;
2009 * gtk_window_get_type_hint:
2010 * @window: a #GtkWindow
2012 * Gets the type hint for this window. See gtk_window_set_type_hint().
2014 * Return value: the type hint for @window.
2017 gtk_window_get_type_hint (GtkWindow *window)
2019 GtkWindowPrivate *priv;
2021 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2023 priv = GTK_WINDOW_GET_PRIVATE (window);
2025 return priv->type_hint;
2029 * gtk_window_set_skip_taskbar_hint:
2030 * @window: a #GtkWindow
2031 * @setting: %TRUE to keep this window from appearing in the task bar
2033 * Windows may set a hint asking the desktop environment not to display
2034 * the window in the task bar. This function sets this hint.
2039 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2042 GtkWindowPrivate *priv;
2044 g_return_if_fail (GTK_IS_WINDOW (window));
2046 priv = GTK_WINDOW_GET_PRIVATE (window);
2048 setting = setting != FALSE;
2050 if (priv->skips_taskbar != setting)
2052 priv->skips_taskbar = setting;
2053 if (GTK_WIDGET_REALIZED (window))
2054 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
2055 priv->skips_taskbar);
2056 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2061 * gtk_window_get_skip_taskbar_hint:
2062 * @window: a #GtkWindow
2064 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2066 * Return value: %TRUE if window shouldn't be in taskbar
2071 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2073 GtkWindowPrivate *priv;
2075 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2077 priv = GTK_WINDOW_GET_PRIVATE (window);
2079 return priv->skips_taskbar;
2083 * gtk_window_set_skip_pager_hint:
2084 * @window: a #GtkWindow
2085 * @setting: %TRUE to keep this window from appearing in the pager
2087 * Windows may set a hint asking the desktop environment not to display
2088 * the window in the pager. This function sets this hint.
2089 * (A "pager" is any desktop navigation tool such as a workspace
2090 * switcher that displays a thumbnail representation of the windows
2096 gtk_window_set_skip_pager_hint (GtkWindow *window,
2099 GtkWindowPrivate *priv;
2101 g_return_if_fail (GTK_IS_WINDOW (window));
2103 priv = GTK_WINDOW_GET_PRIVATE (window);
2105 setting = setting != FALSE;
2107 if (priv->skips_pager != setting)
2109 priv->skips_pager = setting;
2110 if (GTK_WIDGET_REALIZED (window))
2111 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2113 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2118 * gtk_window_get_skip_pager_hint:
2119 * @window: a #GtkWindow
2121 * Gets the value set by gtk_window_set_skip_pager_hint().
2123 * Return value: %TRUE if window shouldn't be in pager
2128 gtk_window_get_skip_pager_hint (GtkWindow *window)
2130 GtkWindowPrivate *priv;
2132 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2134 priv = GTK_WINDOW_GET_PRIVATE (window);
2136 return priv->skips_pager;
2140 * gtk_window_set_urgency_hint:
2141 * @window: a #GtkWindow
2142 * @setting: %TRUE to mark this window as urgent
2144 * Windows may set a hint asking the desktop environment to draw
2145 * the users attention to the window. This function sets this hint.
2150 gtk_window_set_urgency_hint (GtkWindow *window,
2153 GtkWindowPrivate *priv;
2155 g_return_if_fail (GTK_IS_WINDOW (window));
2157 priv = GTK_WINDOW_GET_PRIVATE (window);
2159 setting = setting != FALSE;
2161 if (priv->urgent != setting)
2163 priv->urgent = setting;
2164 if (GTK_WIDGET_REALIZED (window))
2165 gdk_window_set_urgency_hint (GTK_WIDGET (window)->window,
2167 g_object_notify (G_OBJECT (window), "urgency-hint");
2172 * gtk_window_get_urgency_hint:
2173 * @window: a #GtkWindow
2175 * Gets the value set by gtk_window_set_urgency_hint()
2177 * Return value: %TRUE if window is urgent
2182 gtk_window_get_urgency_hint (GtkWindow *window)
2184 GtkWindowPrivate *priv;
2186 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2188 priv = GTK_WINDOW_GET_PRIVATE (window);
2190 return priv->urgent;
2194 * gtk_window_set_accept_focus:
2195 * @window: a #GtkWindow
2196 * @setting: %TRUE to let this window receive input focus
2198 * Windows may set a hint asking the desktop environment not to receive
2199 * the input focus. This function sets this hint.
2204 gtk_window_set_accept_focus (GtkWindow *window,
2207 GtkWindowPrivate *priv;
2209 g_return_if_fail (GTK_IS_WINDOW (window));
2211 priv = GTK_WINDOW_GET_PRIVATE (window);
2213 setting = setting != FALSE;
2215 if (priv->accept_focus != setting)
2217 priv->accept_focus = setting;
2218 if (GTK_WIDGET_REALIZED (window))
2219 gdk_window_set_accept_focus (GTK_WIDGET (window)->window,
2220 priv->accept_focus);
2221 g_object_notify (G_OBJECT (window), "accept-focus");
2226 * gtk_window_get_accept_focus:
2227 * @window: a #GtkWindow
2229 * Gets the value set by gtk_window_set_accept_focus().
2231 * Return value: %TRUE if window should receive the input focus
2236 gtk_window_get_accept_focus (GtkWindow *window)
2238 GtkWindowPrivate *priv;
2240 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2242 priv = GTK_WINDOW_GET_PRIVATE (window);
2244 return priv->accept_focus;
2248 * gtk_window_set_focus_on_map:
2249 * @window: a #GtkWindow
2250 * @setting: %TRUE to let this window receive input focus on map
2252 * Windows may set a hint asking the desktop environment not to receive
2253 * the input focus when the window is mapped. This function sets this
2259 gtk_window_set_focus_on_map (GtkWindow *window,
2262 GtkWindowPrivate *priv;
2264 g_return_if_fail (GTK_IS_WINDOW (window));
2266 priv = GTK_WINDOW_GET_PRIVATE (window);
2268 setting = setting != FALSE;
2270 if (priv->focus_on_map != setting)
2272 priv->focus_on_map = setting;
2273 if (GTK_WIDGET_REALIZED (window))
2274 gdk_window_set_focus_on_map (GTK_WIDGET (window)->window,
2275 priv->focus_on_map);
2276 g_object_notify (G_OBJECT (window), "focus-on-map");
2281 * gtk_window_get_focus_on_map:
2282 * @window: a #GtkWindow
2284 * Gets the value set by gtk_window_set_focus_on_map().
2286 * Return value: %TRUE if window should receive the input focus when
2292 gtk_window_get_focus_on_map (GtkWindow *window)
2294 GtkWindowPrivate *priv;
2296 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2298 priv = GTK_WINDOW_GET_PRIVATE (window);
2300 return priv->focus_on_map;
2304 * gtk_window_set_destroy_with_parent:
2305 * @window: a #GtkWindow
2306 * @setting: whether to destroy @window with its transient parent
2308 * If @setting is %TRUE, then destroying the transient parent of @window
2309 * will also destroy @window itself. This is useful for dialogs that
2310 * shouldn't persist beyond the lifetime of the main window they're
2311 * associated with, for example.
2314 gtk_window_set_destroy_with_parent (GtkWindow *window,
2317 g_return_if_fail (GTK_IS_WINDOW (window));
2319 if (window->destroy_with_parent == (setting != FALSE))
2322 if (window->destroy_with_parent)
2324 disconnect_parent_destroyed (window);
2328 connect_parent_destroyed (window);
2331 window->destroy_with_parent = setting;
2333 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2337 * gtk_window_get_destroy_with_parent:
2338 * @window: a #GtkWindow
2340 * Returns whether the window will be destroyed with its transient parent. See
2341 * gtk_window_set_destroy_with_parent ().
2343 * Return value: %TRUE if the window will be destroyed with its transient parent.
2346 gtk_window_get_destroy_with_parent (GtkWindow *window)
2348 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2350 return window->destroy_with_parent;
2353 static GtkWindowGeometryInfo*
2354 gtk_window_get_geometry_info (GtkWindow *window,
2357 GtkWindowGeometryInfo *info;
2359 info = window->geometry_info;
2360 if (!info && create)
2362 info = g_new0 (GtkWindowGeometryInfo, 1);
2364 info->default_width = -1;
2365 info->default_height = -1;
2366 info->resize_width = -1;
2367 info->resize_height = -1;
2368 info->initial_x = 0;
2369 info->initial_y = 0;
2370 info->initial_pos_set = FALSE;
2371 info->default_is_geometry = FALSE;
2372 info->position_constraints_changed = FALSE;
2373 info->last.configure_request.x = 0;
2374 info->last.configure_request.y = 0;
2375 info->last.configure_request.width = -1;
2376 info->last.configure_request.height = -1;
2377 info->widget = NULL;
2379 window->geometry_info = info;
2386 * gtk_window_set_geometry_hints:
2387 * @window: a #GtkWindow
2388 * @geometry_widget: widget the geometry hints will be applied to
2389 * @geometry: struct containing geometry information
2390 * @geom_mask: mask indicating which struct fields should be paid attention to
2392 * This function sets up hints about how a window can be resized by
2393 * the user. You can set a minimum and maximum size; allowed resize
2394 * increments (e.g. for xterm, you can only resize by the size of a
2395 * character); aspect ratios; and more. See the #GdkGeometry struct.
2399 gtk_window_set_geometry_hints (GtkWindow *window,
2400 GtkWidget *geometry_widget,
2401 GdkGeometry *geometry,
2402 GdkWindowHints geom_mask)
2404 GtkWindowGeometryInfo *info;
2406 g_return_if_fail (GTK_IS_WINDOW (window));
2407 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2409 info = gtk_window_get_geometry_info (window, TRUE);
2412 g_signal_handlers_disconnect_by_func (info->widget,
2413 gtk_widget_destroyed,
2416 info->widget = geometry_widget;
2418 g_signal_connect (geometry_widget, "destroy",
2419 G_CALLBACK (gtk_widget_destroyed),
2423 info->geometry = *geometry;
2425 /* We store gravity in window->gravity not in the hints. */
2426 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2428 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2430 gtk_window_set_gravity (window, geometry->win_gravity);
2433 gtk_widget_queue_resize (GTK_WIDGET (window));
2437 * gtk_window_set_decorated:
2438 * @window: a #GtkWindow
2439 * @setting: %TRUE to decorate the window
2441 * By default, windows are decorated with a title bar, resize
2442 * controls, etc. Some <link linkend="gtk-X11-arch">window
2443 * managers</link> allow GTK+ to disable these decorations, creating a
2444 * borderless window. If you set the decorated property to %FALSE
2445 * using this function, GTK+ will do its best to convince the window
2446 * manager not to decorate the window. Depending on the system, this
2447 * function may not have any effect when called on a window that is
2448 * already visible, so you should call it before calling gtk_window_show().
2450 * On Windows, this function always works, since there's no window manager
2455 gtk_window_set_decorated (GtkWindow *window,
2458 g_return_if_fail (GTK_IS_WINDOW (window));
2460 setting = setting != FALSE;
2462 if (setting == window->decorated)
2465 window->decorated = setting;
2467 if (GTK_WIDGET (window)->window)
2469 if (window->decorated)
2470 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2473 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2477 g_object_notify (G_OBJECT (window), "decorated");
2481 * gtk_window_get_decorated:
2482 * @window: a #GtkWindow
2484 * Returns whether the window has been set to have decorations
2485 * such as a title bar via gtk_window_set_decorated().
2487 * Return value: %TRUE if the window has been set to have decorations
2490 gtk_window_get_decorated (GtkWindow *window)
2492 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2494 return window->decorated;
2498 * gtk_window_set_deletable:
2499 * @window: a #GtkWindow
2500 * @setting: %TRUE to decorate the window as deletable
2502 * By default, windows have a close button in the window frame. Some
2503 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
2504 * disable this button. If you set the deletable property to %FALSE
2505 * using this function, GTK+ will do its best to convince the window
2506 * manager not to show a close button. Depending on the system, this
2507 * function may not have any effect when called on a window that is
2508 * already visible, so you should call it before calling gtk_window_show().
2510 * On Windows, this function always works, since there's no window manager
2516 gtk_window_set_deletable (GtkWindow *window,
2519 GtkWindowPrivate *priv;
2521 g_return_if_fail (GTK_IS_WINDOW (window));
2523 priv = GTK_WINDOW_GET_PRIVATE (window);
2525 setting = setting != FALSE;
2527 if (setting == priv->deletable)
2530 priv->deletable = setting;
2532 if (GTK_WIDGET (window)->window)
2534 if (priv->deletable)
2535 gdk_window_set_functions (GTK_WIDGET (window)->window,
2538 gdk_window_set_functions (GTK_WIDGET (window)->window,
2539 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
2542 g_object_notify (G_OBJECT (window), "deletable");
2546 * gtk_window_get_deletable:
2547 * @window: a #GtkWindow
2549 * Returns whether the window has been set to have a close button
2550 * via gtk_window_set_deletable().
2552 * Return value: %TRUE if the window has been set to have a close button
2557 gtk_window_get_deletable (GtkWindow *window)
2559 GtkWindowPrivate *priv;
2561 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2563 priv = GTK_WINDOW_GET_PRIVATE (window);
2565 return priv->deletable;
2568 static GtkWindowIconInfo*
2569 get_icon_info (GtkWindow *window)
2571 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
2575 free_icon_info (GtkWindowIconInfo *info)
2577 g_free (info->icon_name);
2578 g_slice_free (GtkWindowIconInfo, info);
2582 static GtkWindowIconInfo*
2583 ensure_icon_info (GtkWindow *window)
2585 GtkWindowIconInfo *info;
2587 info = get_icon_info (window);
2591 info = g_slice_new0 (GtkWindowIconInfo);
2592 g_object_set_qdata_full (G_OBJECT (window),
2593 quark_gtk_window_icon_info,
2595 (GDestroyNotify)free_icon_info);
2607 static ScreenIconInfo *
2608 get_screen_icon_info (GdkScreen *screen)
2610 ScreenIconInfo *info = g_object_get_qdata (G_OBJECT (screen),
2611 quark_gtk_window_default_icon_pixmap);
2614 info = g_slice_new0 (ScreenIconInfo);
2615 g_object_set_qdata (G_OBJECT (screen),
2616 quark_gtk_window_default_icon_pixmap, info);
2619 if (info->serial != default_icon_serial)
2623 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2624 info->pixmap = NULL;
2629 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2633 info->serial = default_icon_serial;
2640 get_pixmap_and_mask (GdkWindow *window,
2641 GtkWindowIconInfo *parent_info,
2642 gboolean is_default_list,
2644 GdkPixmap **pmap_return,
2645 GdkBitmap **mask_return)
2647 GdkScreen *screen = gdk_drawable_get_screen (window);
2648 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2649 GdkPixbuf *best_icon;
2653 *pmap_return = NULL;
2654 *mask_return = NULL;
2656 if (is_default_list &&
2657 default_icon_info->pixmap != NULL)
2659 /* Use shared icon pixmap for all windows on this screen.
2661 if (default_icon_info->pixmap)
2662 g_object_ref (default_icon_info->pixmap);
2663 if (default_icon_info->mask)
2664 g_object_ref (default_icon_info->mask);
2666 *pmap_return = default_icon_info->pixmap;
2667 *mask_return = default_icon_info->mask;
2669 else if (parent_info && parent_info->icon_pixmap)
2671 if (parent_info->icon_pixmap)
2672 g_object_ref (parent_info->icon_pixmap);
2673 if (parent_info->icon_mask)
2674 g_object_ref (parent_info->icon_mask);
2676 *pmap_return = parent_info->icon_pixmap;
2677 *mask_return = parent_info->icon_mask;
2681 #define IDEAL_SIZE 48
2683 best_size = G_MAXINT;
2685 tmp_list = icon_list;
2686 while (tmp_list != NULL)
2688 GdkPixbuf *pixbuf = tmp_list->data;
2691 /* average width and height - if someone passes in a rectangular
2692 * icon they deserve what they get.
2694 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2697 if (best_icon == NULL)
2704 /* icon is better if it's 32 pixels or larger, and closer to
2705 * the ideal size than the current best.
2708 (ABS (best_size - IDEAL_SIZE) <
2709 ABS (this - IDEAL_SIZE)))
2716 tmp_list = tmp_list->next;
2720 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2721 gdk_screen_get_system_colormap (screen),
2726 /* Save pmap/mask for others to use if appropriate */
2729 parent_info->icon_pixmap = *pmap_return;
2730 parent_info->icon_mask = *mask_return;
2732 if (parent_info->icon_pixmap)
2733 g_object_ref (parent_info->icon_pixmap);
2734 if (parent_info->icon_mask)
2735 g_object_ref (parent_info->icon_mask);
2737 else if (is_default_list)
2739 default_icon_info->pixmap = *pmap_return;
2740 default_icon_info->mask = *mask_return;
2742 if (default_icon_info->pixmap)
2743 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2744 (gpointer*)&default_icon_info->pixmap);
2745 if (default_icon_info->mask)
2746 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2747 (gpointer*)&default_icon_info->mask);
2753 icon_list_from_theme (GtkWidget *widget,
2758 GtkIconTheme *icon_theme;
2763 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
2765 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
2768 for (i = 0; sizes[i]; i++)
2771 * We need an EWMH extension to handle scalable icons
2772 * by passing their name to the WM. For now just use a
2776 icon = gtk_icon_theme_load_icon (icon_theme, name,
2779 icon = gtk_icon_theme_load_icon (icon_theme, name,
2782 list = g_list_append (list, icon);
2792 gtk_window_realize_icon (GtkWindow *window)
2795 GtkWindowIconInfo *info;
2798 widget = GTK_WIDGET (window);
2800 g_return_if_fail (widget->window != NULL);
2802 /* no point setting an icon on override-redirect */
2803 if (window->type == GTK_WINDOW_POPUP)
2808 info = ensure_icon_info (window);
2813 g_return_if_fail (info->icon_pixmap == NULL);
2814 g_return_if_fail (info->icon_mask == NULL);
2816 info->using_default_icon = FALSE;
2817 info->using_parent_icon = FALSE;
2818 info->using_themed_icon = FALSE;
2820 icon_list = info->icon_list;
2822 /* Look up themed icon */
2823 if (icon_list == NULL && info->icon_name)
2825 icon_list = icon_list_from_theme (widget, info->icon_name);
2827 info->using_themed_icon = TRUE;
2830 /* Inherit from transient parent */
2831 if (icon_list == NULL && window->transient_parent)
2833 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2835 info->using_parent_icon = TRUE;
2838 /* Inherit from default */
2839 if (icon_list == NULL)
2841 icon_list = default_icon_list;
2843 info->using_default_icon = TRUE;
2846 /* Look up themed icon */
2847 if (icon_list == NULL && default_icon_name)
2849 icon_list = icon_list_from_theme (widget, default_icon_name);
2850 info->using_default_icon = TRUE;
2851 info->using_themed_icon = TRUE;
2854 gdk_window_set_icon_list (widget->window, icon_list);
2856 get_pixmap_and_mask (widget->window,
2857 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2858 info->using_default_icon,
2863 /* This is a slight ICCCM violation since it's a color pixmap not
2864 * a bitmap, but everyone does it.
2866 gdk_window_set_icon (widget->window,
2871 info->realized = TRUE;
2873 if (info->using_themed_icon)
2875 GtkIconTheme *icon_theme;
2877 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
2878 g_list_free (icon_list);
2880 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2881 g_signal_connect (icon_theme, "changed",
2882 G_CALLBACK (update_themed_icon), window);
2887 gtk_window_unrealize_icon (GtkWindow *window)
2889 GtkWindowIconInfo *info;
2891 info = get_icon_info (window);
2896 if (info->icon_pixmap)
2897 g_object_unref (info->icon_pixmap);
2899 if (info->icon_mask)
2900 g_object_unref (info->icon_mask);
2902 info->icon_pixmap = NULL;
2903 info->icon_mask = NULL;
2905 if (info->using_themed_icon)
2907 GtkIconTheme *icon_theme;
2909 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2911 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
2914 /* We don't clear the properties on the window, just figure the
2915 * window is going away.
2918 info->realized = FALSE;
2923 * gtk_window_set_icon_list:
2924 * @window: a #GtkWindow
2925 * @list: list of #GdkPixbuf
2927 * Sets up the icon representing a #GtkWindow. The icon is used when
2928 * the window is minimized (also known as iconified). Some window
2929 * managers or desktop environments may also place it in the window
2930 * frame, or display it in other contexts.
2932 * gtk_window_set_icon_list() allows you to pass in the same icon in
2933 * several hand-drawn sizes. The list should contain the natural sizes
2934 * your icon is available in; that is, don't scale the image before
2935 * passing it to GTK+. Scaling is postponed until the last minute,
2936 * when the desired final size is known, to allow best quality.
2938 * By passing several sizes, you may improve the final image quality
2939 * of the icon, by reducing or eliminating automatic image scaling.
2941 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2942 * larger images (64x64, 128x128) if you have them.
2944 * See also gtk_window_set_default_icon_list() to set the icon
2945 * for all windows in your application in one go.
2947 * Note that transient windows (those who have been set transient for another
2948 * window using gtk_window_set_transient_for()) will inherit their
2949 * icon from their transient parent. So there's no need to explicitly
2950 * set the icon on transient windows.
2953 gtk_window_set_icon_list (GtkWindow *window,
2956 GtkWindowIconInfo *info;
2958 g_return_if_fail (GTK_IS_WINDOW (window));
2960 info = ensure_icon_info (window);
2962 if (info->icon_list == list) /* check for NULL mostly */
2965 g_list_foreach (list,
2966 (GFunc) g_object_ref, NULL);
2968 g_list_foreach (info->icon_list,
2969 (GFunc) g_object_unref, NULL);
2971 g_list_free (info->icon_list);
2973 info->icon_list = g_list_copy (list);
2975 g_object_notify (G_OBJECT (window), "icon");
2977 gtk_window_unrealize_icon (window);
2979 if (GTK_WIDGET_REALIZED (window))
2980 gtk_window_realize_icon (window);
2982 /* We could try to update our transient children, but I don't think
2983 * it's really worth it. If we did it, the best way would probably
2984 * be to have children connect to notify::icon-list
2989 * gtk_window_get_icon_list:
2990 * @window: a #GtkWindow
2992 * Retrieves the list of icons set by gtk_window_set_icon_list().
2993 * The list is copied, but the reference count on each
2994 * member won't be incremented.
2996 * Return value: copy of window's icon list
2999 gtk_window_get_icon_list (GtkWindow *window)
3001 GtkWindowIconInfo *info;
3003 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3005 info = get_icon_info (window);
3008 return g_list_copy (info->icon_list);
3014 * gtk_window_set_icon:
3015 * @window: a #GtkWindow
3016 * @icon: icon image, or %NULL
3018 * Sets up the icon representing a #GtkWindow. This icon is used when
3019 * the window is minimized (also known as iconified). Some window
3020 * managers or desktop environments may also place it in the window
3021 * frame, or display it in other contexts.
3023 * The icon should be provided in whatever size it was naturally
3024 * drawn; that is, don't scale the image before passing it to
3025 * GTK+. Scaling is postponed until the last minute, when the desired
3026 * final size is known, to allow best quality.
3028 * If you have your icon hand-drawn in multiple sizes, use
3029 * gtk_window_set_icon_list(). Then the best size will be used.
3031 * This function is equivalent to calling gtk_window_set_icon_list()
3032 * with a 1-element list.
3034 * See also gtk_window_set_default_icon_list() to set the icon
3035 * for all windows in your application in one go.
3038 gtk_window_set_icon (GtkWindow *window,
3043 g_return_if_fail (GTK_IS_WINDOW (window));
3044 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3049 list = g_list_append (list, icon);
3051 gtk_window_set_icon_list (window, list);
3057 update_themed_icon (GtkIconTheme *icon_theme,
3060 g_object_notify (G_OBJECT (window), "icon");
3062 gtk_window_unrealize_icon (window);
3064 if (GTK_WIDGET_REALIZED (window))
3065 gtk_window_realize_icon (window);
3069 * gtk_window_set_icon_name:
3070 * @window: a #GtkWindow
3071 * @name: the name of the themed icon
3073 * Sets the icon for the window from a named themed icon. See
3074 * the docs for #GtkIconTheme for more details.
3076 * Note that this has nothing to do with the WM_ICON_NAME
3077 * property which is mentioned in the ICCCM.
3082 gtk_window_set_icon_name (GtkWindow *window,
3085 GtkWindowIconInfo *info;
3088 g_return_if_fail (GTK_IS_WINDOW (window));
3090 info = ensure_icon_info (window);
3092 tmp = info->icon_name;
3093 info->icon_name = g_strdup (name);
3096 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3097 g_list_free (info->icon_list);
3098 info->icon_list = NULL;
3100 update_themed_icon (NULL, window);
3102 g_object_notify (G_OBJECT (window), "icon-name");
3106 * gtk_window_get_icon_name:
3107 * @window: a #GtkWindow
3109 * Returns the name of the themed icon for the window,
3110 * see gtk_window_set_icon_name().
3112 * Returns: the icon name or %NULL if the window has
3117 G_CONST_RETURN gchar *
3118 gtk_window_get_icon_name (GtkWindow *window)
3120 GtkWindowIconInfo *info;
3122 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3124 info = ensure_icon_info (window);
3126 return info->icon_name;
3130 * gtk_window_get_icon:
3131 * @window: a #GtkWindow
3133 * Gets the value set by gtk_window_set_icon() (or if you've
3134 * called gtk_window_set_icon_list(), gets the first icon in
3137 * Return value: icon for window
3140 gtk_window_get_icon (GtkWindow *window)
3142 GtkWindowIconInfo *info;
3144 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3146 info = get_icon_info (window);
3147 if (info && info->icon_list)
3148 return GDK_PIXBUF (info->icon_list->data);
3153 /* Load pixbuf, printing warning on failure if error == NULL
3156 load_pixbuf_verbosely (const char *filename,
3159 GError *local_err = NULL;
3162 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3170 g_warning ("Error loading icon from file '%s':\n\t%s",
3171 filename, local_err->message);
3172 g_error_free (local_err);
3180 * gtk_window_set_icon_from_file:
3181 * @window: a #GtkWindow
3182 * @filename: location of icon file
3183 * @err: location to store error, or %NULL.
3185 * Sets the icon for @window.
3186 * Warns on failure if @err is %NULL.
3188 * This function is equivalent to calling gtk_window_set_icon()
3189 * with a pixbuf created by loading the image from @filename.
3191 * Returns: %TRUE if setting the icon succeeded.
3196 gtk_window_set_icon_from_file (GtkWindow *window,
3197 const gchar *filename,
3200 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3204 gtk_window_set_icon (window, pixbuf);
3205 g_object_unref (pixbuf);
3214 * gtk_window_set_default_icon_list:
3215 * @list: a list of #GdkPixbuf
3217 * Sets an icon list to be used as fallback for windows that haven't
3218 * had gtk_window_set_icon_list() called on them to set up a
3219 * window-specific icon list. This function allows you to set up the
3220 * icon for all windows in your app at once.
3222 * See gtk_window_set_icon_list() for more details.
3226 gtk_window_set_default_icon_list (GList *list)
3230 if (list == default_icon_list)
3233 /* Update serial so we don't used cached pixmaps/masks
3235 default_icon_serial++;
3237 g_list_foreach (list,
3238 (GFunc) g_object_ref, NULL);
3240 g_list_foreach (default_icon_list,
3241 (GFunc) g_object_unref, NULL);
3243 g_list_free (default_icon_list);
3245 default_icon_list = g_list_copy (list);
3247 /* Update all toplevels */
3248 toplevels = gtk_window_list_toplevels ();
3249 tmp_list = toplevels;
3250 while (tmp_list != NULL)
3252 GtkWindowIconInfo *info;
3253 GtkWindow *w = tmp_list->data;
3255 info = get_icon_info (w);
3256 if (info && info->using_default_icon)
3258 gtk_window_unrealize_icon (w);
3259 if (GTK_WIDGET_REALIZED (w))
3260 gtk_window_realize_icon (w);
3263 tmp_list = tmp_list->next;
3265 g_list_free (toplevels);
3269 * gtk_window_set_default_icon:
3272 * Sets an icon to be used as fallback for windows that haven't
3273 * had gtk_window_set_icon() called on them from a pixbuf.
3278 gtk_window_set_default_icon (GdkPixbuf *icon)
3282 g_return_if_fail (GDK_IS_PIXBUF (icon));
3284 list = g_list_prepend (NULL, icon);
3285 gtk_window_set_default_icon_list (list);
3290 * gtk_window_set_default_icon_name:
3291 * @name: the name of the themed icon
3293 * Sets an icon to be used as fallback for windows that haven't
3294 * had gtk_window_set_icon_list() called on them from a named
3295 * themed icon, see gtk_window_set_icon_name().
3300 gtk_window_set_default_icon_name (const gchar *name)
3305 /* Update serial so we don't used cached pixmaps/masks
3307 default_icon_serial++;
3309 g_free (default_icon_name);
3310 default_icon_name = g_strdup (name);
3312 g_list_foreach (default_icon_list,
3313 (GFunc) g_object_unref, NULL);
3315 g_list_free (default_icon_list);
3316 default_icon_list = NULL;
3318 /* Update all toplevels */
3319 toplevels = gtk_window_list_toplevels ();
3320 tmp_list = toplevels;
3321 while (tmp_list != NULL)
3323 GtkWindowIconInfo *info;
3324 GtkWindow *w = tmp_list->data;
3326 info = get_icon_info (w);
3327 if (info && info->using_default_icon && info->using_themed_icon)
3329 gtk_window_unrealize_icon (w);
3330 if (GTK_WIDGET_REALIZED (w))
3331 gtk_window_realize_icon (w);
3334 tmp_list = tmp_list->next;
3336 g_list_free (toplevels);
3340 * gtk_window_set_default_icon_from_file:
3341 * @filename: location of icon file
3342 * @err: location to store error, or %NULL.
3344 * Sets an icon to be used as fallback for windows that haven't
3345 * had gtk_window_set_icon_list() called on them from a file
3346 * on disk. Warns on failure if @err is %NULL.
3348 * Returns: %TRUE if setting the icon succeeded.
3353 gtk_window_set_default_icon_from_file (const gchar *filename,
3356 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3360 gtk_window_set_default_icon (pixbuf);
3361 g_object_unref (pixbuf);
3370 * gtk_window_get_default_icon_list:
3372 * Gets the value set by gtk_window_set_default_icon_list().
3373 * The list is a copy and should be freed with g_list_free(),
3374 * but the pixbufs in the list have not had their reference count
3377 * Return value: copy of default icon list
3380 gtk_window_get_default_icon_list (void)
3382 return g_list_copy (default_icon_list);
3386 gtk_window_set_default_size_internal (GtkWindow *window,
3387 gboolean change_width,
3389 gboolean change_height,
3391 gboolean is_geometry)
3393 GtkWindowGeometryInfo *info;
3395 g_return_if_fail (change_width == FALSE || width >= -1);
3396 g_return_if_fail (change_height == FALSE || height >= -1);
3398 info = gtk_window_get_geometry_info (window, TRUE);
3400 g_object_freeze_notify (G_OBJECT (window));
3402 info->default_is_geometry = is_geometry != FALSE;
3412 info->default_width = width;
3414 g_object_notify (G_OBJECT (window), "default-width");
3425 info->default_height = height;
3427 g_object_notify (G_OBJECT (window), "default-height");
3430 g_object_thaw_notify (G_OBJECT (window));
3432 gtk_widget_queue_resize (GTK_WIDGET (window));
3436 * gtk_window_set_default_size:
3437 * @window: a #GtkWindow
3438 * @width: width in pixels, or -1 to unset the default width
3439 * @height: height in pixels, or -1 to unset the default height
3441 * Sets the default size of a window. If the window's "natural" size
3442 * (its size request) is larger than the default, the default will be
3443 * ignored. More generally, if the default size does not obey the
3444 * geometry hints for the window (gtk_window_set_geometry_hints() can
3445 * be used to set these explicitly), the default size will be clamped
3446 * to the nearest permitted size.
3448 * Unlike gtk_widget_set_size_request(), which sets a size request for
3449 * a widget and thus would keep users from shrinking the window, this
3450 * function only sets the initial size, just as if the user had
3451 * resized the window themselves. Users can still shrink the window
3452 * again as they normally would. Setting a default size of -1 means to
3453 * use the "natural" default size (the size request of the window).
3455 * For more control over a window's initial size and how resizing works,
3456 * investigate gtk_window_set_geometry_hints().
3458 * For some uses, gtk_window_resize() is a more appropriate function.
3459 * gtk_window_resize() changes the current size of the window, rather
3460 * than the size to be used on initial display. gtk_window_resize() always
3461 * affects the window itself, not the geometry widget.
3463 * The default size of a window only affects the first time a window is
3464 * shown; if a window is hidden and re-shown, it will remember the size
3465 * it had prior to hiding, rather than using the default size.
3467 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3468 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3471 gtk_window_set_default_size (GtkWindow *window,
3475 g_return_if_fail (GTK_IS_WINDOW (window));
3476 g_return_if_fail (width >= -1);
3477 g_return_if_fail (height >= -1);
3479 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3483 * gtk_window_get_default_size:
3484 * @window: a #GtkWindow
3485 * @width: location to store the default width, or %NULL
3486 * @height: location to store the default height, or %NULL
3488 * Gets the default size of the window. A value of -1 for the width or
3489 * height indicates that a default size has not been explicitly set
3490 * for that dimension, so the "natural" size of the window will be
3495 gtk_window_get_default_size (GtkWindow *window,
3499 GtkWindowGeometryInfo *info;
3501 g_return_if_fail (GTK_IS_WINDOW (window));
3503 info = gtk_window_get_geometry_info (window, FALSE);
3506 *width = info ? info->default_width : -1;
3509 *height = info ? info->default_height : -1;
3513 * gtk_window_resize:
3514 * @window: a #GtkWindow
3515 * @width: width in pixels to resize the window to
3516 * @height: height in pixels to resize the window to
3518 * Resizes the window as if the user had done so, obeying geometry
3519 * constraints. The default geometry constraint is that windows may
3520 * not be smaller than their size request; to override this
3521 * constraint, call gtk_widget_set_size_request() to set the window's
3522 * request to a smaller value.
3524 * If gtk_window_resize() is called before showing a window for the
3525 * first time, it overrides any default size set with
3526 * gtk_window_set_default_size().
3528 * Windows may not be resized smaller than 1 by 1 pixels.
3532 gtk_window_resize (GtkWindow *window,
3536 GtkWindowGeometryInfo *info;
3538 g_return_if_fail (GTK_IS_WINDOW (window));
3539 g_return_if_fail (width > 0);
3540 g_return_if_fail (height > 0);
3542 info = gtk_window_get_geometry_info (window, TRUE);
3544 info->resize_width = width;
3545 info->resize_height = height;
3547 gtk_widget_queue_resize (GTK_WIDGET (window));
3551 * gtk_window_get_size:
3552 * @window: a #GtkWindow
3553 * @width: return location for width, or %NULL
3554 * @height: return location for height, or %NULL
3556 * Obtains the current size of @window. If @window is not onscreen,
3557 * it returns the size GTK+ will suggest to the <link
3558 * linkend="gtk-X11-arch">window manager</link> for the initial window
3559 * size (but this is not reliably the same as the size the window
3560 * manager will actually select). The size obtained by
3561 * gtk_window_get_size() is the last size received in a
3562 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
3563 * rather than querying the X server for the size. As a result, if you
3564 * call gtk_window_resize() then immediately call
3565 * gtk_window_get_size(), the size won't have taken effect yet. After
3566 * the window manager processes the resize request, GTK+ receives
3567 * notification that the size has changed via a configure event, and
3568 * the size of the window gets updated.
3570 * Note 1: Nearly any use of this function creates a race condition,
3571 * because the size of the window may change between the time that you
3572 * get the size and the time that you perform some action assuming
3573 * that size is the current size. To avoid race conditions, connect to
3574 * "configure_event" on the window and adjust your size-dependent
3575 * state to match the size delivered in the #GdkEventConfigure.
3577 * Note 2: The returned size does <emphasis>not</emphasis> include the
3578 * size of the window manager decorations (aka the window frame or
3579 * border). Those are not drawn by GTK+ and GTK+ has no reliable
3580 * method of determining their size.
3582 * Note 3: If you are getting a window size in order to position
3583 * the window onscreen, there may be a better way. The preferred
3584 * way is to simply set the window's semantic type with
3585 * gtk_window_set_type_hint(), which allows the window manager to
3586 * e.g. center dialogs. Also, if you set the transient parent of
3587 * dialogs with gtk_window_set_transient_for() window managers
3588 * will often center the dialog over its parent window. It's
3589 * much preferred to let the window manager handle these
3590 * things rather than doing it yourself, because all apps will
3591 * behave consistently and according to user prefs if the window
3592 * manager handles it. Also, the window manager can take the size
3593 * of the window decorations/border into account, while your
3594 * application cannot.
3596 * In any case, if you insist on application-specified window
3597 * positioning, there's <emphasis>still</emphasis> a better way than
3598 * doing it yourself - gtk_window_set_position() will frequently
3599 * handle the details for you.
3603 gtk_window_get_size (GtkWindow *window,
3609 g_return_if_fail (GTK_IS_WINDOW (window));
3611 if (width == NULL && height == NULL)
3614 if (GTK_WIDGET_MAPPED (window))
3616 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3621 GdkRectangle configure_request;
3623 gtk_window_compute_configure_request (window,
3627 w = configure_request.width;
3628 h = configure_request.height;
3639 * @window: a #GtkWindow
3640 * @x: X coordinate to move window to
3641 * @y: Y coordinate to move window to
3643 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3644 * @window to the given position. Window managers are free to ignore
3645 * this; most window managers ignore requests for initial window
3646 * positions (instead using a user-defined placement algorithm) and
3647 * honor requests after the window has already been shown.
3649 * Note: the position is the position of the gravity-determined
3650 * reference point for the window. The gravity determines two things:
3651 * first, the location of the reference point in root window
3652 * coordinates; and second, which point on the window is positioned at
3653 * the reference point.
3655 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3656 * point is simply the @x, @y supplied to gtk_window_move(). The
3657 * top-left corner of the window decorations (aka window frame or
3658 * border) will be placed at @x, @y. Therefore, to position a window
3659 * at the top left of the screen, you want to use the default gravity
3660 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3662 * To position a window at the bottom right corner of the screen, you
3663 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3664 * point is at @x + the window width and @y + the window height, and
3665 * the bottom-right corner of the window border will be placed at that
3666 * reference point. So, to place a window in the bottom right corner
3667 * you would first set gravity to south east, then write:
3668 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3669 * gdk_screen_height () - window_height)</literal> (note that this
3670 * example does not take multi-head scenarios into account).
3672 * The Extended Window Manager Hints specification at <ulink
3673 * url="http://www.freedesktop.org/Standards/wm-spec">
3674 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
3675 * nice table of gravities in the "implementation notes" section.
3677 * The gtk_window_get_position() documentation may also be relevant.
3680 gtk_window_move (GtkWindow *window,
3684 GtkWindowGeometryInfo *info;
3687 g_return_if_fail (GTK_IS_WINDOW (window));
3689 widget = GTK_WIDGET (window);
3691 info = gtk_window_get_geometry_info (window, TRUE);
3693 if (GTK_WIDGET_MAPPED (window))
3695 /* we have now sent a request with this position
3696 * with currently-active constraints, so toggle flag.
3698 info->position_constraints_changed = FALSE;
3700 /* we only constrain if mapped - if not mapped,
3701 * then gtk_window_compute_configure_request()
3702 * will apply the constraints later, and we
3703 * don't want to lose information about
3704 * what position the user set before then.
3705 * i.e. if you do a move() then turn off POS_CENTER
3706 * then show the window, your move() will work.
3708 gtk_window_constrain_position (window,
3709 widget->allocation.width,
3710 widget->allocation.height,
3713 /* Note that this request doesn't go through our standard request
3714 * framework, e.g. doesn't increment configure_request_count,
3715 * doesn't set info->last, etc.; that's because
3716 * we don't save the info needed to arrive at this same request
3719 * To gtk_window_move_resize(), this will end up looking exactly
3720 * the same as the position being changed by the window
3724 /* FIXME are we handling gravity properly for framed windows? */
3726 gdk_window_move (window->frame,
3727 x - window->frame_left,
3728 y - window->frame_top);
3730 gdk_window_move (GTK_WIDGET (window)->window,
3735 /* Save this position to apply on mapping */
3736 info->initial_x = x;
3737 info->initial_y = y;
3738 info->initial_pos_set = TRUE;
3743 * gtk_window_get_position:
3744 * @window: a #GtkWindow
3745 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3746 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3748 * This function returns the position you need to pass to
3749 * gtk_window_move() to keep @window in its current position. This
3750 * means that the meaning of the returned value varies with window
3751 * gravity. See gtk_window_move() for more details.
3753 * If you haven't changed the window gravity, its gravity will be
3754 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3755 * gets the position of the top-left corner of the window manager
3756 * frame for the window. gtk_window_move() sets the position of this
3757 * same top-left corner.
3759 * gtk_window_get_position() is not 100% reliable because the X Window System
3760 * does not specify a way to obtain the geometry of the
3761 * decorations placed on a window by the window manager.
3762 * Thus GTK+ is using a "best guess" that works with most
3765 * Moreover, nearly all window managers are historically broken with
3766 * respect to their handling of window gravity. So moving a window to
3767 * its current position as returned by gtk_window_get_position() tends
3768 * to result in moving the window slightly. Window managers are
3769 * slowly getting better over time.
3771 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3772 * frame is not relevant, and thus gtk_window_get_position() will
3773 * always produce accurate results. However you can't use static
3774 * gravity to do things like place a window in a corner of the screen,
3775 * because static gravity ignores the window manager decorations.
3777 * If you are saving and restoring your application's window
3778 * positions, you should know that it's impossible for applications to
3779 * do this without getting it somewhat wrong because applications do
3780 * not have sufficient knowledge of window manager state. The Correct
3781 * Mechanism is to support the session management protocol (see the
3782 * "GnomeClient" object in the GNOME libraries for example) and allow
3783 * the window manager to save your window sizes and positions.
3788 gtk_window_get_position (GtkWindow *window,
3794 g_return_if_fail (GTK_IS_WINDOW (window));
3796 widget = GTK_WIDGET (window);
3798 if (window->gravity == GDK_GRAVITY_STATIC)
3800 if (GTK_WIDGET_MAPPED (widget))
3802 /* This does a server round-trip, which is sort of wrong;
3803 * but a server round-trip is inevitable for
3804 * gdk_window_get_frame_extents() in the usual
3805 * NorthWestGravity case below, so not sure what else to
3806 * do. We should likely be consistent about whether we get
3807 * the client-side info or the server-side info.
3809 gdk_window_get_origin (widget->window, root_x, root_y);
3813 GdkRectangle configure_request;
3815 gtk_window_compute_configure_request (window,
3819 *root_x = configure_request.x;
3820 *root_y = configure_request.y;
3825 GdkRectangle frame_extents;
3830 if (GTK_WIDGET_MAPPED (widget))
3833 gdk_window_get_frame_extents (window->frame, &frame_extents);
3835 gdk_window_get_frame_extents (widget->window, &frame_extents);
3836 x = frame_extents.x;
3837 y = frame_extents.y;
3838 gtk_window_get_size (window, &w, &h);
3842 /* We just say the frame has 0 size on all sides.
3843 * Not sure what else to do.
3845 gtk_window_compute_configure_request (window,
3848 x = frame_extents.x;
3849 y = frame_extents.y;
3850 w = frame_extents.width;
3851 h = frame_extents.height;
3854 switch (window->gravity)
3856 case GDK_GRAVITY_NORTH:
3857 case GDK_GRAVITY_CENTER:
3858 case GDK_GRAVITY_SOUTH:
3859 /* Find center of frame. */
3860 x += frame_extents.width / 2;
3861 /* Center client window on that point. */
3865 case GDK_GRAVITY_SOUTH_EAST:
3866 case GDK_GRAVITY_EAST:
3867 case GDK_GRAVITY_NORTH_EAST:
3868 /* Find right edge of frame */
3869 x += frame_extents.width;
3870 /* Align left edge of client at that point. */
3877 switch (window->gravity)
3879 case GDK_GRAVITY_WEST:
3880 case GDK_GRAVITY_CENTER:
3881 case GDK_GRAVITY_EAST:
3882 /* Find center of frame. */
3883 y += frame_extents.height / 2;
3884 /* Center client window there. */
3887 case GDK_GRAVITY_SOUTH_WEST:
3888 case GDK_GRAVITY_SOUTH:
3889 case GDK_GRAVITY_SOUTH_EAST:
3890 /* Find south edge of frame */
3891 y += frame_extents.height;
3892 /* Place bottom edge of client there */
3907 * gtk_window_reshow_with_initial_size:
3908 * @window: a #GtkWindow
3910 * Hides @window, then reshows it, resetting the
3911 * default size and position of the window. Used
3912 * by GUI builders only.
3915 gtk_window_reshow_with_initial_size (GtkWindow *window)
3919 g_return_if_fail (GTK_IS_WINDOW (window));
3921 widget = GTK_WIDGET (window);
3923 gtk_widget_hide (widget);
3924 gtk_widget_unrealize (widget);
3925 gtk_widget_show (widget);
3929 gtk_window_destroy (GtkObject *object)
3931 GtkWindow *window = GTK_WINDOW (object);
3933 toplevel_list = g_slist_remove (toplevel_list, window);
3935 if (window->transient_parent)
3936 gtk_window_set_transient_for (window, NULL);
3938 /* frees the icons */
3939 gtk_window_set_icon_list (window, NULL);
3941 if (window->has_user_ref_count)
3943 window->has_user_ref_count = FALSE;
3944 g_object_unref (window);
3948 gtk_window_group_remove_window (window->group, window);
3950 gtk_window_free_key_hash (window);
3952 GTK_OBJECT_CLASS (gtk_window_parent_class)->destroy (object);
3956 gtk_window_finalize (GObject *object)
3958 GtkWindow *window = GTK_WINDOW (object);
3959 GtkMnemonicHash *mnemonic_hash;
3961 g_free (window->title);
3962 g_free (window->wmclass_name);
3963 g_free (window->wmclass_class);
3964 g_free (window->wm_role);
3966 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
3968 _gtk_mnemonic_hash_free (mnemonic_hash);
3970 if (window->geometry_info)
3972 if (window->geometry_info->widget)
3973 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3974 gtk_widget_destroyed,
3975 &window->geometry_info->widget);
3976 g_free (window->geometry_info);
3979 if (window->keys_changed_handler)
3981 g_source_remove (window->keys_changed_handler);
3982 window->keys_changed_handler = 0;
3987 g_signal_handlers_disconnect_by_func (window->screen,
3988 gtk_window_on_composited_changed, window);
3991 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
3995 gtk_window_show (GtkWidget *widget)
3997 GtkWindow *window = GTK_WINDOW (widget);
3998 GtkContainer *container = GTK_CONTAINER (window);
3999 gboolean need_resize;
4001 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
4003 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
4004 container->need_resize = FALSE;
4008 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4009 GtkAllocation allocation = { 0, 0 };
4010 GdkRectangle configure_request;
4011 GdkGeometry new_geometry;
4013 gboolean was_realized;
4015 /* We are going to go ahead and perform this configure request
4016 * and then emulate a configure notify by going ahead and
4017 * doing a size allocate. Sort of a synchronous
4018 * mini-copy of gtk_window_move_resize() here.
4020 gtk_window_compute_configure_request (window,
4025 /* We update this because we are going to go ahead
4026 * and gdk_window_resize() below, rather than
4029 info->last.configure_request.width = configure_request.width;
4030 info->last.configure_request.height = configure_request.height;
4032 /* and allocate the window - this is normally done
4033 * in move_resize in response to configure notify
4035 allocation.width = configure_request.width;
4036 allocation.height = configure_request.height;
4037 gtk_widget_size_allocate (widget, &allocation);
4039 /* Then we guarantee we have a realize */
4040 was_realized = FALSE;
4041 if (!GTK_WIDGET_REALIZED (widget))
4043 gtk_widget_realize (widget);
4044 was_realized = TRUE;
4047 /* Must be done after the windows are realized,
4048 * so that the decorations can be read
4050 gtk_decorated_window_calculate_frame_size (window);
4052 /* We only send configure request if we didn't just finish
4053 * creating the window; if we just created the window
4054 * then we created it with widget->allocation anyhow.
4057 gdk_window_move_resize (widget->window,
4058 configure_request.x,
4059 configure_request.y,
4060 configure_request.width,
4061 configure_request.height);
4064 gtk_container_check_resize (container);
4066 gtk_widget_map (widget);
4068 /* Try to make sure that we have some focused widget
4070 if (!window->focus_widget && !GTK_IS_PLUG (window))
4071 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4074 gtk_grab_add (widget);
4078 gtk_window_hide (GtkWidget *widget)
4080 GtkWindow *window = GTK_WINDOW (widget);
4082 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4083 gtk_widget_unmap (widget);
4086 gtk_grab_remove (widget);
4090 gtk_window_map (GtkWidget *widget)
4092 GtkWindow *window = GTK_WINDOW (widget);
4093 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4094 GdkWindow *toplevel;
4096 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4098 if (window->bin.child &&
4099 GTK_WIDGET_VISIBLE (window->bin.child) &&
4100 !GTK_WIDGET_MAPPED (window->bin.child))
4101 gtk_widget_map (window->bin.child);
4104 toplevel = window->frame;
4106 toplevel = widget->window;
4108 if (window->maximize_initially)
4109 gdk_window_maximize (toplevel);
4111 gdk_window_unmaximize (toplevel);
4113 if (window->stick_initially)
4114 gdk_window_stick (toplevel);
4116 gdk_window_unstick (toplevel);
4118 if (window->iconify_initially)
4119 gdk_window_iconify (toplevel);
4121 gdk_window_deiconify (toplevel);
4123 if (priv->fullscreen_initially)
4124 gdk_window_fullscreen (toplevel);
4126 gdk_window_unfullscreen (toplevel);
4128 gdk_window_set_keep_above (toplevel, priv->above_initially);
4130 gdk_window_set_keep_below (toplevel, priv->below_initially);
4132 /* No longer use the default settings */
4133 window->need_default_size = FALSE;
4134 window->need_default_position = FALSE;
4136 if (priv->reset_type_hint)
4138 /* We should only reset the type hint when the application
4139 * used gtk_window_set_type_hint() to change the hint.
4140 * Some applications use X directly to change the properties;
4141 * in that case, we shouldn't overwrite what they did.
4143 gdk_window_set_type_hint (widget->window, priv->type_hint);
4144 priv->reset_type_hint = FALSE;
4147 gdk_window_show (widget->window);
4150 gdk_window_show (window->frame);
4152 if (!disable_startup_notification &&
4153 !sent_startup_notification)
4155 sent_startup_notification = TRUE;
4156 gdk_notify_startup_complete ();
4161 gtk_window_map_event (GtkWidget *widget,
4164 if (!GTK_WIDGET_MAPPED (widget))
4166 /* we should be be unmapped, but are getting a MapEvent, this may happen
4167 * to toplevel XWindows if mapping was intercepted by a window manager
4168 * and an unmap request occoured while the MapRequestEvent was still
4169 * being handled. we work around this situaiton here by re-requesting
4170 * the window being unmapped. more details can be found in:
4171 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4173 gdk_window_hide (widget->window);
4179 gtk_window_unmap (GtkWidget *widget)
4181 GtkWindow *window = GTK_WINDOW (widget);
4182 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
4183 GtkWindowGeometryInfo *info;
4184 GdkWindowState state;
4186 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4188 gdk_window_withdraw (window->frame);
4190 gdk_window_withdraw (widget->window);
4192 window->configure_request_count = 0;
4193 window->configure_notify_received = FALSE;
4195 /* on unmap, we reset the default positioning of the window,
4196 * so it's placed again, but we don't reset the default
4197 * size of the window, so it's remembered.
4199 window->need_default_position = TRUE;
4201 info = gtk_window_get_geometry_info (window, FALSE);
4204 info->initial_pos_set = FALSE;
4205 info->position_constraints_changed = FALSE;
4208 state = gdk_window_get_state (widget->window);
4209 window->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4210 window->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4211 window->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4212 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4213 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4217 gtk_window_realize (GtkWidget *widget)
4220 GdkWindow *parent_window;
4221 GdkWindowAttr attributes;
4222 gint attributes_mask;
4223 GtkWindowPrivate *priv;
4225 window = GTK_WINDOW (widget);
4227 priv = GTK_WINDOW_GET_PRIVATE (window);
4229 /* ensure widget tree is properly size allocated */
4230 if (widget->allocation.x == -1 &&
4231 widget->allocation.y == -1 &&
4232 widget->allocation.width == 1 &&
4233 widget->allocation.height == 1)
4235 GtkRequisition requisition;
4236 GtkAllocation allocation = { 0, 0, 200, 200 };
4238 gtk_widget_size_request (widget, &requisition);
4239 if (requisition.width || requisition.height)
4241 /* non-empty window */
4242 allocation.width = requisition.width;
4243 allocation.height = requisition.height;
4245 gtk_widget_size_allocate (widget, &allocation);
4247 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4249 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
4252 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4254 switch (window->type)
4256 case GTK_WINDOW_TOPLEVEL:
4257 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4259 case GTK_WINDOW_POPUP:
4260 attributes.window_type = GDK_WINDOW_TEMP;
4263 g_warning (G_STRLOC": Unknown window type %d!", window->type);
4267 attributes.title = window->title;
4268 attributes.wmclass_name = window->wmclass_name;
4269 attributes.wmclass_class = window->wmclass_class;
4270 attributes.wclass = GDK_INPUT_OUTPUT;
4271 attributes.visual = gtk_widget_get_visual (widget);
4272 attributes.colormap = gtk_widget_get_colormap (widget);
4274 if (window->has_frame)
4276 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
4277 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
4278 attributes.event_mask = (GDK_EXPOSURE_MASK |
4279 GDK_KEY_PRESS_MASK |
4280 GDK_ENTER_NOTIFY_MASK |
4281 GDK_LEAVE_NOTIFY_MASK |
4282 GDK_FOCUS_CHANGE_MASK |
4283 GDK_STRUCTURE_MASK |
4284 GDK_BUTTON_MOTION_MASK |
4285 GDK_POINTER_MOTION_HINT_MASK |
4286 GDK_BUTTON_PRESS_MASK |
4287 GDK_BUTTON_RELEASE_MASK);
4289 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4291 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4292 &attributes, attributes_mask);
4294 gdk_window_set_user_data (window->frame, widget);
4296 attributes.window_type = GDK_WINDOW_CHILD;
4297 attributes.x = window->frame_left;
4298 attributes.y = window->frame_top;
4300 attributes_mask = GDK_WA_X | GDK_WA_Y;
4302 parent_window = window->frame;
4304 g_signal_connect (window,
4306 G_CALLBACK (gtk_window_event),
4311 attributes_mask = 0;
4312 parent_window = gtk_widget_get_root_window (widget);
4315 attributes.width = widget->allocation.width;
4316 attributes.height = widget->allocation.height;
4317 attributes.event_mask = gtk_widget_get_events (widget);
4318 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4319 GDK_KEY_PRESS_MASK |
4320 GDK_KEY_RELEASE_MASK |
4321 GDK_ENTER_NOTIFY_MASK |
4322 GDK_LEAVE_NOTIFY_MASK |
4323 GDK_FOCUS_CHANGE_MASK |
4324 GDK_STRUCTURE_MASK);
4326 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
4327 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
4328 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
4330 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
4332 gdk_window_enable_synchronized_configure (widget->window);
4334 gdk_window_set_user_data (widget->window, window);
4336 widget->style = gtk_style_attach (widget->style, widget->window);
4337 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4339 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
4341 /* This is a bad hack to set the window background. */
4342 gtk_window_paint (widget, NULL);
4344 if (window->transient_parent &&
4345 GTK_WIDGET_REALIZED (window->transient_parent))
4346 gdk_window_set_transient_for (widget->window,
4347 GTK_WIDGET (window->transient_parent)->window);
4349 if (window->wm_role)
4350 gdk_window_set_role (widget->window, window->wm_role);
4352 if (!window->decorated)
4353 gdk_window_set_decorations (widget->window, 0);
4355 if (!priv->deletable)
4356 gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4358 gdk_window_set_type_hint (widget->window, priv->type_hint);
4360 if (gtk_window_get_skip_pager_hint (window))
4361 gdk_window_set_skip_pager_hint (widget->window, TRUE);
4363 if (gtk_window_get_skip_taskbar_hint (window))
4364 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
4366 if (gtk_window_get_accept_focus (window))
4367 gdk_window_set_accept_focus (widget->window, TRUE);
4369 gdk_window_set_accept_focus (widget->window, FALSE);
4371 if (gtk_window_get_focus_on_map (window))
4372 gdk_window_set_focus_on_map (widget->window, TRUE);
4374 gdk_window_set_focus_on_map (widget->window, FALSE);
4377 gdk_window_set_modal_hint (widget->window, TRUE);
4379 gdk_window_set_modal_hint (widget->window, FALSE);
4382 gtk_window_realize_icon (window);
4386 gtk_window_unrealize (GtkWidget *widget)
4389 GtkWindowGeometryInfo *info;
4391 window = GTK_WINDOW (widget);
4393 /* On unrealize, we reset the size of the window such
4394 * that we will re-apply the default sizing stuff
4395 * next time we show the window.
4397 * Default positioning is reset on unmap, instead of unrealize.
4399 window->need_default_size = TRUE;
4400 info = gtk_window_get_geometry_info (window, FALSE);
4403 info->resize_width = -1;
4404 info->resize_height = -1;
4405 info->last.configure_request.x = 0;
4406 info->last.configure_request.y = 0;
4407 info->last.configure_request.width = -1;
4408 info->last.configure_request.height = -1;
4409 /* be sure we reset geom hints on re-realize */
4410 info->last.flags = 0;
4415 gdk_window_set_user_data (window->frame, NULL);
4416 gdk_window_destroy (window->frame);
4417 window->frame = NULL;
4421 gtk_window_unrealize_icon (window);
4423 (* GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize) (widget);
4427 gtk_window_size_request (GtkWidget *widget,
4428 GtkRequisition *requisition)
4433 window = GTK_WINDOW (widget);
4434 bin = GTK_BIN (window);
4436 requisition->width = GTK_CONTAINER (window)->border_width * 2;
4437 requisition->height = GTK_CONTAINER (window)->border_width * 2;
4439 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
4441 GtkRequisition child_requisition;
4443 gtk_widget_size_request (bin->child, &child_requisition);
4445 requisition->width += child_requisition.width;
4446 requisition->height += child_requisition.height;
4451 gtk_window_size_allocate (GtkWidget *widget,
4452 GtkAllocation *allocation)
4455 GtkAllocation child_allocation;
4457 window = GTK_WINDOW (widget);
4458 widget->allocation = *allocation;
4460 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
4462 child_allocation.x = GTK_CONTAINER (window)->border_width;
4463 child_allocation.y = GTK_CONTAINER (window)->border_width;
4464 child_allocation.width =
4465 MAX (1, (gint)allocation->width - child_allocation.x * 2);
4466 child_allocation.height =
4467 MAX (1, (gint)allocation->height - child_allocation.y * 2);
4469 gtk_widget_size_allocate (window->bin.child, &child_allocation);
4472 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4474 gdk_window_resize (window->frame,
4475 allocation->width + window->frame_left + window->frame_right,
4476 allocation->height + window->frame_top + window->frame_bottom);
4481 gtk_window_event (GtkWidget *widget, GdkEvent *event)
4484 gboolean return_val;
4486 window = GTK_WINDOW (widget);
4488 if (window->frame && (event->any.window == window->frame))
4490 if ((event->type != GDK_KEY_PRESS) &&
4491 (event->type != GDK_KEY_RELEASE) &&
4492 (event->type != GDK_FOCUS_CHANGE))
4494 g_signal_stop_emission_by_name (widget, "event");
4496 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
4501 g_object_unref (event->any.window);
4502 event->any.window = g_object_ref (widget->window);
4510 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
4512 GdkEventConfigure *configure_event;
4515 switch (event->type)
4518 configure_event = (GdkEventConfigure *)event;
4520 /* Invalidate the decorations */
4523 rect.width = configure_event->width;
4524 rect.height = configure_event->height;
4526 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
4528 /* Pass on the (modified) configure event */
4529 configure_event->width -= window->frame_left + window->frame_right;
4530 configure_event->height -= window->frame_top + window->frame_bottom;
4531 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
4540 gtk_window_configure_event (GtkWidget *widget,
4541 GdkEventConfigure *event)
4543 GtkWindow *window = GTK_WINDOW (widget);
4544 gboolean expected_reply = window->configure_request_count > 0;
4546 /* window->configure_request_count incremented for each
4547 * configure request, and decremented to a min of 0 for
4548 * each configure notify.
4550 * All it means is that we know we will get at least
4551 * window->configure_request_count more configure notifies.
4552 * We could get more configure notifies than that; some
4553 * of the configure notifies we get may be unrelated to
4554 * the configure requests. But we will get at least
4555 * window->configure_request_count notifies.
4558 if (window->configure_request_count > 0)
4559 window->configure_request_count -= 1;
4561 /* As an optimization, we avoid a resize when possible.
4563 * The only times we can avoid a resize are:
4564 * - we know only the position changed, not the size
4565 * - we know we have made more requests and so will get more
4566 * notifies and can wait to resize when we get them
4569 if (!expected_reply &&
4570 (widget->allocation.width == event->width &&
4571 widget->allocation.height == event->height))
4573 gdk_window_configure_finished (widget->window);
4578 * If we do need to resize, we do that by:
4579 * - filling in widget->allocation with the new size
4580 * - setting configure_notify_received to TRUE
4581 * for use in gtk_window_move_resize()
4582 * - queueing a resize, leading to invocation of
4583 * gtk_window_move_resize() in an idle handler
4587 window->configure_notify_received = TRUE;
4589 widget->allocation.width = event->width;
4590 widget->allocation.height = event->height;
4592 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4597 /* the accel_key and accel_mods fields of the key have to be setup
4598 * upon calling this function. it'll then return whether that key
4599 * is at all used as accelerator, and if so will OR in the
4600 * accel_flags member of the key.
4603 _gtk_window_query_nonaccels (GtkWindow *window,
4605 GdkModifierType accel_mods)
4607 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4609 /* movement keys are considered locked accels */
4612 static const guint bindings[] = {
4613 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
4614 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
4618 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
4619 if (bindings[i] == accel_key)
4623 /* mnemonics are considered locked accels */
4624 if (accel_mods == window->mnemonic_modifier)
4626 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4627 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
4635 * gtk_window_propagate_key_event:
4636 * @window: a #GtkWindow
4637 * @event: a #GdkEventKey
4639 * Propagate a key press or release event to the focus widget and
4640 * up the focus container chain until a widget handles @event.
4641 * This is normally called by the default ::key_press_event and
4642 * ::key_release_event handlers for toplevel windows,
4643 * however in some cases it may be useful to call this directly when
4644 * overriding the standard key handling for a toplevel window.
4646 * Return value: %TRUE if a widget in the focus chain handled the event.
4649 gtk_window_propagate_key_event (GtkWindow *window,
4652 gboolean handled = FALSE;
4653 GtkWidget *widget, *focus;
4655 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4657 widget = GTK_WIDGET (window);
4658 focus = window->focus_widget;
4660 g_object_ref (focus);
4663 focus && focus != widget &&
4664 gtk_widget_get_toplevel (focus) == widget)
4668 if (GTK_WIDGET_IS_SENSITIVE (focus))
4669 handled = gtk_widget_event (focus, (GdkEvent*) event);
4671 parent = focus->parent;
4673 g_object_ref (parent);
4675 g_object_unref (focus);
4681 g_object_unref (focus);
4687 gtk_window_key_press_event (GtkWidget *widget,
4690 GtkWindow *window = GTK_WINDOW (widget);
4691 gboolean handled = FALSE;
4693 /* handle mnemonics and accelerators */
4695 handled = gtk_window_activate_key (window, event);
4697 /* handle focus widget key events */
4699 handled = gtk_window_propagate_key_event (window, event);
4701 /* Chain up, invokes binding set */
4703 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
4709 gtk_window_key_release_event (GtkWidget *widget,
4712 GtkWindow *window = GTK_WINDOW (widget);
4713 gboolean handled = FALSE;
4715 /* handle focus widget key events */
4717 handled = gtk_window_propagate_key_event (window, event);
4719 /* Chain up, invokes binding set */
4721 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
4727 gtk_window_real_activate_default (GtkWindow *window)
4729 gtk_window_activate_default (window);
4733 gtk_window_real_activate_focus (GtkWindow *window)
4735 gtk_window_activate_focus (window);
4739 gtk_window_move_focus (GtkWindow *window,
4740 GtkDirectionType dir)
4742 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4744 if (!GTK_CONTAINER (window)->focus_child)
4745 gtk_window_set_focus (window, NULL);
4749 gtk_window_enter_notify_event (GtkWidget *widget,
4750 GdkEventCrossing *event)
4756 gtk_window_leave_notify_event (GtkWidget *widget,
4757 GdkEventCrossing *event)
4763 do_focus_change (GtkWidget *widget,
4766 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4768 g_object_ref (widget);
4771 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4773 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4775 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4776 fevent->focus_change.window = widget->window;
4778 g_object_ref (widget->window);
4779 fevent->focus_change.in = in;
4781 gtk_widget_event (widget, fevent);
4783 g_object_notify (G_OBJECT (widget), "has-focus");
4785 g_object_unref (widget);
4786 gdk_event_free (fevent);
4790 gtk_window_focus_in_event (GtkWidget *widget,
4791 GdkEventFocus *event)
4793 GtkWindow *window = GTK_WINDOW (widget);
4795 /* It appears spurious focus in events can occur when
4796 * the window is hidden. So we'll just check to see if
4797 * the window is visible before actually handling the
4800 if (GTK_WIDGET_VISIBLE (widget))
4802 _gtk_window_set_has_toplevel_focus (window, TRUE);
4803 _gtk_window_set_is_active (window, TRUE);
4810 gtk_window_focus_out_event (GtkWidget *widget,
4811 GdkEventFocus *event)
4813 GtkWindow *window = GTK_WINDOW (widget);
4815 _gtk_window_set_has_toplevel_focus (window, FALSE);
4816 _gtk_window_set_is_active (window, FALSE);
4821 static GdkAtom atom_rcfiles = GDK_NONE;
4822 static GdkAtom atom_iconthemes = GDK_NONE;
4825 send_client_message_to_embedded_windows (GtkWidget *widget,
4826 GdkAtom message_type)
4828 GList *embedded_windows;
4830 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
4831 if (embedded_windows)
4833 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4836 for (i = 0; i < 5; i++)
4837 send_event->client.data.l[i] = 0;
4838 send_event->client.data_format = 32;
4839 send_event->client.message_type = message_type;
4841 while (embedded_windows)
4843 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4844 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4845 embedded_windows = embedded_windows->next;
4848 gdk_event_free (send_event);
4853 gtk_window_client_event (GtkWidget *widget,
4854 GdkEventClient *event)
4858 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
4859 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
4862 if (event->message_type == atom_rcfiles)
4864 send_client_message_to_embedded_windows (widget, atom_rcfiles);
4865 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4868 if (event->message_type == atom_iconthemes)
4870 send_client_message_to_embedded_windows (widget, atom_iconthemes);
4871 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
4878 gtk_window_check_resize (GtkContainer *container)
4880 GtkWindow *window = GTK_WINDOW (container);
4882 if (GTK_WIDGET_VISIBLE (container))
4883 gtk_window_move_resize (window);
4887 gtk_window_focus (GtkWidget *widget,
4888 GtkDirectionType direction)
4892 GtkContainer *container;
4893 GtkWidget *old_focus_child;
4896 container = GTK_CONTAINER (widget);
4897 window = GTK_WINDOW (widget);
4898 bin = GTK_BIN (widget);
4900 old_focus_child = container->focus_child;
4902 /* We need a special implementation here to deal properly with wrapping
4903 * around in the tab chain without the danger of going into an
4906 if (old_focus_child)
4908 if (gtk_widget_child_focus (old_focus_child, direction))
4912 if (window->focus_widget)
4914 if (direction == GTK_DIR_LEFT ||
4915 direction == GTK_DIR_RIGHT ||
4916 direction == GTK_DIR_UP ||
4917 direction == GTK_DIR_DOWN)
4922 /* Wrapped off the end, clear the focus setting for the toplpevel */
4923 parent = window->focus_widget->parent;
4926 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4927 parent = GTK_WIDGET (parent)->parent;
4930 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4933 /* Now try to focus the first widget in the window */
4936 if (gtk_widget_child_focus (bin->child, direction))
4944 gtk_window_real_set_focus (GtkWindow *window,
4947 GtkWidget *old_focus = window->focus_widget;
4948 gboolean had_default = FALSE;
4949 gboolean focus_had_default = FALSE;
4950 gboolean old_focus_had_default = FALSE;
4954 g_object_ref (old_focus);
4955 g_object_freeze_notify (G_OBJECT (old_focus));
4956 old_focus_had_default = GTK_WIDGET_HAS_DEFAULT (old_focus);
4960 g_object_ref (focus);
4961 g_object_freeze_notify (G_OBJECT (focus));
4962 focus_had_default = GTK_WIDGET_HAS_DEFAULT (focus);
4965 if (window->default_widget)
4966 had_default = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4968 if (window->focus_widget)
4970 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4971 (window->focus_widget != window->default_widget))
4973 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4974 gtk_widget_queue_draw (window->focus_widget);
4976 if (window->default_widget)
4977 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4980 window->focus_widget = NULL;
4982 if (window->has_focus)
4983 do_focus_change (old_focus, FALSE);
4985 g_object_notify (G_OBJECT (old_focus), "is-focus");
4988 /* The above notifications may have set a new focus widget,
4989 * if so, we don't want to override it.
4991 if (focus && !window->focus_widget)
4993 window->focus_widget = focus;
4995 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4996 (window->focus_widget != window->default_widget))
4998 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4999 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
5001 if (window->default_widget)
5002 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
5005 if (window->has_focus)
5006 do_focus_change (window->focus_widget, TRUE);
5008 g_object_notify (G_OBJECT (window->focus_widget), "is-focus");
5011 /* If the default widget changed, a redraw will have been queued
5012 * on the old and new default widgets by gtk_window_set_default(), so
5013 * we only have to worry about the case where it didn't change.
5014 * We'll sometimes queue a draw twice on the new widget but that
5017 if (window->default_widget &&
5018 (had_default != GTK_WIDGET_HAS_DEFAULT (window->default_widget)))
5019 gtk_widget_queue_draw (window->default_widget);
5023 if (old_focus_had_default != GTK_WIDGET_HAS_DEFAULT (old_focus))
5024 gtk_widget_queue_draw (old_focus);
5026 g_object_thaw_notify (G_OBJECT (old_focus));
5027 g_object_unref (old_focus);
5031 if (focus_had_default != GTK_WIDGET_HAS_DEFAULT (focus))
5032 gtk_widget_queue_draw (focus);
5034 g_object_thaw_notify (G_OBJECT (focus));
5035 g_object_unref (focus);
5040 * _gtk_window_unset_focus_and_default:
5041 * @window: a #GtkWindow
5042 * @widget: a widget inside of @window
5044 * Checks whether the focus and default widgets of @window are
5045 * @widget or a descendent of @widget, and if so, unset them.
5048 _gtk_window_unset_focus_and_default (GtkWindow *window,
5054 g_object_ref (window);
5055 g_object_ref (widget);
5057 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
5059 child = window->focus_widget;
5061 while (child && child != widget)
5062 child = child->parent;
5064 if (child == widget)
5065 gtk_window_set_focus (GTK_WINDOW (window), NULL);
5068 child = window->default_widget;
5070 while (child && child != widget)
5071 child = child->parent;
5073 if (child == widget)
5074 gtk_window_set_default (window, NULL);
5076 g_object_unref (widget);
5077 g_object_unref (window);
5080 /*********************************
5081 * Functions related to resizing *
5082 *********************************/
5084 /* This function doesn't constrain to geometry hints */
5086 gtk_window_compute_configure_request_size (GtkWindow *window,
5090 GtkRequisition requisition;
5091 GtkWindowGeometryInfo *info;
5095 * - we've done a size request
5098 widget = GTK_WIDGET (window);
5100 info = gtk_window_get_geometry_info (window, FALSE);
5102 if (window->need_default_size)
5104 gtk_widget_get_child_requisition (widget, &requisition);
5106 /* Default to requisition */
5107 *width = requisition.width;
5108 *height = requisition.height;
5110 /* If window is empty so requests 0, default to random nonzero size */
5111 if (*width == 0 && *height == 0)
5117 /* Override requisition with default size */
5121 gint base_width = 0;
5122 gint base_height = 0;
5124 gint min_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 if (flags & GDK_HINT_MIN_SIZE)
5143 min_width = geometry.min_width;
5144 min_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 = MAX (info->default_width * width_inc + base_width, min_width);
5156 if (info->default_height > 0)
5157 *height = MAX (info->default_height * height_inc + base_height, min_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_updates (widget->window, TRUE);
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"