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;
177 guint reset_type_hint : 1;
178 GdkWindowTypeHint type_hint;
181 static void gtk_window_dispose (GObject *object);
182 static void gtk_window_destroy (GtkObject *object);
183 static void gtk_window_finalize (GObject *object);
184 static void gtk_window_show (GtkWidget *widget);
185 static void gtk_window_hide (GtkWidget *widget);
186 static void gtk_window_map (GtkWidget *widget);
187 static void gtk_window_unmap (GtkWidget *widget);
188 static void gtk_window_realize (GtkWidget *widget);
189 static void gtk_window_unrealize (GtkWidget *widget);
190 static void gtk_window_size_request (GtkWidget *widget,
191 GtkRequisition *requisition);
192 static void gtk_window_size_allocate (GtkWidget *widget,
193 GtkAllocation *allocation);
194 static gint gtk_window_event (GtkWidget *widget,
196 static gboolean gtk_window_map_event (GtkWidget *widget,
198 static gboolean gtk_window_frame_event (GtkWindow *window,
200 static gint gtk_window_configure_event (GtkWidget *widget,
201 GdkEventConfigure *event);
202 static gint gtk_window_key_press_event (GtkWidget *widget,
204 static gint gtk_window_key_release_event (GtkWidget *widget,
206 static gint gtk_window_enter_notify_event (GtkWidget *widget,
207 GdkEventCrossing *event);
208 static gint gtk_window_leave_notify_event (GtkWidget *widget,
209 GdkEventCrossing *event);
210 static gint gtk_window_focus_in_event (GtkWidget *widget,
211 GdkEventFocus *event);
212 static gint gtk_window_focus_out_event (GtkWidget *widget,
213 GdkEventFocus *event);
214 static gint gtk_window_client_event (GtkWidget *widget,
215 GdkEventClient *event);
216 static void gtk_window_check_resize (GtkContainer *container);
217 static gint gtk_window_focus (GtkWidget *widget,
218 GtkDirectionType direction);
219 static void gtk_window_real_set_focus (GtkWindow *window,
222 static void gtk_window_real_activate_default (GtkWindow *window);
223 static void gtk_window_real_activate_focus (GtkWindow *window);
224 static void gtk_window_move_focus (GtkWindow *window,
225 GtkDirectionType dir);
226 static void gtk_window_keys_changed (GtkWindow *window);
227 static void gtk_window_paint (GtkWidget *widget,
229 static gint gtk_window_expose (GtkWidget *widget,
230 GdkEventExpose *event);
231 static void gtk_window_unset_transient_for (GtkWindow *window);
232 static void gtk_window_transient_parent_realized (GtkWidget *parent,
234 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
237 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
239 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
242 static void gtk_window_move_resize (GtkWindow *window);
243 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
245 GdkGeometry *geometry_b,
247 static void gtk_window_constrain_size (GtkWindow *window,
248 GdkGeometry *geometry,
254 static void gtk_window_constrain_position (GtkWindow *window,
259 static void gtk_window_compute_hints (GtkWindow *window,
260 GdkGeometry *new_geometry,
262 static void gtk_window_compute_configure_request (GtkWindow *window,
263 GdkRectangle *request,
264 GdkGeometry *geometry,
267 static void gtk_window_set_default_size_internal (GtkWindow *window,
268 gboolean change_width,
270 gboolean change_height,
272 gboolean is_geometry);
274 static void update_themed_icon (GtkIconTheme *theme,
276 static GList *icon_list_from_theme (GtkWidget *widget,
278 static void gtk_window_realize_icon (GtkWindow *window);
279 static void gtk_window_unrealize_icon (GtkWindow *window);
281 static void gtk_window_notify_keys_changed (GtkWindow *window);
282 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
283 static void gtk_window_free_key_hash (GtkWindow *window);
284 static void gtk_window_on_composited_changed (GdkScreen *screen,
287 static GSList *toplevel_list = NULL;
288 static guint window_signals[LAST_SIGNAL] = { 0 };
289 static GList *default_icon_list = NULL;
290 static gchar *default_icon_name = NULL;
291 static guint default_icon_serial = 0;
292 static gboolean disable_startup_notification = FALSE;
293 static gboolean sent_startup_notification = FALSE;
295 static GQuark quark_gtk_embedded = 0;
296 static GQuark quark_gtk_window_key_hash = 0;
297 static GQuark quark_gtk_window_default_icon_pixmap = 0;
298 static GQuark quark_gtk_window_icon_info = 0;
300 static void gtk_window_set_property (GObject *object,
304 static void gtk_window_get_property (GObject *object,
310 G_DEFINE_TYPE (GtkWindow, gtk_window, GTK_TYPE_BIN);
313 add_tab_bindings (GtkBindingSet *binding_set,
314 GdkModifierType modifiers,
315 GtkDirectionType direction)
317 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
319 GTK_TYPE_DIRECTION_TYPE, direction);
320 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
322 GTK_TYPE_DIRECTION_TYPE, direction);
326 add_arrow_bindings (GtkBindingSet *binding_set,
328 GtkDirectionType direction)
330 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
332 gtk_binding_entry_add_signal (binding_set, keysym, 0,
334 GTK_TYPE_DIRECTION_TYPE, direction);
335 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
337 GTK_TYPE_DIRECTION_TYPE, direction);
338 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
340 GTK_TYPE_DIRECTION_TYPE, direction);
341 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
343 GTK_TYPE_DIRECTION_TYPE, direction);
348 gtk_window_class_init (GtkWindowClass *klass)
350 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
351 GtkObjectClass *object_class;
352 GtkWidgetClass *widget_class;
353 GtkContainerClass *container_class;
354 GtkBindingSet *binding_set;
356 object_class = (GtkObjectClass*) klass;
357 widget_class = (GtkWidgetClass*) klass;
358 container_class = (GtkContainerClass*) klass;
360 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
361 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
362 quark_gtk_window_default_icon_pixmap = g_quark_from_static_string ("gtk-window-default-icon-pixmap");
363 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
365 gobject_class->dispose = gtk_window_dispose;
366 gobject_class->finalize = gtk_window_finalize;
368 gobject_class->set_property = gtk_window_set_property;
369 gobject_class->get_property = gtk_window_get_property;
371 object_class->destroy = gtk_window_destroy;
373 widget_class->show = gtk_window_show;
374 widget_class->hide = gtk_window_hide;
375 widget_class->map = gtk_window_map;
376 widget_class->map_event = gtk_window_map_event;
377 widget_class->unmap = gtk_window_unmap;
378 widget_class->realize = gtk_window_realize;
379 widget_class->unrealize = gtk_window_unrealize;
380 widget_class->size_request = gtk_window_size_request;
381 widget_class->size_allocate = gtk_window_size_allocate;
382 widget_class->configure_event = gtk_window_configure_event;
383 widget_class->key_press_event = gtk_window_key_press_event;
384 widget_class->key_release_event = gtk_window_key_release_event;
385 widget_class->enter_notify_event = gtk_window_enter_notify_event;
386 widget_class->leave_notify_event = gtk_window_leave_notify_event;
387 widget_class->focus_in_event = gtk_window_focus_in_event;
388 widget_class->focus_out_event = gtk_window_focus_out_event;
389 widget_class->client_event = gtk_window_client_event;
390 widget_class->focus = gtk_window_focus;
392 widget_class->expose_event = gtk_window_expose;
394 container_class->check_resize = gtk_window_check_resize;
396 klass->set_focus = gtk_window_real_set_focus;
397 klass->frame_event = gtk_window_frame_event;
399 klass->activate_default = gtk_window_real_activate_default;
400 klass->activate_focus = gtk_window_real_activate_focus;
401 klass->move_focus = gtk_window_move_focus;
402 klass->keys_changed = gtk_window_keys_changed;
404 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
407 g_object_class_install_property (gobject_class,
409 g_param_spec_enum ("type",
411 P_("The type of the window"),
412 GTK_TYPE_WINDOW_TYPE,
414 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
416 g_object_class_install_property (gobject_class,
418 g_param_spec_string ("title",
420 P_("The title of the window"),
422 GTK_PARAM_READWRITE));
424 g_object_class_install_property (gobject_class,
426 g_param_spec_string ("role",
428 P_("Unique identifier for the window to be used when restoring a session"),
430 GTK_PARAM_READWRITE));
432 g_object_class_install_property (gobject_class,
434 g_param_spec_boolean ("allow-shrink",
436 /* xgettext:no-c-format */
437 P_("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
439 GTK_PARAM_READWRITE));
441 g_object_class_install_property (gobject_class,
443 g_param_spec_boolean ("allow-grow",
445 P_("If TRUE, users can expand the window beyond its minimum size"),
447 GTK_PARAM_READWRITE));
449 g_object_class_install_property (gobject_class,
451 g_param_spec_boolean ("resizable",
453 P_("If TRUE, users can resize the window"),
455 GTK_PARAM_READWRITE));
457 g_object_class_install_property (gobject_class,
459 g_param_spec_boolean ("modal",
461 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
463 GTK_PARAM_READWRITE));
465 g_object_class_install_property (gobject_class,
467 g_param_spec_enum ("window-position",
468 P_("Window Position"),
469 P_("The initial position of the window"),
470 GTK_TYPE_WINDOW_POSITION,
472 GTK_PARAM_READWRITE));
474 g_object_class_install_property (gobject_class,
476 g_param_spec_int ("default-width",
478 P_("The default width of the window, used when initially showing the window"),
482 GTK_PARAM_READWRITE));
484 g_object_class_install_property (gobject_class,
486 g_param_spec_int ("default-height",
487 P_("Default Height"),
488 P_("The default height of the window, used when initially showing the window"),
492 GTK_PARAM_READWRITE));
494 g_object_class_install_property (gobject_class,
495 PROP_DESTROY_WITH_PARENT,
496 g_param_spec_boolean ("destroy-with-parent",
497 P_("Destroy with Parent"),
498 P_("If this window should be destroyed when the parent is destroyed"),
500 GTK_PARAM_READWRITE));
502 g_object_class_install_property (gobject_class,
504 g_param_spec_object ("icon",
506 P_("Icon for this window"),
508 GTK_PARAM_READWRITE));
511 * GtkWindow:icon-name:
513 * The :icon-name property specifies the name of the themed icon to
514 * use as the window icon. See #GtkIconTheme for more details.
518 g_object_class_install_property (gobject_class,
520 g_param_spec_string ("icon-name",
522 P_("Name of the themed icon for this window"),
524 GTK_PARAM_READWRITE));
526 g_object_class_install_property (gobject_class,
528 g_param_spec_object ("screen",
530 P_("The screen where this window will be displayed"),
532 GTK_PARAM_READWRITE));
534 g_object_class_install_property (gobject_class,
536 g_param_spec_boolean ("is-active",
538 P_("Whether the toplevel is the current active window"),
540 GTK_PARAM_READABLE));
542 g_object_class_install_property (gobject_class,
543 PROP_HAS_TOPLEVEL_FOCUS,
544 g_param_spec_boolean ("has-toplevel-focus",
545 P_("Focus in Toplevel"),
546 P_("Whether the input focus is within this GtkWindow"),
548 GTK_PARAM_READABLE));
550 g_object_class_install_property (gobject_class,
552 g_param_spec_enum ("type-hint",
554 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
555 GDK_TYPE_WINDOW_TYPE_HINT,
556 GDK_WINDOW_TYPE_HINT_NORMAL,
557 GTK_PARAM_READWRITE));
559 g_object_class_install_property (gobject_class,
560 PROP_SKIP_TASKBAR_HINT,
561 g_param_spec_boolean ("skip-taskbar-hint",
563 P_("TRUE if the window should not be in the task bar."),
565 GTK_PARAM_READWRITE));
567 g_object_class_install_property (gobject_class,
568 PROP_SKIP_PAGER_HINT,
569 g_param_spec_boolean ("skip-pager-hint",
571 P_("TRUE if the window should not be in the pager."),
573 GTK_PARAM_READWRITE));
575 g_object_class_install_property (gobject_class,
577 g_param_spec_boolean ("urgency-hint",
579 P_("TRUE if the window should be brought to the user's attention."),
581 GTK_PARAM_READWRITE));
584 * GtkWindow:accept-focus-hint:
586 * Whether the window should receive the input focus.
590 g_object_class_install_property (gobject_class,
592 g_param_spec_boolean ("accept-focus",
594 P_("TRUE if the window should receive the input focus."),
596 GTK_PARAM_READWRITE));
599 * GtkWindow:focus-on-map-hint:
601 * Whether the window should receive the input focus when mapped.
605 g_object_class_install_property (gobject_class,
607 g_param_spec_boolean ("focus-on-map",
609 P_("TRUE if the window should receive the input focus when mapped."),
611 GTK_PARAM_READWRITE));
614 * GtkWindow:decorated:
616 * Whether the window should be decorated by the window manager.
620 g_object_class_install_property (gobject_class,
622 g_param_spec_boolean ("decorated",
624 P_("Whether the window should be decorated by the window manager"),
626 GTK_PARAM_READWRITE));
629 * GtkWindow:deletable:
631 * Whether the window frame should have a close button.
635 g_object_class_install_property (gobject_class,
637 g_param_spec_boolean ("deletable",
639 P_("Whether the window frame should have a close button"),
641 GTK_PARAM_READWRITE));
647 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
648 * more details about window gravity.
652 g_object_class_install_property (gobject_class,
654 g_param_spec_enum ("gravity",
656 P_("The window gravity of the window"),
658 GDK_GRAVITY_NORTH_WEST,
659 GTK_PARAM_READWRITE));
663 * GtkWindow:transient-for:
665 * The transient parent of the window. See gtk_window_set_transient_for() for
666 * more details about transient windows.
670 g_object_class_install_property (gobject_class,
672 g_param_spec_object ("transient-for",
673 P_("Transient for Window"),
674 P_("The transient parent of the dialog"),
676 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
678 window_signals[SET_FOCUS] =
679 g_signal_new (I_("set_focus"),
680 G_TYPE_FROM_CLASS (gobject_class),
682 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
684 _gtk_marshal_VOID__OBJECT,
688 window_signals[FRAME_EVENT] =
689 g_signal_new (I_("frame_event"),
690 G_TYPE_FROM_CLASS (gobject_class),
692 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
693 _gtk_boolean_handled_accumulator, NULL,
694 _gtk_marshal_BOOLEAN__BOXED,
698 window_signals[ACTIVATE_FOCUS] =
699 g_signal_new (I_("activate_focus"),
700 G_TYPE_FROM_CLASS (gobject_class),
701 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
702 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
704 _gtk_marshal_VOID__VOID,
708 window_signals[ACTIVATE_DEFAULT] =
709 g_signal_new (I_("activate_default"),
710 G_TYPE_FROM_CLASS (gobject_class),
711 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
712 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
714 _gtk_marshal_VOID__VOID,
718 window_signals[MOVE_FOCUS] =
719 g_signal_new (I_("move_focus"),
720 G_TYPE_FROM_CLASS (gobject_class),
721 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
722 G_STRUCT_OFFSET (GtkWindowClass, move_focus),
724 _gtk_marshal_VOID__ENUM,
727 GTK_TYPE_DIRECTION_TYPE);
729 window_signals[KEYS_CHANGED] =
730 g_signal_new (I_("keys_changed"),
731 G_TYPE_FROM_CLASS (gobject_class),
733 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
735 _gtk_marshal_VOID__VOID,
743 binding_set = gtk_binding_set_by_class (klass);
745 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
746 "activate_focus", 0);
747 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
748 "activate_focus", 0);
750 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
751 "activate_default", 0);
753 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
754 "activate_default", 0);
756 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
757 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
758 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
759 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
761 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
762 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
763 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
764 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
768 gtk_window_init (GtkWindow *window)
770 GdkColormap *colormap;
771 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
773 GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
774 GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
776 GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
778 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
780 window->title = NULL;
781 window->wmclass_name = g_strdup (g_get_prgname ());
782 window->wmclass_class = g_strdup (gdk_get_program_class ());
783 window->wm_role = NULL;
784 window->geometry_info = NULL;
785 window->type = GTK_WINDOW_TOPLEVEL;
786 window->focus_widget = NULL;
787 window->default_widget = NULL;
788 window->configure_request_count = 0;
789 window->allow_shrink = FALSE;
790 window->allow_grow = TRUE;
791 window->configure_notify_received = FALSE;
792 window->position = GTK_WIN_POS_NONE;
793 window->need_default_size = TRUE;
794 window->need_default_position = TRUE;
795 window->modal = FALSE;
796 window->frame = NULL;
797 window->has_frame = FALSE;
798 window->frame_left = 0;
799 window->frame_right = 0;
800 window->frame_top = 0;
801 window->frame_bottom = 0;
802 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
803 window->gravity = GDK_GRAVITY_NORTH_WEST;
804 window->decorated = TRUE;
805 window->mnemonic_modifier = GDK_MOD1_MASK;
806 window->screen = gdk_screen_get_default ();
808 priv->accept_focus = TRUE;
809 priv->focus_on_map = TRUE;
810 priv->deletable = TRUE;
811 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
813 colormap = _gtk_widget_peek_colormap ();
815 gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
817 g_object_ref_sink (window);
818 window->has_user_ref_count = TRUE;
819 toplevel_list = g_slist_prepend (toplevel_list, window);
821 gtk_decorated_window_init (window);
823 g_signal_connect (window->screen, "composited_changed",
824 G_CALLBACK (gtk_window_on_composited_changed), window);
828 gtk_window_set_property (GObject *object,
835 window = GTK_WINDOW (object);
840 window->type = g_value_get_enum (value);
843 gtk_window_set_title (window, g_value_get_string (value));
846 gtk_window_set_role (window, g_value_get_string (value));
848 case PROP_ALLOW_SHRINK:
849 window->allow_shrink = g_value_get_boolean (value);
850 gtk_widget_queue_resize (GTK_WIDGET (window));
852 case PROP_ALLOW_GROW:
853 window->allow_grow = g_value_get_boolean (value);
854 gtk_widget_queue_resize (GTK_WIDGET (window));
855 g_object_notify (G_OBJECT (window), "resizable");
858 window->allow_grow = g_value_get_boolean (value);
859 gtk_widget_queue_resize (GTK_WIDGET (window));
860 g_object_notify (G_OBJECT (window), "allow-grow");
863 gtk_window_set_modal (window, g_value_get_boolean (value));
866 gtk_window_set_position (window, g_value_get_enum (value));
868 case PROP_DEFAULT_WIDTH:
869 gtk_window_set_default_size_internal (window,
870 TRUE, g_value_get_int (value),
873 case PROP_DEFAULT_HEIGHT:
874 gtk_window_set_default_size_internal (window,
876 TRUE, g_value_get_int (value), FALSE);
878 case PROP_DESTROY_WITH_PARENT:
879 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
882 gtk_window_set_icon (window,
883 g_value_get_object (value));
886 gtk_window_set_icon_name (window, g_value_get_string (value));
889 gtk_window_set_screen (window, g_value_get_object (value));
892 gtk_window_set_type_hint (window,
893 g_value_get_enum (value));
895 case PROP_SKIP_TASKBAR_HINT:
896 gtk_window_set_skip_taskbar_hint (window,
897 g_value_get_boolean (value));
899 case PROP_SKIP_PAGER_HINT:
900 gtk_window_set_skip_pager_hint (window,
901 g_value_get_boolean (value));
903 case PROP_URGENCY_HINT:
904 gtk_window_set_urgency_hint (window,
905 g_value_get_boolean (value));
907 case PROP_ACCEPT_FOCUS:
908 gtk_window_set_accept_focus (window,
909 g_value_get_boolean (value));
911 case PROP_FOCUS_ON_MAP:
912 gtk_window_set_focus_on_map (window,
913 g_value_get_boolean (value));
916 gtk_window_set_decorated (window, g_value_get_boolean (value));
919 gtk_window_set_deletable (window, g_value_get_boolean (value));
922 gtk_window_set_gravity (window, g_value_get_enum (value));
924 case PROP_TRANSIENT_FOR:
925 gtk_window_set_transient_for (window, g_value_get_object (value));
933 gtk_window_get_property (GObject *object,
939 GtkWindowPrivate *priv;
941 window = GTK_WINDOW (object);
942 priv = GTK_WINDOW_GET_PRIVATE (window);
946 GtkWindowGeometryInfo *info;
948 g_value_set_enum (value, window->type);
951 g_value_set_string (value, window->wm_role);
954 g_value_set_string (value, window->title);
956 case PROP_ALLOW_SHRINK:
957 g_value_set_boolean (value, window->allow_shrink);
959 case PROP_ALLOW_GROW:
960 g_value_set_boolean (value, window->allow_grow);
963 g_value_set_boolean (value, window->allow_grow);
966 g_value_set_boolean (value, window->modal);
969 g_value_set_enum (value, window->position);
971 case PROP_DEFAULT_WIDTH:
972 info = gtk_window_get_geometry_info (window, FALSE);
974 g_value_set_int (value, -1);
976 g_value_set_int (value, info->default_width);
978 case PROP_DEFAULT_HEIGHT:
979 info = gtk_window_get_geometry_info (window, FALSE);
981 g_value_set_int (value, -1);
983 g_value_set_int (value, info->default_height);
985 case PROP_DESTROY_WITH_PARENT:
986 g_value_set_boolean (value, window->destroy_with_parent);
989 g_value_set_object (value, gtk_window_get_icon (window));
992 g_value_set_string (value, gtk_window_get_icon_name (window));
995 g_value_set_object (value, window->screen);
998 g_value_set_boolean (value, window->is_active);
1000 case PROP_HAS_TOPLEVEL_FOCUS:
1001 g_value_set_boolean (value, window->has_toplevel_focus);
1003 case PROP_TYPE_HINT:
1004 g_value_set_enum (value, priv->type_hint);
1006 case PROP_SKIP_TASKBAR_HINT:
1007 g_value_set_boolean (value,
1008 gtk_window_get_skip_taskbar_hint (window));
1010 case PROP_SKIP_PAGER_HINT:
1011 g_value_set_boolean (value,
1012 gtk_window_get_skip_pager_hint (window));
1014 case PROP_URGENCY_HINT:
1015 g_value_set_boolean (value,
1016 gtk_window_get_urgency_hint (window));
1018 case PROP_ACCEPT_FOCUS:
1019 g_value_set_boolean (value,
1020 gtk_window_get_accept_focus (window));
1022 case PROP_FOCUS_ON_MAP:
1023 g_value_set_boolean (value,
1024 gtk_window_get_focus_on_map (window));
1026 case PROP_DECORATED:
1027 g_value_set_boolean (value, gtk_window_get_decorated (window));
1029 case PROP_DELETABLE:
1030 g_value_set_boolean (value, gtk_window_get_deletable (window));
1033 g_value_set_enum (value, gtk_window_get_gravity (window));
1035 case PROP_TRANSIENT_FOR:
1036 g_value_set_object (value, gtk_window_get_transient_for (window));
1039 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1046 * @type: type of window
1048 * Creates a new #GtkWindow, which is a toplevel window that can
1049 * contain other widgets. Nearly always, the type of the window should
1050 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1051 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1052 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1053 * dialogs, though in some other toolkits dialogs are called "popups".
1054 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1055 * On X11, popup windows are not controlled by the <link
1056 * linkend="gtk-X11-arch">window manager</link>.
1058 * If you simply want an undecorated window (no window borders), use
1059 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1061 * Return value: a new #GtkWindow.
1064 gtk_window_new (GtkWindowType type)
1068 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1070 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1072 window->type = type;
1074 return GTK_WIDGET (window);
1078 * gtk_window_set_title:
1079 * @window: a #GtkWindow
1080 * @title: title of the window
1082 * Sets the title of the #GtkWindow. The title of a window will be
1083 * displayed in its title bar; on the X Window System, the title bar
1084 * is rendered by the <link linkend="gtk-X11-arch">window
1085 * manager</link>, so exactly how the title appears to users may vary
1086 * according to a user's exact configuration. The title should help a
1087 * user distinguish this window from other windows they may have
1088 * open. A good title might include the application name and current
1089 * document filename, for example.
1093 gtk_window_set_title (GtkWindow *window,
1098 g_return_if_fail (GTK_IS_WINDOW (window));
1100 new_title = g_strdup (title);
1101 g_free (window->title);
1102 window->title = new_title;
1104 if (GTK_WIDGET_REALIZED (window))
1106 gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
1108 gtk_decorated_window_set_title (window, title);
1111 g_object_notify (G_OBJECT (window), "title");
1115 * gtk_window_get_title:
1116 * @window: a #GtkWindow
1118 * Retrieves the title of the window. See gtk_window_set_title().
1120 * Return value: the title of the window, or %NULL if none has
1121 * been set explicitely. The returned string is owned by the widget
1122 * and must not be modified or freed.
1124 G_CONST_RETURN gchar *
1125 gtk_window_get_title (GtkWindow *window)
1127 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1129 return window->title;
1133 * gtk_window_set_wmclass:
1134 * @window: a #GtkWindow
1135 * @wmclass_name: window name hint
1136 * @wmclass_class: window class hint
1138 * Don't use this function. It sets the X Window System "class" and
1139 * "name" hints for a window. According to the ICCCM, you should
1140 * always set these to the same value for all windows in an
1141 * application, and GTK+ sets them to that value by default, so calling
1142 * this function is sort of pointless. However, you may want to call
1143 * gtk_window_set_role() on each window in your application, for the
1144 * benefit of the session manager. Setting the role allows the window
1145 * manager to restore window positions when loading a saved session.
1149 gtk_window_set_wmclass (GtkWindow *window,
1150 const gchar *wmclass_name,
1151 const gchar *wmclass_class)
1153 g_return_if_fail (GTK_IS_WINDOW (window));
1155 g_free (window->wmclass_name);
1156 window->wmclass_name = g_strdup (wmclass_name);
1158 g_free (window->wmclass_class);
1159 window->wmclass_class = g_strdup (wmclass_class);
1161 if (GTK_WIDGET_REALIZED (window))
1162 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1166 * gtk_window_set_role:
1167 * @window: a #GtkWindow
1168 * @role: unique identifier for the window to be used when restoring a session
1170 * This function is only useful on X11, not with other GTK+ targets.
1172 * In combination with the window title, the window role allows a
1173 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1174 * same" window when an application is restarted. So for example you
1175 * might set the "toolbox" role on your app's toolbox window, so that
1176 * when the user restarts their session, the window manager can put
1177 * the toolbox back in the same place.
1179 * If a window already has a unique title, you don't need to set the
1180 * role, since the WM can use the title to identify the window when
1181 * restoring the session.
1185 gtk_window_set_role (GtkWindow *window,
1190 g_return_if_fail (GTK_IS_WINDOW (window));
1192 new_role = g_strdup (role);
1193 g_free (window->wm_role);
1194 window->wm_role = new_role;
1196 if (GTK_WIDGET_REALIZED (window))
1197 gdk_window_set_role (GTK_WIDGET (window)->window, window->wm_role);
1199 g_object_notify (G_OBJECT (window), "role");
1203 * gtk_window_get_role:
1204 * @window: a #GtkWindow
1206 * Returns the role of the window. See gtk_window_set_role() for
1207 * further explanation.
1209 * Return value: the role of the window if set, or %NULL. The
1210 * returned is owned by the widget and must not be modified
1213 G_CONST_RETURN gchar *
1214 gtk_window_get_role (GtkWindow *window)
1216 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1218 return window->wm_role;
1222 * gtk_window_set_focus:
1223 * @window: a #GtkWindow
1224 * @focus: widget to be the new focus widget, or %NULL to unset
1225 * any focus widget for the toplevel window.
1227 * If @focus is not the current focus widget, and is focusable, sets
1228 * it as the focus widget for the window. If @focus is %NULL, unsets
1229 * the focus widget for this window. To set the focus to a particular
1230 * widget in the toplevel, it is usually more convenient to use
1231 * gtk_widget_grab_focus() instead of this function.
1234 gtk_window_set_focus (GtkWindow *window,
1237 g_return_if_fail (GTK_IS_WINDOW (window));
1240 g_return_if_fail (GTK_IS_WIDGET (focus));
1241 g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1245 gtk_widget_grab_focus (focus);
1248 /* Clear the existing focus chain, so that when we focus into
1249 * the window again, we start at the beginnning.
1251 GtkWidget *widget = window->focus_widget;
1254 while (widget->parent)
1256 widget = widget->parent;
1257 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1261 _gtk_window_internal_set_focus (window, NULL);
1266 _gtk_window_internal_set_focus (GtkWindow *window,
1269 g_return_if_fail (GTK_IS_WINDOW (window));
1271 if ((window->focus_widget != focus) ||
1272 (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1273 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1277 * gtk_window_set_default:
1278 * @window: a #GtkWindow
1279 * @default_widget: widget to be the default, or %NULL to unset the
1280 * default widget for the toplevel.
1282 * The default widget is the widget that's activated when the user
1283 * presses Enter in a dialog (for example). This function sets or
1284 * unsets the default widget for a #GtkWindow about. When setting
1285 * (rather than unsetting) the default widget it's generally easier to
1286 * call gtk_widget_grab_focus() on the widget. Before making a widget
1287 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1288 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1291 gtk_window_set_default (GtkWindow *window,
1292 GtkWidget *default_widget)
1294 g_return_if_fail (GTK_IS_WINDOW (window));
1297 g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1299 if (window->default_widget != default_widget)
1301 GtkWidget *old_default_widget = NULL;
1304 g_object_ref (default_widget);
1306 if (window->default_widget)
1308 old_default_widget = window->default_widget;
1310 if (window->focus_widget != window->default_widget ||
1311 !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1312 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1313 gtk_widget_queue_draw (window->default_widget);
1316 window->default_widget = default_widget;
1318 if (window->default_widget)
1320 if (window->focus_widget == NULL ||
1321 !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1322 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1323 gtk_widget_queue_draw (window->default_widget);
1326 if (old_default_widget)
1327 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1331 g_object_notify (G_OBJECT (default_widget), "has-default");
1332 g_object_unref (default_widget);
1338 gtk_window_set_policy (GtkWindow *window,
1339 gboolean allow_shrink,
1340 gboolean allow_grow,
1341 gboolean auto_shrink)
1343 g_return_if_fail (GTK_IS_WINDOW (window));
1345 window->allow_shrink = (allow_shrink != FALSE);
1346 window->allow_grow = (allow_grow != FALSE);
1348 g_object_freeze_notify (G_OBJECT (window));
1349 g_object_notify (G_OBJECT (window), "allow-shrink");
1350 g_object_notify (G_OBJECT (window), "allow-grow");
1351 g_object_notify (G_OBJECT (window), "resizable");
1352 g_object_thaw_notify (G_OBJECT (window));
1354 gtk_widget_queue_resize (GTK_WIDGET (window));
1358 handle_keys_changed (gpointer data)
1362 GDK_THREADS_ENTER ();
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);
1372 GDK_THREADS_LEAVE ();
1378 gtk_window_notify_keys_changed (GtkWindow *window)
1380 if (!window->keys_changed_handler)
1381 window->keys_changed_handler = g_idle_add (handle_keys_changed, window);
1385 * gtk_window_add_accel_group:
1386 * @window: window to attach accelerator group to
1387 * @accel_group: a #GtkAccelGroup
1389 * Associate @accel_group with @window, such that calling
1390 * gtk_accel_groups_activate() on @window will activate accelerators
1394 gtk_window_add_accel_group (GtkWindow *window,
1395 GtkAccelGroup *accel_group)
1397 g_return_if_fail (GTK_IS_WINDOW (window));
1398 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1400 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1401 g_signal_connect_object (accel_group, "accel_changed",
1402 G_CALLBACK (gtk_window_notify_keys_changed),
1403 window, G_CONNECT_SWAPPED);
1407 * gtk_window_remove_accel_group:
1408 * @window: a #GtkWindow
1409 * @accel_group: a #GtkAccelGroup
1411 * Reverses the effects of gtk_window_add_accel_group().
1414 gtk_window_remove_accel_group (GtkWindow *window,
1415 GtkAccelGroup *accel_group)
1417 g_return_if_fail (GTK_IS_WINDOW (window));
1418 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1420 g_signal_handlers_disconnect_by_func (accel_group,
1421 gtk_window_notify_keys_changed,
1423 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1426 static GtkMnemonicHash *
1427 gtk_window_get_mnemonic_hash (GtkWindow *window,
1430 GtkWindowPrivate *private = GTK_WINDOW_GET_PRIVATE (window);
1431 if (!private->mnemonic_hash && create)
1432 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1434 return private->mnemonic_hash;
1438 * gtk_window_add_mnemonic:
1439 * @window: a #GtkWindow
1440 * @keyval: the mnemonic
1441 * @target: the widget that gets activated by the mnemonic
1443 * Adds a mnemonic to this window.
1446 gtk_window_add_mnemonic (GtkWindow *window,
1450 g_return_if_fail (GTK_IS_WINDOW (window));
1451 g_return_if_fail (GTK_IS_WIDGET (target));
1453 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1455 gtk_window_notify_keys_changed (window);
1459 * gtk_window_remove_mnemonic:
1460 * @window: a #GtkWindow
1461 * @keyval: the mnemonic
1462 * @target: the widget that gets activated by the mnemonic
1464 * Removes a mnemonic from this window.
1467 gtk_window_remove_mnemonic (GtkWindow *window,
1471 g_return_if_fail (GTK_IS_WINDOW (window));
1472 g_return_if_fail (GTK_IS_WIDGET (target));
1474 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
1476 gtk_window_notify_keys_changed (window);
1480 * gtk_window_mnemonic_activate:
1481 * @window: a #GtkWindow
1482 * @keyval: the mnemonic
1483 * @modifier: the modifiers
1484 * @returns: %TRUE if the activation is done.
1486 * Activates the targets associated with the mnemonic.
1489 gtk_window_mnemonic_activate (GtkWindow *window,
1491 GdkModifierType modifier)
1493 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1495 if (window->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
1497 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
1499 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
1506 * gtk_window_set_mnemonic_modifier:
1507 * @window: a #GtkWindow
1508 * @modifier: the modifier mask used to activate
1509 * mnemonics on this window.
1511 * Sets the mnemonic modifier for this window.
1514 gtk_window_set_mnemonic_modifier (GtkWindow *window,
1515 GdkModifierType modifier)
1517 g_return_if_fail (GTK_IS_WINDOW (window));
1518 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1520 window->mnemonic_modifier = modifier;
1521 gtk_window_notify_keys_changed (window);
1525 * gtk_window_get_mnemonic_modifier:
1526 * @window: a #GtkWindow
1528 * Returns the mnemonic modifier for this window. See
1529 * gtk_window_set_mnemonic_modifier().
1531 * Return value: the modifier mask used to activate
1532 * mnemonics on this window.
1535 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1537 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1539 return window->mnemonic_modifier;
1543 * gtk_window_set_position:
1544 * @window: a #GtkWindow.
1545 * @position: a position constraint.
1547 * Sets a position constraint for this window. If the old or new
1548 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1549 * the window to be repositioned to satisfy the new constraint.
1552 gtk_window_set_position (GtkWindow *window,
1553 GtkWindowPosition position)
1555 g_return_if_fail (GTK_IS_WINDOW (window));
1557 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1558 window->position == GTK_WIN_POS_CENTER_ALWAYS)
1560 GtkWindowGeometryInfo *info;
1562 info = gtk_window_get_geometry_info (window, TRUE);
1564 /* this flag causes us to re-request the CENTER_ALWAYS
1565 * constraint in gtk_window_move_resize(), see
1566 * comment in that function.
1568 info->position_constraints_changed = TRUE;
1570 gtk_widget_queue_resize (GTK_WIDGET (window));
1573 window->position = position;
1575 g_object_notify (G_OBJECT (window), "window-position");
1579 * gtk_window_activate_focus:
1580 * @window: a #GtkWindow
1582 * Activates the current focused widget within the window.
1584 * Return value: %TRUE if a widget got activated.
1587 gtk_window_activate_focus (GtkWindow *window)
1589 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1591 if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1592 return gtk_widget_activate (window->focus_widget);
1598 * gtk_window_get_focus:
1599 * @window: a #GtkWindow
1601 * Retrieves the current focused widget within the window.
1602 * Note that this is the widget that would have the focus
1603 * if the toplevel window focused; if the toplevel window
1604 * is not focused then <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1605 * not be %TRUE for the widget.
1607 * Return value: the currently focused widget, or %NULL if there is none.
1610 gtk_window_get_focus (GtkWindow *window)
1612 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1614 return window->focus_widget;
1618 * gtk_window_activate_default:
1619 * @window: a #GtkWindow
1621 * Activates the default widget for the window, unless the current
1622 * focused widget has been configured to receive the default action
1623 * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
1624 * focused widget is activated.
1626 * Return value: %TRUE if a widget got activated.
1629 gtk_window_activate_default (GtkWindow *window)
1631 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1633 if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1634 (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1635 return gtk_widget_activate (window->default_widget);
1636 else if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1637 return gtk_widget_activate (window->focus_widget);
1643 * gtk_window_set_modal:
1644 * @window: a #GtkWindow
1645 * @modal: whether the window is modal
1647 * Sets a window modal or non-modal. Modal windows prevent interaction
1648 * with other windows in the same application. To keep modal dialogs
1649 * on top of main application windows, use
1650 * gtk_window_set_transient_for() to make the dialog transient for the
1651 * parent; most <link linkend="gtk-X11-arch">window managers</link>
1652 * will then disallow lowering the dialog below the parent.
1657 gtk_window_set_modal (GtkWindow *window,
1660 g_return_if_fail (GTK_IS_WINDOW (window));
1662 modal = modal != FALSE;
1663 if (window->modal == modal)
1666 window->modal = modal;
1668 /* adjust desired modality state */
1669 if (GTK_WIDGET_REALIZED (window))
1671 GtkWidget *widget = GTK_WIDGET (window);
1674 gdk_window_set_modal_hint (widget->window, TRUE);
1676 gdk_window_set_modal_hint (widget->window, FALSE);
1679 if (GTK_WIDGET_VISIBLE (window))
1682 gtk_grab_add (GTK_WIDGET (window));
1684 gtk_grab_remove (GTK_WIDGET (window));
1687 g_object_notify (G_OBJECT (window), "modal");
1691 * gtk_window_get_modal:
1692 * @window: a #GtkWindow
1694 * Returns whether the window is modal. See gtk_window_set_modal().
1696 * Return value: %TRUE if the window is set to be modal and
1697 * establishes a grab when shown
1700 gtk_window_get_modal (GtkWindow *window)
1702 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1704 return window->modal;
1708 * gtk_window_list_toplevels:
1710 * Returns a list of all existing toplevel windows. The widgets
1711 * in the list are not individually referenced. If you want
1712 * to iterate through the list and perform actions involving
1713 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1714 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1715 * then unref all the widgets afterwards.
1717 * Return value: list of toplevel widgets
1720 gtk_window_list_toplevels (void)
1725 for (slist = toplevel_list; slist; slist = slist->next)
1726 list = g_list_prepend (list, slist->data);
1732 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1734 GList *embedded_windows;
1736 g_return_if_fail (GTK_IS_WINDOW (window));
1738 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
1739 if (embedded_windows)
1740 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
1741 embedded_windows = g_list_prepend (embedded_windows,
1742 GUINT_TO_POINTER (xid));
1744 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
1747 (GDestroyNotify) g_list_free : NULL);
1751 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1753 GList *embedded_windows;
1756 g_return_if_fail (GTK_IS_WINDOW (window));
1758 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
1759 if (embedded_windows)
1760 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
1762 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1765 embedded_windows = g_list_remove_link (embedded_windows, node);
1766 g_list_free_1 (node);
1769 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
1772 (GDestroyNotify) g_list_free : NULL);
1776 _gtk_window_reposition (GtkWindow *window,
1780 g_return_if_fail (GTK_IS_WINDOW (window));
1782 gtk_window_move (window, x, y);
1786 gtk_window_dispose (GObject *object)
1788 GtkWindow *window = GTK_WINDOW (object);
1790 gtk_window_set_focus (window, NULL);
1791 gtk_window_set_default (window, NULL);
1793 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
1797 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1799 gtk_widget_destroy (GTK_WIDGET (child));
1803 connect_parent_destroyed (GtkWindow *window)
1805 if (window->transient_parent)
1807 g_signal_connect (window->transient_parent,
1809 G_CALLBACK (parent_destroyed_callback),
1815 disconnect_parent_destroyed (GtkWindow *window)
1817 if (window->transient_parent)
1819 g_signal_handlers_disconnect_by_func (window->transient_parent,
1820 parent_destroyed_callback,
1826 gtk_window_transient_parent_realized (GtkWidget *parent,
1829 if (GTK_WIDGET_REALIZED (window))
1830 gdk_window_set_transient_for (window->window, parent->window);
1834 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1837 if (GTK_WIDGET_REALIZED (window))
1838 gdk_property_delete (window->window,
1839 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
1843 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
1847 gtk_window_set_screen (window, parent->screen);
1851 gtk_window_unset_transient_for (GtkWindow *window)
1853 if (window->transient_parent)
1855 if (window->transient_parent->group)
1856 gtk_window_group_remove_window (window->transient_parent->group,
1859 g_signal_handlers_disconnect_by_func (window->transient_parent,
1860 gtk_window_transient_parent_realized,
1862 g_signal_handlers_disconnect_by_func (window->transient_parent,
1863 gtk_window_transient_parent_unrealized,
1865 g_signal_handlers_disconnect_by_func (window->transient_parent,
1866 gtk_window_transient_parent_screen_changed,
1868 g_signal_handlers_disconnect_by_func (window->transient_parent,
1869 gtk_widget_destroyed,
1870 &window->transient_parent);
1872 if (window->destroy_with_parent)
1873 disconnect_parent_destroyed (window);
1875 window->transient_parent = NULL;
1880 * gtk_window_set_transient_for:
1881 * @window: a #GtkWindow
1882 * @parent: parent window
1884 * Dialog windows should be set transient for the main application
1885 * window they were spawned from. This allows <link
1886 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1887 * dialog on top of the main window, or center the dialog over the
1888 * main window. gtk_dialog_new_with_buttons() and other convenience
1889 * functions in GTK+ will sometimes call
1890 * gtk_window_set_transient_for() on your behalf.
1892 * On Windows, this function will and put the child window
1893 * on top of the parent, much as the window manager would have
1898 gtk_window_set_transient_for (GtkWindow *window,
1901 g_return_if_fail (GTK_IS_WINDOW (window));
1902 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1903 g_return_if_fail (window != parent);
1905 if (window->transient_parent)
1907 if (GTK_WIDGET_REALIZED (window) &&
1908 GTK_WIDGET_REALIZED (window->transient_parent) &&
1909 (!parent || !GTK_WIDGET_REALIZED (parent)))
1910 gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1911 GTK_WIDGET (window));
1913 gtk_window_unset_transient_for (window);
1916 window->transient_parent = parent;
1920 g_signal_connect (parent, "destroy",
1921 G_CALLBACK (gtk_widget_destroyed),
1922 &window->transient_parent);
1923 g_signal_connect (parent, "realize",
1924 G_CALLBACK (gtk_window_transient_parent_realized),
1926 g_signal_connect (parent, "unrealize",
1927 G_CALLBACK (gtk_window_transient_parent_unrealized),
1929 g_signal_connect (parent, "notify::screen",
1930 G_CALLBACK (gtk_window_transient_parent_screen_changed),
1933 gtk_window_set_screen (window, parent->screen);
1935 if (window->destroy_with_parent)
1936 connect_parent_destroyed (window);
1938 if (GTK_WIDGET_REALIZED (window) &&
1939 GTK_WIDGET_REALIZED (parent))
1940 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1941 GTK_WIDGET (window));
1944 gtk_window_group_add_window (parent->group, window);
1949 * gtk_window_get_transient_for:
1950 * @window: a #GtkWindow
1952 * Fetches the transient parent for this window. See
1953 * gtk_window_set_transient_for().
1955 * Return value: the transient parent for this window, or %NULL
1956 * if no transient parent has been set.
1959 gtk_window_get_transient_for (GtkWindow *window)
1961 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1963 return window->transient_parent;
1967 * gtk_window_set_type_hint:
1968 * @window: a #GtkWindow
1969 * @hint: the window type
1971 * By setting the type hint for the window, you allow the window
1972 * manager to decorate and handle the window in a way which is
1973 * suitable to the function of the window in your application.
1975 * This function should be called before the window becomes visible.
1977 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1978 * will sometimes call gtk_window_set_type_hint() on your behalf.
1982 gtk_window_set_type_hint (GtkWindow *window,
1983 GdkWindowTypeHint hint)
1985 GtkWindowPrivate *priv;
1987 g_return_if_fail (GTK_IS_WINDOW (window));
1988 g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1990 priv = GTK_WINDOW_GET_PRIVATE (window);
1992 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
1993 window->type_hint = hint;
1995 window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1997 priv->reset_type_hint = TRUE;
1998 priv->type_hint = hint;
2002 * gtk_window_get_type_hint:
2003 * @window: a #GtkWindow
2005 * Gets the type hint for this window. See gtk_window_set_type_hint().
2007 * Return value: the type hint for @window.
2010 gtk_window_get_type_hint (GtkWindow *window)
2012 GtkWindowPrivate *priv;
2014 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2016 priv = GTK_WINDOW_GET_PRIVATE (window);
2018 return priv->type_hint;
2022 * gtk_window_set_skip_taskbar_hint:
2023 * @window: a #GtkWindow
2024 * @setting: %TRUE to keep this window from appearing in the task bar
2026 * Windows may set a hint asking the desktop environment not to display
2027 * the window in the task bar. This function sets this hint.
2032 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2035 GtkWindowPrivate *priv;
2037 g_return_if_fail (GTK_IS_WINDOW (window));
2039 priv = GTK_WINDOW_GET_PRIVATE (window);
2041 setting = setting != FALSE;
2043 if (priv->skips_taskbar != setting)
2045 priv->skips_taskbar = setting;
2046 if (GTK_WIDGET_REALIZED (window))
2047 gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
2048 priv->skips_taskbar);
2049 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2054 * gtk_window_get_skip_taskbar_hint:
2055 * @window: a #GtkWindow
2057 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2059 * Return value: %TRUE if window shouldn't be in taskbar
2064 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2066 GtkWindowPrivate *priv;
2068 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2070 priv = GTK_WINDOW_GET_PRIVATE (window);
2072 return priv->skips_taskbar;
2076 * gtk_window_set_skip_pager_hint:
2077 * @window: a #GtkWindow
2078 * @setting: %TRUE to keep this window from appearing in the pager
2080 * Windows may set a hint asking the desktop environment not to display
2081 * the window in the pager. This function sets this hint.
2082 * (A "pager" is any desktop navigation tool such as a workspace
2083 * switcher that displays a thumbnail representation of the windows
2089 gtk_window_set_skip_pager_hint (GtkWindow *window,
2092 GtkWindowPrivate *priv;
2094 g_return_if_fail (GTK_IS_WINDOW (window));
2096 priv = GTK_WINDOW_GET_PRIVATE (window);
2098 setting = setting != FALSE;
2100 if (priv->skips_pager != setting)
2102 priv->skips_pager = setting;
2103 if (GTK_WIDGET_REALIZED (window))
2104 gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2106 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2111 * gtk_window_get_skip_pager_hint:
2112 * @window: a #GtkWindow
2114 * Gets the value set by gtk_window_set_skip_pager_hint().
2116 * Return value: %TRUE if window shouldn't be in pager
2121 gtk_window_get_skip_pager_hint (GtkWindow *window)
2123 GtkWindowPrivate *priv;
2125 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2127 priv = GTK_WINDOW_GET_PRIVATE (window);
2129 return priv->skips_pager;
2133 * gtk_window_set_urgency_hint:
2134 * @window: a #GtkWindow
2135 * @setting: %TRUE to mark this window as urgent
2137 * Windows may set a hint asking the desktop environment to draw
2138 * the users attention to the window. This function sets this hint.
2143 gtk_window_set_urgency_hint (GtkWindow *window,
2146 GtkWindowPrivate *priv;
2148 g_return_if_fail (GTK_IS_WINDOW (window));
2150 priv = GTK_WINDOW_GET_PRIVATE (window);
2152 setting = setting != FALSE;
2154 if (priv->urgent != setting)
2156 priv->urgent = setting;
2157 if (GTK_WIDGET_REALIZED (window))
2158 gdk_window_set_urgency_hint (GTK_WIDGET (window)->window,
2160 g_object_notify (G_OBJECT (window), "urgency-hint");
2165 * gtk_window_get_urgency_hint:
2166 * @window: a #GtkWindow
2168 * Gets the value set by gtk_window_set_urgency_hint()
2170 * Return value: %TRUE if window is urgent
2175 gtk_window_get_urgency_hint (GtkWindow *window)
2177 GtkWindowPrivate *priv;
2179 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2181 priv = GTK_WINDOW_GET_PRIVATE (window);
2183 return priv->urgent;
2187 * gtk_window_set_accept_focus:
2188 * @window: a #GtkWindow
2189 * @setting: %TRUE to let this window receive input focus
2191 * Windows may set a hint asking the desktop environment not to receive
2192 * the input focus. This function sets this hint.
2197 gtk_window_set_accept_focus (GtkWindow *window,
2200 GtkWindowPrivate *priv;
2202 g_return_if_fail (GTK_IS_WINDOW (window));
2204 priv = GTK_WINDOW_GET_PRIVATE (window);
2206 setting = setting != FALSE;
2208 if (priv->accept_focus != setting)
2210 priv->accept_focus = setting;
2211 if (GTK_WIDGET_REALIZED (window))
2212 gdk_window_set_accept_focus (GTK_WIDGET (window)->window,
2213 priv->accept_focus);
2214 g_object_notify (G_OBJECT (window), "accept-focus");
2219 * gtk_window_get_accept_focus:
2220 * @window: a #GtkWindow
2222 * Gets the value set by gtk_window_set_accept_focus().
2224 * Return value: %TRUE if window should receive the input focus
2229 gtk_window_get_accept_focus (GtkWindow *window)
2231 GtkWindowPrivate *priv;
2233 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2235 priv = GTK_WINDOW_GET_PRIVATE (window);
2237 return priv->accept_focus;
2241 * gtk_window_set_focus_on_map:
2242 * @window: a #GtkWindow
2243 * @setting: %TRUE to let this window receive input focus on map
2245 * Windows may set a hint asking the desktop environment not to receive
2246 * the input focus when the window is mapped. This function sets this
2252 gtk_window_set_focus_on_map (GtkWindow *window,
2255 GtkWindowPrivate *priv;
2257 g_return_if_fail (GTK_IS_WINDOW (window));
2259 priv = GTK_WINDOW_GET_PRIVATE (window);
2261 setting = setting != FALSE;
2263 if (priv->focus_on_map != setting)
2265 priv->focus_on_map = setting;
2266 if (GTK_WIDGET_REALIZED (window))
2267 gdk_window_set_focus_on_map (GTK_WIDGET (window)->window,
2268 priv->focus_on_map);
2269 g_object_notify (G_OBJECT (window), "focus-on-map");
2274 * gtk_window_get_focus_on_map:
2275 * @window: a #GtkWindow
2277 * Gets the value set by gtk_window_set_focus_on_map().
2279 * Return value: %TRUE if window should receive the input focus when
2285 gtk_window_get_focus_on_map (GtkWindow *window)
2287 GtkWindowPrivate *priv;
2289 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2291 priv = GTK_WINDOW_GET_PRIVATE (window);
2293 return priv->focus_on_map;
2297 * gtk_window_set_destroy_with_parent:
2298 * @window: a #GtkWindow
2299 * @setting: whether to destroy @window with its transient parent
2301 * If @setting is %TRUE, then destroying the transient parent of @window
2302 * will also destroy @window itself. This is useful for dialogs that
2303 * shouldn't persist beyond the lifetime of the main window they're
2304 * associated with, for example.
2307 gtk_window_set_destroy_with_parent (GtkWindow *window,
2310 g_return_if_fail (GTK_IS_WINDOW (window));
2312 if (window->destroy_with_parent == (setting != FALSE))
2315 if (window->destroy_with_parent)
2317 disconnect_parent_destroyed (window);
2321 connect_parent_destroyed (window);
2324 window->destroy_with_parent = setting;
2326 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2330 * gtk_window_get_destroy_with_parent:
2331 * @window: a #GtkWindow
2333 * Returns whether the window will be destroyed with its transient parent. See
2334 * gtk_window_set_destroy_with_parent ().
2336 * Return value: %TRUE if the window will be destroyed with its transient parent.
2339 gtk_window_get_destroy_with_parent (GtkWindow *window)
2341 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2343 return window->destroy_with_parent;
2346 static GtkWindowGeometryInfo*
2347 gtk_window_get_geometry_info (GtkWindow *window,
2350 GtkWindowGeometryInfo *info;
2352 info = window->geometry_info;
2353 if (!info && create)
2355 info = g_new0 (GtkWindowGeometryInfo, 1);
2357 info->default_width = -1;
2358 info->default_height = -1;
2359 info->resize_width = -1;
2360 info->resize_height = -1;
2361 info->initial_x = 0;
2362 info->initial_y = 0;
2363 info->initial_pos_set = FALSE;
2364 info->default_is_geometry = FALSE;
2365 info->position_constraints_changed = FALSE;
2366 info->last.configure_request.x = 0;
2367 info->last.configure_request.y = 0;
2368 info->last.configure_request.width = -1;
2369 info->last.configure_request.height = -1;
2370 info->widget = NULL;
2372 window->geometry_info = info;
2379 * gtk_window_set_geometry_hints:
2380 * @window: a #GtkWindow
2381 * @geometry_widget: widget the geometry hints will be applied to
2382 * @geometry: struct containing geometry information
2383 * @geom_mask: mask indicating which struct fields should be paid attention to
2385 * This function sets up hints about how a window can be resized by
2386 * the user. You can set a minimum and maximum size; allowed resize
2387 * increments (e.g. for xterm, you can only resize by the size of a
2388 * character); aspect ratios; and more. See the #GdkGeometry struct.
2392 gtk_window_set_geometry_hints (GtkWindow *window,
2393 GtkWidget *geometry_widget,
2394 GdkGeometry *geometry,
2395 GdkWindowHints geom_mask)
2397 GtkWindowGeometryInfo *info;
2399 g_return_if_fail (GTK_IS_WINDOW (window));
2400 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2402 info = gtk_window_get_geometry_info (window, TRUE);
2405 g_signal_handlers_disconnect_by_func (info->widget,
2406 gtk_widget_destroyed,
2409 info->widget = geometry_widget;
2411 g_signal_connect (geometry_widget, "destroy",
2412 G_CALLBACK (gtk_widget_destroyed),
2416 info->geometry = *geometry;
2418 /* We store gravity in window->gravity not in the hints. */
2419 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2421 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2423 gtk_window_set_gravity (window, geometry->win_gravity);
2426 gtk_widget_queue_resize (GTK_WIDGET (window));
2430 * gtk_window_set_decorated:
2431 * @window: a #GtkWindow
2432 * @setting: %TRUE to decorate the window
2434 * By default, windows are decorated with a title bar, resize
2435 * controls, etc. Some <link linkend="gtk-X11-arch">window
2436 * managers</link> allow GTK+ to disable these decorations, creating a
2437 * borderless window. If you set the decorated property to %FALSE
2438 * using this function, GTK+ will do its best to convince the window
2439 * manager not to decorate the window. Depending on the system, this
2440 * function may not have any effect when called on a window that is
2441 * already visible, so you should call it before calling gtk_window_show().
2443 * On Windows, this function always works, since there's no window manager
2448 gtk_window_set_decorated (GtkWindow *window,
2451 g_return_if_fail (GTK_IS_WINDOW (window));
2453 setting = setting != FALSE;
2455 if (setting == window->decorated)
2458 window->decorated = setting;
2460 if (GTK_WIDGET (window)->window)
2462 if (window->decorated)
2463 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2466 gdk_window_set_decorations (GTK_WIDGET (window)->window,
2470 g_object_notify (G_OBJECT (window), "decorated");
2474 * gtk_window_get_decorated:
2475 * @window: a #GtkWindow
2477 * Returns whether the window has been set to have decorations
2478 * such as a title bar via gtk_window_set_decorated().
2480 * Return value: %TRUE if the window has been set to have decorations
2483 gtk_window_get_decorated (GtkWindow *window)
2485 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2487 return window->decorated;
2491 * gtk_window_set_deletable:
2492 * @window: a #GtkWindow
2493 * @setting: %TRUE to decorate the window as deletable
2495 * By default, windows have a close button in the window frame. Some
2496 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
2497 * disable this button. If you set the deletable property to %FALSE
2498 * using this function, GTK+ will do its best to convince the window
2499 * manager not to show a close button. Depending on the system, this
2500 * function may not have any effect when called on a window that is
2501 * already visible, so you should call it before calling gtk_window_show().
2503 * On Windows, this function always works, since there's no window manager
2509 gtk_window_set_deletable (GtkWindow *window,
2512 GtkWindowPrivate *priv;
2514 g_return_if_fail (GTK_IS_WINDOW (window));
2516 priv = GTK_WINDOW_GET_PRIVATE (window);
2518 setting = setting != FALSE;
2520 if (setting == priv->deletable)
2523 priv->deletable = setting;
2525 if (GTK_WIDGET (window)->window)
2527 if (priv->deletable)
2528 gdk_window_set_functions (GTK_WIDGET (window)->window,
2531 gdk_window_set_functions (GTK_WIDGET (window)->window,
2532 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
2535 g_object_notify (G_OBJECT (window), "deletable");
2539 * gtk_window_get_deletable:
2540 * @window: a #GtkWindow
2542 * Returns whether the window has been set to have a close button
2543 * via gtk_window_set_deletable().
2545 * Return value: %TRUE if the window has been set to have a close button
2550 gtk_window_get_deletable (GtkWindow *window)
2552 GtkWindowPrivate *priv;
2554 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2556 priv = GTK_WINDOW_GET_PRIVATE (window);
2558 return priv->deletable;
2561 static GtkWindowIconInfo*
2562 get_icon_info (GtkWindow *window)
2564 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
2568 free_icon_info (GtkWindowIconInfo *info)
2570 g_free (info->icon_name);
2571 g_slice_free (GtkWindowIconInfo, info);
2575 static GtkWindowIconInfo*
2576 ensure_icon_info (GtkWindow *window)
2578 GtkWindowIconInfo *info;
2580 info = get_icon_info (window);
2584 info = g_slice_new0 (GtkWindowIconInfo);
2585 g_object_set_qdata_full (G_OBJECT (window),
2586 quark_gtk_window_icon_info,
2588 (GDestroyNotify)free_icon_info);
2600 static ScreenIconInfo *
2601 get_screen_icon_info (GdkScreen *screen)
2603 ScreenIconInfo *info = g_object_get_qdata (G_OBJECT (screen),
2604 quark_gtk_window_default_icon_pixmap);
2607 info = g_slice_new0 (ScreenIconInfo);
2608 g_object_set_qdata (G_OBJECT (screen),
2609 quark_gtk_window_default_icon_pixmap, info);
2612 if (info->serial != default_icon_serial)
2616 g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2617 info->pixmap = NULL;
2622 g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2626 info->serial = default_icon_serial;
2633 get_pixmap_and_mask (GdkWindow *window,
2634 GtkWindowIconInfo *parent_info,
2635 gboolean is_default_list,
2637 GdkPixmap **pmap_return,
2638 GdkBitmap **mask_return)
2640 GdkScreen *screen = gdk_drawable_get_screen (window);
2641 ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2642 GdkPixbuf *best_icon;
2646 *pmap_return = NULL;
2647 *mask_return = NULL;
2649 if (is_default_list &&
2650 default_icon_info->pixmap != NULL)
2652 /* Use shared icon pixmap for all windows on this screen.
2654 if (default_icon_info->pixmap)
2655 g_object_ref (default_icon_info->pixmap);
2656 if (default_icon_info->mask)
2657 g_object_ref (default_icon_info->mask);
2659 *pmap_return = default_icon_info->pixmap;
2660 *mask_return = default_icon_info->mask;
2662 else if (parent_info && parent_info->icon_pixmap)
2664 if (parent_info->icon_pixmap)
2665 g_object_ref (parent_info->icon_pixmap);
2666 if (parent_info->icon_mask)
2667 g_object_ref (parent_info->icon_mask);
2669 *pmap_return = parent_info->icon_pixmap;
2670 *mask_return = parent_info->icon_mask;
2674 #define IDEAL_SIZE 48
2676 best_size = G_MAXINT;
2678 tmp_list = icon_list;
2679 while (tmp_list != NULL)
2681 GdkPixbuf *pixbuf = tmp_list->data;
2684 /* average width and height - if someone passes in a rectangular
2685 * icon they deserve what they get.
2687 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2690 if (best_icon == NULL)
2697 /* icon is better if it's 32 pixels or larger, and closer to
2698 * the ideal size than the current best.
2701 (ABS (best_size - IDEAL_SIZE) <
2702 ABS (this - IDEAL_SIZE)))
2709 tmp_list = tmp_list->next;
2713 gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2714 gdk_screen_get_system_colormap (screen),
2719 /* Save pmap/mask for others to use if appropriate */
2722 parent_info->icon_pixmap = *pmap_return;
2723 parent_info->icon_mask = *mask_return;
2725 if (parent_info->icon_pixmap)
2726 g_object_ref (parent_info->icon_pixmap);
2727 if (parent_info->icon_mask)
2728 g_object_ref (parent_info->icon_mask);
2730 else if (is_default_list)
2732 default_icon_info->pixmap = *pmap_return;
2733 default_icon_info->mask = *mask_return;
2735 if (default_icon_info->pixmap)
2736 g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2737 (gpointer*)&default_icon_info->pixmap);
2738 if (default_icon_info->mask)
2739 g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2740 (gpointer*)&default_icon_info->mask);
2746 icon_list_from_theme (GtkWidget *widget,
2751 GtkIconTheme *icon_theme;
2756 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
2758 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
2761 for (i = 0; sizes[i]; i++)
2764 * We need an EWMH extension to handle scalable icons
2765 * by passing their name to the WM. For now just use a
2769 icon = gtk_icon_theme_load_icon (icon_theme, name,
2772 icon = gtk_icon_theme_load_icon (icon_theme, name,
2775 list = g_list_append (list, icon);
2785 gtk_window_realize_icon (GtkWindow *window)
2788 GtkWindowIconInfo *info;
2791 widget = GTK_WIDGET (window);
2793 g_return_if_fail (widget->window != NULL);
2795 /* no point setting an icon on override-redirect */
2796 if (window->type == GTK_WINDOW_POPUP)
2801 info = ensure_icon_info (window);
2806 g_return_if_fail (info->icon_pixmap == NULL);
2807 g_return_if_fail (info->icon_mask == NULL);
2809 info->using_default_icon = FALSE;
2810 info->using_parent_icon = FALSE;
2811 info->using_themed_icon = FALSE;
2813 icon_list = info->icon_list;
2815 /* Look up themed icon */
2816 if (icon_list == NULL && info->icon_name)
2818 icon_list = icon_list_from_theme (widget, info->icon_name);
2820 info->using_themed_icon = TRUE;
2823 /* Inherit from transient parent */
2824 if (icon_list == NULL && window->transient_parent)
2826 icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2828 info->using_parent_icon = TRUE;
2831 /* Inherit from default */
2832 if (icon_list == NULL)
2834 icon_list = default_icon_list;
2836 info->using_default_icon = TRUE;
2839 /* Look up themed icon */
2840 if (icon_list == NULL && default_icon_name)
2842 icon_list = icon_list_from_theme (widget, default_icon_name);
2843 info->using_default_icon = TRUE;
2844 info->using_themed_icon = TRUE;
2847 gdk_window_set_icon_list (widget->window, icon_list);
2849 get_pixmap_and_mask (widget->window,
2850 info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2851 info->using_default_icon,
2856 /* This is a slight ICCCM violation since it's a color pixmap not
2857 * a bitmap, but everyone does it.
2859 gdk_window_set_icon (widget->window,
2864 info->realized = TRUE;
2866 if (info->using_themed_icon)
2868 GtkIconTheme *icon_theme;
2870 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
2871 g_list_free (icon_list);
2873 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2874 g_signal_connect (icon_theme, "changed",
2875 G_CALLBACK (update_themed_icon), window);
2880 gtk_window_unrealize_icon (GtkWindow *window)
2882 GtkWindowIconInfo *info;
2884 info = get_icon_info (window);
2889 if (info->icon_pixmap)
2890 g_object_unref (info->icon_pixmap);
2892 if (info->icon_mask)
2893 g_object_unref (info->icon_mask);
2895 info->icon_pixmap = NULL;
2896 info->icon_mask = NULL;
2898 if (info->using_themed_icon)
2900 GtkIconTheme *icon_theme;
2902 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2904 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
2907 /* We don't clear the properties on the window, just figure the
2908 * window is going away.
2911 info->realized = FALSE;
2916 * gtk_window_set_icon_list:
2917 * @window: a #GtkWindow
2918 * @list: list of #GdkPixbuf
2920 * Sets up the icon representing a #GtkWindow. The icon is used when
2921 * the window is minimized (also known as iconified). Some window
2922 * managers or desktop environments may also place it in the window
2923 * frame, or display it in other contexts.
2925 * gtk_window_set_icon_list() allows you to pass in the same icon in
2926 * several hand-drawn sizes. The list should contain the natural sizes
2927 * your icon is available in; that is, don't scale the image before
2928 * passing it to GTK+. Scaling is postponed until the last minute,
2929 * when the desired final size is known, to allow best quality.
2931 * By passing several sizes, you may improve the final image quality
2932 * of the icon, by reducing or eliminating automatic image scaling.
2934 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2935 * larger images (64x64, 128x128) if you have them.
2937 * See also gtk_window_set_default_icon_list() to set the icon
2938 * for all windows in your application in one go.
2940 * Note that transient windows (those who have been set transient for another
2941 * window using gtk_window_set_transient_for()) will inherit their
2942 * icon from their transient parent. So there's no need to explicitly
2943 * set the icon on transient windows.
2946 gtk_window_set_icon_list (GtkWindow *window,
2949 GtkWindowIconInfo *info;
2951 g_return_if_fail (GTK_IS_WINDOW (window));
2953 info = ensure_icon_info (window);
2955 if (info->icon_list == list) /* check for NULL mostly */
2958 g_list_foreach (list,
2959 (GFunc) g_object_ref, NULL);
2961 g_list_foreach (info->icon_list,
2962 (GFunc) g_object_unref, NULL);
2964 g_list_free (info->icon_list);
2966 info->icon_list = g_list_copy (list);
2968 g_object_notify (G_OBJECT (window), "icon");
2970 gtk_window_unrealize_icon (window);
2972 if (GTK_WIDGET_REALIZED (window))
2973 gtk_window_realize_icon (window);
2975 /* We could try to update our transient children, but I don't think
2976 * it's really worth it. If we did it, the best way would probably
2977 * be to have children connect to notify::icon-list
2982 * gtk_window_get_icon_list:
2983 * @window: a #GtkWindow
2985 * Retrieves the list of icons set by gtk_window_set_icon_list().
2986 * The list is copied, but the reference count on each
2987 * member won't be incremented.
2989 * Return value: copy of window's icon list
2992 gtk_window_get_icon_list (GtkWindow *window)
2994 GtkWindowIconInfo *info;
2996 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2998 info = get_icon_info (window);
3001 return g_list_copy (info->icon_list);
3007 * gtk_window_set_icon:
3008 * @window: a #GtkWindow
3009 * @icon: icon image, or %NULL
3011 * Sets up the icon representing a #GtkWindow. This icon is used when
3012 * the window is minimized (also known as iconified). Some window
3013 * managers or desktop environments may also place it in the window
3014 * frame, or display it in other contexts.
3016 * The icon should be provided in whatever size it was naturally
3017 * drawn; that is, don't scale the image before passing it to
3018 * GTK+. Scaling is postponed until the last minute, when the desired
3019 * final size is known, to allow best quality.
3021 * If you have your icon hand-drawn in multiple sizes, use
3022 * gtk_window_set_icon_list(). Then the best size will be used.
3024 * This function is equivalent to calling gtk_window_set_icon_list()
3025 * with a 1-element list.
3027 * See also gtk_window_set_default_icon_list() to set the icon
3028 * for all windows in your application in one go.
3031 gtk_window_set_icon (GtkWindow *window,
3036 g_return_if_fail (GTK_IS_WINDOW (window));
3037 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3042 list = g_list_append (list, icon);
3044 gtk_window_set_icon_list (window, list);
3050 update_themed_icon (GtkIconTheme *icon_theme,
3053 g_object_notify (G_OBJECT (window), "icon");
3055 gtk_window_unrealize_icon (window);
3057 if (GTK_WIDGET_REALIZED (window))
3058 gtk_window_realize_icon (window);
3062 * gtk_window_set_icon_name:
3063 * @window: a #GtkWindow
3064 * @name: the name of the themed icon
3066 * Sets the icon for the window from a named themed icon. See
3067 * the docs for #GtkIconTheme for more details.
3069 * Note that this has nothing to do with the WM_ICON_NAME
3070 * property which is mentioned in the ICCCM.
3075 gtk_window_set_icon_name (GtkWindow *window,
3078 GtkWindowIconInfo *info;
3081 g_return_if_fail (GTK_IS_WINDOW (window));
3083 info = ensure_icon_info (window);
3085 tmp = info->icon_name;
3086 info->icon_name = g_strdup (name);
3089 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3090 g_list_free (info->icon_list);
3091 info->icon_list = NULL;
3093 update_themed_icon (NULL, window);
3095 g_object_notify (G_OBJECT (window), "icon-name");
3099 * gtk_window_get_icon_name:
3100 * @window: a #GtkWindow
3102 * Returns the name of the themed icon for the window,
3103 * see gtk_window_set_icon_name().
3105 * Returns: the icon name or %NULL if the window has
3110 G_CONST_RETURN gchar *
3111 gtk_window_get_icon_name (GtkWindow *window)
3113 GtkWindowIconInfo *info;
3115 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3117 info = ensure_icon_info (window);
3119 return info->icon_name;
3123 * gtk_window_get_icon:
3124 * @window: a #GtkWindow
3126 * Gets the value set by gtk_window_set_icon() (or if you've
3127 * called gtk_window_set_icon_list(), gets the first icon in
3130 * Return value: icon for window
3133 gtk_window_get_icon (GtkWindow *window)
3135 GtkWindowIconInfo *info;
3137 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3139 info = get_icon_info (window);
3140 if (info && info->icon_list)
3141 return GDK_PIXBUF (info->icon_list->data);
3146 /* Load pixbuf, printing warning on failure if error == NULL
3149 load_pixbuf_verbosely (const char *filename,
3152 GError *local_err = NULL;
3155 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3163 g_warning ("Error loading icon from file '%s':\n\t%s",
3164 filename, local_err->message);
3165 g_error_free (local_err);
3173 * gtk_window_set_icon_from_file:
3174 * @window: a #GtkWindow
3175 * @filename: location of icon file
3176 * @err: location to store error, or %NULL.
3178 * Sets the icon for @window.
3179 * Warns on failure if @err is %NULL.
3181 * This function is equivalent to calling gtk_window_set_icon()
3182 * with a pixbuf created by loading the image from @filename.
3184 * Returns: %TRUE if setting the icon succeeded.
3189 gtk_window_set_icon_from_file (GtkWindow *window,
3190 const gchar *filename,
3193 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3197 gtk_window_set_icon (window, pixbuf);
3198 g_object_unref (pixbuf);
3207 * gtk_window_set_default_icon_list:
3208 * @list: a list of #GdkPixbuf
3210 * Sets an icon list to be used as fallback for windows that haven't
3211 * had gtk_window_set_icon_list() called on them to set up a
3212 * window-specific icon list. This function allows you to set up the
3213 * icon for all windows in your app at once.
3215 * See gtk_window_set_icon_list() for more details.
3219 gtk_window_set_default_icon_list (GList *list)
3223 if (list == default_icon_list)
3226 /* Update serial so we don't used cached pixmaps/masks
3228 default_icon_serial++;
3230 g_list_foreach (list,
3231 (GFunc) g_object_ref, NULL);
3233 g_list_foreach (default_icon_list,
3234 (GFunc) g_object_unref, NULL);
3236 g_list_free (default_icon_list);
3238 default_icon_list = g_list_copy (list);
3240 /* Update all toplevels */
3241 toplevels = gtk_window_list_toplevels ();
3242 tmp_list = toplevels;
3243 while (tmp_list != NULL)
3245 GtkWindowIconInfo *info;
3246 GtkWindow *w = tmp_list->data;
3248 info = get_icon_info (w);
3249 if (info && info->using_default_icon)
3251 gtk_window_unrealize_icon (w);
3252 if (GTK_WIDGET_REALIZED (w))
3253 gtk_window_realize_icon (w);
3256 tmp_list = tmp_list->next;
3258 g_list_free (toplevels);
3262 * gtk_window_set_default_icon:
3265 * Sets an icon to be used as fallback for windows that haven't
3266 * had gtk_window_set_icon() called on them from a pixbuf.
3271 gtk_window_set_default_icon (GdkPixbuf *icon)
3275 g_return_if_fail (GDK_IS_PIXBUF (icon));
3277 list = g_list_prepend (NULL, icon);
3278 gtk_window_set_default_icon_list (list);
3283 * gtk_window_set_default_icon_name:
3284 * @name: the name of the themed icon
3286 * Sets an icon to be used as fallback for windows that haven't
3287 * had gtk_window_set_icon_list() called on them from a named
3288 * themed icon, see gtk_window_set_icon_name().
3293 gtk_window_set_default_icon_name (const gchar *name)
3298 /* Update serial so we don't used cached pixmaps/masks
3300 default_icon_serial++;
3302 g_free (default_icon_name);
3303 default_icon_name = g_strdup (name);
3305 g_list_foreach (default_icon_list,
3306 (GFunc) g_object_unref, NULL);
3308 g_list_free (default_icon_list);
3309 default_icon_list = NULL;
3311 /* Update all toplevels */
3312 toplevels = gtk_window_list_toplevels ();
3313 tmp_list = toplevels;
3314 while (tmp_list != NULL)
3316 GtkWindowIconInfo *info;
3317 GtkWindow *w = tmp_list->data;
3319 info = get_icon_info (w);
3320 if (info && info->using_default_icon && info->using_themed_icon)
3322 gtk_window_unrealize_icon (w);
3323 if (GTK_WIDGET_REALIZED (w))
3324 gtk_window_realize_icon (w);
3327 tmp_list = tmp_list->next;
3329 g_list_free (toplevels);
3333 * gtk_window_set_default_icon_from_file:
3334 * @filename: location of icon file
3335 * @err: location to store error, or %NULL.
3337 * Sets an icon to be used as fallback for windows that haven't
3338 * had gtk_window_set_icon_list() called on them from a file
3339 * on disk. Warns on failure if @err is %NULL.
3341 * Returns: %TRUE if setting the icon succeeded.
3346 gtk_window_set_default_icon_from_file (const gchar *filename,
3349 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3353 gtk_window_set_default_icon (pixbuf);
3354 g_object_unref (pixbuf);
3363 * gtk_window_get_default_icon_list:
3365 * Gets the value set by gtk_window_set_default_icon_list().
3366 * The list is a copy and should be freed with g_list_free(),
3367 * but the pixbufs in the list have not had their reference count
3370 * Return value: copy of default icon list
3373 gtk_window_get_default_icon_list (void)
3375 return g_list_copy (default_icon_list);
3379 gtk_window_set_default_size_internal (GtkWindow *window,
3380 gboolean change_width,
3382 gboolean change_height,
3384 gboolean is_geometry)
3386 GtkWindowGeometryInfo *info;
3388 g_return_if_fail (change_width == FALSE || width >= -1);
3389 g_return_if_fail (change_height == FALSE || height >= -1);
3391 info = gtk_window_get_geometry_info (window, TRUE);
3393 g_object_freeze_notify (G_OBJECT (window));
3395 info->default_is_geometry = is_geometry != FALSE;
3405 info->default_width = width;
3407 g_object_notify (G_OBJECT (window), "default-width");
3418 info->default_height = height;
3420 g_object_notify (G_OBJECT (window), "default-height");
3423 g_object_thaw_notify (G_OBJECT (window));
3425 gtk_widget_queue_resize (GTK_WIDGET (window));
3429 * gtk_window_set_default_size:
3430 * @window: a #GtkWindow
3431 * @width: width in pixels, or -1 to unset the default width
3432 * @height: height in pixels, or -1 to unset the default height
3434 * Sets the default size of a window. If the window's "natural" size
3435 * (its size request) is larger than the default, the default will be
3436 * ignored. More generally, if the default size does not obey the
3437 * geometry hints for the window (gtk_window_set_geometry_hints() can
3438 * be used to set these explicitly), the default size will be clamped
3439 * to the nearest permitted size.
3441 * Unlike gtk_widget_set_size_request(), which sets a size request for
3442 * a widget and thus would keep users from shrinking the window, this
3443 * function only sets the initial size, just as if the user had
3444 * resized the window themselves. Users can still shrink the window
3445 * again as they normally would. Setting a default size of -1 means to
3446 * use the "natural" default size (the size request of the window).
3448 * For more control over a window's initial size and how resizing works,
3449 * investigate gtk_window_set_geometry_hints().
3451 * For some uses, gtk_window_resize() is a more appropriate function.
3452 * gtk_window_resize() changes the current size of the window, rather
3453 * than the size to be used on initial display. gtk_window_resize() always
3454 * affects the window itself, not the geometry widget.
3456 * The default size of a window only affects the first time a window is
3457 * shown; if a window is hidden and re-shown, it will remember the size
3458 * it had prior to hiding, rather than using the default size.
3460 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3461 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3464 gtk_window_set_default_size (GtkWindow *window,
3468 g_return_if_fail (GTK_IS_WINDOW (window));
3469 g_return_if_fail (width >= -1);
3470 g_return_if_fail (height >= -1);
3472 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3476 * gtk_window_get_default_size:
3477 * @window: a #GtkWindow
3478 * @width: location to store the default width, or %NULL
3479 * @height: location to store the default height, or %NULL
3481 * Gets the default size of the window. A value of -1 for the width or
3482 * height indicates that a default size has not been explicitly set
3483 * for that dimension, so the "natural" size of the window will be
3488 gtk_window_get_default_size (GtkWindow *window,
3492 GtkWindowGeometryInfo *info;
3494 g_return_if_fail (GTK_IS_WINDOW (window));
3496 info = gtk_window_get_geometry_info (window, FALSE);
3499 *width = info ? info->default_width : -1;
3502 *height = info ? info->default_height : -1;
3506 * gtk_window_resize:
3507 * @window: a #GtkWindow
3508 * @width: width in pixels to resize the window to
3509 * @height: height in pixels to resize the window to
3511 * Resizes the window as if the user had done so, obeying geometry
3512 * constraints. The default geometry constraint is that windows may
3513 * not be smaller than their size request; to override this
3514 * constraint, call gtk_widget_set_size_request() to set the window's
3515 * request to a smaller value.
3517 * If gtk_window_resize() is called before showing a window for the
3518 * first time, it overrides any default size set with
3519 * gtk_window_set_default_size().
3521 * Windows may not be resized smaller than 1 by 1 pixels.
3525 gtk_window_resize (GtkWindow *window,
3529 GtkWindowGeometryInfo *info;
3531 g_return_if_fail (GTK_IS_WINDOW (window));
3532 g_return_if_fail (width > 0);
3533 g_return_if_fail (height > 0);
3535 info = gtk_window_get_geometry_info (window, TRUE);
3537 info->resize_width = width;
3538 info->resize_height = height;
3540 gtk_widget_queue_resize (GTK_WIDGET (window));
3544 * gtk_window_get_size:
3545 * @window: a #GtkWindow
3546 * @width: return location for width, or %NULL
3547 * @height: return location for height, or %NULL
3549 * Obtains the current size of @window. If @window is not onscreen,
3550 * it returns the size GTK+ will suggest to the <link
3551 * linkend="gtk-X11-arch">window manager</link> for the initial window
3552 * size (but this is not reliably the same as the size the window
3553 * manager will actually select). The size obtained by
3554 * gtk_window_get_size() is the last size received in a
3555 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
3556 * rather than querying the X server for the size. As a result, if you
3557 * call gtk_window_resize() then immediately call
3558 * gtk_window_get_size(), the size won't have taken effect yet. After
3559 * the window manager processes the resize request, GTK+ receives
3560 * notification that the size has changed via a configure event, and
3561 * the size of the window gets updated.
3563 * Note 1: Nearly any use of this function creates a race condition,
3564 * because the size of the window may change between the time that you
3565 * get the size and the time that you perform some action assuming
3566 * that size is the current size. To avoid race conditions, connect to
3567 * "configure_event" on the window and adjust your size-dependent
3568 * state to match the size delivered in the #GdkEventConfigure.
3570 * Note 2: The returned size does <emphasis>not</emphasis> include the
3571 * size of the window manager decorations (aka the window frame or
3572 * border). Those are not drawn by GTK+ and GTK+ has no reliable
3573 * method of determining their size.
3575 * Note 3: If you are getting a window size in order to position
3576 * the window onscreen, there may be a better way. The preferred
3577 * way is to simply set the window's semantic type with
3578 * gtk_window_set_type_hint(), which allows the window manager to
3579 * e.g. center dialogs. Also, if you set the transient parent of
3580 * dialogs with gtk_window_set_transient_for() window managers
3581 * will often center the dialog over its parent window. It's
3582 * much preferred to let the window manager handle these
3583 * things rather than doing it yourself, because all apps will
3584 * behave consistently and according to user prefs if the window
3585 * manager handles it. Also, the window manager can take the size
3586 * of the window decorations/border into account, while your
3587 * application cannot.
3589 * In any case, if you insist on application-specified window
3590 * positioning, there's <emphasis>still</emphasis> a better way than
3591 * doing it yourself - gtk_window_set_position() will frequently
3592 * handle the details for you.
3596 gtk_window_get_size (GtkWindow *window,
3602 g_return_if_fail (GTK_IS_WINDOW (window));
3604 if (width == NULL && height == NULL)
3607 if (GTK_WIDGET_MAPPED (window))
3609 gdk_drawable_get_size (GTK_WIDGET (window)->window,
3614 GdkRectangle configure_request;
3616 gtk_window_compute_configure_request (window,
3620 w = configure_request.width;
3621 h = configure_request.height;
3632 * @window: a #GtkWindow
3633 * @x: X coordinate to move window to
3634 * @y: Y coordinate to move window to
3636 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3637 * @window to the given position. Window managers are free to ignore
3638 * this; most window managers ignore requests for initial window
3639 * positions (instead using a user-defined placement algorithm) and
3640 * honor requests after the window has already been shown.
3642 * Note: the position is the position of the gravity-determined
3643 * reference point for the window. The gravity determines two things:
3644 * first, the location of the reference point in root window
3645 * coordinates; and second, which point on the window is positioned at
3646 * the reference point.
3648 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3649 * point is simply the @x, @y supplied to gtk_window_move(). The
3650 * top-left corner of the window decorations (aka window frame or
3651 * border) will be placed at @x, @y. Therefore, to position a window
3652 * at the top left of the screen, you want to use the default gravity
3653 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3655 * To position a window at the bottom right corner of the screen, you
3656 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3657 * point is at @x + the window width and @y + the window height, and
3658 * the bottom-right corner of the window border will be placed at that
3659 * reference point. So, to place a window in the bottom right corner
3660 * you would first set gravity to south east, then write:
3661 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3662 * gdk_screen_height () - window_height)</literal>.
3664 * The Extended Window Manager Hints specification at <ulink
3665 * url="http://www.freedesktop.org/Standards/wm-spec">
3666 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
3667 * nice table of gravities in the "implementation notes" section.
3669 * The gtk_window_get_position() documentation may also be relevant.
3673 gtk_window_move (GtkWindow *window,
3677 GtkWindowGeometryInfo *info;
3680 g_return_if_fail (GTK_IS_WINDOW (window));
3682 widget = GTK_WIDGET (window);
3684 info = gtk_window_get_geometry_info (window, TRUE);
3686 if (GTK_WIDGET_MAPPED (window))
3688 /* we have now sent a request with this position
3689 * with currently-active constraints, so toggle flag.
3691 info->position_constraints_changed = FALSE;
3693 /* we only constrain if mapped - if not mapped,
3694 * then gtk_window_compute_configure_request()
3695 * will apply the constraints later, and we
3696 * don't want to lose information about
3697 * what position the user set before then.
3698 * i.e. if you do a move() then turn off POS_CENTER
3699 * then show the window, your move() will work.
3701 gtk_window_constrain_position (window,
3702 widget->allocation.width,
3703 widget->allocation.height,
3706 /* Note that this request doesn't go through our standard request
3707 * framework, e.g. doesn't increment configure_request_count,
3708 * doesn't set info->last, etc.; that's because
3709 * we don't save the info needed to arrive at this same request
3712 * To gtk_window_move_resize(), this will end up looking exactly
3713 * the same as the position being changed by the window
3717 /* FIXME are we handling gravity properly for framed windows? */
3719 gdk_window_move (window->frame,
3720 x - window->frame_left,
3721 y - window->frame_top);
3723 gdk_window_move (GTK_WIDGET (window)->window,
3728 /* Save this position to apply on mapping */
3729 info->initial_x = x;
3730 info->initial_y = y;
3731 info->initial_pos_set = TRUE;
3736 * gtk_window_get_position:
3737 * @window: a #GtkWindow
3738 * @root_x: return location for X coordinate of gravity-determined reference p\oint
3739 * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3741 * This function returns the position you need to pass to
3742 * gtk_window_move() to keep @window in its current position. This
3743 * means that the meaning of the returned value varies with window
3744 * gravity. See gtk_window_move() for more details.
3746 * If you haven't changed the window gravity, its gravity will be
3747 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3748 * gets the position of the top-left corner of the window manager
3749 * frame for the window. gtk_window_move() sets the position of this
3750 * same top-left corner.
3752 * gtk_window_get_position() is not 100% reliable because the X Window System
3753 * does not specify a way to obtain the geometry of the
3754 * decorations placed on a window by the window manager.
3755 * Thus GTK+ is using a "best guess" that works with most
3758 * Moreover, nearly all window managers are historically broken with
3759 * respect to their handling of window gravity. So moving a window to
3760 * its current position as returned by gtk_window_get_position() tends
3761 * to result in moving the window slightly. Window managers are
3762 * slowly getting better over time.
3764 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3765 * frame is not relevant, and thus gtk_window_get_position() will
3766 * always produce accurate results. However you can't use static
3767 * gravity to do things like place a window in a corner of the screen,
3768 * because static gravity ignores the window manager decorations.
3770 * If you are saving and restoring your application's window
3771 * positions, you should know that it's impossible for applications to
3772 * do this without getting it somewhat wrong because applications do
3773 * not have sufficient knowledge of window manager state. The Correct
3774 * Mechanism is to support the session management protocol (see the
3775 * "GnomeClient" object in the GNOME libraries for example) and allow
3776 * the window manager to save your window sizes and positions.
3781 gtk_window_get_position (GtkWindow *window,
3787 g_return_if_fail (GTK_IS_WINDOW (window));
3789 widget = GTK_WIDGET (window);
3791 if (window->gravity == GDK_GRAVITY_STATIC)
3793 if (GTK_WIDGET_MAPPED (widget))
3795 /* This does a server round-trip, which is sort of wrong;
3796 * but a server round-trip is inevitable for
3797 * gdk_window_get_frame_extents() in the usual
3798 * NorthWestGravity case below, so not sure what else to
3799 * do. We should likely be consistent about whether we get
3800 * the client-side info or the server-side info.
3802 gdk_window_get_origin (widget->window, root_x, root_y);
3806 GdkRectangle configure_request;
3808 gtk_window_compute_configure_request (window,
3812 *root_x = configure_request.x;
3813 *root_y = configure_request.y;
3818 GdkRectangle frame_extents;
3823 if (GTK_WIDGET_MAPPED (widget))
3826 gdk_window_get_frame_extents (window->frame, &frame_extents);
3828 gdk_window_get_frame_extents (widget->window, &frame_extents);
3829 x = frame_extents.x;
3830 y = frame_extents.y;
3831 gtk_window_get_size (window, &w, &h);
3835 /* We just say the frame has 0 size on all sides.
3836 * Not sure what else to do.
3838 gtk_window_compute_configure_request (window,
3841 x = frame_extents.x;
3842 y = frame_extents.y;
3843 w = frame_extents.width;
3844 h = frame_extents.height;
3847 switch (window->gravity)
3849 case GDK_GRAVITY_NORTH:
3850 case GDK_GRAVITY_CENTER:
3851 case GDK_GRAVITY_SOUTH:
3852 /* Find center of frame. */
3853 x += frame_extents.width / 2;
3854 /* Center client window on that point. */
3858 case GDK_GRAVITY_SOUTH_EAST:
3859 case GDK_GRAVITY_EAST:
3860 case GDK_GRAVITY_NORTH_EAST:
3861 /* Find right edge of frame */
3862 x += frame_extents.width;
3863 /* Align left edge of client at that point. */
3870 switch (window->gravity)
3872 case GDK_GRAVITY_WEST:
3873 case GDK_GRAVITY_CENTER:
3874 case GDK_GRAVITY_EAST:
3875 /* Find center of frame. */
3876 y += frame_extents.height / 2;
3877 /* Center client window there. */
3880 case GDK_GRAVITY_SOUTH_WEST:
3881 case GDK_GRAVITY_SOUTH:
3882 case GDK_GRAVITY_SOUTH_EAST:
3883 /* Find south edge of frame */
3884 y += frame_extents.height;
3885 /* Place bottom edge of client there */
3900 * gtk_window_reshow_with_initial_size:
3901 * @window: a #GtkWindow
3903 * Hides @window, then reshows it, resetting the
3904 * default size and position of the window. Used
3905 * by GUI builders only.
3908 gtk_window_reshow_with_initial_size (GtkWindow *window)
3912 g_return_if_fail (GTK_IS_WINDOW (window));
3914 widget = GTK_WIDGET (window);
3916 gtk_widget_hide (widget);
3917 gtk_widget_unrealize (widget);
3918 gtk_widget_show (widget);
3922 gtk_window_destroy (GtkObject *object)
3924 GtkWindow *window = GTK_WINDOW (object);
3926 toplevel_list = g_slist_remove (toplevel_list, window);
3928 if (window->transient_parent)
3929 gtk_window_set_transient_for (window, NULL);
3931 /* frees the icons */
3932 gtk_window_set_icon_list (window, NULL);
3934 if (window->has_user_ref_count)
3936 window->has_user_ref_count = FALSE;
3937 g_object_unref (window);
3941 gtk_window_group_remove_window (window->group, window);
3943 gtk_window_free_key_hash (window);
3945 GTK_OBJECT_CLASS (gtk_window_parent_class)->destroy (object);
3949 gtk_window_finalize (GObject *object)
3951 GtkWindow *window = GTK_WINDOW (object);
3952 GtkMnemonicHash *mnemonic_hash;
3954 g_free (window->title);
3955 g_free (window->wmclass_name);
3956 g_free (window->wmclass_class);
3957 g_free (window->wm_role);
3959 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
3961 _gtk_mnemonic_hash_free (mnemonic_hash);
3963 if (window->geometry_info)
3965 if (window->geometry_info->widget)
3966 g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3967 gtk_widget_destroyed,
3968 &window->geometry_info->widget);
3969 g_free (window->geometry_info);
3972 if (window->keys_changed_handler)
3974 g_source_remove (window->keys_changed_handler);
3975 window->keys_changed_handler = 0;
3980 g_signal_handlers_disconnect_by_func (window->screen,
3981 gtk_window_on_composited_changed, window);
3984 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
3988 gtk_window_show (GtkWidget *widget)
3990 GtkWindow *window = GTK_WINDOW (widget);
3991 GtkContainer *container = GTK_CONTAINER (window);
3992 gboolean need_resize;
3994 GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3996 need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3997 container->need_resize = FALSE;
4001 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4002 GtkAllocation allocation = { 0, 0 };
4003 GdkRectangle configure_request;
4004 GdkGeometry new_geometry;
4006 gboolean was_realized;
4008 /* We are going to go ahead and perform this configure request
4009 * and then emulate a configure notify by going ahead and
4010 * doing a size allocate. Sort of a synchronous
4011 * mini-copy of gtk_window_move_resize() here.
4013 gtk_window_compute_configure_request (window,
4018 /* We update this because we are going to go ahead
4019 * and gdk_window_resize() below, rather than
4022 info->last.configure_request.width = configure_request.width;
4023 info->last.configure_request.height = configure_request.height;
4025 /* and allocate the window - this is normally done
4026 * in move_resize in response to configure notify
4028 allocation.width = configure_request.width;
4029 allocation.height = configure_request.height;
4030 gtk_widget_size_allocate (widget, &allocation);
4032 /* Then we guarantee we have a realize */
4033 was_realized = FALSE;
4034 if (!GTK_WIDGET_REALIZED (widget))
4036 gtk_widget_realize (widget);
4037 was_realized = TRUE;
4040 /* Must be done after the windows are realized,
4041 * so that the decorations can be read
4043 gtk_decorated_window_calculate_frame_size (window);
4045 /* We only send configure request if we didn't just finish
4046 * creating the window; if we just created the window
4047 * then we created it with widget->allocation anyhow.
4050 gdk_window_move_resize (widget->window,
4051 configure_request.x,
4052 configure_request.y,
4053 configure_request.width,
4054 configure_request.height);
4057 gtk_container_check_resize (container);
4059 gtk_widget_map (widget);
4061 /* Try to make sure that we have some focused widget
4063 if (!window->focus_widget && !GTK_IS_PLUG (window))
4064 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4067 gtk_grab_add (widget);
4071 gtk_window_hide (GtkWidget *widget)
4073 GtkWindow *window = GTK_WINDOW (widget);
4075 GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4076 gtk_widget_unmap (widget);
4079 gtk_grab_remove (widget);
4083 gtk_window_map (GtkWidget *widget)
4085 GtkWindow *window = GTK_WINDOW (widget);
4086 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4087 GdkWindow *toplevel;
4089 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4091 if (window->bin.child &&
4092 GTK_WIDGET_VISIBLE (window->bin.child) &&
4093 !GTK_WIDGET_MAPPED (window->bin.child))
4094 gtk_widget_map (window->bin.child);
4097 toplevel = window->frame;
4099 toplevel = widget->window;
4101 if (window->maximize_initially)
4102 gdk_window_maximize (toplevel);
4104 gdk_window_unmaximize (toplevel);
4106 if (window->stick_initially)
4107 gdk_window_stick (toplevel);
4109 gdk_window_unstick (toplevel);
4111 if (window->iconify_initially)
4112 gdk_window_iconify (toplevel);
4114 gdk_window_deiconify (toplevel);
4116 if (priv->fullscreen_initially)
4117 gdk_window_fullscreen (toplevel);
4119 gdk_window_unfullscreen (toplevel);
4121 gdk_window_set_keep_above (toplevel, priv->above_initially);
4123 gdk_window_set_keep_below (toplevel, priv->below_initially);
4125 /* No longer use the default settings */
4126 window->need_default_size = FALSE;
4127 window->need_default_position = FALSE;
4129 if (priv->reset_type_hint)
4131 /* We should only reset the type hint when the application
4132 * used gtk_window_set_type_hint() to change the hint.
4133 * Some applications use X directly to change the properties;
4134 * in that case, we shouldn't overwrite what they did.
4136 gdk_window_set_type_hint (widget->window, priv->type_hint);
4137 priv->reset_type_hint = FALSE;
4140 gdk_window_show (widget->window);
4143 gdk_window_show (window->frame);
4145 if (!disable_startup_notification &&
4146 !sent_startup_notification)
4148 sent_startup_notification = TRUE;
4149 gdk_notify_startup_complete ();
4154 gtk_window_map_event (GtkWidget *widget,
4157 if (!GTK_WIDGET_MAPPED (widget))
4159 /* we should be be unmapped, but are getting a MapEvent, this may happen
4160 * to toplevel XWindows if mapping was intercepted by a window manager
4161 * and an unmap request occoured while the MapRequestEvent was still
4162 * being handled. we work around this situaiton here by re-requesting
4163 * the window being unmapped. more details can be found in:
4164 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4166 gdk_window_hide (widget->window);
4172 gtk_window_unmap (GtkWidget *widget)
4174 GtkWindow *window = GTK_WINDOW (widget);
4175 GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
4176 GtkWindowGeometryInfo *info;
4177 GdkWindowState state;
4179 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4181 gdk_window_withdraw (window->frame);
4183 gdk_window_withdraw (widget->window);
4185 window->configure_request_count = 0;
4186 window->configure_notify_received = FALSE;
4188 /* on unmap, we reset the default positioning of the window,
4189 * so it's placed again, but we don't reset the default
4190 * size of the window, so it's remembered.
4192 window->need_default_position = TRUE;
4194 info = gtk_window_get_geometry_info (window, FALSE);
4197 info->initial_pos_set = FALSE;
4198 info->position_constraints_changed = FALSE;
4201 state = gdk_window_get_state (widget->window);
4202 window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
4203 window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
4204 window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
4205 priv->above_initially = state & GDK_WINDOW_STATE_ABOVE;
4206 priv->below_initially = state & GDK_WINDOW_STATE_BELOW;
4210 gtk_window_realize (GtkWidget *widget)
4213 GdkWindow *parent_window;
4214 GdkWindowAttr attributes;
4215 gint attributes_mask;
4216 GtkWindowPrivate *priv;
4218 window = GTK_WINDOW (widget);
4220 priv = GTK_WINDOW_GET_PRIVATE (window);
4222 /* ensure widget tree is properly size allocated */
4223 if (widget->allocation.x == -1 &&
4224 widget->allocation.y == -1 &&
4225 widget->allocation.width == 1 &&
4226 widget->allocation.height == 1)
4228 GtkRequisition requisition;
4229 GtkAllocation allocation = { 0, 0, 200, 200 };
4231 gtk_widget_size_request (widget, &requisition);
4232 if (requisition.width || requisition.height)
4234 /* non-empty window */
4235 allocation.width = requisition.width;
4236 allocation.height = requisition.height;
4238 gtk_widget_size_allocate (widget, &allocation);
4240 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4242 g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
4245 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4247 switch (window->type)
4249 case GTK_WINDOW_TOPLEVEL:
4250 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4252 case GTK_WINDOW_POPUP:
4253 attributes.window_type = GDK_WINDOW_TEMP;
4256 g_warning (G_STRLOC": Unknown window type %d!", window->type);
4260 attributes.title = window->title;
4261 attributes.wmclass_name = window->wmclass_name;
4262 attributes.wmclass_class = window->wmclass_class;
4263 attributes.wclass = GDK_INPUT_OUTPUT;
4264 attributes.visual = gtk_widget_get_visual (widget);
4265 attributes.colormap = gtk_widget_get_colormap (widget);
4267 if (window->has_frame)
4269 attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
4270 attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
4271 attributes.event_mask = (GDK_EXPOSURE_MASK |
4272 GDK_KEY_PRESS_MASK |
4273 GDK_ENTER_NOTIFY_MASK |
4274 GDK_LEAVE_NOTIFY_MASK |
4275 GDK_FOCUS_CHANGE_MASK |
4276 GDK_STRUCTURE_MASK |
4277 GDK_BUTTON_MOTION_MASK |
4278 GDK_POINTER_MOTION_HINT_MASK |
4279 GDK_BUTTON_PRESS_MASK |
4280 GDK_BUTTON_RELEASE_MASK);
4282 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4284 window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4285 &attributes, attributes_mask);
4287 gdk_window_set_user_data (window->frame, widget);
4289 attributes.window_type = GDK_WINDOW_CHILD;
4290 attributes.x = window->frame_left;
4291 attributes.y = window->frame_top;
4293 attributes_mask = GDK_WA_X | GDK_WA_Y;
4295 parent_window = window->frame;
4297 g_signal_connect (window,
4299 G_CALLBACK (gtk_window_event),
4304 attributes_mask = 0;
4305 parent_window = gtk_widget_get_root_window (widget);
4308 attributes.width = widget->allocation.width;
4309 attributes.height = widget->allocation.height;
4310 attributes.event_mask = gtk_widget_get_events (widget);
4311 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4312 GDK_KEY_PRESS_MASK |
4313 GDK_KEY_RELEASE_MASK |
4314 GDK_ENTER_NOTIFY_MASK |
4315 GDK_LEAVE_NOTIFY_MASK |
4316 GDK_FOCUS_CHANGE_MASK |
4317 GDK_STRUCTURE_MASK);
4319 attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
4320 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
4321 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
4323 widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
4325 gdk_window_enable_synchronized_configure (widget->window);
4327 gdk_window_set_user_data (widget->window, window);
4329 widget->style = gtk_style_attach (widget->style, widget->window);
4330 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4332 gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
4334 /* This is a bad hack to set the window background. */
4335 gtk_window_paint (widget, NULL);
4337 if (window->transient_parent &&
4338 GTK_WIDGET_REALIZED (window->transient_parent))
4339 gdk_window_set_transient_for (widget->window,
4340 GTK_WIDGET (window->transient_parent)->window);
4342 if (window->wm_role)
4343 gdk_window_set_role (widget->window, window->wm_role);
4345 if (!window->decorated)
4346 gdk_window_set_decorations (widget->window, 0);
4348 if (!priv->deletable)
4349 gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4351 gdk_window_set_type_hint (widget->window, priv->type_hint);
4353 if (gtk_window_get_skip_pager_hint (window))
4354 gdk_window_set_skip_pager_hint (widget->window, TRUE);
4356 if (gtk_window_get_skip_taskbar_hint (window))
4357 gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
4359 if (gtk_window_get_accept_focus (window))
4360 gdk_window_set_accept_focus (widget->window, TRUE);
4362 gdk_window_set_accept_focus (widget->window, FALSE);
4364 if (gtk_window_get_focus_on_map (window))
4365 gdk_window_set_focus_on_map (widget->window, TRUE);
4367 gdk_window_set_focus_on_map (widget->window, FALSE);
4370 gdk_window_set_modal_hint (widget->window, TRUE);
4372 gdk_window_set_modal_hint (widget->window, FALSE);
4375 gtk_window_realize_icon (window);
4379 gtk_window_unrealize (GtkWidget *widget)
4382 GtkWindowGeometryInfo *info;
4384 window = GTK_WINDOW (widget);
4386 /* On unrealize, we reset the size of the window such
4387 * that we will re-apply the default sizing stuff
4388 * next time we show the window.
4390 * Default positioning is reset on unmap, instead of unrealize.
4392 window->need_default_size = TRUE;
4393 info = gtk_window_get_geometry_info (window, FALSE);
4396 info->resize_width = -1;
4397 info->resize_height = -1;
4398 info->last.configure_request.x = 0;
4399 info->last.configure_request.y = 0;
4400 info->last.configure_request.width = -1;
4401 info->last.configure_request.height = -1;
4402 /* be sure we reset geom hints on re-realize */
4403 info->last.flags = 0;
4408 gdk_window_set_user_data (window->frame, NULL);
4409 gdk_window_destroy (window->frame);
4410 window->frame = NULL;
4414 gtk_window_unrealize_icon (window);
4416 (* GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize) (widget);
4420 gtk_window_size_request (GtkWidget *widget,
4421 GtkRequisition *requisition)
4426 window = GTK_WINDOW (widget);
4427 bin = GTK_BIN (window);
4429 requisition->width = GTK_CONTAINER (window)->border_width * 2;
4430 requisition->height = GTK_CONTAINER (window)->border_width * 2;
4432 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
4434 GtkRequisition child_requisition;
4436 gtk_widget_size_request (bin->child, &child_requisition);
4438 requisition->width += child_requisition.width;
4439 requisition->height += child_requisition.height;
4444 gtk_window_size_allocate (GtkWidget *widget,
4445 GtkAllocation *allocation)
4448 GtkAllocation child_allocation;
4450 window = GTK_WINDOW (widget);
4451 widget->allocation = *allocation;
4453 if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
4455 child_allocation.x = GTK_CONTAINER (window)->border_width;
4456 child_allocation.y = GTK_CONTAINER (window)->border_width;
4457 child_allocation.width =
4458 MAX (1, (gint)allocation->width - child_allocation.x * 2);
4459 child_allocation.height =
4460 MAX (1, (gint)allocation->height - child_allocation.y * 2);
4462 gtk_widget_size_allocate (window->bin.child, &child_allocation);
4465 if (GTK_WIDGET_REALIZED (widget) && window->frame)
4467 gdk_window_resize (window->frame,
4468 allocation->width + window->frame_left + window->frame_right,
4469 allocation->height + window->frame_top + window->frame_bottom);
4474 gtk_window_event (GtkWidget *widget, GdkEvent *event)
4477 gboolean return_val;
4479 window = GTK_WINDOW (widget);
4481 if (window->frame && (event->any.window == window->frame))
4483 if ((event->type != GDK_KEY_PRESS) &&
4484 (event->type != GDK_KEY_RELEASE) &&
4485 (event->type != GDK_FOCUS_CHANGE))
4487 g_signal_stop_emission_by_name (widget, "event");
4489 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
4494 g_object_unref (event->any.window);
4495 event->any.window = g_object_ref (widget->window);
4503 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
4505 GdkEventConfigure *configure_event;
4508 switch (event->type)
4511 configure_event = (GdkEventConfigure *)event;
4513 /* Invalidate the decorations */
4516 rect.width = configure_event->width;
4517 rect.height = configure_event->height;
4519 gdk_window_invalidate_rect (window->frame, &rect, FALSE);
4521 /* Pass on the (modified) configure event */
4522 configure_event->width -= window->frame_left + window->frame_right;
4523 configure_event->height -= window->frame_top + window->frame_bottom;
4524 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
4533 gtk_window_configure_event (GtkWidget *widget,
4534 GdkEventConfigure *event)
4536 GtkWindow *window = GTK_WINDOW (widget);
4537 gboolean expected_reply = window->configure_request_count > 0;
4539 /* window->configure_request_count incremented for each
4540 * configure request, and decremented to a min of 0 for
4541 * each configure notify.
4543 * All it means is that we know we will get at least
4544 * window->configure_request_count more configure notifies.
4545 * We could get more configure notifies than that; some
4546 * of the configure notifies we get may be unrelated to
4547 * the configure requests. But we will get at least
4548 * window->configure_request_count notifies.
4551 if (window->configure_request_count > 0)
4552 window->configure_request_count -= 1;
4554 /* As an optimization, we avoid a resize when possible.
4556 * The only times we can avoid a resize are:
4557 * - we know only the position changed, not the size
4558 * - we know we have made more requests and so will get more
4559 * notifies and can wait to resize when we get them
4562 if (!expected_reply &&
4563 (widget->allocation.width == event->width &&
4564 widget->allocation.height == event->height))
4566 gdk_window_configure_finished (widget->window);
4571 * If we do need to resize, we do that by:
4572 * - filling in widget->allocation with the new size
4573 * - setting configure_notify_received to TRUE
4574 * for use in gtk_window_move_resize()
4575 * - queueing a resize, leading to invocation of
4576 * gtk_window_move_resize() in an idle handler
4580 window->configure_notify_received = TRUE;
4582 widget->allocation.width = event->width;
4583 widget->allocation.height = event->height;
4585 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4590 /* the accel_key and accel_mods fields of the key have to be setup
4591 * upon calling this function. it'll then return whether that key
4592 * is at all used as accelerator, and if so will OR in the
4593 * accel_flags member of the key.
4596 _gtk_window_query_nonaccels (GtkWindow *window,
4598 GdkModifierType accel_mods)
4600 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4602 /* movement keys are considered locked accels */
4605 static const guint bindings[] = {
4606 GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
4607 GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
4611 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
4612 if (bindings[i] == accel_key)
4616 /* mnemonics are considered locked accels */
4617 if (accel_mods == window->mnemonic_modifier)
4619 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4620 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
4628 * gtk_window_propagate_key_event:
4629 * @window: a #GtkWindow
4630 * @event: a #GdkEventKey
4632 * Propagate a key press or release event to the focus widget and
4633 * up the focus container chain until a widget handles @event.
4634 * This is normally called by the default ::key_press_event and
4635 * ::key_release_event handlers for toplevel windows,
4636 * however in some cases it may be useful to call this directly when
4637 * overriding the standard key handling for a toplevel window.
4639 * Return value: %TRUE if a widget in the focus chain handled the event.
4642 gtk_window_propagate_key_event (GtkWindow *window,
4645 gboolean handled = FALSE;
4646 GtkWidget *widget, *focus;
4648 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4650 widget = GTK_WIDGET (window);
4651 focus = window->focus_widget;
4653 g_object_ref (focus);
4656 focus && focus != widget &&
4657 gtk_widget_get_toplevel (focus) == widget)
4661 if (GTK_WIDGET_IS_SENSITIVE (focus))
4662 handled = gtk_widget_event (focus, (GdkEvent*) event);
4664 parent = focus->parent;
4666 g_object_ref (parent);
4668 g_object_unref (focus);
4674 g_object_unref (focus);
4680 gtk_window_key_press_event (GtkWidget *widget,
4683 GtkWindow *window = GTK_WINDOW (widget);
4684 gboolean handled = FALSE;
4686 /* handle mnemonics and accelerators */
4688 handled = gtk_window_activate_key (window, event);
4690 /* handle focus widget key events */
4692 handled = gtk_window_propagate_key_event (window, event);
4694 /* Chain up, invokes binding set */
4696 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
4702 gtk_window_key_release_event (GtkWidget *widget,
4705 GtkWindow *window = GTK_WINDOW (widget);
4706 gboolean handled = FALSE;
4708 /* handle focus widget key events */
4710 handled = gtk_window_propagate_key_event (window, event);
4712 /* Chain up, invokes binding set */
4714 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
4720 gtk_window_real_activate_default (GtkWindow *window)
4722 gtk_window_activate_default (window);
4726 gtk_window_real_activate_focus (GtkWindow *window)
4728 gtk_window_activate_focus (window);
4732 gtk_window_move_focus (GtkWindow *window,
4733 GtkDirectionType dir)
4735 gtk_widget_child_focus (GTK_WIDGET (window), dir);
4737 if (!GTK_CONTAINER (window)->focus_child)
4738 gtk_window_set_focus (window, NULL);
4742 gtk_window_enter_notify_event (GtkWidget *widget,
4743 GdkEventCrossing *event)
4749 gtk_window_leave_notify_event (GtkWidget *widget,
4750 GdkEventCrossing *event)
4756 do_focus_change (GtkWidget *widget,
4759 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4761 g_object_ref (widget);
4764 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4766 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4768 fevent->focus_change.type = GDK_FOCUS_CHANGE;
4769 fevent->focus_change.window = widget->window;
4771 g_object_ref (widget->window);
4772 fevent->focus_change.in = in;
4774 gtk_widget_event (widget, fevent);
4776 g_object_notify (G_OBJECT (widget), "has-focus");
4778 g_object_unref (widget);
4779 gdk_event_free (fevent);
4783 gtk_window_focus_in_event (GtkWidget *widget,
4784 GdkEventFocus *event)
4786 GtkWindow *window = GTK_WINDOW (widget);
4788 /* It appears spurious focus in events can occur when
4789 * the window is hidden. So we'll just check to see if
4790 * the window is visible before actually handling the
4793 if (GTK_WIDGET_VISIBLE (widget))
4795 _gtk_window_set_has_toplevel_focus (window, TRUE);
4796 _gtk_window_set_is_active (window, TRUE);
4803 gtk_window_focus_out_event (GtkWidget *widget,
4804 GdkEventFocus *event)
4806 GtkWindow *window = GTK_WINDOW (widget);
4808 _gtk_window_set_has_toplevel_focus (window, FALSE);
4809 _gtk_window_set_is_active (window, FALSE);
4814 static GdkAtom atom_rcfiles = GDK_NONE;
4815 static GdkAtom atom_iconthemes = GDK_NONE;
4818 send_client_message_to_embedded_windows (GtkWidget *widget,
4819 GdkAtom message_type)
4821 GList *embedded_windows;
4823 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
4824 if (embedded_windows)
4826 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4829 for (i = 0; i < 5; i++)
4830 send_event->client.data.l[i] = 0;
4831 send_event->client.data_format = 32;
4832 send_event->client.message_type = message_type;
4834 while (embedded_windows)
4836 guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4837 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4838 embedded_windows = embedded_windows->next;
4841 gdk_event_free (send_event);
4846 gtk_window_client_event (GtkWidget *widget,
4847 GdkEventClient *event)
4851 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
4852 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
4855 if (event->message_type == atom_rcfiles)
4857 send_client_message_to_embedded_windows (widget, atom_rcfiles);
4858 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4861 if (event->message_type == atom_iconthemes)
4863 send_client_message_to_embedded_windows (widget, atom_iconthemes);
4864 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
4871 gtk_window_check_resize (GtkContainer *container)
4873 GtkWindow *window = GTK_WINDOW (container);
4875 if (GTK_WIDGET_VISIBLE (container))
4876 gtk_window_move_resize (window);
4880 gtk_window_focus (GtkWidget *widget,
4881 GtkDirectionType direction)
4885 GtkContainer *container;
4886 GtkWidget *old_focus_child;
4889 container = GTK_CONTAINER (widget);
4890 window = GTK_WINDOW (widget);
4891 bin = GTK_BIN (widget);
4893 old_focus_child = container->focus_child;
4895 /* We need a special implementation here to deal properly with wrapping
4896 * around in the tab chain without the danger of going into an
4899 if (old_focus_child)
4901 if (gtk_widget_child_focus (old_focus_child, direction))
4905 if (window->focus_widget)
4907 if (direction == GTK_DIR_LEFT ||
4908 direction == GTK_DIR_RIGHT ||
4909 direction == GTK_DIR_UP ||
4910 direction == GTK_DIR_DOWN)
4915 /* Wrapped off the end, clear the focus setting for the toplpevel */
4916 parent = window->focus_widget->parent;
4919 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4920 parent = GTK_WIDGET (parent)->parent;
4923 gtk_window_set_focus (GTK_WINDOW (container), NULL);
4926 /* Now try to focus the first widget in the window */
4929 if (gtk_widget_child_focus (bin->child, direction))
4937 gtk_window_real_set_focus (GtkWindow *window,
4940 GtkWidget *old_focus = window->focus_widget;
4941 gboolean had_default = FALSE;
4942 gboolean focus_had_default = FALSE;
4943 gboolean old_focus_had_default = FALSE;
4947 g_object_ref (old_focus);
4948 g_object_freeze_notify (G_OBJECT (old_focus));
4949 old_focus_had_default = GTK_WIDGET_HAS_DEFAULT (old_focus);
4953 g_object_ref (focus);
4954 g_object_freeze_notify (G_OBJECT (focus));
4955 focus_had_default = GTK_WIDGET_HAS_DEFAULT (focus);
4958 if (window->default_widget)
4959 had_default = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4961 if (window->focus_widget)
4963 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4964 (window->focus_widget != window->default_widget))
4966 GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4967 gtk_widget_queue_draw (window->focus_widget);
4969 if (window->default_widget)
4970 GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4973 window->focus_widget = NULL;
4975 if (window->has_focus)
4976 do_focus_change (old_focus, FALSE);
4978 g_object_notify (G_OBJECT (old_focus), "is-focus");
4981 /* The above notifications may have set a new focus widget,
4982 * if so, we don't want to override it.
4984 if (focus && !window->focus_widget)
4986 window->focus_widget = focus;
4988 if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4989 (window->focus_widget != window->default_widget))
4991 if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4992 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4994 if (window->default_widget)
4995 GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4998 if (window->has_focus)
4999 do_focus_change (window->focus_widget, TRUE);
5001 g_object_notify (G_OBJECT (window->focus_widget), "is-focus");
5004 /* If the default widget changed, a redraw will have been queued
5005 * on the old and new default widgets by gtk_window_set_default(), so
5006 * we only have to worry about the case where it didn't change.
5007 * We'll sometimes queue a draw twice on the new widget but that
5010 if (window->default_widget &&
5011 (had_default != GTK_WIDGET_HAS_DEFAULT (window->default_widget)))
5012 gtk_widget_queue_draw (window->default_widget);
5016 if (old_focus_had_default != GTK_WIDGET_HAS_DEFAULT (old_focus))
5017 gtk_widget_queue_draw (old_focus);
5019 g_object_thaw_notify (G_OBJECT (old_focus));
5020 g_object_unref (old_focus);
5024 if (focus_had_default != GTK_WIDGET_HAS_DEFAULT (focus))
5025 gtk_widget_queue_draw (focus);
5027 g_object_thaw_notify (G_OBJECT (focus));
5028 g_object_unref (focus);
5033 * _gtk_window_unset_focus_and_default:
5034 * @window: a #GtkWindow
5035 * @widget: a widget inside of @window
5037 * Checks whether the focus and default widgets of @window are
5038 * @widget or a descendent of @widget, and if so, unset them.
5041 _gtk_window_unset_focus_and_default (GtkWindow *window,
5047 g_object_ref (window);
5048 g_object_ref (widget);
5050 if (GTK_CONTAINER (widget->parent)->focus_child == widget)
5052 child = window->focus_widget;
5054 while (child && child != widget)
5055 child = child->parent;
5057 if (child == widget)
5058 gtk_window_set_focus (GTK_WINDOW (window), NULL);
5061 child = window->default_widget;
5063 while (child && child != widget)
5064 child = child->parent;
5066 if (child == widget)
5067 gtk_window_set_default (window, NULL);
5069 g_object_unref (widget);
5070 g_object_unref (window);
5073 /*********************************
5074 * Functions related to resizing *
5075 *********************************/
5077 /* This function doesn't constrain to geometry hints */
5079 gtk_window_compute_configure_request_size (GtkWindow *window,
5083 GtkRequisition requisition;
5084 GtkWindowGeometryInfo *info;
5088 * - we've done a size request
5091 widget = GTK_WIDGET (window);
5093 info = gtk_window_get_geometry_info (window, FALSE);
5095 if (window->need_default_size)
5097 gtk_widget_get_child_requisition (widget, &requisition);
5099 /* Default to requisition */
5100 *width = requisition.width;
5101 *height = requisition.height;
5103 /* If window is empty so requests 0, default to random nonzero size */
5104 if (*width == 0 && *height == 0)
5110 /* Override requisition with default size */
5114 gint base_width = 0;
5115 gint base_height = 0;
5117 gint height_inc = 1;
5119 if (info->default_is_geometry &&
5120 (info->default_width > 0 || info->default_height > 0))
5122 GdkGeometry geometry;
5125 gtk_window_compute_hints (window, &geometry, &flags);
5127 if (flags & GDK_HINT_BASE_SIZE)
5129 base_width = geometry.base_width;
5130 base_height = geometry.base_height;
5132 else if (flags & GDK_HINT_MIN_SIZE)
5134 base_width = geometry.min_width;
5135 base_height = geometry.min_height;
5137 if (flags & GDK_HINT_RESIZE_INC)
5139 width_inc = geometry.width_inc;
5140 height_inc = geometry.height_inc;
5144 if (info->default_width > 0)
5145 *width = info->default_width * width_inc + base_width;
5147 if (info->default_height > 0)
5148 *height = info->default_height * height_inc + base_height;
5153 /* Default to keeping current size */
5154 *width = widget->allocation.width;
5155 *height = widget->allocation.height;
5158 /* Override any size with gtk_window_resize() values */
5161 if (info->resize_width > 0)
5162 *width = info->resize_width;
5164 if (info->resize_height > 0)
5165 *height = info->resize_height;
5169 static GtkWindowPosition
5170 get_effective_position (GtkWindow *window)
5172 GtkWindowPosition pos = window->position;
5173 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5174 (window->transient_parent == NULL ||
5175 !GTK_WIDGET_MAPPED (window->transient_parent)))
5176 pos = GTK_WIN_POS_NONE;
5182 get_center_monitor_of_window (GtkWindow *window)
5184 /* We could try to sort out the relative positions of the monitors and
5185 * stuff, or we could just be losers and assume you have a row
5186 * or column of monitors.
5188 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5192 get_monitor_containing_pointer (GtkWindow *window)
5196 GdkScreen *window_screen;
5197 GdkScreen *pointer_screen;
5199 window_screen = gtk_window_check_screen (window);
5200 gdk_display_get_pointer (gdk_screen_get_display (window_screen),
5204 if (pointer_screen == window_screen)
5205 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5213 center_window_on_monitor (GtkWindow *window,
5219 GdkRectangle monitor;
5222 monitor_num = get_monitor_containing_pointer (window);
5224 if (monitor_num == -1)
5225 monitor_num = get_center_monitor_of_window (window);
5227 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5228 monitor_num, &monitor);
5230 *x = (monitor.width - w) / 2 + monitor.x;
5231 *y = (monitor.height - h) / 2 + monitor.y;
5233 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5234 * and WM decorations.
5243 clamp_window_to_rectangle (gint *x,
5247 const GdkRectangle *rect)
5249 gint outside_w, outside_h;
5251 outside_w = (*x + w) - (rect->x + rect->width);
5255 outside_h = (*y + h) - (rect->y + rect->height);
5259 /* if larger than the screen, center on the screen. */
5261 *x += (rect->x - *x) / 2;
5263 *y += (rect->y - *y) / 2;
5268 gtk_window_compute_configure_request (GtkWindow *window,
5269 GdkRectangle *request,
5270 GdkGeometry *geometry,
5273 GdkGeometry new_geometry;
5277 GtkWindowPosition pos;
5278 GtkWidget *parent_widget;
5279 GtkWindowGeometryInfo *info;
5283 widget = GTK_WIDGET (window);
5285 screen = gtk_window_check_screen (window);
5287 gtk_widget_size_request (widget, NULL);
5288 gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
5290 gtk_window_compute_hints (window, &new_geometry, &new_flags);
5291 gtk_window_constrain_size (window,
5292 &new_geometry, new_flags,
5296 parent_widget = (GtkWidget*) window->transient_parent;
5298 pos = get_effective_position (window);
5299 info = gtk_window_get_geometry_info (window, FALSE);
5301 /* by default, don't change position requested */
5304 x = info->last.configure_request.x;
5305 y = info->last.configure_request.y;
5314 if (window->need_default_position)
5317 /* FIXME this all interrelates with window gravity.
5318 * For most of them I think we want to set GRAVITY_CENTER.
5320 * Not sure how to go about that.
5325 /* here we are only handling CENTER_ALWAYS
5326 * as it relates to default positioning,
5327 * where it's equivalent to simply CENTER
5329 case GTK_WIN_POS_CENTER_ALWAYS:
5330 case GTK_WIN_POS_CENTER:
5331 center_window_on_monitor (window, w, h, &x, &y);
5334 case GTK_WIN_POS_CENTER_ON_PARENT:
5337 GdkRectangle monitor;
5340 g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
5342 if (parent_widget->window != NULL)
5343 monitor_num = gdk_screen_get_monitor_at_window (screen,
5344 parent_widget->window);
5348 gdk_window_get_origin (parent_widget->window,
5351 x = ox + (parent_widget->allocation.width - w) / 2;
5352 y = oy + (parent_widget->allocation.height - h) / 2;
5354 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5355 * WM decorations. If parent wasn't on a monitor, just
5358 if (monitor_num >= 0)
5360 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5361 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5366 case GTK_WIN_POS_MOUSE:
5368 gint screen_width = gdk_screen_get_width (screen);
5369 gint screen_height = gdk_screen_get_height (screen);
5371 GdkRectangle monitor;
5372 GdkScreen *pointer_screen;
5375 gdk_display_get_pointer (gdk_screen_get_display (screen),
5379 if (pointer_screen == screen)
5380 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
5386 x = CLAMP (x, 0, screen_width - w);
5387 y = CLAMP (y, 0, screen_height - h);
5389 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5390 * WM decorations. Don't try to figure out what's going
5391 * on if the mouse wasn't inside a monitor.
5393 if (monitor_num >= 0)
5395 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5396 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5404 } /* if (window->need_default_position) */
5406 if (window->need_default_position && info &&
5407 info->initial_pos_set)
5409 x = info->initial_x;
5410 y = info->initial_y;
5411 gtk_window_constrain_position (window, w, h, &x, &y);
5417 request->height = h;
5420 *geometry = new_geometry;
5426 gtk_window_constrain_position (GtkWindow *window,
5432 /* See long comments in gtk_window_move_resize()
5433 * on when it's safe to call this function.
5435 if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
5437 gint center_x, center_y;
5439 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
5447 gtk_window_move_resize (GtkWindow *window)
5451 * First we determine whether any information has changed that would
5452 * cause us to revise our last configure request. If we would send
5453 * a different configure request from last time, then
5454 * configure_request_size_changed = TRUE or
5455 * configure_request_pos_changed = TRUE. configure_request_size_changed
5456 * may be true due to new hints, a gtk_window_resize(), or whatever.
5457 * configure_request_pos_changed may be true due to gtk_window_set_position()
5458 * or gtk_window_move().
5460 * If the configure request has changed, we send off a new one. To
5461 * ensure GTK+ invariants are maintained (resize queue does what it
5462 * should), we go ahead and size_allocate the requested size in this
5465 * If the configure request has not changed, we don't ever resend
5466 * it, because it could mean fighting the user or window manager.
5469 * To prepare the configure request, we come up with a base size/pos:
5470 * - the one from gtk_window_move()/gtk_window_resize()
5471 * - else default_width, default_height if we haven't ever
5473 * - else the size request if we haven't ever been mapped,
5474 * as a substitute default size
5475 * - else the current size of the window, as received from
5476 * configure notifies (i.e. the current allocation)
5478 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
5479 * the position request to be centered.
5482 GtkContainer *container;
5483 GtkWindowGeometryInfo *info;
5484 GdkGeometry new_geometry;
5486 GdkRectangle new_request;
5487 gboolean configure_request_size_changed;
5488 gboolean configure_request_pos_changed;
5489 gboolean hints_changed; /* do we need to send these again */
5490 GtkWindowLastGeometryInfo saved_last_info;
5492 widget = GTK_WIDGET (window);
5493 container = GTK_CONTAINER (widget);
5494 info = gtk_window_get_geometry_info (window, TRUE);
5496 configure_request_size_changed = FALSE;
5497 configure_request_pos_changed = FALSE;
5499 gtk_window_compute_configure_request (window, &new_request,
5500 &new_geometry, &new_flags);
5502 /* This check implies the invariant that we never set info->last
5503 * without setting the hints and sending off a configure request.
5505 * If we change info->last without sending the request, we may
5508 if (info->last.configure_request.x != new_request.x ||
5509 info->last.configure_request.y != new_request.y)
5510 configure_request_pos_changed = TRUE;
5512 if ((info->last.configure_request.width != new_request.width ||
5513 info->last.configure_request.height != new_request.height))
5514 configure_request_size_changed = TRUE;
5516 hints_changed = FALSE;
5518 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
5519 &new_geometry, new_flags))
5521 hints_changed = TRUE;
5524 /* Position Constraints
5525 * ====================
5527 * POS_CENTER_ALWAYS is conceptually a constraint rather than
5528 * a default. The other POS_ values are used only when the
5529 * window is shown, not after that.
5531 * However, we can't implement a position constraint as
5532 * "anytime the window size changes, center the window"
5533 * because this may well end up fighting the WM or user. In
5534 * fact it gets in an infinite loop with at least one WM.
5536 * Basically, applications are in no way in a position to
5537 * constrain the position of a window, with one exception:
5538 * override redirect windows. (Really the intended purpose
5539 * of CENTER_ALWAYS anyhow, I would think.)
5541 * So the way we implement this "constraint" is to say that when WE
5542 * cause a move or resize, i.e. we make a configure request changing
5543 * window size, we recompute the CENTER_ALWAYS position to reflect
5544 * the new window size, and include it in our request. Also, if we
5545 * just turned on CENTER_ALWAYS we snap to center with a new
5546 * request. Otherwise, if we are just NOTIFIED of a move or resize
5547 * done by someone else e.g. the window manager, we do NOT send a
5548 * new configure request.
5550 * For override redirect windows, this works fine; all window
5551 * sizes are from our configure requests. For managed windows,
5552 * it is at least semi-sane, though who knows what the
5553 * app author is thinking.
5556 /* This condition should be kept in sync with the condition later on
5557 * that determines whether we send a configure request. i.e. we
5558 * should do this position constraining anytime we were going to
5559 * send a configure request anyhow, plus when constraints have
5562 if (configure_request_pos_changed ||
5563 configure_request_size_changed ||
5565 info->position_constraints_changed)
5567 /* We request the constrained position if:
5568 * - we were changing position, and need to clamp
5569 * the change to the constraint
5570 * - we're changing the size anyway
5571 * - set_position() was called to toggle CENTER_ALWAYS on
5574 gtk_window_constrain_position (window,
5580 /* Update whether we need to request a move */
5581 if (info->last.configure_request.x != new_request.x ||
5582 info->last.configure_request.y != new_request.y)
5583 configure_request_pos_changed = TRUE;
5585 configure_request_pos_changed = FALSE;
5589 if (window->type == GTK_WINDOW_TOPLEVEL)
5591 int notify_x, notify_y;
5593 /* this is the position from the last configure notify */
5594 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
5596 g_message ("--- %s ---\n"
5597 "last : %d,%d\t%d x %d\n"
5598 "this : %d,%d\t%d x %d\n"
5599 "alloc : %d,%d\t%d x %d\n"
5601 "resize: \t%d x %d\n"
5602 "size_changed: %d pos_changed: %d hints_changed: %d\n"
5603 "configure_notify_received: %d\n"
5604 "configure_request_count: %d\n"
5605 "position_constraints_changed: %d\n",
5606 window->title ? window->title : "(no title)",
5607 info->last.configure_request.x,
5608 info->last.configure_request.y,
5609 info->last.configure_request.width,
5610 info->last.configure_request.height,
5616 widget->allocation.width,
5617 widget->allocation.height,
5618 widget->requisition.width,
5619 widget->requisition.height,
5621 info->resize_height,
5622 configure_request_pos_changed,
5623 configure_request_size_changed,
5625 window->configure_notify_received,
5626 window->configure_request_count,
5627 info->position_constraints_changed);
5631 saved_last_info = info->last;
5632 info->last.geometry = new_geometry;
5633 info->last.flags = new_flags;
5634 info->last.configure_request = new_request;
5636 /* need to set PPosition so the WM will look at our position,
5637 * but we don't want to count PPosition coming and going as a hints
5638 * change for future iterations. So we saved info->last prior to
5642 /* Also, if the initial position was explicitly set, then we always
5643 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
5647 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
5648 * this is an initial map
5651 if ((configure_request_pos_changed ||
5652 info->initial_pos_set ||
5653 (window->need_default_position &&
5654 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
5655 (new_flags & GDK_HINT_POS) == 0)
5657 new_flags |= GDK_HINT_POS;
5658 hints_changed = TRUE;
5661 /* Set hints if necessary
5664 gdk_window_set_geometry_hints (widget->window,
5668 /* handle resizing/moving and widget tree allocation
5670 if (window->configure_notify_received)
5672 GtkAllocation allocation;
5674 /* If we have received a configure event since
5675 * the last time in this function, we need to
5676 * accept our new size and size_allocate child widgets.
5677 * (see gtk_window_configure_event() for more details).
5679 * 1 or more configure notifies may have been received.
5680 * Also, configure_notify_received will only be TRUE
5681 * if all expected configure notifies have been received
5682 * (one per configure request), as an optimization.
5685 window->configure_notify_received = FALSE;
5687 /* gtk_window_configure_event() filled in widget->allocation */
5688 allocation = widget->allocation;
5689 gtk_widget_size_allocate (widget, &allocation);
5691 gdk_window_process_all_updates ();
5693 gdk_window_configure_finished (widget->window);
5695 /* If the configure request changed, it means that
5697 * 1) coincidentally changed hints or widget properties
5698 * impacting the configure request before getting
5699 * a configure notify, or
5700 * 2) some broken widget is changing its size request
5701 * during size allocation, resulting in
5702 * a false appearance of changed configure request.
5704 * For 1), we could just go ahead and ask for the
5705 * new size right now, but doing that for 2)
5706 * might well be fighting the user (and can even
5707 * trigger a loop). Since we really don't want to
5708 * do that, we requeue a resize in hopes that
5709 * by the time it gets handled, the child has seen
5710 * the light and is willing to go along with the
5711 * new size. (this happens for the zvt widget, since
5712 * the size_allocate() above will have stored the
5713 * requisition corresponding to the new size in the
5716 * This doesn't buy us anything for 1), but it shouldn't
5717 * hurt us too badly, since it is what would have
5718 * happened if we had gotten the configure event before
5719 * the new size had been set.
5722 if (configure_request_size_changed ||
5723 configure_request_pos_changed)
5725 /* Don't change the recorded last info after all, because we
5726 * haven't actually updated to the new info yet - we decided
5727 * to postpone our configure request until later.
5729 info->last = saved_last_info;
5731 gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
5734 return; /* Bail out, we didn't really process the move/resize */
5736 else if ((configure_request_size_changed || hints_changed) &&
5737 (widget->allocation.width != new_request.width ||
5738 widget->allocation.height != new_request.height))
5741 /* We are in one of the following situations:
5742 * A. configure_request_size_changed
5743 * our requisition has changed and we need a different window size,
5744 * so we request it from the window manager.
5745 * B. !configure_request_size_changed && hints_changed
5746 * the window manager rejects our size, but we have just changed the
5747 * window manager hints, so there's a chance our request will
5748 * be honoured this time, so we try again.
5750 * However, if the new requisition is the same as the current allocation,
5751 * we don't request it again, since we won't get a ConfigureNotify back from
5752 * the window manager unless it decides to change our requisition. If
5753 * we don't get the ConfigureNotify back, the resize queue will never be run.
5756 /* Now send the configure request */
5757 if (configure_request_pos_changed)
5761 gdk_window_move_resize (window->frame,
5762 new_request.x - window->frame_left,
5763 new_request.y - window->frame_top,
5764 new_request.width + window->frame_left + window->frame_right,
5765 new_request.height + window->frame_top + window->frame_bottom);
5766 gdk_window_resize (widget->window,
5767 new_request.width, new_request.height);
5770 gdk_window_move_resize (widget->window,
5771 new_request.x, new_request.y,
5772 new_request.width, new_request.height);
5774 else /* only size changed */
5777 gdk_window_resize (window->frame,
5778 new_request.width + window->frame_left + window->frame_right,
5779 new_request.height + window->frame_top + window->frame_bottom);
5780 gdk_window_resize (widget->window,
5781 new_request.width, new_request.height);
5784 /* Increment the number of have-not-yet-received-notify requests */
5785 window->configure_request_count += 1;
5787 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5788 * configure event in response to our resizing request.
5789 * the configure event will cause a new resize with
5790 * ->configure_notify_received=TRUE.
5791 * until then, we want to
5792 * - discard expose events
5793 * - coalesce resizes for our children
5794 * - defer any window resizes until the configure event arrived
5795 * to achieve this, we queue a resize for the window, but remove its
5796 * resizing handler, so resizing will not be handled from the next
5797 * idle handler but when the configure event arrives.
5799 * FIXME: we should also dequeue the pending redraws here, since
5800 * we handle those ourselves upon ->configure_notify_received==TRUE.
5802 if (container->resize_mode == GTK_RESIZE_QUEUE)
5804 gtk_widget_queue_resize (widget);
5805 _gtk_container_dequeue_resize_handler (container);
5810 /* Handle any position changes.
5812 if (configure_request_pos_changed)
5816 gdk_window_move (window->frame,
5817 new_request.x - window->frame_left,
5818 new_request.y - window->frame_top);
5821 gdk_window_move (widget->window,
5822 new_request.x, new_request.y);
5825 /* And run the resize queue.
5827 gtk_container_resize_children (container);
5830 /* We have now processed a move/resize since the last position
5831 * constraint change, setting of the initial position, or resize.
5832 * (Not resetting these flags here can lead to infinite loops for
5833 * GTK_RESIZE_IMMEDIATE containers)
5835 info->position_constraints_changed = FALSE;
5836 info->initial_pos_set = FALSE;
5837 info->resize_width = -1;
5838 info->resize_height = -1;
5841 /* Compare two sets of Geometry hints for equality.
5844 gtk_window_compare_hints (GdkGeometry *geometry_a,
5846 GdkGeometry *geometry_b,
5849 if (flags_a != flags_b)
5852 if ((flags_a & GDK_HINT_MIN_SIZE) &&
5853 (geometry_a->min_width != geometry_b->min_width ||
5854 geometry_a->min_height != geometry_b->min_height))
5857 if ((flags_a & GDK_HINT_MAX_SIZE) &&
5858 (geometry_a->max_width != geometry_b->max_width ||
5859 geometry_a->max_height != geometry_b->max_height))
5862 if ((flags_a & GDK_HINT_BASE_SIZE) &&
5863 (geometry_a->base_width != geometry_b->base_width ||
5864 geometry_a->base_height != geometry_b->base_height))
5867 if ((flags_a & GDK_HINT_ASPECT) &&
5868 (geometry_a->min_aspect != geometry_b->min_aspect ||
5869 geometry_a->max_aspect != geometry_b->max_aspect))
5872 if ((flags_a & GDK_HINT_RESIZE_INC) &&
5873 (geometry_a->width_inc != geometry_b->width_inc ||
5874 geometry_a->height_inc != geometry_b->height_inc))
5877 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5878 geometry_a->win_gravity != geometry_b->win_gravity)
5885 _gtk_window_constrain_size (GtkWindow *window,
5891 GtkWindowGeometryInfo *info;
5893 g_return_if_fail (GTK_IS_WINDOW (window));
5895 info = window->geometry_info;
5898 GdkWindowHints flags = info->last.flags;
5899 GdkGeometry *geometry = &info->last.geometry;
5901 gtk_window_constrain_size (window,
5912 gtk_window_constrain_size (GtkWindow *window,
5913 GdkGeometry *geometry,
5920 gdk_window_constrain_size (geometry, flags, width, height,
5921 new_width, new_height);
5924 /* Compute the set of geometry hints and flags for a window
5925 * based on the application set geometry, and requisiition
5926 * of the window. gtk_widget_size_request() must have been
5930 gtk_window_compute_hints (GtkWindow *window,
5931 GdkGeometry *new_geometry,
5935 gint extra_width = 0;
5936 gint extra_height = 0;
5937 GtkWindowGeometryInfo *geometry_info;
5938 GtkRequisition requisition;
5940 widget = GTK_WIDGET (window);
5942 gtk_widget_get_child_requisition (widget, &requisition);
5943 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5947 *new_flags = geometry_info->mask;
5948 *new_geometry = geometry_info->geometry;
5955 if (geometry_info && geometry_info->widget)
5957 GtkRequisition child_requisition;
5959 /* FIXME: This really isn't right. It gets the min size wrong and forces
5960 * callers to do horrible hacks like set a huge usize on the child requisition
5961 * to get the base size right. We really want to find the answers to:
5963 * - If the geometry widget was infinitely big, how much extra space
5964 * would be needed for the stuff around it.
5966 * - If the geometry widget was infinitely small, how big would the
5967 * window still have to be.
5969 * Finding these answers would be a bit of a mess here. (Bug #68668)
5971 gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5973 extra_width = widget->requisition.width - child_requisition.width;
5974 extra_height = widget->requisition.height - child_requisition.height;
5977 /* We don't want to set GDK_HINT_POS in here, we just set it
5978 * in gtk_window_move_resize() when we want the position
5982 if (*new_flags & GDK_HINT_BASE_SIZE)
5984 new_geometry->base_width += extra_width;
5985 new_geometry->base_height += extra_height;
5987 else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5988 (*new_flags & GDK_HINT_RESIZE_INC) &&
5989 ((extra_width != 0) || (extra_height != 0)))
5991 *new_flags |= GDK_HINT_BASE_SIZE;
5993 new_geometry->base_width = extra_width;
5994 new_geometry->base_height = extra_height;
5997 if (*new_flags & GDK_HINT_MIN_SIZE)
5999 if (new_geometry->min_width < 0)
6000 new_geometry->min_width = requisition.width;
6002 new_geometry->min_width += extra_width;
6004 if (new_geometry->min_height < 0)
6005 new_geometry->min_height = requisition.height;
6007 new_geometry->min_height += extra_height;
6009 else if (!window->allow_shrink)
6011 *new_flags |= GDK_HINT_MIN_SIZE;
6013 new_geometry->min_width = requisition.width;
6014 new_geometry->min_height = requisition.height;
6017 if (*new_flags & GDK_HINT_MAX_SIZE)
6019 if (new_geometry->max_width < 0)
6020 new_geometry->max_width = requisition.width;
6022 new_geometry->max_width += extra_width;
6024 if (new_geometry->max_height < 0)
6025 new_geometry->max_height = requisition.height;
6027 new_geometry->max_height += extra_height;
6029 else if (!window->allow_grow)
6031 *new_flags |= GDK_HINT_MAX_SIZE;
6033 new_geometry->max_width = requisition.width;
6034 new_geometry->max_height = requisition.height;
6037 *new_flags |= GDK_HINT_WIN_GRAVITY;
6038 new_geometry->win_gravity = window->gravity;
6041 /***********************
6042 * Redrawing functions *
6043 ***********************/
6046 gtk_window_paint (GtkWidget *widget,
6049 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
6050 GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
6054 gtk_window_expose (GtkWidget *widget,
6055 GdkEventExpose *event)
6057 if (!GTK_WIDGET_APP_PAINTABLE (widget))
6058 gtk_window_paint (widget, &event->area);
6060 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event)
6061 return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event);
6067 * gtk_window_set_has_frame:
6068 * @window: a #GtkWindow
6069 * @setting: a boolean
6071 * (Note: this is a special-purpose function for the framebuffer port,
6072 * that causes GTK+ to draw its own window border. For most applications,
6073 * you want gtk_window_set_decorated() instead, which tells the window
6074 * manager whether to draw the window border.)
6076 * If this function is called on a window with setting of %TRUE, before
6077 * it is realized or showed, it will have a "frame" window around
6078 * @window->window, accessible in @window->frame. Using the signal
6079 * frame_event you can receive all events targeted at the frame.
6081 * This function is used by the linux-fb port to implement managed
6082 * windows, but it could conceivably be used by X-programs that
6083 * want to do their own window decorations.
6087 gtk_window_set_has_frame (GtkWindow *window,
6090 g_return_if_fail (GTK_IS_WINDOW (window));
6091 g_return_if_fail (!GTK_WIDGET_REALIZED (window));
6093 window->has_frame = setting != FALSE;
6097 * gtk_window_get_has_frame:
6098 * @window: a #GtkWindow
6100 * Accessor for whether the window has a frame window exterior to
6101 * @window->window. Gets the value set by gtk_window_set_has_frame ().
6103 * Return value: %TRUE if a frame has been added to the window
6104 * via gtk_window_set_has_frame().
6107 gtk_window_get_has_frame (GtkWindow *window)
6109 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6111 return window->has_frame;
6115 * gtk_window_set_frame_dimensions:
6116 * @window: a #GtkWindow that has a frame
6117 * @left: The width of the left border
6118 * @top: The height of the top border
6119 * @right: The width of the right border
6120 * @bottom: The height of the bottom border
6122 * (Note: this is a special-purpose function intended for the framebuffer
6123 * port; see gtk_window_set_has_frame(). It will have no effect on the
6124 * window border drawn by the window manager, which is the normal
6125 * case when using the X Window system.)
6127 * For windows with frames (see gtk_window_set_has_frame()) this function
6128 * can be used to change the size of the frame border.
6131 gtk_window_set_frame_dimensions (GtkWindow *window,
6139 g_return_if_fail (GTK_IS_WINDOW (window));
6141 widget = GTK_WIDGET (window);
6143 if (window->frame_left == left &&
6144 window->frame_top == top &&
6145 window->frame_right == right &&
6146 window->frame_bottom == bottom)
6149 window->frame_left = left;
6150 window->frame_top = top;
6151 window->frame_right = right;
6152 window->frame_bottom = bottom;
6154 if (GTK_WIDGET_REALIZED (widget) && window->frame)
6156 gint width = widget->allocation.width + left + right;
6157 gint height = widget->allocation.height + top + bottom;
6158 gdk_window_resize (window->frame, width, height);
6159 gtk_decorated_window_move_resize_window (window,
6161 widget->allocation.width,
6162 widget->allocation.height);
6167 * gtk_window_present:
6168 * @window: a #GtkWindow
6170 * Presents a window to the user. This may mean raising the window
6171 * in the stacking order, deiconifying it, moving it to the current
6172 * desktop, and/or giving it the keyboard focus, possibly dependent
6173 * on the user's platform, window manager, and preferences.
6175 * If @window is hidden, this function calls gtk_widget_show()
6178 * This function should be used when the user tries to open a window
6179 * that's already open. Say for example the preferences dialog is
6180 * currently open, and the user chooses Preferences from the menu
6181 * a second time; use gtk_window_present() to move the already-open dialog
6182 * where the user can see it.
6184 * If you are calling this function in response to a user interaction,
6185 * it is preferable to use gtk_window_present_with_time().
6189 gtk_window_present (GtkWindow *window)
6191 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6195 * gtk_window_present_with_time:
6196 * @window: a #GtkWindow
6197 * @timestamp: the timestamp of the user interaction (typically a
6198 * button or key press event) which triggered this call
6200 * Presents a window to the user in response to a user interaction.
6201 * If you need to present a window without a timestamp, use
6202 * gtk_window_present(). See gtk_window_present() for details.
6207 gtk_window_present_with_time (GtkWindow *window,
6212 g_return_if_fail (GTK_IS_WINDOW (window));
6214 widget = GTK_WIDGET (window);
6216 if (GTK_WIDGET_VISIBLE (window))
6218 g_assert (widget->window != NULL);
6220 gdk_window_show (widget->window);
6222 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
6223 if (timestamp == GDK_CURRENT_TIME)
6225 #ifdef GDK_WINDOWING_X11
6226 GdkDisplay *display;
6228 display = gtk_widget_get_display (GTK_WIDGET (window));
6229 timestamp = gdk_x11_display_get_user_time (display);
6231 timestamp = gtk_get_current_event_time ();
6235 gdk_window_focus (widget->window, timestamp);
6239 gtk_widget_show (widget);
6244 * gtk_window_iconify:
6245 * @window: a #GtkWindow
6247 * Asks to iconify (i.e. minimize) the specified @window. Note that
6248 * you shouldn't assume the window is definitely iconified afterward,
6249 * because other entities (e.g. the user or <link
6250 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
6251 * again, or there may not be a window manager in which case
6252 * iconification isn't possible, etc. But normally the window will end
6253 * up iconified. Just don't write code that crashes if not.
6255 * It's permitted to call this function before showing a window,
6256 * in which case the window will be iconified before it ever appears
6259 * You can track iconification via the "window_state_event" signal
6264 gtk_window_iconify (GtkWindow *window)
6267 GdkWindow *toplevel;
6269 g_return_if_fail (GTK_IS_WINDOW (window));
6271 widget = GTK_WIDGET (window);
6273 window->iconify_initially = TRUE;
6276 toplevel = window->frame;
6278 toplevel = widget->window;
6280 if (toplevel != NULL)
6281 gdk_window_iconify (toplevel);
6285 * gtk_window_deiconify:
6286 * @window: a #GtkWindow
6288 * Asks to deiconify (i.e. unminimize) the specified @window. Note
6289 * that you shouldn't assume the window is definitely deiconified
6290 * afterward, because other entities (e.g. the user or <link
6291 * linkend="gtk-X11-arch">window manager</link>) could iconify it
6292 * again before your code which assumes deiconification gets to run.
6294 * You can track iconification via the "window_state_event" signal
6298 gtk_window_deiconify (GtkWindow *window)
6301 GdkWindow *toplevel;
6303 g_return_if_fail (GTK_IS_WINDOW (window));
6305 widget = GTK_WIDGET (window);
6307 window->iconify_initially = FALSE;
6310 toplevel = window->frame;
6312 toplevel = widget->window;
6314 if (toplevel != NULL)
6315 gdk_window_deiconify (toplevel);
6320 * @window: a #GtkWindow
6322 * Asks to stick @window, which means that it will appear on all user
6323 * desktops. Note that you shouldn't assume the window is definitely
6324 * stuck afterward, because other entities (e.g. the user or <link
6325 * linkend="gtk-X11-arch">window manager</link>) could unstick it
6326 * again, and some window managers do not support sticking
6327 * windows. But normally the window will end up stuck. Just don't
6328 * write code that crashes if not.
6330 * It's permitted to call this function before showing a window.
6332 * You can track stickiness via the "window_state_event" signal
6337 gtk_window_stick (GtkWindow *window)
6340 GdkWindow *toplevel;
6342 g_return_if_fail (GTK_IS_WINDOW (window));
6344 widget = GTK_WIDGET (window);
6346 window->stick_initially = TRUE;
6349 toplevel = window->frame;
6351 toplevel = widget->window;
6353 if (toplevel != NULL)
6354 gdk_window_stick (toplevel);
6358 * gtk_window_unstick:
6359 * @window: a #GtkWindow
6361 * Asks to unstick @window, which means that it will appear on only
6362 * one of the user's desktops. Note that you shouldn't assume the
6363 * window is definitely unstuck afterward, because other entities
6364 * (e.g. the user or <link linkend="gtk-X11-arch">window
6365 * manager</link>) could stick it again. But normally the window will
6366 * end up stuck. Just don't write code that crashes if not.
6368 * You can track stickiness via the "window_state_event" signal
6373 gtk_window_unstick (GtkWindow *window)
6376 GdkWindow *toplevel;
6378 g_return_if_fail (GTK_IS_WINDOW (window));
6380 widget = GTK_WIDGET (window);
6382 window->stick_initially = FALSE;
6385 toplevel = window->frame;
6387 toplevel = widget->window;
6389 if (toplevel != NULL)
6390 gdk_window_unstick (toplevel);
6394 * gtk_window_maximize:
6395 * @window: a #GtkWindow
6397 * Asks to maximize @window, so that it becomes full-screen. Note that
6398 * you shouldn't assume the window is definitely maximized afterward,
6399 * because other entities (e.g. the user or <link
6400 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
6401 * again, and not all window managers support maximization. But
6402 * normally the window will end up maximized. Just don't write code
6403 * that crashes if not.
6405 * It's permitted to call this function before showing a window,
6406 * in which case the window will be maximized when it appears onscreen
6409 * You can track maximization via the "window_state_event" signal
6414 gtk_window_maximize (GtkWindow *window)
6417 GdkWindow *toplevel;
6419 g_return_if_fail (GTK_IS_WINDOW (window));
6421 widget = GTK_WIDGET (window);
6423 window->maximize_initially = TRUE;
6426 toplevel = window->frame;
6428 toplevel = widget->window;
6430 if (toplevel != NULL)
6431 gdk_window_maximize (toplevel);
6435 * gtk_window_unmaximize:
6436 * @window: a #GtkWindow
6438 * Asks to unmaximize @window. Note that you shouldn't assume the
6439 * window is definitely unmaximized afterward, because other entities
6440 * (e.g. the user or <link linkend="gtk-X11-arch">window
6441 * manager</link>) could maximize it again, and not all window
6442 * managers honor requests to unmaximize. But normally the window will
6443 * end up unmaximized. Just don't write code that crashes if not.
6445 * You can track maximization via the "window_state_event" signal
6450 gtk_window_unmaximize (GtkWindow *window)
6453 GdkWindow *toplevel;
6455 g_return_if_fail (GTK_IS_WINDOW (window));
6457 widget = GTK_WIDGET (window);
6459 window->maximize_initially = FALSE;
6462 toplevel = window->frame;
6464 toplevel = widget->window;
6466 if (toplevel != NULL)
6467 gdk_window_unmaximize (toplevel);
6471 * gtk_window_fullscreen:
6472 * @window: a #GtkWindow
6474 * Asks to place @window in the fullscreen state. Note that you
6475 * shouldn't assume the window is definitely full screen afterward,
6476 * because other entities (e.g. the user or <link
6477 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
6478 * again, and not all window managers honor requests to fullscreen
6479 * windows. But normally the window will end up fullscreen. Just
6480 * don't write code that crashes if not.
6482 * You can track the fullscreen state via the "window_state_event" signal
6488 gtk_window_fullscreen (GtkWindow *window)
6491 GdkWindow *toplevel;
6492 GtkWindowPrivate *priv;
6494 g_return_if_fail (GTK_IS_WINDOW (window));
6496 widget = GTK_WIDGET (window);
6497 priv = GTK_WINDOW_GET_PRIVATE (window);
6499 priv->fullscreen_initially = TRUE;
6502 toplevel = window->frame;
6504 toplevel = widget->window;
6506 if (toplevel != NULL)
6507 gdk_window_fullscreen (toplevel);
6511 * gtk_window_unfullscreen:
6512 * @window: a #GtkWindow
6514 * Asks to toggle off the fullscreen state for @window. Note that you
6515 * shouldn't assume the window is definitely not full screen
6516 * afterward, because other entities (e.g. the user or <link
6517 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
6518 * again, and not all window managers honor requests to unfullscreen
6519 * windows. But normally the window will end up restored to its normal
6520 * state. Just don't write code that crashes if not.
6522 * You can track the fullscreen state via the "window_state_event" signal
6528 gtk_window_unfullscreen (GtkWindow *window)
6531 GdkWindow *toplevel;
6532 GtkWindowPrivate *priv;
6534 g_return_if_fail (GTK_IS_WINDOW (window));
6536 widget = GTK_WIDGET (window);
6537 priv = GTK_WINDOW_GET_PRIVATE (window);
6539 priv->fullscreen_initially = FALSE;
6542 toplevel = window->frame;
6544 toplevel = widget->window;
6546 if (toplevel != NULL)
6547 gdk_window_unfullscreen (toplevel);
6551 * gtk_window_set_keep_above:
6552 * @window: a #GtkWindow
6553 * @setting: whether to keep @window above other windows
6555 * Asks to keep @window above, so that it stays on top. Note that
6556 * you shouldn't assume the window is definitely above afterward,
6557 * because other entities (e.g. the user or <link
6558 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
6559 * and not all window managers support keeping windows above. But
6560 * normally the window will end kept above. Just don't write code
6561 * that crashes if not.
6563 * It's permitted to call this function before showing a window,
6564 * in which case the window will be kept above when it appears onscreen
6567 * You can track the above state via the "window_state_event" signal
6570 * Note that, according to the <ulink
6571 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
6572 * Manager Hints</ulink> specification, the above state is mainly meant
6573 * for user preferences and should not be used by applications e.g. for
6574 * drawing attention to their dialogs.
6579 gtk_window_set_keep_above (GtkWindow *window,
6583 GtkWindowPrivate *priv;
6584 GdkWindow *toplevel;
6586 g_return_if_fail (GTK_IS_WINDOW (window));
6588 widget = GTK_WIDGET (window);
6589 priv = GTK_WINDOW_GET_PRIVATE (window);
6591 priv->above_initially = setting;
6593 priv->below_initially = FALSE;
6596 toplevel = window->frame;
6598 toplevel = widget->window;
6600 if (toplevel != NULL)
6601 gdk_window_set_keep_above (toplevel, setting);
6605 * gtk_window_set_keep_below:
6606 * @window: a #GtkWindow
6607 * @setting: whether to keep @window below other windows
6609 * Asks to keep @window below, so that it stays in bottom. Note that
6610 * you shouldn't assume the window is definitely below afterward,
6611 * because other entities (e.g. the user or <link
6612 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
6613 * and not all window managers support putting windows below. But
6614 * normally the window will be kept below. Just don't write code
6615 * that crashes if not.
6617 * It's permitted to call this function before showing a window,
6618 * in which case the window will be kept below when it appears onscreen
6621 * You can track the below state via the "window_state_event" signal
6624 * Note that, according to the <ulink
6625 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
6626 * Manager Hints</ulink> specification, the above state is mainly meant
6627 * for user preferences and should not be used by applications e.g. for
6628 * drawing attention to their dialogs.
6633 gtk_window_set_keep_below (GtkWindow *window,
6637 GtkWindowPrivate *priv;
6638 GdkWindow *toplevel;
6640 g_return_if_fail (GTK_IS_WINDOW (window));
6642 widget = GTK_WIDGET (window);
6643 priv = GTK_WINDOW_GET_PRIVATE (window);
6645 priv->below_initially = setting;
6647 priv->above_initially = FALSE;
6650 toplevel = window->frame;
6652 toplevel = widget->window;
6654 if (toplevel != NULL)
6655 gdk_window_set_keep_below (toplevel, setting);
6659 * gtk_window_set_resizable:
6660 * @window: a #GtkWindow
6661 * @resizable: %TRUE if the user can resize this window
6663 * Sets whether the user can resize a window. Windows are user resizable
6667 gtk_window_set_resizable (GtkWindow *window,
6670 g_return_if_fail (GTK_IS_WINDOW (window));
6672 gtk_window_set_policy (window, FALSE, resizable, FALSE);
6676 * gtk_window_get_resizable:
6677 * @window: a #GtkWindow
6679 * Gets the value set by gtk_window_set_resizable().
6681 * Return value: %TRUE if the user can resize the window
6684 gtk_window_get_resizable (GtkWindow *window)
6686 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6688 /* allow_grow is most likely to indicate the semantic concept we
6689 * mean by "resizable" (and will be a reliable indicator if
6690 * set_policy() hasn't been called)
6692 return window->allow_grow;
6696 * gtk_window_set_gravity:
6697 * @window: a #GtkWindow
6698 * @gravity: window gravity
6700 * Window gravity defines the meaning of coordinates passed to
6701 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
6704 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
6705 * typically "do what you mean."
6709 gtk_window_set_gravity (GtkWindow *window,
6712 g_return_if_fail (GTK_IS_WINDOW (window));
6714 if (gravity != window->gravity)
6716 window->gravity = gravity;
6718 /* gtk_window_move_resize() will adapt gravity
6720 gtk_widget_queue_resize (GTK_WIDGET (window));
6722 g_object_notify (G_OBJECT (window), "gravity");
6727 * gtk_window_get_gravity:
6728 * @window: a #GtkWindow
6730 * Gets the value set by gtk_window_set_gravity().
6732 * Return value: window gravity
6735 gtk_window_get_gravity (GtkWindow *window)
6737 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
6739 return window->gravity;
6743 * gtk_window_begin_resize_drag:
6744 * @window: a #GtkWindow
6745 * @button: mouse button that initiated the drag
6746 * @edge: position of the resize control
6747 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6748 * @root_y: Y position where the user clicked to initiate the drag
6749 * @timestamp: timestamp from the click event that initiated the drag
6751 * Starts resizing a window. This function is used if an application
6752 * has window resizing controls. When GDK can support it, the resize
6753 * will be done using the standard mechanism for the <link
6754 * linkend="gtk-X11-arch">window manager</link> or windowing
6755 * system. Otherwise, GDK will try to emulate window resizing,
6756 * potentially not all that well, depending on the windowing system.
6760 gtk_window_begin_resize_drag (GtkWindow *window,
6768 GdkWindow *toplevel;
6770 g_return_if_fail (GTK_IS_WINDOW (window));
6771 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6773 widget = GTK_WIDGET (window);
6776 toplevel = window->frame;
6778 toplevel = widget->window;
6780 gdk_window_begin_resize_drag (toplevel,
6787 * gtk_window_get_frame_dimensions:
6788 * @window: a #GtkWindow
6789 * @left: location to store the width of the frame at the left, or %NULL
6790 * @top: location to store the height of the frame at the top, or %NULL
6791 * @right: location to store the width of the frame at the returns, or %NULL
6792 * @bottom: location to store the height of the frame at the bottom, or %NULL
6794 * (Note: this is a special-purpose function intended for the
6795 * framebuffer port; see gtk_window_set_has_frame(). It will not
6796 * return the size of the window border drawn by the <link
6797 * linkend="gtk-X11-arch">window manager</link>, which is the normal
6798 * case when using a windowing system. See
6799 * gdk_window_get_frame_extents() to get the standard window border
6802 * Retrieves the dimensions of the frame window for this toplevel.
6803 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
6806 gtk_window_get_frame_dimensions (GtkWindow *window,
6812 g_return_if_fail (GTK_IS_WINDOW (window));
6815 *left = window->frame_left;
6817 *top = window->frame_top;
6819 *right = window->frame_right;
6821 *bottom = window->frame_bottom;
6825 * gtk_window_begin_move_drag:
6826 * @window: a #GtkWindow
6827 * @button: mouse button that initiated the drag
6828 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6829 * @root_y: Y position where the user clicked to initiate the drag
6830 * @timestamp: timestamp from the click event that initiated the drag
6832 * Starts moving a window. This function is used if an application has
6833 * window movement grips. When GDK can support it, the window movement
6834 * will be done using the standard mechanism for the <link
6835 * linkend="gtk-X11-arch">window manager</link> or windowing
6836 * system. Otherwise, GDK will try to emulate window movement,
6837 * potentially not all that well, depending on the windowing system.
6841 gtk_window_begin_move_drag (GtkWindow *window,
6848 GdkWindow *toplevel;
6850 g_return_if_fail (GTK_IS_WINDOW (window));
6851 g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6853 widget = GTK_WIDGET (window);
6856 toplevel = window->frame;
6858 toplevel = widget->window;
6860 gdk_window_begin_move_drag (toplevel,
6867 * gtk_window_set_screen:
6868 * @window: a #GtkWindow.
6869 * @screen: a #GdkScreen.
6871 * Sets the #GdkScreen where the @window is displayed; if
6872 * the window is already mapped, it will be unmapped, and
6873 * then remapped on the new screen.
6878 gtk_window_set_screen (GtkWindow *window,
6882 GdkScreen *previous_screen;
6883 gboolean was_mapped;
6885 g_return_if_fail (GTK_IS_WINDOW (window));
6886 g_return_if_fail (GDK_IS_SCREEN (screen));
6888 if (screen == window->screen)
6891 widget = GTK_WIDGET (window);
6893 previous_screen = window->screen;
6894 was_mapped = GTK_WIDGET_MAPPED (widget);
6897 gtk_widget_unmap (widget);
6898 if (GTK_WIDGET_REALIZED (widget))
6899 gtk_widget_unrealize (widget);
6901 gtk_window_free_key_hash (window);
6902 window->screen = screen;
6903 gtk_widget_reset_rc_styles (widget);
6904 if (screen != previous_screen)
6906 g_signal_handlers_disconnect_by_func (previous_screen,
6907 gtk_window_on_composited_changed, window);
6908 g_signal_connect (screen, "composited_changed",
6909 G_CALLBACK (gtk_window_on_composited_changed), window);
6911 _gtk_widget_propagate_screen_changed (widget, previous_screen);
6912 _gtk_widget_propagate_composited_changed (widget);
6914 g_object_notify (G_OBJECT (window), "screen");
6917 gtk_widget_map (widget);
6921 gtk_window_on_composited_changed (GdkScreen *screen,
6924 gtk_widget_queue_draw (GTK_WIDGET (window));
6926 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
6930 gtk_window_check_screen (GtkWindow *window)
6933 return window->screen;
6936 g_warning ("Screen for GtkWindow not set; you must always set\n"
6937 "a screen for a GtkWindow before using the window");
6943 * gtk_window_get_screen:
6944 * @window: a #GtkWindow.
6946 * Returns the #GdkScreen associated with @window.
6948 * Return value: a #GdkScreen.
6953 gtk_window_get_screen (GtkWindow *window)
6955 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6957 return window->screen;
6961 * gtk_window_is_active:
6962 * @window: a #GtkWindow
6964 * Returns whether the window is part of the current active toplevel.
6965 * (That is, the toplevel window receiving keystrokes.)
6966 * The return value is %TRUE if the window is active toplevel
6967 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
6968 * You might use this function if you wanted to draw a widget
6969 * differently in an active window from a widget in an inactive window.
6970 * See gtk_window_has_toplevel_focus()
6972 * Return value: %TRUE if the window part of the current active window.
6977 gtk_window_is_active (GtkWindow *window)
6979 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6981 return window->is_active;
6985 * gtk_window_has_toplevel_focus:
6986 * @window: a #GtkWindow
6988 * Returns whether the input focus is within this GtkWindow.
6989 * For real toplevel windows, this is identical to gtk_window_is_active(),
6990 * but for embedded windows, like #GtkPlug, the results will differ.
6992 * Return value: %TRUE if the input focus is within this GtkWindow
6997 gtk_window_has_toplevel_focus (GtkWindow *window)
6999 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7001 return window->has_toplevel_focus;
7005 gtk_window_group_class_init (GtkWindowGroupClass *klass)
7010 gtk_window_group_get_type (void)
7012 static GType window_group_type = 0;
7014 if (!window_group_type)
7016 static const GTypeInfo window_group_info =
7018 sizeof (GtkWindowGroupClass),
7019 NULL, /* base_init */
7020 NULL, /* base_finalize */
7021 (GClassInitFunc) gtk_window_group_class_init,
7022 NULL, /* class_finalize */
7023 NULL, /* class_data */
7024 sizeof (GtkWindowGroup),
7025 0, /* n_preallocs */
7026 (GInstanceInitFunc) NULL,
7029 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
7030 &window_group_info, 0);
7033 return window_group_type;
7037 * gtk_window_group_new:
7039 * Creates a new #GtkWindowGroup object. Grabs added with
7040 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
7042 * Return value: a new #GtkWindowGroup.
7045 gtk_window_group_new (void)
7047 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
7051 window_group_cleanup_grabs (GtkWindowGroup *group,
7055 GSList *to_remove = NULL;
7057 tmp_list = group->grabs;
7060 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
7061 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
7062 tmp_list = tmp_list->next;
7067 gtk_grab_remove (to_remove->data);
7068 g_object_unref (to_remove->data);
7069 to_remove = g_slist_delete_link (to_remove, to_remove);
7074 * gtk_window_group_add_window:
7075 * @window_group: a #GtkWindowGroup
7076 * @window: the #GtkWindow to add
7078 * Adds a window to a #GtkWindowGroup.
7081 gtk_window_group_add_window (GtkWindowGroup *window_group,
7084 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7085 g_return_if_fail (GTK_IS_WINDOW (window));
7087 if (window->group != window_group)
7089 g_object_ref (window);
7090 g_object_ref (window_group);
7093 gtk_window_group_remove_window (window->group, window);
7095 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
7097 window->group = window_group;
7099 g_object_unref (window);
7104 * gtk_window_group_remove_window:
7105 * @window_group: a #GtkWindowGroup
7106 * @window: the #GtkWindow to remove
7108 * Removes a window from a #GtkWindowGroup.
7111 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7114 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7115 g_return_if_fail (GTK_IS_WIDGET (window));
7116 g_return_if_fail (window->group == window_group);
7118 g_object_ref (window);
7120 window_group_cleanup_grabs (window_group, window);
7121 window->group = NULL;
7123 g_object_unref (window_group);
7124 g_object_unref (window);
7128 * gtk_window_get_group:
7129 * @window: a #GtkWindow, or %NULL
7131 * Returns the group for @window or the default group, if
7132 * @window is %NULL or if @window does not have an explicit
7135 * Returns: the #GtkWindowGroup for a window or the default group
7140 gtk_window_get_group (GtkWindow *window)
7142 if (window && window->group)
7143 return window->group;
7146 static GtkWindowGroup *default_group = NULL;
7149 default_group = gtk_window_group_new ();
7151 return default_group;
7155 /* Return the current grab widget of the given group
7158 _gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
7160 if (window_group->grabs)
7161 return GTK_WIDGET (window_group->grabs->data);
7166 Derived from XParseGeometry() in XFree86
7168 Copyright 1985, 1986, 1987,1998 The Open Group
7170 All Rights Reserved.
7172 The above copyright notice and this permission notice shall be included
7173 in all copies or substantial portions of the Software.
7175 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
7176 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7177 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7178 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
7179 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7180 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
7181 OTHER DEALINGS IN THE SOFTWARE.
7183 Except as contained in this notice, the name of The Open Group shall
7184 not be used in advertising or otherwise to promote the sale, use or
7185 other dealings in this Software without prior written authorization
7186 from The Open Group.
7191 * XParseGeometry parses strings of the form
7192 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
7193 * width, height, xoffset, and yoffset are unsigned integers.
7194 * Example: "=80x24+300-49"
7195 * The equal sign is optional.
7196 * It returns a bitmask that indicates which of the four values
7197 * were actually found in the string. For each value found,
7198 * the corresponding argument is updated; for each value
7199 * not found, the corresponding argument is left unchanged.
7202 /* The following code is from Xlib, and is minimally modified, so we
7203 * can track any upstream changes if required. Don't change this
7204 * code. Or if you do, put in a huge comment marking which thing
7209 read_int (gchar *string,
7217 else if (*string == '-')
7223 for (; (*string >= '0') && (*string <= '9'); string++)
7225 result = (result * 10) + (*string - '0');
7237 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
7238 * value (x, y, width, height) was found in the parsed string.
7240 #define NoValue 0x0000
7241 #define XValue 0x0001
7242 #define YValue 0x0002
7243 #define WidthValue 0x0004
7244 #define HeightValue 0x0008
7245 #define AllValues 0x000F
7246 #define XNegative 0x0010
7247 #define YNegative 0x0020
7249 /* Try not to reformat/modify, so we can compare/sync with X sources */
7251 gtk_XParseGeometry (const char *string,
7254 unsigned int *width,
7255 unsigned int *height)
7259 unsigned int tempWidth, tempHeight;
7261 char *nextCharacter;
7263 /* These initializations are just to silence gcc */
7269 if ( (string == NULL) || (*string == '\0')) return(mask);
7271 string++; /* ignore possible '=' at beg of geometry spec */
7273 strind = (char *)string;
7274 if (*strind != '+' && *strind != '-' && *strind != 'x') {
7275 tempWidth = read_int(strind, &nextCharacter);
7276 if (strind == nextCharacter)
7278 strind = nextCharacter;
7282 if (*strind == 'x' || *strind == 'X') {
7284 tempHeight = read_int(strind, &nextCharacter);
7285 if (strind == nextCharacter)
7287 strind = nextCharacter;
7288 mask |= HeightValue;
7291 if ((*strind == '+') || (*strind == '-')) {
7292 if (*strind == '-') {
7294 tempX = -read_int(strind, &nextCharacter);
7295 if (strind == nextCharacter)
7297 strind = nextCharacter;
7303 tempX = read_int(strind, &nextCharacter);
7304 if (strind == nextCharacter)
7306 strind = nextCharacter;
7309 if ((*strind == '+') || (*strind == '-')) {
7310 if (*strind == '-') {
7312 tempY = -read_int(strind, &nextCharacter);
7313 if (strind == nextCharacter)
7315 strind = nextCharacter;
7322 tempY = read_int(strind, &nextCharacter);
7323 if (strind == nextCharacter)
7325 strind = nextCharacter;
7331 /* If strind isn't at the end of the string the it's an invalid
7332 geometry specification. */
7334 if (*strind != '\0') return (0);
7340 if (mask & WidthValue)
7342 if (mask & HeightValue)
7343 *height = tempHeight;
7348 * gtk_window_parse_geometry:
7349 * @window: a #GtkWindow
7350 * @geometry: geometry string
7352 * Parses a standard X Window System geometry string - see the
7353 * manual page for X (type 'man X') for details on this.
7354 * gtk_window_parse_geometry() does work on all GTK+ ports
7355 * including Win32 but is primarily intended for an X environment.
7357 * If either a size or a position can be extracted from the
7358 * geometry string, gtk_window_parse_geometry() returns %TRUE
7359 * and calls gtk_window_set_default_size() and/or gtk_window_move()
7360 * to resize/move the window.
7362 * If gtk_window_parse_geometry() returns %TRUE, it will also
7363 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
7364 * indicating to the window manager that the size/position of
7365 * the window was user-specified. This causes most window
7366 * managers to honor the geometry.
7368 * Note that for gtk_window_parse_geometry() to work as expected, it has
7369 * to be called when the window has its "final" size, i.e. after calling
7370 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
7373 * <informalexample><programlisting>
7374 * #include <gtk/gtk.h>
7377 * fill_with_content (GtkWidget *vbox)
7379 * /<!-- -->* fill with content... *<!-- -->/
7383 * main (int argc, char *argv[])
7385 * GtkWidget *window, *vbox;
7386 * GdkGeometry size_hints = {
7387 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
7390 * gtk_init (&argc, &argv);
7392 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7393 * vbox = gtk_vbox_new (FALSE, 0);
7395 * gtk_container_add (GTK_CONTAINER (window), vbox);
7396 * fill_with_content (vbox);
7397 * gtk_widget_show_all (vbox);
7399 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
7402 * GDK_HINT_MIN_SIZE |
7403 * GDK_HINT_BASE_SIZE |
7404 * GDK_HINT_RESIZE_INC);
7408 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
7409 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
7412 * gtk_widget_show_all (window);
7417 * </programlisting></informalexample>
7419 * Return value: %TRUE if string was parsed successfully
7422 gtk_window_parse_geometry (GtkWindow *window,
7423 const gchar *geometry)
7425 gint result, x = 0, y = 0;
7428 gboolean size_set, pos_set;
7431 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7432 g_return_val_if_fail (geometry != NULL, FALSE);
7434 screen = gtk_window_check_screen (window);
7436 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
7439 if ((result & WidthValue) || (result & HeightValue))
7441 gtk_window_set_default_size_internal (window,
7442 TRUE, result & WidthValue ? w : -1,
7443 TRUE, result & HeightValue ? h : -1,
7448 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
7450 grav = GDK_GRAVITY_NORTH_WEST;
7452 if ((result & XNegative) && (result & YNegative))
7453 grav = GDK_GRAVITY_SOUTH_EAST;
7454 else if (result & XNegative)
7455 grav = GDK_GRAVITY_NORTH_EAST;
7456 else if (result & YNegative)
7457 grav = GDK_GRAVITY_SOUTH_WEST;
7459 if ((result & XValue) == 0)
7462 if ((result & YValue) == 0)
7465 if (grav == GDK_GRAVITY_SOUTH_WEST ||
7466 grav == GDK_GRAVITY_SOUTH_EAST)
7467 y = gdk_screen_get_height (screen) - h + y;
7469 if (grav == GDK_GRAVITY_SOUTH_EAST ||
7470 grav == GDK_GRAVITY_NORTH_EAST)
7471 x = gdk_screen_get_width (screen) - w + x;
7473 /* we don't let you put a window offscreen; maybe some people would
7474 * prefer to be able to, but it's kind of a bogus thing to do.
7483 if ((result & XValue) || (result & YValue))
7485 gtk_window_set_gravity (window, grav);
7486 gtk_window_move (window, x, y);
7490 if (size_set || pos_set)
7492 /* Set USSize, USPosition hints */
7493 GtkWindowGeometryInfo *info;
7495 info = gtk_window_get_geometry_info (window, TRUE);
7498 info->mask |= GDK_HINT_USER_POS;
7500 info->mask |= GDK_HINT_USER_SIZE;
7507 gtk_window_mnemonic_hash_foreach (guint keyval,
7513 GtkWindowKeysForeachFunc func;
7517 (*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
7521 _gtk_window_keys_foreach (GtkWindow *window,
7522 GtkWindowKeysForeachFunc func,
7526 GtkMnemonicHash *mnemonic_hash;
7530 GtkWindowKeysForeachFunc func;
7534 info.window = window;
7536 info.func_data = func_data;
7538 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
7540 _gtk_mnemonic_hash_foreach (mnemonic_hash,
7541 gtk_window_mnemonic_hash_foreach, &info);
7543 groups = gtk_accel_groups_from_object (G_OBJECT (window));
7546 GtkAccelGroup *group = groups->data;
7549 for (i = 0; i < group->n_accels; i++)
7551 GtkAccelKey *key = &group->priv_accels[i].key;
7554 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
7557 groups = groups->next;
7562 gtk_window_keys_changed (GtkWindow *window)
7564 gtk_window_free_key_hash (window);
7565 gtk_window_get_key_hash (window);
7568 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
7570 struct _GtkWindowKeyEntry
7574 guint is_mnemonic : 1;
7578 window_key_entry_destroy (gpointer data)
7580 g_slice_free (GtkWindowKeyEntry, data);
7584 add_to_key_hash (GtkWindow *window,
7586 GdkModifierType modifiers,
7587 gboolean is_mnemonic,
7590 GtkKeyHash *key_hash = data;
7592 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
7594 entry->keyval = keyval;
7595 entry->modifiers = modifiers;
7596 entry->is_mnemonic = is_mnemonic;
7598 /* GtkAccelGroup stores lowercased accelerators. To deal
7599 * with this, if <Shift> was specified, uppercase.
7601 if (modifiers & GDK_SHIFT_MASK)
7603 if (keyval == GDK_Tab)
7604 keyval = GDK_ISO_Left_Tab;
7606 keyval = gdk_keyval_to_upper (keyval);
7609 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
7613 gtk_window_get_key_hash (GtkWindow *window)
7615 GdkScreen *screen = gtk_window_check_screen (window);
7616 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7621 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
7622 (GDestroyNotify)window_key_entry_destroy);
7623 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
7624 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
7630 gtk_window_free_key_hash (GtkWindow *window)
7632 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7635 _gtk_key_hash_free (key_hash);
7636 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
7641 * gtk_window_activate_key:
7642 * @window: a #GtkWindow
7643 * @event: a #GdkEventKey
7645 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
7646 * called by the default ::key_press_event handler for toplevel windows,
7647 * however in some cases it may be useful to call this directly when
7648 * overriding the standard key handling for a toplevel window.
7650 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
7653 gtk_window_activate_key (GtkWindow *window,
7656 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7657 GtkWindowKeyEntry *found_entry = NULL;
7661 gtk_window_keys_changed (window);
7662 key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
7667 GSList *entries = _gtk_key_hash_lookup (key_hash,
7668 event->hardware_keycode,
7670 gtk_accelerator_get_default_mod_mask (),
7674 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
7676 GtkWindowKeyEntry *entry = tmp_list->data;
7677 if (entry->is_mnemonic)
7679 found_entry = entry;
7684 if (!found_entry && entries)
7685 found_entry = entries->data;
7687 g_slist_free (entries);
7692 if (found_entry->is_mnemonic)
7693 return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
7695 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
7702 window_update_has_focus (GtkWindow *window)
7704 GtkWidget *widget = GTK_WIDGET (window);
7705 gboolean has_focus = window->has_toplevel_focus && window->is_active;
7707 if (has_focus != window->has_focus)
7709 window->has_focus = has_focus;
7713 if (window->focus_widget &&
7714 window->focus_widget != widget &&
7715 !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7716 do_focus_change (window->focus_widget, TRUE);
7720 if (window->focus_widget &&
7721 window->focus_widget != widget &&
7722 GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7723 do_focus_change (window->focus_widget, FALSE);
7729 * _gtk_window_set_is_active:
7730 * @window: a #GtkWindow
7731 * @is_active: %TRUE if the window is in the currently active toplevel
7733 * Internal function that sets whether the #GtkWindow is part
7734 * of the currently active toplevel window (taking into account inter-process
7738 _gtk_window_set_is_active (GtkWindow *window,
7741 g_return_if_fail (GTK_IS_WINDOW (window));
7743 is_active = is_active != FALSE;
7745 if (is_active != window->is_active)
7747 window->is_active = is_active;
7748 window_update_has_focus (window);
7750 g_object_notify (G_OBJECT (window), "is-active");
7755 * _gtk_window_set_has_toplevel_focus:
7756 * @window: a #GtkWindow
7757 * @has_toplevel_focus: %TRUE if the in
7759 * Internal function that sets whether the keyboard focus for the
7760 * toplevel window (taking into account inter-process embedding.)
7763 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
7764 gboolean has_toplevel_focus)
7766 g_return_if_fail (GTK_IS_WINDOW (window));
7768 has_toplevel_focus = has_toplevel_focus != FALSE;
7770 if (has_toplevel_focus != window->has_toplevel_focus)
7772 window->has_toplevel_focus = has_toplevel_focus;
7773 window_update_has_focus (window);
7775 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
7780 * gtk_window_set_auto_startup_notification:
7781 * @setting: %TRUE to automatically do startup notification
7783 * By default, after showing the first #GtkWindow, GTK+ calls
7784 * gdk_notify_startup_complete(). Call this function to disable
7785 * the automatic startup notification. You might do this if your
7786 * first window is a splash screen, and you want to delay notification
7787 * until after your real main window has been shown, for example.
7789 * In that example, you would disable startup notification
7790 * temporarily, show your splash screen, then re-enable it so that
7791 * showing the main window would automatically result in notification.
7796 gtk_window_set_auto_startup_notification (gboolean setting)
7798 disable_startup_notification = !setting;
7803 #undef gtk_window_set_icon_from_file
7806 gtk_window_set_icon_from_file (GtkWindow *window,
7807 const gchar *filename,
7810 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
7813 if (utf8_filename == NULL)
7816 retval = gtk_window_set_icon_from_file_utf8 (window, utf8_filename, err);
7818 g_free (utf8_filename);
7823 #undef gtk_window_set_default_icon_from_file
7826 gtk_window_set_default_icon_from_file (const gchar *filename,
7829 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
7832 if (utf8_filename == NULL)
7835 retval = gtk_window_set_default_icon_from_file_utf8 (utf8_filename, err);
7837 g_free (utf8_filename);
7844 #define __GTK_WINDOW_C__
7845 #include "gtkaliasdef.c"