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/.
29 #include "gtkwindow.h"
36 #include "gtkprivate.h"
38 #include "gtkwindowprivate.h"
39 #include "gtkaccelgroupprivate.h"
40 #include "gtkbindings.h"
41 #include "gtkkeyhash.h"
43 #include "gtkmnemonichash.h"
44 #include "gtkmenubar.h"
45 #include "gtkiconfactory.h"
46 #include "gtkicontheme.h"
47 #include "gtkmarshalers.h"
49 #include "gtkbuildable.h"
50 #include "gtkwidgetprivate.h"
52 #include "gtktypebuiltins.h"
54 #ifdef GDK_WINDOWING_X11
61 * @short_description: Toplevel which can contain other widgets
63 * A GtkWindow is a toplevel window which can contain other widgets.
64 * Windows normally have decorations that are under the control
65 * of the windowing system and allow the user to manipulate the window
66 * (resize it, move it, close it,...).
68 * GTK+ also allows windows to have a resize grip (a small area in the lower
69 * right or left corner) which can be clicked to reszie the window. To
70 * control whether a window has a resize grip, use
71 * gtk_window_set_has_resize_grip().
73 * <refsect2 id="GtkWindow-BUILDER-UI">
74 * <title>GtkWindow as GtkBuildable</title>
76 * The GtkWindow implementation of the GtkBuildable interface supports a
77 * custom <tag class="starttag">accel-groups</tag> element, which supports
78 * any number of <tag class="starttag">group</tag> elements representing the
79 * #GtkAccelGroup objects you want to add to your window (synonymous with
80 * gtk_window_add_accel_group().
83 * <title>A UI definition fragment with accel groups</title>
84 * <programlisting><![CDATA[
85 * <object class="GtkWindow">
87 * <group name="accelgroup1"/>
93 * <object class="GtkAccelGroup" id="accelgroup1"/>
94 * ]]></programlisting>
99 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
101 struct _GtkWindowPrivate
103 GtkMnemonicHash *mnemonic_hash;
105 GtkWidget *default_widget;
106 GtkWidget *focus_widget;
107 GtkWindow *transient_parent;
108 GtkWindowGeometryInfo *geometry_info;
109 GtkWindowGroup *group;
111 GdkModifierType mnemonic_modifier;
113 GdkWindowTypeHint gdk_type_hint;
115 GtkApplication *application;
119 GdkWindow *grip_window;
123 gchar *wmclass_class;
127 guint keys_changed_handler;
129 guint16 configure_request_count;
131 /* The following flags are initially TRUE (before a window is mapped).
132 * They cause us to compute a configure request that involves
133 * default-only parameters. Once mapped, we set them to FALSE.
134 * Then we set them to TRUE again on unmap (for position)
135 * and on unrealize (for size).
137 guint need_default_position : 1;
138 guint need_default_size : 1;
140 guint above_initially : 1;
141 guint accept_focus : 1;
142 guint below_initially : 1;
143 guint builder_visible : 1;
144 guint configure_notify_received : 1;
147 guint destroy_with_parent : 1;
148 guint focus_on_map : 1;
149 guint fullscreen_initially : 1;
150 guint gravity : 5; /* GdkGravity */
152 guint has_user_ref_count : 1;
153 guint has_toplevel_focus : 1;
154 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
156 guint maximize_initially : 1;
157 guint mnemonics_visible : 1;
158 guint mnemonics_visible_set : 1;
160 guint opacity_set : 1;
162 guint reset_type_hint : 1;
164 guint skips_pager : 1;
165 guint skips_taskbar : 1;
166 guint stick_initially : 1;
167 guint transient_parent_group : 1;
168 guint type : 4; /* GtkWindowType */
169 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
170 * one of the original eight. If not,
172 * GDK_WINDOW_TYPE_HINT_NORMAL
175 guint has_resize_grip : 1;
176 guint resize_grip_visible : 1; /* don't use, just for "resize-
177 * grip-visible" notification
205 PROP_DESTROY_WITH_PARENT,
210 PROP_SKIP_TASKBAR_HINT,
211 PROP_SKIP_PAGER_HINT,
220 PROP_HAS_RESIZE_GRIP,
221 PROP_RESIZE_GRIP_VISIBLE,
223 /* Readonly properties */
225 PROP_HAS_TOPLEVEL_FOCUS,
227 /* Writeonly properties */
230 PROP_MNEMONICS_VISIBLE,
240 guint using_default_icon : 1;
241 guint using_parent_icon : 1;
242 guint using_themed_icon : 1;
246 GdkGeometry geometry; /* Last set of geometry hints we set */
247 GdkWindowHints flags;
248 GdkRectangle configure_request;
249 } GtkWindowLastGeometryInfo;
251 struct _GtkWindowGeometryInfo
253 /* Properties that the app has set on the window
255 GdkGeometry geometry; /* Geometry hints */
257 GtkWidget *widget; /* subwidget to which hints apply */
258 /* from last gtk_window_resize () - if > 0, indicates that
259 * we should resize to this size.
264 /* From last gtk_window_move () prior to mapping -
265 * only used if initial_pos_set
270 /* Default size - used only the FIRST time we map a window,
275 /* whether to use initial_x, initial_y */
276 guint initial_pos_set : 1;
277 /* CENTER_ALWAYS or other position constraint changed since
278 * we sent the last configure request.
280 guint position_constraints_changed : 1;
282 /* if true, default_width, height should be multiplied by the
283 * increments and affect the geometry widget only
285 guint default_is_geometry : 1;
287 /* if true, resize_width, height should be multiplied by the
288 * increments and affect the geometry widget only
290 guint resize_is_geometry : 1;
292 GtkWindowLastGeometryInfo last;
296 struct _GtkDeviceGrabInfo
300 guint block_others : 1;
303 struct _GtkWindowGroupPrivate
306 GSList *device_grabs;
309 static void gtk_window_dispose (GObject *object);
310 static void gtk_window_finalize (GObject *object);
311 static void gtk_window_destroy (GtkWidget *widget);
312 static void gtk_window_show (GtkWidget *widget);
313 static void gtk_window_hide (GtkWidget *widget);
314 static void gtk_window_map (GtkWidget *widget);
315 static void gtk_window_unmap (GtkWidget *widget);
316 static void gtk_window_realize (GtkWidget *widget);
317 static void gtk_window_unrealize (GtkWidget *widget);
318 static void gtk_window_size_allocate (GtkWidget *widget,
319 GtkAllocation *allocation);
320 static gboolean gtk_window_map_event (GtkWidget *widget,
322 static gint gtk_window_configure_event (GtkWidget *widget,
323 GdkEventConfigure *event);
324 static gint gtk_window_key_press_event (GtkWidget *widget,
326 static gint gtk_window_key_release_event (GtkWidget *widget,
328 static gint gtk_window_button_press_event (GtkWidget *widget,
329 GdkEventButton *event);
330 static gint gtk_window_enter_notify_event (GtkWidget *widget,
331 GdkEventCrossing *event);
332 static gint gtk_window_leave_notify_event (GtkWidget *widget,
333 GdkEventCrossing *event);
334 static gint gtk_window_focus_in_event (GtkWidget *widget,
335 GdkEventFocus *event);
336 static gint gtk_window_focus_out_event (GtkWidget *widget,
337 GdkEventFocus *event);
338 static void gtk_window_style_updated (GtkWidget *widget);
339 static gint gtk_window_client_event (GtkWidget *widget,
340 GdkEventClient *event);
341 static gboolean gtk_window_state_event (GtkWidget *widget,
342 GdkEventWindowState *event);
343 static void gtk_window_check_resize (GtkContainer *container);
344 static gint gtk_window_focus (GtkWidget *widget,
345 GtkDirectionType direction);
346 static void gtk_window_move_focus (GtkWidget *widget,
347 GtkDirectionType dir);
348 static void gtk_window_real_set_focus (GtkWindow *window,
350 static void gtk_window_direction_changed (GtkWidget *widget,
351 GtkTextDirection prev_dir);
352 static void gtk_window_state_changed (GtkWidget *widget,
353 GtkStateType previous_state);
355 static void gtk_window_real_activate_default (GtkWindow *window);
356 static void gtk_window_real_activate_focus (GtkWindow *window);
357 static void gtk_window_keys_changed (GtkWindow *window);
358 static gint gtk_window_draw (GtkWidget *widget,
360 static void gtk_window_unset_transient_for (GtkWindow *window);
361 static void gtk_window_transient_parent_realized (GtkWidget *parent,
363 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
366 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
368 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
371 static void gtk_window_move_resize (GtkWindow *window);
372 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
374 GdkGeometry *geometry_b,
376 static void gtk_window_constrain_size (GtkWindow *window,
377 GdkGeometry *geometry,
383 static void gtk_window_constrain_position (GtkWindow *window,
388 static void gtk_window_compute_hints (GtkWindow *window,
389 GdkGeometry *new_geometry,
391 static void gtk_window_compute_configure_request (GtkWindow *window,
392 GdkRectangle *request,
393 GdkGeometry *geometry,
396 static void gtk_window_set_default_size_internal (GtkWindow *window,
397 gboolean change_width,
399 gboolean change_height,
401 gboolean is_geometry);
403 static void update_themed_icon (GtkIconTheme *theme,
405 static GList *icon_list_from_theme (GtkWidget *widget,
407 static void gtk_window_realize_icon (GtkWindow *window);
408 static void gtk_window_unrealize_icon (GtkWindow *window);
409 static void resize_grip_create_window (GtkWindow *window);
410 static void resize_grip_destroy_window (GtkWindow *window);
411 static void update_grip_visibility (GtkWindow *window);
413 static void gtk_window_notify_keys_changed (GtkWindow *window);
414 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
415 static void gtk_window_free_key_hash (GtkWindow *window);
416 static void gtk_window_on_composited_changed (GdkScreen *screen,
419 static GSList *toplevel_list = NULL;
420 static guint window_signals[LAST_SIGNAL] = { 0 };
421 static GList *default_icon_list = NULL;
422 static gchar *default_icon_name = NULL;
423 static guint default_icon_serial = 0;
424 static gboolean disable_startup_notification = FALSE;
425 static gboolean sent_startup_notification = FALSE;
427 static GQuark quark_gtk_embedded = 0;
428 static GQuark quark_gtk_window_key_hash = 0;
429 static GQuark quark_gtk_window_icon_info = 0;
430 static GQuark quark_gtk_buildable_accels = 0;
432 static GtkBuildableIface *parent_buildable_iface;
434 static void gtk_window_set_property (GObject *object,
438 static void gtk_window_get_property (GObject *object,
444 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
445 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
448 const GValue *value);
449 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
450 GtkBuilder *builder);
451 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
454 const gchar *tagname,
455 GMarkupParser *parser,
457 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
460 const gchar *tagname,
464 static void gtk_window_get_preferred_width (GtkWidget *widget,
467 static void gtk_window_get_preferred_height (GtkWidget *widget,
471 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
472 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
473 gtk_window_buildable_interface_init))
476 add_tab_bindings (GtkBindingSet *binding_set,
477 GdkModifierType modifiers,
478 GtkDirectionType direction)
480 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
482 GTK_TYPE_DIRECTION_TYPE, direction);
483 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
485 GTK_TYPE_DIRECTION_TYPE, direction);
489 add_arrow_bindings (GtkBindingSet *binding_set,
491 GtkDirectionType direction)
493 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
495 gtk_binding_entry_add_signal (binding_set, keysym, 0,
497 GTK_TYPE_DIRECTION_TYPE, direction);
498 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
500 GTK_TYPE_DIRECTION_TYPE, direction);
501 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
503 GTK_TYPE_DIRECTION_TYPE, direction);
504 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
506 GTK_TYPE_DIRECTION_TYPE, direction);
510 extract_time_from_startup_id (const gchar* startup_id)
512 gchar *timestr = g_strrstr (startup_id, "_TIME");
513 guint32 retval = GDK_CURRENT_TIME;
520 /* Skip past the "_TIME" part */
525 timestamp = g_ascii_strtoull (timestr, &end, 0);
526 if (errno == 0 && end != timestr)
534 startup_id_is_fake (const gchar* startup_id)
536 return strncmp (startup_id, "_TIME", 5) == 0;
540 gtk_window_class_init (GtkWindowClass *klass)
542 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
543 GtkWidgetClass *widget_class;
544 GtkContainerClass *container_class;
545 GtkBindingSet *binding_set;
547 widget_class = (GtkWidgetClass*) klass;
548 container_class = (GtkContainerClass*) klass;
550 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
551 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
552 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
553 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
555 gobject_class->dispose = gtk_window_dispose;
556 gobject_class->finalize = gtk_window_finalize;
558 gobject_class->set_property = gtk_window_set_property;
559 gobject_class->get_property = gtk_window_get_property;
561 widget_class->destroy = gtk_window_destroy;
562 widget_class->show = gtk_window_show;
563 widget_class->hide = gtk_window_hide;
564 widget_class->map = gtk_window_map;
565 widget_class->map_event = gtk_window_map_event;
566 widget_class->unmap = gtk_window_unmap;
567 widget_class->realize = gtk_window_realize;
568 widget_class->unrealize = gtk_window_unrealize;
569 widget_class->size_allocate = gtk_window_size_allocate;
570 widget_class->configure_event = gtk_window_configure_event;
571 widget_class->key_press_event = gtk_window_key_press_event;
572 widget_class->key_release_event = gtk_window_key_release_event;
573 widget_class->enter_notify_event = gtk_window_enter_notify_event;
574 widget_class->leave_notify_event = gtk_window_leave_notify_event;
575 widget_class->focus_in_event = gtk_window_focus_in_event;
576 widget_class->button_press_event = gtk_window_button_press_event;
577 widget_class->focus_out_event = gtk_window_focus_out_event;
578 widget_class->client_event = gtk_window_client_event;
579 widget_class->focus = gtk_window_focus;
580 widget_class->move_focus = gtk_window_move_focus;
581 widget_class->draw = gtk_window_draw;
582 widget_class->get_preferred_width = gtk_window_get_preferred_width;
583 widget_class->get_preferred_height = gtk_window_get_preferred_height;
584 widget_class->window_state_event = gtk_window_state_event;
585 widget_class->direction_changed = gtk_window_direction_changed;
586 widget_class->state_changed = gtk_window_state_changed;
587 widget_class->style_updated = gtk_window_style_updated;
589 container_class->check_resize = gtk_window_check_resize;
591 klass->set_focus = gtk_window_real_set_focus;
593 klass->activate_default = gtk_window_real_activate_default;
594 klass->activate_focus = gtk_window_real_activate_focus;
595 klass->keys_changed = gtk_window_keys_changed;
597 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
600 g_object_class_install_property (gobject_class,
602 g_param_spec_enum ("type",
604 P_("The type of the window"),
605 GTK_TYPE_WINDOW_TYPE,
607 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
609 g_object_class_install_property (gobject_class,
611 g_param_spec_string ("title",
613 P_("The title of the window"),
615 GTK_PARAM_READWRITE));
617 g_object_class_install_property (gobject_class,
619 g_param_spec_string ("role",
621 P_("Unique identifier for the window to be used when restoring a session"),
623 GTK_PARAM_READWRITE));
626 * GtkWindow:startup-id:
628 * The :startup-id is a write-only property for setting window's
629 * startup notification identifier. See gtk_window_set_startup_id()
634 g_object_class_install_property (gobject_class,
636 g_param_spec_string ("startup-id",
638 P_("Unique startup identifier for the window used by startup-notification"),
640 GTK_PARAM_WRITABLE));
642 g_object_class_install_property (gobject_class,
644 g_param_spec_boolean ("resizable",
646 P_("If TRUE, users can resize the window"),
648 GTK_PARAM_READWRITE));
650 g_object_class_install_property (gobject_class,
652 g_param_spec_boolean ("modal",
654 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
656 GTK_PARAM_READWRITE));
658 g_object_class_install_property (gobject_class,
660 g_param_spec_enum ("window-position",
661 P_("Window Position"),
662 P_("The initial position of the window"),
663 GTK_TYPE_WINDOW_POSITION,
665 GTK_PARAM_READWRITE));
667 g_object_class_install_property (gobject_class,
669 g_param_spec_int ("default-width",
671 P_("The default width of the window, used when initially showing the window"),
675 GTK_PARAM_READWRITE));
677 g_object_class_install_property (gobject_class,
679 g_param_spec_int ("default-height",
680 P_("Default Height"),
681 P_("The default height of the window, used when initially showing the window"),
685 GTK_PARAM_READWRITE));
687 g_object_class_install_property (gobject_class,
688 PROP_DESTROY_WITH_PARENT,
689 g_param_spec_boolean ("destroy-with-parent",
690 P_("Destroy with Parent"),
691 P_("If this window should be destroyed when the parent is destroyed"),
693 GTK_PARAM_READWRITE));
695 g_object_class_install_property (gobject_class,
697 g_param_spec_object ("icon",
699 P_("Icon for this window"),
701 GTK_PARAM_READWRITE));
702 g_object_class_install_property (gobject_class,
703 PROP_MNEMONICS_VISIBLE,
704 g_param_spec_boolean ("mnemonics-visible",
705 P_("Mnemonics Visible"),
706 P_("Whether mnemonics are currently visible in this window"),
708 GTK_PARAM_READWRITE));
711 * GtkWindow:icon-name:
713 * The :icon-name property specifies the name of the themed icon to
714 * use as the window icon. See #GtkIconTheme for more details.
718 g_object_class_install_property (gobject_class,
720 g_param_spec_string ("icon-name",
722 P_("Name of the themed icon for this window"),
724 GTK_PARAM_READWRITE));
726 g_object_class_install_property (gobject_class,
728 g_param_spec_object ("screen",
730 P_("The screen where this window will be displayed"),
732 GTK_PARAM_READWRITE));
734 g_object_class_install_property (gobject_class,
736 g_param_spec_boolean ("is-active",
738 P_("Whether the toplevel is the current active window"),
740 GTK_PARAM_READABLE));
742 g_object_class_install_property (gobject_class,
743 PROP_HAS_TOPLEVEL_FOCUS,
744 g_param_spec_boolean ("has-toplevel-focus",
745 P_("Focus in Toplevel"),
746 P_("Whether the input focus is within this GtkWindow"),
748 GTK_PARAM_READABLE));
750 g_object_class_install_property (gobject_class,
752 g_param_spec_enum ("type-hint",
754 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
755 GDK_TYPE_WINDOW_TYPE_HINT,
756 GDK_WINDOW_TYPE_HINT_NORMAL,
757 GTK_PARAM_READWRITE));
759 g_object_class_install_property (gobject_class,
760 PROP_SKIP_TASKBAR_HINT,
761 g_param_spec_boolean ("skip-taskbar-hint",
763 P_("TRUE if the window should not be in the task bar."),
765 GTK_PARAM_READWRITE));
767 g_object_class_install_property (gobject_class,
768 PROP_SKIP_PAGER_HINT,
769 g_param_spec_boolean ("skip-pager-hint",
771 P_("TRUE if the window should not be in the pager."),
773 GTK_PARAM_READWRITE));
775 g_object_class_install_property (gobject_class,
777 g_param_spec_boolean ("urgency-hint",
779 P_("TRUE if the window should be brought to the user's attention."),
781 GTK_PARAM_READWRITE));
784 * GtkWindow:accept-focus:
786 * Whether the window should receive the input focus.
790 g_object_class_install_property (gobject_class,
792 g_param_spec_boolean ("accept-focus",
794 P_("TRUE if the window should receive the input focus."),
796 GTK_PARAM_READWRITE));
799 * GtkWindow:focus-on-map:
801 * Whether the window should receive the input focus when mapped.
805 g_object_class_install_property (gobject_class,
807 g_param_spec_boolean ("focus-on-map",
809 P_("TRUE if the window should receive the input focus when mapped."),
811 GTK_PARAM_READWRITE));
814 * GtkWindow:decorated:
816 * Whether the window should be decorated by the window manager.
820 g_object_class_install_property (gobject_class,
822 g_param_spec_boolean ("decorated",
824 P_("Whether the window should be decorated by the window manager"),
826 GTK_PARAM_READWRITE));
829 * GtkWindow:deletable:
831 * Whether the window frame should have a close button.
835 g_object_class_install_property (gobject_class,
837 g_param_spec_boolean ("deletable",
839 P_("Whether the window frame should have a close button"),
841 GTK_PARAM_READWRITE));
844 * GtkWindow:has-resize-grip
846 * Whether the window has a corner resize grip.
848 * Note that the resize grip is only shown if the window is
849 * actually resizable and not maximized. Use
850 * #GtkWindow:resize-grip-visible to find out if the resize
851 * grip is currently shown.
855 g_object_class_install_property (gobject_class,
856 PROP_HAS_RESIZE_GRIP,
857 g_param_spec_boolean ("has-resize-grip",
859 P_("Specifies whether the window should have a resize grip"),
861 GTK_PARAM_READWRITE));
864 * GtkWindow:resize-grip-visible:
866 * Whether a corner resize grip is currently shown.
870 g_object_class_install_property (gobject_class,
871 PROP_RESIZE_GRIP_VISIBLE,
872 g_param_spec_boolean ("resize-grip-visible",
873 P_("Resize grip is visible"),
874 P_("Specifies whether the window's resize grip is visible."),
876 GTK_PARAM_READABLE));
882 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
883 * more details about window gravity.
887 g_object_class_install_property (gobject_class,
889 g_param_spec_enum ("gravity",
891 P_("The window gravity of the window"),
893 GDK_GRAVITY_NORTH_WEST,
894 GTK_PARAM_READWRITE));
898 * GtkWindow:transient-for:
900 * The transient parent of the window. See gtk_window_set_transient_for() for
901 * more details about transient windows.
905 g_object_class_install_property (gobject_class,
907 g_param_spec_object ("transient-for",
908 P_("Transient for Window"),
909 P_("The transient parent of the dialog"),
911 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
916 * The requested opacity of the window. See gtk_window_set_opacity() for
917 * more details about window opacity.
921 g_object_class_install_property (gobject_class,
923 g_param_spec_double ("opacity",
924 P_("Opacity for Window"),
925 P_("The opacity of the window, from 0 to 1"),
929 GTK_PARAM_READWRITE));
933 gtk_widget_class_install_style_property (widget_class,
934 g_param_spec_int ("resize-grip-width",
935 P_("Width of resize grip"),
936 P_("Width of resize grip"),
937 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
939 gtk_widget_class_install_style_property (widget_class,
940 g_param_spec_int ("resize-grip-height",
941 P_("Height of resize grip"),
942 P_("Height of resize grip"),
943 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
947 * GtkWindow:application:
949 * The #GtkApplication associated with the window.
951 * The application will be kept alive for at least as long as it
952 * has any windows associated with it (see g_application_hold()
953 * for a way to keep it alive without windows).
955 * Normally, the connection between the application and the window
956 * will remain until the window is destroyed, but you can explicitly
957 * remove it by setting the ::application property to %NULL.
961 g_object_class_install_property (gobject_class,
963 g_param_spec_object ("application",
964 P_("GtkApplication"),
965 P_("The GtkApplication for the window"),
966 GTK_TYPE_APPLICATION,
967 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
969 window_signals[SET_FOCUS] =
970 g_signal_new (I_("set-focus"),
971 G_TYPE_FROM_CLASS (gobject_class),
973 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
975 _gtk_marshal_VOID__OBJECT,
980 * GtkWindow::activate-focus:
981 * @window: the window which received the signal
983 * The ::activate-focus signal is a
984 * <link linkend="keybinding-signals">keybinding signal</link>
985 * which gets emitted when the user activates the currently
986 * focused widget of @window.
988 window_signals[ACTIVATE_FOCUS] =
989 g_signal_new (I_("activate-focus"),
990 G_TYPE_FROM_CLASS (gobject_class),
991 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
992 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
994 _gtk_marshal_VOID__VOID,
999 * GtkWindow::activate-default:
1000 * @window: the window which received the signal
1002 * The ::activate-default signal is a
1003 * <link linkend="keybinding-signals">keybinding signal</link>
1004 * which gets emitted when the user activates the default widget
1007 window_signals[ACTIVATE_DEFAULT] =
1008 g_signal_new (I_("activate-default"),
1009 G_TYPE_FROM_CLASS (gobject_class),
1010 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1011 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1013 _gtk_marshal_VOID__VOID,
1018 * GtkWindow::keys-changed:
1019 * @window: the window which received the signal
1021 * The ::keys-changed signal gets emitted when the set of accelerators
1022 * or mnemonics that are associated with @window changes.
1024 window_signals[KEYS_CHANGED] =
1025 g_signal_new (I_("keys-changed"),
1026 G_TYPE_FROM_CLASS (gobject_class),
1028 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1030 _gtk_marshal_VOID__VOID,
1038 binding_set = gtk_binding_set_by_class (klass);
1040 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1041 "activate-focus", 0);
1042 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1043 "activate-focus", 0);
1045 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1046 "activate-default", 0);
1047 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1048 "activate-default", 0);
1049 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1050 "activate-default", 0);
1052 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1053 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1054 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1055 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1057 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1058 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1059 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1060 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1064 gtk_window_init (GtkWindow *window)
1066 GtkWindowPrivate *priv;
1068 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1071 priv = window->priv;
1073 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1074 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1076 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1078 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1081 priv->wmclass_name = g_strdup (g_get_prgname ());
1082 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1083 priv->wm_role = NULL;
1084 priv->geometry_info = NULL;
1085 priv->type = GTK_WINDOW_TOPLEVEL;
1086 priv->focus_widget = NULL;
1087 priv->default_widget = NULL;
1088 priv->configure_request_count = 0;
1089 priv->resizable = TRUE;
1090 priv->configure_notify_received = FALSE;
1091 priv->position = GTK_WIN_POS_NONE;
1092 priv->need_default_size = TRUE;
1093 priv->need_default_position = TRUE;
1094 priv->modal = FALSE;
1095 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1096 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1097 priv->decorated = TRUE;
1098 priv->mnemonic_modifier = GDK_MOD1_MASK;
1099 priv->screen = gdk_screen_get_default ();
1101 priv->accept_focus = TRUE;
1102 priv->focus_on_map = TRUE;
1103 priv->deletable = TRUE;
1104 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1105 priv->opacity = 1.0;
1106 priv->startup_id = NULL;
1107 priv->has_resize_grip = TRUE;
1108 priv->mnemonics_visible = TRUE;
1110 g_object_ref_sink (window);
1111 priv->has_user_ref_count = TRUE;
1112 toplevel_list = g_slist_prepend (toplevel_list, window);
1114 g_signal_connect (priv->screen, "composited-changed",
1115 G_CALLBACK (gtk_window_on_composited_changed), window);
1119 gtk_window_set_property (GObject *object,
1121 const GValue *value,
1124 GtkWindow *window = GTK_WINDOW (object);
1125 GtkWindowPrivate *priv = window->priv;
1130 priv->type = g_value_get_enum (value);
1133 gtk_window_set_title (window, g_value_get_string (value));
1136 gtk_window_set_role (window, g_value_get_string (value));
1138 case PROP_STARTUP_ID:
1139 gtk_window_set_startup_id (window, g_value_get_string (value));
1141 case PROP_RESIZABLE:
1142 gtk_window_set_resizable (window, g_value_get_boolean (value));
1145 gtk_window_set_modal (window, g_value_get_boolean (value));
1148 gtk_window_set_position (window, g_value_get_enum (value));
1150 case PROP_DEFAULT_WIDTH:
1151 gtk_window_set_default_size_internal (window,
1152 TRUE, g_value_get_int (value),
1155 case PROP_DEFAULT_HEIGHT:
1156 gtk_window_set_default_size_internal (window,
1158 TRUE, g_value_get_int (value), FALSE);
1160 case PROP_DESTROY_WITH_PARENT:
1161 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1164 gtk_window_set_icon (window,
1165 g_value_get_object (value));
1167 case PROP_ICON_NAME:
1168 gtk_window_set_icon_name (window, g_value_get_string (value));
1171 gtk_window_set_screen (window, g_value_get_object (value));
1173 case PROP_TYPE_HINT:
1174 gtk_window_set_type_hint (window,
1175 g_value_get_enum (value));
1177 case PROP_SKIP_TASKBAR_HINT:
1178 gtk_window_set_skip_taskbar_hint (window,
1179 g_value_get_boolean (value));
1181 case PROP_SKIP_PAGER_HINT:
1182 gtk_window_set_skip_pager_hint (window,
1183 g_value_get_boolean (value));
1185 case PROP_URGENCY_HINT:
1186 gtk_window_set_urgency_hint (window,
1187 g_value_get_boolean (value));
1189 case PROP_ACCEPT_FOCUS:
1190 gtk_window_set_accept_focus (window,
1191 g_value_get_boolean (value));
1193 case PROP_FOCUS_ON_MAP:
1194 gtk_window_set_focus_on_map (window,
1195 g_value_get_boolean (value));
1197 case PROP_DECORATED:
1198 gtk_window_set_decorated (window, g_value_get_boolean (value));
1200 case PROP_DELETABLE:
1201 gtk_window_set_deletable (window, g_value_get_boolean (value));
1204 gtk_window_set_gravity (window, g_value_get_enum (value));
1206 case PROP_TRANSIENT_FOR:
1207 gtk_window_set_transient_for (window, g_value_get_object (value));
1210 gtk_window_set_opacity (window, g_value_get_double (value));
1212 case PROP_HAS_RESIZE_GRIP:
1213 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1215 case PROP_APPLICATION:
1216 gtk_window_set_application (window, g_value_get_object (value));
1218 case PROP_MNEMONICS_VISIBLE:
1219 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1222 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1228 gtk_window_get_property (GObject *object,
1233 GtkWindow *window = GTK_WINDOW (object);
1234 GtkWindowPrivate *priv = window->priv;
1238 GtkWindowGeometryInfo *info;
1240 g_value_set_enum (value, priv->type);
1243 g_value_set_string (value, priv->wm_role);
1246 g_value_set_string (value, priv->title);
1248 case PROP_RESIZABLE:
1249 g_value_set_boolean (value, priv->resizable);
1252 g_value_set_boolean (value, priv->modal);
1255 g_value_set_enum (value, priv->position);
1257 case PROP_DEFAULT_WIDTH:
1258 info = gtk_window_get_geometry_info (window, FALSE);
1260 g_value_set_int (value, -1);
1262 g_value_set_int (value, info->default_width);
1264 case PROP_DEFAULT_HEIGHT:
1265 info = gtk_window_get_geometry_info (window, FALSE);
1267 g_value_set_int (value, -1);
1269 g_value_set_int (value, info->default_height);
1271 case PROP_DESTROY_WITH_PARENT:
1272 g_value_set_boolean (value, priv->destroy_with_parent);
1275 g_value_set_object (value, gtk_window_get_icon (window));
1277 case PROP_ICON_NAME:
1278 g_value_set_string (value, gtk_window_get_icon_name (window));
1281 g_value_set_object (value, priv->screen);
1283 case PROP_IS_ACTIVE:
1284 g_value_set_boolean (value, priv->is_active);
1286 case PROP_HAS_TOPLEVEL_FOCUS:
1287 g_value_set_boolean (value, priv->has_toplevel_focus);
1289 case PROP_TYPE_HINT:
1290 g_value_set_enum (value, priv->type_hint);
1292 case PROP_SKIP_TASKBAR_HINT:
1293 g_value_set_boolean (value,
1294 gtk_window_get_skip_taskbar_hint (window));
1296 case PROP_SKIP_PAGER_HINT:
1297 g_value_set_boolean (value,
1298 gtk_window_get_skip_pager_hint (window));
1300 case PROP_URGENCY_HINT:
1301 g_value_set_boolean (value,
1302 gtk_window_get_urgency_hint (window));
1304 case PROP_ACCEPT_FOCUS:
1305 g_value_set_boolean (value,
1306 gtk_window_get_accept_focus (window));
1308 case PROP_FOCUS_ON_MAP:
1309 g_value_set_boolean (value,
1310 gtk_window_get_focus_on_map (window));
1312 case PROP_DECORATED:
1313 g_value_set_boolean (value, gtk_window_get_decorated (window));
1315 case PROP_DELETABLE:
1316 g_value_set_boolean (value, gtk_window_get_deletable (window));
1319 g_value_set_enum (value, gtk_window_get_gravity (window));
1321 case PROP_TRANSIENT_FOR:
1322 g_value_set_object (value, gtk_window_get_transient_for (window));
1325 g_value_set_double (value, gtk_window_get_opacity (window));
1327 case PROP_HAS_RESIZE_GRIP:
1328 g_value_set_boolean (value, priv->has_resize_grip);
1330 case PROP_RESIZE_GRIP_VISIBLE:
1331 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1333 case PROP_APPLICATION:
1334 g_value_set_object (value, gtk_window_get_application (window));
1336 case PROP_MNEMONICS_VISIBLE:
1337 g_value_set_boolean (value, priv->mnemonics_visible);
1340 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1346 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1348 parent_buildable_iface = g_type_interface_peek_parent (iface);
1349 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1350 iface->parser_finished = gtk_window_buildable_parser_finished;
1351 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1352 iface->custom_finished = gtk_window_buildable_custom_finished;
1356 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1357 GtkBuilder *builder,
1359 const GValue *value)
1361 GtkWindow *window = GTK_WINDOW (buildable);
1362 GtkWindowPrivate *priv = window->priv;
1364 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1365 priv->builder_visible = TRUE;
1367 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1371 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1372 GtkBuilder *builder)
1374 GtkWindow *window = GTK_WINDOW (buildable);
1375 GtkWindowPrivate *priv = window->priv;
1379 if (priv->builder_visible)
1380 gtk_widget_show (GTK_WIDGET (buildable));
1382 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1383 for (l = accels; l; l = l->next)
1385 object = gtk_builder_get_object (builder, l->data);
1388 g_warning ("Unknown accel group %s specified in window %s",
1389 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1392 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1393 GTK_ACCEL_GROUP (object));
1397 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1399 parent_buildable_iface->parser_finished (buildable, builder);
1405 } GSListSubParserData;
1408 window_start_element (GMarkupParseContext *context,
1409 const gchar *element_name,
1410 const gchar **names,
1411 const gchar **values,
1416 GSListSubParserData *data = (GSListSubParserData*)user_data;
1418 if (strcmp (element_name, "group") == 0)
1420 for (i = 0; names[i]; i++)
1422 if (strcmp (names[i], "name") == 0)
1423 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1426 else if (strcmp (element_name, "accel-groups") == 0)
1429 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1434 static const GMarkupParser window_parser =
1436 window_start_element
1440 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1441 GtkBuilder *builder,
1443 const gchar *tagname,
1444 GMarkupParser *parser,
1447 GSListSubParserData *parser_data;
1449 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1450 tagname, parser, data))
1453 if (strcmp (tagname, "accel-groups") == 0)
1455 parser_data = g_slice_new0 (GSListSubParserData);
1456 parser_data->items = NULL;
1457 parser_data->object = G_OBJECT (buildable);
1459 *parser = window_parser;
1460 *data = parser_data;
1468 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1469 GtkBuilder *builder,
1471 const gchar *tagname,
1474 GSListSubParserData *data;
1476 parent_buildable_iface->custom_finished (buildable, builder, child,
1477 tagname, user_data);
1479 if (strcmp (tagname, "accel-groups") != 0)
1482 data = (GSListSubParserData*)user_data;
1484 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1485 data->items, (GDestroyNotify) g_slist_free);
1487 g_slice_free (GSListSubParserData, data);
1492 * @type: type of window
1494 * Creates a new #GtkWindow, which is a toplevel window that can
1495 * contain other widgets. Nearly always, the type of the window should
1496 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1497 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1498 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1499 * dialogs, though in some other toolkits dialogs are called "popups".
1500 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1501 * On X11, popup windows are not controlled by the <link
1502 * linkend="gtk-X11-arch">window manager</link>.
1504 * If you simply want an undecorated window (no window borders), use
1505 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1507 * Return value: a new #GtkWindow.
1510 gtk_window_new (GtkWindowType type)
1512 GtkWindowPrivate *priv;
1515 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1517 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1518 priv = window->priv;
1522 return GTK_WIDGET (window);
1526 * gtk_window_set_title:
1527 * @window: a #GtkWindow
1528 * @title: title of the window
1530 * Sets the title of the #GtkWindow. The title of a window will be
1531 * displayed in its title bar; on the X Window System, the title bar
1532 * is rendered by the <link linkend="gtk-X11-arch">window
1533 * manager</link>, so exactly how the title appears to users may vary
1534 * according to a user's exact configuration. The title should help a
1535 * user distinguish this window from other windows they may have
1536 * open. A good title might include the application name and current
1537 * document filename, for example.
1541 gtk_window_set_title (GtkWindow *window,
1544 GtkWindowPrivate *priv;
1548 g_return_if_fail (GTK_IS_WINDOW (window));
1550 priv = window->priv;
1551 widget = GTK_WIDGET (window);
1553 new_title = g_strdup (title);
1554 g_free (priv->title);
1555 priv->title = new_title;
1557 if (gtk_widget_get_realized (widget))
1559 gdk_window_set_title (gtk_widget_get_window (widget),
1563 g_object_notify (G_OBJECT (window), "title");
1567 * gtk_window_get_title:
1568 * @window: a #GtkWindow
1570 * Retrieves the title of the window. See gtk_window_set_title().
1572 * Return value: the title of the window, or %NULL if none has
1573 * been set explicitely. The returned string is owned by the widget
1574 * and must not be modified or freed.
1576 G_CONST_RETURN gchar *
1577 gtk_window_get_title (GtkWindow *window)
1579 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1581 return window->priv->title;
1585 * gtk_window_set_wmclass:
1586 * @window: a #GtkWindow
1587 * @wmclass_name: window name hint
1588 * @wmclass_class: window class hint
1590 * Don't use this function. It sets the X Window System "class" and
1591 * "name" hints for a window. According to the ICCCM, you should
1592 * always set these to the same value for all windows in an
1593 * application, and GTK+ sets them to that value by default, so calling
1594 * this function is sort of pointless. However, you may want to call
1595 * gtk_window_set_role() on each window in your application, for the
1596 * benefit of the session manager. Setting the role allows the window
1597 * manager to restore window positions when loading a saved session.
1601 gtk_window_set_wmclass (GtkWindow *window,
1602 const gchar *wmclass_name,
1603 const gchar *wmclass_class)
1605 GtkWindowPrivate *priv;
1607 g_return_if_fail (GTK_IS_WINDOW (window));
1609 priv = window->priv;
1611 g_free (priv->wmclass_name);
1612 priv->wmclass_name = g_strdup (wmclass_name);
1614 g_free (priv->wmclass_class);
1615 priv->wmclass_class = g_strdup (wmclass_class);
1617 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1618 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1622 * gtk_window_set_role:
1623 * @window: a #GtkWindow
1624 * @role: unique identifier for the window to be used when restoring a session
1626 * This function is only useful on X11, not with other GTK+ targets.
1628 * In combination with the window title, the window role allows a
1629 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1630 * same" window when an application is restarted. So for example you
1631 * might set the "toolbox" role on your app's toolbox window, so that
1632 * when the user restarts their session, the window manager can put
1633 * the toolbox back in the same place.
1635 * If a window already has a unique title, you don't need to set the
1636 * role, since the WM can use the title to identify the window when
1637 * restoring the session.
1641 gtk_window_set_role (GtkWindow *window,
1644 GtkWindowPrivate *priv;
1647 g_return_if_fail (GTK_IS_WINDOW (window));
1649 priv = window->priv;
1651 new_role = g_strdup (role);
1652 g_free (priv->wm_role);
1653 priv->wm_role = new_role;
1655 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1656 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1659 g_object_notify (G_OBJECT (window), "role");
1663 * gtk_window_set_startup_id:
1664 * @window: a #GtkWindow
1665 * @startup_id: a string with startup-notification identifier
1667 * Startup notification identifiers are used by desktop environment to
1668 * track application startup, to provide user feedback and other
1669 * features. This function changes the corresponding property on the
1670 * underlying GdkWindow. Normally, startup identifier is managed
1671 * automatically and you should only use this function in special cases
1672 * like transferring focus from other processes. You should use this
1673 * function before calling gtk_window_present() or any equivalent
1674 * function generating a window map event.
1676 * This function is only useful on X11, not with other GTK+ targets.
1681 gtk_window_set_startup_id (GtkWindow *window,
1682 const gchar *startup_id)
1684 GtkWindowPrivate *priv;
1687 g_return_if_fail (GTK_IS_WINDOW (window));
1689 priv = window->priv;
1690 widget = GTK_WIDGET (window);
1692 g_free (priv->startup_id);
1693 priv->startup_id = g_strdup (startup_id);
1695 if (gtk_widget_get_realized (widget))
1697 GdkWindow *gdk_window;
1698 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1700 gdk_window = gtk_widget_get_window (widget);
1702 #ifdef GDK_WINDOWING_X11
1703 if (timestamp != GDK_CURRENT_TIME)
1704 gdk_x11_window_set_user_time (gdk_window, timestamp);
1707 /* Here we differentiate real and "fake" startup notification IDs,
1708 * constructed on purpose just to pass interaction timestamp
1710 if (startup_id_is_fake (priv->startup_id))
1711 gtk_window_present_with_time (window, timestamp);
1714 gdk_window_set_startup_id (gdk_window,
1717 /* If window is mapped, terminate the startup-notification too */
1718 if (gtk_widget_get_mapped (widget) &&
1719 !disable_startup_notification)
1720 gdk_notify_startup_complete_with_id (priv->startup_id);
1724 g_object_notify (G_OBJECT (window), "startup-id");
1728 * gtk_window_get_role:
1729 * @window: a #GtkWindow
1731 * Returns the role of the window. See gtk_window_set_role() for
1732 * further explanation.
1734 * Return value: the role of the window if set, or %NULL. The
1735 * returned is owned by the widget and must not be modified
1738 G_CONST_RETURN gchar *
1739 gtk_window_get_role (GtkWindow *window)
1741 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1743 return window->priv->wm_role;
1747 * gtk_window_set_focus:
1748 * @window: a #GtkWindow
1749 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1750 * any focus widget for the toplevel window.
1752 * If @focus is not the current focus widget, and is focusable, sets
1753 * it as the focus widget for the window. If @focus is %NULL, unsets
1754 * the focus widget for this window. To set the focus to a particular
1755 * widget in the toplevel, it is usually more convenient to use
1756 * gtk_widget_grab_focus() instead of this function.
1759 gtk_window_set_focus (GtkWindow *window,
1762 GtkWindowPrivate *priv;
1765 g_return_if_fail (GTK_IS_WINDOW (window));
1767 priv = window->priv;
1771 g_return_if_fail (GTK_IS_WIDGET (focus));
1772 g_return_if_fail (gtk_widget_get_can_focus (focus));
1776 gtk_widget_grab_focus (focus);
1779 /* Clear the existing focus chain, so that when we focus into
1780 * the window again, we start at the beginnning.
1782 GtkWidget *widget = priv->focus_widget;
1785 while ((parent = gtk_widget_get_parent (widget)))
1788 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1792 _gtk_window_internal_set_focus (window, NULL);
1797 _gtk_window_internal_set_focus (GtkWindow *window,
1800 GtkWindowPrivate *priv;
1802 g_return_if_fail (GTK_IS_WINDOW (window));
1804 priv = window->priv;
1806 if ((priv->focus_widget != focus) ||
1807 (focus && !gtk_widget_has_focus (focus)))
1808 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1812 * gtk_window_set_default:
1813 * @window: a #GtkWindow
1814 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1815 * default widget for the toplevel.
1817 * The default widget is the widget that's activated when the user
1818 * presses Enter in a dialog (for example). This function sets or
1819 * unsets the default widget for a #GtkWindow about. When setting
1820 * (rather than unsetting) the default widget it's generally easier to
1821 * call gtk_widget_grab_focus() on the widget. Before making a widget
1822 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1823 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1826 gtk_window_set_default (GtkWindow *window,
1827 GtkWidget *default_widget)
1829 GtkWindowPrivate *priv;
1831 g_return_if_fail (GTK_IS_WINDOW (window));
1833 priv = window->priv;
1836 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1838 if (priv->default_widget != default_widget)
1840 GtkWidget *old_default_widget = NULL;
1843 g_object_ref (default_widget);
1845 if (priv->default_widget)
1847 old_default_widget = priv->default_widget;
1849 if (priv->focus_widget != priv->default_widget ||
1850 !gtk_widget_get_receives_default (priv->default_widget))
1851 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1853 gtk_widget_queue_draw (priv->default_widget);
1856 priv->default_widget = default_widget;
1858 if (priv->default_widget)
1860 if (priv->focus_widget == NULL ||
1861 !gtk_widget_get_receives_default (priv->focus_widget))
1862 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1864 gtk_widget_queue_draw (priv->default_widget);
1867 if (old_default_widget)
1868 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1872 g_object_notify (G_OBJECT (default_widget), "has-default");
1873 g_object_unref (default_widget);
1879 * gtk_window_get_default_widget:
1880 * @window: a #GtkWindow
1882 * Returns the default widget for @window. See gtk_window_set_default()
1885 * Returns: (transfer none): the default widget, or %NULL if there is none.
1890 gtk_window_get_default_widget (GtkWindow *window)
1892 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1894 return window->priv->default_widget;
1898 handle_keys_changed (gpointer data)
1900 GtkWindow *window = GTK_WINDOW (data);
1901 GtkWindowPrivate *priv = window->priv;
1903 if (priv->keys_changed_handler)
1905 g_source_remove (priv->keys_changed_handler);
1906 priv->keys_changed_handler = 0;
1909 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1915 gtk_window_notify_keys_changed (GtkWindow *window)
1917 GtkWindowPrivate *priv = window->priv;
1919 if (!priv->keys_changed_handler)
1920 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1924 * gtk_window_add_accel_group:
1925 * @window: window to attach accelerator group to
1926 * @accel_group: a #GtkAccelGroup
1928 * Associate @accel_group with @window, such that calling
1929 * gtk_accel_groups_activate() on @window will activate accelerators
1933 gtk_window_add_accel_group (GtkWindow *window,
1934 GtkAccelGroup *accel_group)
1936 g_return_if_fail (GTK_IS_WINDOW (window));
1937 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1939 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1940 g_signal_connect_object (accel_group, "accel-changed",
1941 G_CALLBACK (gtk_window_notify_keys_changed),
1942 window, G_CONNECT_SWAPPED);
1943 gtk_window_notify_keys_changed (window);
1947 * gtk_window_remove_accel_group:
1948 * @window: a #GtkWindow
1949 * @accel_group: a #GtkAccelGroup
1951 * Reverses the effects of gtk_window_add_accel_group().
1954 gtk_window_remove_accel_group (GtkWindow *window,
1955 GtkAccelGroup *accel_group)
1957 g_return_if_fail (GTK_IS_WINDOW (window));
1958 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1960 g_signal_handlers_disconnect_by_func (accel_group,
1961 gtk_window_notify_keys_changed,
1963 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1964 gtk_window_notify_keys_changed (window);
1967 static GtkMnemonicHash *
1968 gtk_window_get_mnemonic_hash (GtkWindow *window,
1971 GtkWindowPrivate *private = window->priv;
1973 if (!private->mnemonic_hash && create)
1974 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1976 return private->mnemonic_hash;
1980 * gtk_window_add_mnemonic:
1981 * @window: a #GtkWindow
1982 * @keyval: the mnemonic
1983 * @target: the widget that gets activated by the mnemonic
1985 * Adds a mnemonic to this window.
1988 gtk_window_add_mnemonic (GtkWindow *window,
1992 g_return_if_fail (GTK_IS_WINDOW (window));
1993 g_return_if_fail (GTK_IS_WIDGET (target));
1995 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1997 gtk_window_notify_keys_changed (window);
2001 * gtk_window_remove_mnemonic:
2002 * @window: a #GtkWindow
2003 * @keyval: the mnemonic
2004 * @target: the widget that gets activated by the mnemonic
2006 * Removes a mnemonic from this window.
2009 gtk_window_remove_mnemonic (GtkWindow *window,
2013 g_return_if_fail (GTK_IS_WINDOW (window));
2014 g_return_if_fail (GTK_IS_WIDGET (target));
2016 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2018 gtk_window_notify_keys_changed (window);
2022 * gtk_window_mnemonic_activate:
2023 * @window: a #GtkWindow
2024 * @keyval: the mnemonic
2025 * @modifier: the modifiers
2026 * @returns: %TRUE if the activation is done.
2028 * Activates the targets associated with the mnemonic.
2031 gtk_window_mnemonic_activate (GtkWindow *window,
2033 GdkModifierType modifier)
2035 GtkWindowPrivate *priv;
2037 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2039 priv = window->priv;
2041 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2043 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2045 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2052 * gtk_window_set_mnemonic_modifier:
2053 * @window: a #GtkWindow
2054 * @modifier: the modifier mask used to activate
2055 * mnemonics on this window.
2057 * Sets the mnemonic modifier for this window.
2060 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2061 GdkModifierType modifier)
2063 GtkWindowPrivate *priv;
2065 g_return_if_fail (GTK_IS_WINDOW (window));
2066 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2068 priv = window->priv;
2070 priv->mnemonic_modifier = modifier;
2071 gtk_window_notify_keys_changed (window);
2075 * gtk_window_get_mnemonic_modifier:
2076 * @window: a #GtkWindow
2078 * Returns the mnemonic modifier for this window. See
2079 * gtk_window_set_mnemonic_modifier().
2081 * Return value: the modifier mask used to activate
2082 * mnemonics on this window.
2085 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2087 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2089 return window->priv->mnemonic_modifier;
2093 * gtk_window_set_position:
2094 * @window: a #GtkWindow.
2095 * @position: a position constraint.
2097 * Sets a position constraint for this window. If the old or new
2098 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2099 * the window to be repositioned to satisfy the new constraint.
2102 gtk_window_set_position (GtkWindow *window,
2103 GtkWindowPosition position)
2105 GtkWindowPrivate *priv;
2107 g_return_if_fail (GTK_IS_WINDOW (window));
2109 priv = window->priv;
2111 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2112 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2114 GtkWindowGeometryInfo *info;
2116 info = gtk_window_get_geometry_info (window, TRUE);
2118 /* this flag causes us to re-request the CENTER_ALWAYS
2119 * constraint in gtk_window_move_resize(), see
2120 * comment in that function.
2122 info->position_constraints_changed = TRUE;
2124 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2127 priv->position = position;
2129 g_object_notify (G_OBJECT (window), "window-position");
2133 * gtk_window_activate_focus:
2134 * @window: a #GtkWindow
2136 * Activates the current focused widget within the window.
2138 * Return value: %TRUE if a widget got activated.
2141 gtk_window_activate_focus (GtkWindow *window)
2143 GtkWindowPrivate *priv;
2145 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2147 priv = window->priv;
2149 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2150 return gtk_widget_activate (priv->focus_widget);
2156 * gtk_window_get_focus:
2157 * @window: a #GtkWindow
2159 * Retrieves the current focused widget within the window.
2160 * Note that this is the widget that would have the focus
2161 * if the toplevel window focused; if the toplevel window
2162 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2163 * not be %TRUE for the widget.
2165 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2168 gtk_window_get_focus (GtkWindow *window)
2170 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2172 return window->priv->focus_widget;
2176 * gtk_window_activate_default:
2177 * @window: a #GtkWindow
2179 * Activates the default widget for the window, unless the current
2180 * focused widget has been configured to receive the default action
2181 * (see gtk_widget_set_receives_default()), in which case the
2182 * focused widget is activated.
2184 * Return value: %TRUE if a widget got activated.
2187 gtk_window_activate_default (GtkWindow *window)
2189 GtkWindowPrivate *priv;
2191 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2193 priv = window->priv;
2195 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2196 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2197 return gtk_widget_activate (priv->default_widget);
2198 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2199 return gtk_widget_activate (priv->focus_widget);
2205 * gtk_window_set_modal:
2206 * @window: a #GtkWindow
2207 * @modal: whether the window is modal
2209 * Sets a window modal or non-modal. Modal windows prevent interaction
2210 * with other windows in the same application. To keep modal dialogs
2211 * on top of main application windows, use
2212 * gtk_window_set_transient_for() to make the dialog transient for the
2213 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2214 * will then disallow lowering the dialog below the parent.
2219 gtk_window_set_modal (GtkWindow *window,
2222 GtkWindowPrivate *priv;
2225 g_return_if_fail (GTK_IS_WINDOW (window));
2227 priv = window->priv;
2229 modal = modal != FALSE;
2230 if (priv->modal == modal)
2233 priv->modal = modal;
2234 widget = GTK_WIDGET (window);
2236 /* adjust desired modality state */
2237 if (gtk_widget_get_realized (widget))
2240 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2242 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2245 if (gtk_widget_get_visible (widget))
2248 gtk_grab_add (widget);
2250 gtk_grab_remove (widget);
2253 g_object_notify (G_OBJECT (window), "modal");
2257 * gtk_window_get_modal:
2258 * @window: a #GtkWindow
2260 * Returns whether the window is modal. See gtk_window_set_modal().
2262 * Return value: %TRUE if the window is set to be modal and
2263 * establishes a grab when shown
2266 gtk_window_get_modal (GtkWindow *window)
2268 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2270 return window->priv->modal;
2274 * gtk_window_list_toplevels:
2276 * Returns a list of all existing toplevel windows. The widgets
2277 * in the list are not individually referenced. If you want
2278 * to iterate through the list and perform actions involving
2279 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2280 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2281 * then unref all the widgets afterwards.
2283 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2286 gtk_window_list_toplevels (void)
2291 for (slist = toplevel_list; slist; slist = slist->next)
2292 list = g_list_prepend (list, slist->data);
2298 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2300 GList *embedded_windows;
2302 g_return_if_fail (GTK_IS_WINDOW (window));
2304 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2305 if (embedded_windows)
2306 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2307 embedded_windows = g_list_prepend (embedded_windows,
2308 GUINT_TO_POINTER (xid));
2310 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2313 (GDestroyNotify) g_list_free : NULL);
2317 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2319 GList *embedded_windows;
2322 g_return_if_fail (GTK_IS_WINDOW (window));
2324 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2325 if (embedded_windows)
2326 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2328 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2331 embedded_windows = g_list_remove_link (embedded_windows, node);
2332 g_list_free_1 (node);
2335 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2338 (GDestroyNotify) g_list_free : NULL);
2342 gtk_window_dispose (GObject *object)
2344 GtkWindow *window = GTK_WINDOW (object);
2346 gtk_window_set_focus (window, NULL);
2347 gtk_window_set_default (window, NULL);
2349 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2353 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2355 gtk_widget_destroy (GTK_WIDGET (child));
2359 connect_parent_destroyed (GtkWindow *window)
2361 GtkWindowPrivate *priv = window->priv;
2363 if (priv->transient_parent)
2365 g_signal_connect (priv->transient_parent,
2367 G_CALLBACK (parent_destroyed_callback),
2373 disconnect_parent_destroyed (GtkWindow *window)
2375 GtkWindowPrivate *priv = window->priv;
2377 if (priv->transient_parent)
2379 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2380 parent_destroyed_callback,
2386 gtk_window_transient_parent_realized (GtkWidget *parent,
2389 if (gtk_widget_get_realized (window))
2390 gdk_window_set_transient_for (gtk_widget_get_window (window),
2391 gtk_widget_get_window (parent));
2395 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2398 if (gtk_widget_get_realized (window))
2399 gdk_property_delete (gtk_widget_get_window (window),
2400 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2404 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2408 gtk_window_set_screen (window, parent->priv->screen);
2412 gtk_window_unset_transient_for (GtkWindow *window)
2414 GtkWindowPrivate *priv = window->priv;
2416 if (priv->transient_parent)
2418 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2419 gtk_window_transient_parent_realized,
2421 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2422 gtk_window_transient_parent_unrealized,
2424 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2425 gtk_window_transient_parent_screen_changed,
2427 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2428 gtk_widget_destroyed,
2429 &priv->transient_parent);
2431 if (priv->destroy_with_parent)
2432 disconnect_parent_destroyed (window);
2434 priv->transient_parent = NULL;
2436 if (priv->transient_parent_group)
2438 priv->transient_parent_group = FALSE;
2439 gtk_window_group_remove_window (priv->group,
2446 * gtk_window_set_transient_for:
2447 * @window: a #GtkWindow
2448 * @parent: (allow-none): parent window, or %NULL
2450 * Dialog windows should be set transient for the main application
2451 * window they were spawned from. This allows <link
2452 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2453 * dialog on top of the main window, or center the dialog over the
2454 * main window. gtk_dialog_new_with_buttons() and other convenience
2455 * functions in GTK+ will sometimes call
2456 * gtk_window_set_transient_for() on your behalf.
2458 * Passing %NULL for @parent unsets the current transient window.
2460 * On Windows, this function puts the child window on top of the parent,
2461 * much as the window manager would have done on X.
2464 gtk_window_set_transient_for (GtkWindow *window,
2467 GtkWindowPrivate *priv;
2469 g_return_if_fail (GTK_IS_WINDOW (window));
2470 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2471 g_return_if_fail (window != parent);
2473 priv = window->priv;
2475 if (priv->transient_parent)
2477 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2478 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2479 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2480 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2481 GTK_WIDGET (window));
2483 gtk_window_unset_transient_for (window);
2486 priv->transient_parent = parent;
2490 g_signal_connect (parent, "destroy",
2491 G_CALLBACK (gtk_widget_destroyed),
2492 &priv->transient_parent);
2493 g_signal_connect (parent, "realize",
2494 G_CALLBACK (gtk_window_transient_parent_realized),
2496 g_signal_connect (parent, "unrealize",
2497 G_CALLBACK (gtk_window_transient_parent_unrealized),
2499 g_signal_connect (parent, "notify::screen",
2500 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2503 gtk_window_set_screen (window, parent->priv->screen);
2505 if (priv->destroy_with_parent)
2506 connect_parent_destroyed (window);
2508 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2509 gtk_widget_get_realized (GTK_WIDGET (parent)))
2510 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2511 GTK_WIDGET (window));
2513 if (parent->priv->group)
2515 gtk_window_group_add_window (parent->priv->group, window);
2516 priv->transient_parent_group = TRUE;
2522 * gtk_window_get_transient_for:
2523 * @window: a #GtkWindow
2525 * Fetches the transient parent for this window. See
2526 * gtk_window_set_transient_for().
2528 * Return value: (transfer none): the transient parent for this window, or %NULL
2529 * if no transient parent has been set.
2532 gtk_window_get_transient_for (GtkWindow *window)
2534 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2536 return window->priv->transient_parent;
2540 * gtk_window_set_opacity:
2541 * @window: a #GtkWindow
2542 * @opacity: desired opacity, between 0 and 1
2544 * Request the windowing system to make @window partially transparent,
2545 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2546 * of the opacity parameter are clamped to the [0,1] range.) On X11
2547 * this has any effect only on X screens with a compositing manager
2548 * running. See gtk_widget_is_composited(). On Windows it should work
2551 * Note that setting a window's opacity after the window has been
2552 * shown causes it to flicker once on Windows.
2557 gtk_window_set_opacity (GtkWindow *window,
2560 GtkWindowPrivate *priv;
2562 g_return_if_fail (GTK_IS_WINDOW (window));
2564 priv = window->priv;
2568 else if (opacity > 1.0)
2571 priv->opacity_set = TRUE;
2572 priv->opacity = opacity;
2574 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2575 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2580 * gtk_window_get_opacity:
2581 * @window: a #GtkWindow
2583 * Fetches the requested opacity for this window. See
2584 * gtk_window_set_opacity().
2586 * Return value: the requested opacity for this window.
2591 gtk_window_get_opacity (GtkWindow *window)
2593 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2595 return window->priv->opacity;
2599 * gtk_window_get_application:
2600 * @window: a #GtkWindow
2602 * Gets the #GtkApplication associated with the window (if any).
2604 * Return value: (transfer none): a #GtkApplication, or %NULL
2609 gtk_window_get_application (GtkWindow *window)
2611 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2613 return window->priv->application;
2617 gtk_window_release_application (GtkWindow *window)
2619 if (window->priv->application)
2621 GtkApplication *application;
2623 /* steal reference into temp variable */
2624 application = window->priv->application;
2625 window->priv->application = NULL;
2627 gtk_application_remove_window (application, window);
2628 g_object_unref (application);
2633 * gtk_window_set_application:
2634 * @window: a #GtkWindow
2635 * @application: (allow-none): a #GtkApplication, or %NULL
2637 * Sets or unsets the #GtkApplication associated with the window.
2639 * The application will be kept alive for at least as long as the window
2645 gtk_window_set_application (GtkWindow *window,
2646 GtkApplication *application)
2648 GtkWindowPrivate *priv;
2650 g_return_if_fail (GTK_IS_WINDOW (window));
2652 priv = window->priv;
2653 if (priv->application != application)
2655 gtk_window_release_application (window);
2657 priv->application = application;
2659 if (priv->application != NULL)
2661 g_object_ref (priv->application);
2663 gtk_application_add_window (priv->application, window);
2666 g_object_notify (G_OBJECT (window), "application");
2671 * gtk_window_set_type_hint:
2672 * @window: a #GtkWindow
2673 * @hint: the window type
2675 * By setting the type hint for the window, you allow the window
2676 * manager to decorate and handle the window in a way which is
2677 * suitable to the function of the window in your application.
2679 * This function should be called before the window becomes visible.
2681 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2682 * will sometimes call gtk_window_set_type_hint() on your behalf.
2686 gtk_window_set_type_hint (GtkWindow *window,
2687 GdkWindowTypeHint hint)
2689 GtkWindowPrivate *priv;
2691 g_return_if_fail (GTK_IS_WINDOW (window));
2692 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2694 priv = window->priv;
2696 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2697 priv->gdk_type_hint = hint;
2699 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2701 priv->reset_type_hint = TRUE;
2702 priv->type_hint = hint;
2706 * gtk_window_get_type_hint:
2707 * @window: a #GtkWindow
2709 * Gets the type hint for this window. See gtk_window_set_type_hint().
2711 * Return value: the type hint for @window.
2714 gtk_window_get_type_hint (GtkWindow *window)
2716 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2718 return window->priv->type_hint;
2722 * gtk_window_set_skip_taskbar_hint:
2723 * @window: a #GtkWindow
2724 * @setting: %TRUE to keep this window from appearing in the task bar
2726 * Windows may set a hint asking the desktop environment not to display
2727 * the window in the task bar. This function sets this hint.
2732 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2735 GtkWindowPrivate *priv;
2737 g_return_if_fail (GTK_IS_WINDOW (window));
2739 priv = window->priv;
2741 setting = setting != FALSE;
2743 if (priv->skips_taskbar != setting)
2745 priv->skips_taskbar = setting;
2746 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2747 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2748 priv->skips_taskbar);
2749 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2754 * gtk_window_get_skip_taskbar_hint:
2755 * @window: a #GtkWindow
2757 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2759 * Return value: %TRUE if window shouldn't be in taskbar
2764 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2766 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2768 return window->priv->skips_taskbar;
2772 * gtk_window_set_skip_pager_hint:
2773 * @window: a #GtkWindow
2774 * @setting: %TRUE to keep this window from appearing in the pager
2776 * Windows may set a hint asking the desktop environment not to display
2777 * the window in the pager. This function sets this hint.
2778 * (A "pager" is any desktop navigation tool such as a workspace
2779 * switcher that displays a thumbnail representation of the windows
2785 gtk_window_set_skip_pager_hint (GtkWindow *window,
2788 GtkWindowPrivate *priv;
2790 g_return_if_fail (GTK_IS_WINDOW (window));
2792 priv = window->priv;
2794 setting = setting != FALSE;
2796 if (priv->skips_pager != setting)
2798 priv->skips_pager = setting;
2799 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2800 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2802 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2807 * gtk_window_get_skip_pager_hint:
2808 * @window: a #GtkWindow
2810 * Gets the value set by gtk_window_set_skip_pager_hint().
2812 * Return value: %TRUE if window shouldn't be in pager
2817 gtk_window_get_skip_pager_hint (GtkWindow *window)
2819 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2821 return window->priv->skips_pager;
2825 * gtk_window_set_urgency_hint:
2826 * @window: a #GtkWindow
2827 * @setting: %TRUE to mark this window as urgent
2829 * Windows may set a hint asking the desktop environment to draw
2830 * the users attention to the window. This function sets this hint.
2835 gtk_window_set_urgency_hint (GtkWindow *window,
2838 GtkWindowPrivate *priv;
2840 g_return_if_fail (GTK_IS_WINDOW (window));
2842 priv = window->priv;
2844 setting = setting != FALSE;
2846 if (priv->urgent != setting)
2848 priv->urgent = setting;
2849 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2850 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2852 g_object_notify (G_OBJECT (window), "urgency-hint");
2857 * gtk_window_get_urgency_hint:
2858 * @window: a #GtkWindow
2860 * Gets the value set by gtk_window_set_urgency_hint()
2862 * Return value: %TRUE if window is urgent
2867 gtk_window_get_urgency_hint (GtkWindow *window)
2869 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2871 return window->priv->urgent;
2875 * gtk_window_set_accept_focus:
2876 * @window: a #GtkWindow
2877 * @setting: %TRUE to let this window receive input focus
2879 * Windows may set a hint asking the desktop environment not to receive
2880 * the input focus. This function sets this hint.
2885 gtk_window_set_accept_focus (GtkWindow *window,
2888 GtkWindowPrivate *priv;
2890 g_return_if_fail (GTK_IS_WINDOW (window));
2892 priv = window->priv;
2894 setting = setting != FALSE;
2896 if (priv->accept_focus != setting)
2898 priv->accept_focus = setting;
2899 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2900 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2901 priv->accept_focus);
2902 g_object_notify (G_OBJECT (window), "accept-focus");
2907 * gtk_window_get_accept_focus:
2908 * @window: a #GtkWindow
2910 * Gets the value set by gtk_window_set_accept_focus().
2912 * Return value: %TRUE if window should receive the input focus
2917 gtk_window_get_accept_focus (GtkWindow *window)
2919 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2921 return window->priv->accept_focus;
2925 * gtk_window_set_focus_on_map:
2926 * @window: a #GtkWindow
2927 * @setting: %TRUE to let this window receive input focus on map
2929 * Windows may set a hint asking the desktop environment not to receive
2930 * the input focus when the window is mapped. This function sets this
2936 gtk_window_set_focus_on_map (GtkWindow *window,
2939 GtkWindowPrivate *priv;
2941 g_return_if_fail (GTK_IS_WINDOW (window));
2943 priv = window->priv;
2945 setting = setting != FALSE;
2947 if (priv->focus_on_map != setting)
2949 priv->focus_on_map = setting;
2950 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2951 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2952 priv->focus_on_map);
2953 g_object_notify (G_OBJECT (window), "focus-on-map");
2958 * gtk_window_get_focus_on_map:
2959 * @window: a #GtkWindow
2961 * Gets the value set by gtk_window_set_focus_on_map().
2963 * Return value: %TRUE if window should receive the input focus when
2969 gtk_window_get_focus_on_map (GtkWindow *window)
2971 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2973 return window->priv->focus_on_map;
2977 * gtk_window_set_destroy_with_parent:
2978 * @window: a #GtkWindow
2979 * @setting: whether to destroy @window with its transient parent
2981 * If @setting is %TRUE, then destroying the transient parent of @window
2982 * will also destroy @window itself. This is useful for dialogs that
2983 * shouldn't persist beyond the lifetime of the main window they're
2984 * associated with, for example.
2987 gtk_window_set_destroy_with_parent (GtkWindow *window,
2990 GtkWindowPrivate *priv;
2992 g_return_if_fail (GTK_IS_WINDOW (window));
2994 priv = window->priv;
2996 if (priv->destroy_with_parent == (setting != FALSE))
2999 if (priv->destroy_with_parent)
3001 disconnect_parent_destroyed (window);
3005 connect_parent_destroyed (window);
3008 priv->destroy_with_parent = setting;
3010 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3014 * gtk_window_get_destroy_with_parent:
3015 * @window: a #GtkWindow
3017 * Returns whether the window will be destroyed with its transient parent. See
3018 * gtk_window_set_destroy_with_parent ().
3020 * Return value: %TRUE if the window will be destroyed with its transient parent.
3023 gtk_window_get_destroy_with_parent (GtkWindow *window)
3025 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3027 return window->priv->destroy_with_parent;
3030 static GtkWindowGeometryInfo*
3031 gtk_window_get_geometry_info (GtkWindow *window,
3034 GtkWindowPrivate *priv = window->priv;
3035 GtkWindowGeometryInfo *info;
3037 info = priv->geometry_info;
3038 if (!info && create)
3040 info = g_new0 (GtkWindowGeometryInfo, 1);
3042 info->default_width = -1;
3043 info->default_height = -1;
3044 info->resize_width = -1;
3045 info->resize_height = -1;
3046 info->initial_x = 0;
3047 info->initial_y = 0;
3048 info->initial_pos_set = FALSE;
3049 info->default_is_geometry = FALSE;
3050 info->position_constraints_changed = FALSE;
3051 info->last.configure_request.x = 0;
3052 info->last.configure_request.y = 0;
3053 info->last.configure_request.width = -1;
3054 info->last.configure_request.height = -1;
3055 info->widget = NULL;
3057 priv->geometry_info = info;
3064 * gtk_window_set_geometry_hints:
3065 * @window: a #GtkWindow
3066 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3067 * @geometry: (allow-none): struct containing geometry information or %NULL
3068 * @geom_mask: mask indicating which struct fields should be paid attention to
3070 * This function sets up hints about how a window can be resized by
3071 * the user. You can set a minimum and maximum size; allowed resize
3072 * increments (e.g. for xterm, you can only resize by the size of a
3073 * character); aspect ratios; and more. See the #GdkGeometry struct.
3077 gtk_window_set_geometry_hints (GtkWindow *window,
3078 GtkWidget *geometry_widget,
3079 GdkGeometry *geometry,
3080 GdkWindowHints geom_mask)
3082 GtkWindowGeometryInfo *info;
3084 g_return_if_fail (GTK_IS_WINDOW (window));
3085 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3087 info = gtk_window_get_geometry_info (window, TRUE);
3090 g_signal_handlers_disconnect_by_func (info->widget,
3091 gtk_widget_destroyed,
3094 info->widget = geometry_widget;
3096 g_signal_connect (geometry_widget, "destroy",
3097 G_CALLBACK (gtk_widget_destroyed),
3101 info->geometry = *geometry;
3103 /* We store gravity in priv->gravity not in the hints. */
3104 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3106 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3108 gtk_window_set_gravity (window, geometry->win_gravity);
3111 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3115 * gtk_window_set_decorated:
3116 * @window: a #GtkWindow
3117 * @setting: %TRUE to decorate the window
3119 * By default, windows are decorated with a title bar, resize
3120 * controls, etc. Some <link linkend="gtk-X11-arch">window
3121 * managers</link> allow GTK+ to disable these decorations, creating a
3122 * borderless window. If you set the decorated property to %FALSE
3123 * using this function, GTK+ will do its best to convince the window
3124 * manager not to decorate the window. Depending on the system, this
3125 * function may not have any effect when called on a window that is
3126 * already visible, so you should call it before calling gtk_widget_show().
3128 * On Windows, this function always works, since there's no window manager
3133 gtk_window_set_decorated (GtkWindow *window,
3136 GtkWindowPrivate *priv;
3137 GdkWindow *gdk_window;
3139 g_return_if_fail (GTK_IS_WINDOW (window));
3141 priv = window->priv;
3143 setting = setting != FALSE;
3145 if (setting == priv->decorated)
3148 priv->decorated = setting;
3150 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3153 if (priv->decorated)
3154 gdk_window_set_decorations (gdk_window,
3157 gdk_window_set_decorations (gdk_window,
3161 g_object_notify (G_OBJECT (window), "decorated");
3165 * gtk_window_get_decorated:
3166 * @window: a #GtkWindow
3168 * Returns whether the window has been set to have decorations
3169 * such as a title bar via gtk_window_set_decorated().
3171 * Return value: %TRUE if the window has been set to have decorations
3174 gtk_window_get_decorated (GtkWindow *window)
3176 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3178 return window->priv->decorated;
3182 * gtk_window_set_deletable:
3183 * @window: a #GtkWindow
3184 * @setting: %TRUE to decorate the window as deletable
3186 * By default, windows have a close button in the window frame. Some
3187 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3188 * disable this button. If you set the deletable property to %FALSE
3189 * using this function, GTK+ will do its best to convince the window
3190 * manager not to show a close button. Depending on the system, this
3191 * function may not have any effect when called on a window that is
3192 * already visible, so you should call it before calling gtk_window_show().
3194 * On Windows, this function always works, since there's no window manager
3200 gtk_window_set_deletable (GtkWindow *window,
3203 GtkWindowPrivate *priv;
3204 GdkWindow *gdk_window;
3206 g_return_if_fail (GTK_IS_WINDOW (window));
3208 priv = window->priv;
3210 setting = setting != FALSE;
3212 if (setting == priv->deletable)
3215 priv->deletable = setting;
3217 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3220 if (priv->deletable)
3221 gdk_window_set_functions (gdk_window,
3224 gdk_window_set_functions (gdk_window,
3225 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3228 g_object_notify (G_OBJECT (window), "deletable");
3232 * gtk_window_get_deletable:
3233 * @window: a #GtkWindow
3235 * Returns whether the window has been set to have a close button
3236 * via gtk_window_set_deletable().
3238 * Return value: %TRUE if the window has been set to have a close button
3243 gtk_window_get_deletable (GtkWindow *window)
3245 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3247 return window->priv->deletable;
3250 static GtkWindowIconInfo*
3251 get_icon_info (GtkWindow *window)
3253 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3257 free_icon_info (GtkWindowIconInfo *info)
3259 g_free (info->icon_name);
3260 g_slice_free (GtkWindowIconInfo, info);
3264 static GtkWindowIconInfo*
3265 ensure_icon_info (GtkWindow *window)
3267 GtkWindowIconInfo *info;
3269 info = get_icon_info (window);
3273 info = g_slice_new0 (GtkWindowIconInfo);
3274 g_object_set_qdata_full (G_OBJECT (window),
3275 quark_gtk_window_icon_info,
3277 (GDestroyNotify)free_icon_info);
3284 icon_list_from_theme (GtkWidget *widget,
3289 GtkIconTheme *icon_theme;
3294 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3296 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3299 for (i = 0; sizes[i]; i++)
3302 * We need an EWMH extension to handle scalable icons
3303 * by passing their name to the WM. For now just use a
3307 icon = gtk_icon_theme_load_icon (icon_theme, name,
3310 icon = gtk_icon_theme_load_icon (icon_theme, name,
3313 list = g_list_append (list, icon);
3323 gtk_window_realize_icon (GtkWindow *window)
3325 GtkWindowPrivate *priv = window->priv;
3327 GtkWindowIconInfo *info;
3328 GdkWindow *gdk_window;
3331 widget = GTK_WIDGET (window);
3332 gdk_window = gtk_widget_get_window (widget);
3334 g_return_if_fail (gdk_window != NULL);
3336 /* no point setting an icon on override-redirect */
3337 if (priv->type == GTK_WINDOW_POPUP)
3342 info = ensure_icon_info (window);
3347 info->using_default_icon = FALSE;
3348 info->using_parent_icon = FALSE;
3349 info->using_themed_icon = FALSE;
3351 icon_list = info->icon_list;
3353 /* Look up themed icon */
3354 if (icon_list == NULL && info->icon_name)
3356 icon_list = icon_list_from_theme (widget, info->icon_name);
3358 info->using_themed_icon = TRUE;
3361 /* Inherit from transient parent */
3362 if (icon_list == NULL && priv->transient_parent)
3364 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3366 info->using_parent_icon = TRUE;
3369 /* Inherit from default */
3370 if (icon_list == NULL)
3372 icon_list = default_icon_list;
3374 info->using_default_icon = TRUE;
3377 /* Look up themed icon */
3378 if (icon_list == NULL && default_icon_name)
3380 icon_list = icon_list_from_theme (widget, default_icon_name);
3381 info->using_default_icon = TRUE;
3382 info->using_themed_icon = TRUE;
3385 info->realized = TRUE;
3387 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3389 if (info->using_themed_icon)
3391 GtkIconTheme *icon_theme;
3393 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3394 g_list_free (icon_list);
3396 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3397 g_signal_connect (icon_theme, "changed",
3398 G_CALLBACK (update_themed_icon), window);
3403 gtk_window_unrealize_icon (GtkWindow *window)
3405 GtkWindowIconInfo *info;
3407 info = get_icon_info (window);
3412 if (info->using_themed_icon)
3414 GtkIconTheme *icon_theme;
3416 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3418 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3421 /* We don't clear the properties on the window, just figure the
3422 * window is going away.
3425 info->realized = FALSE;
3430 * gtk_window_set_icon_list:
3431 * @window: a #GtkWindow
3432 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3434 * Sets up the icon representing a #GtkWindow. The icon is used when
3435 * the window is minimized (also known as iconified). Some window
3436 * managers or desktop environments may also place it in the window
3437 * frame, or display it in other contexts.
3439 * gtk_window_set_icon_list() allows you to pass in the same icon in
3440 * several hand-drawn sizes. The list should contain the natural sizes
3441 * your icon is available in; that is, don't scale the image before
3442 * passing it to GTK+. Scaling is postponed until the last minute,
3443 * when the desired final size is known, to allow best quality.
3445 * By passing several sizes, you may improve the final image quality
3446 * of the icon, by reducing or eliminating automatic image scaling.
3448 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3449 * larger images (64x64, 128x128) if you have them.
3451 * See also gtk_window_set_default_icon_list() to set the icon
3452 * for all windows in your application in one go.
3454 * Note that transient windows (those who have been set transient for another
3455 * window using gtk_window_set_transient_for()) will inherit their
3456 * icon from their transient parent. So there's no need to explicitly
3457 * set the icon on transient windows.
3460 gtk_window_set_icon_list (GtkWindow *window,
3463 GtkWindowIconInfo *info;
3465 g_return_if_fail (GTK_IS_WINDOW (window));
3467 info = ensure_icon_info (window);
3469 if (info->icon_list == list) /* check for NULL mostly */
3472 g_list_foreach (list,
3473 (GFunc) g_object_ref, NULL);
3475 g_list_foreach (info->icon_list,
3476 (GFunc) g_object_unref, NULL);
3478 g_list_free (info->icon_list);
3480 info->icon_list = g_list_copy (list);
3482 g_object_notify (G_OBJECT (window), "icon");
3484 gtk_window_unrealize_icon (window);
3486 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3487 gtk_window_realize_icon (window);
3489 /* We could try to update our transient children, but I don't think
3490 * it's really worth it. If we did it, the best way would probably
3491 * be to have children connect to notify::icon-list
3496 * gtk_window_get_icon_list:
3497 * @window: a #GtkWindow
3499 * Retrieves the list of icons set by gtk_window_set_icon_list().
3500 * The list is copied, but the reference count on each
3501 * member won't be incremented.
3503 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3506 gtk_window_get_icon_list (GtkWindow *window)
3508 GtkWindowIconInfo *info;
3510 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3512 info = get_icon_info (window);
3515 return g_list_copy (info->icon_list);
3521 * gtk_window_set_icon:
3522 * @window: a #GtkWindow
3523 * @icon: (allow-none): icon image, or %NULL
3525 * Sets up the icon representing a #GtkWindow. This icon is used when
3526 * the window is minimized (also known as iconified). Some window
3527 * managers or desktop environments may also place it in the window
3528 * frame, or display it in other contexts.
3530 * The icon should be provided in whatever size it was naturally
3531 * drawn; that is, don't scale the image before passing it to
3532 * GTK+. Scaling is postponed until the last minute, when the desired
3533 * final size is known, to allow best quality.
3535 * If you have your icon hand-drawn in multiple sizes, use
3536 * gtk_window_set_icon_list(). Then the best size will be used.
3538 * This function is equivalent to calling gtk_window_set_icon_list()
3539 * with a 1-element list.
3541 * See also gtk_window_set_default_icon_list() to set the icon
3542 * for all windows in your application in one go.
3545 gtk_window_set_icon (GtkWindow *window,
3550 g_return_if_fail (GTK_IS_WINDOW (window));
3551 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3556 list = g_list_append (list, icon);
3558 gtk_window_set_icon_list (window, list);
3564 update_themed_icon (GtkIconTheme *icon_theme,
3567 g_object_notify (G_OBJECT (window), "icon");
3569 gtk_window_unrealize_icon (window);
3571 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3572 gtk_window_realize_icon (window);
3576 * gtk_window_set_icon_name:
3577 * @window: a #GtkWindow
3578 * @name: (allow-none): the name of the themed icon
3580 * Sets the icon for the window from a named themed icon. See
3581 * the docs for #GtkIconTheme for more details.
3583 * Note that this has nothing to do with the WM_ICON_NAME
3584 * property which is mentioned in the ICCCM.
3589 gtk_window_set_icon_name (GtkWindow *window,
3592 GtkWindowIconInfo *info;
3595 g_return_if_fail (GTK_IS_WINDOW (window));
3597 info = ensure_icon_info (window);
3599 if (g_strcmp0 (info->icon_name, name) == 0)
3602 tmp = info->icon_name;
3603 info->icon_name = g_strdup (name);
3606 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3607 g_list_free (info->icon_list);
3608 info->icon_list = NULL;
3610 update_themed_icon (NULL, window);
3612 g_object_notify (G_OBJECT (window), "icon-name");
3616 * gtk_window_get_icon_name:
3617 * @window: a #GtkWindow
3619 * Returns the name of the themed icon for the window,
3620 * see gtk_window_set_icon_name().
3622 * Returns: the icon name or %NULL if the window has
3628 gtk_window_get_icon_name (GtkWindow *window)
3630 GtkWindowIconInfo *info;
3632 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3634 info = ensure_icon_info (window);
3636 return info->icon_name;
3640 * gtk_window_get_icon:
3641 * @window: a #GtkWindow
3643 * Gets the value set by gtk_window_set_icon() (or if you've
3644 * called gtk_window_set_icon_list(), gets the first icon in
3647 * Return value: (transfer none): icon for window
3650 gtk_window_get_icon (GtkWindow *window)
3652 GtkWindowIconInfo *info;
3654 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3656 info = get_icon_info (window);
3657 if (info && info->icon_list)
3658 return GDK_PIXBUF (info->icon_list->data);
3663 /* Load pixbuf, printing warning on failure if error == NULL
3666 load_pixbuf_verbosely (const char *filename,
3669 GError *local_err = NULL;
3672 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3680 g_warning ("Error loading icon from file '%s':\n\t%s",
3681 filename, local_err->message);
3682 g_error_free (local_err);
3690 * gtk_window_set_icon_from_file:
3691 * @window: a #GtkWindow
3692 * @filename: (type filename): location of icon file
3693 * @err: (allow-none): location to store error, or %NULL.
3695 * Sets the icon for @window.
3696 * Warns on failure if @err is %NULL.
3698 * This function is equivalent to calling gtk_window_set_icon()
3699 * with a pixbuf created by loading the image from @filename.
3701 * Returns: %TRUE if setting the icon succeeded.
3706 gtk_window_set_icon_from_file (GtkWindow *window,
3707 const gchar *filename,
3710 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3714 gtk_window_set_icon (window, pixbuf);
3715 g_object_unref (pixbuf);
3724 * gtk_window_set_default_icon_list:
3725 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3727 * Sets an icon list to be used as fallback for windows that haven't
3728 * had gtk_window_set_icon_list() called on them to set up a
3729 * window-specific icon list. This function allows you to set up the
3730 * icon for all windows in your app at once.
3732 * See gtk_window_set_icon_list() for more details.
3736 gtk_window_set_default_icon_list (GList *list)
3740 if (list == default_icon_list)
3743 /* Update serial so we don't used cached pixmaps/masks
3745 default_icon_serial++;
3747 g_list_foreach (list,
3748 (GFunc) g_object_ref, NULL);
3750 g_list_foreach (default_icon_list,
3751 (GFunc) g_object_unref, NULL);
3753 g_list_free (default_icon_list);
3755 default_icon_list = g_list_copy (list);
3757 /* Update all toplevels */
3758 toplevels = gtk_window_list_toplevels ();
3759 tmp_list = toplevels;
3760 while (tmp_list != NULL)
3762 GtkWindowIconInfo *info;
3763 GtkWindow *w = tmp_list->data;
3765 info = get_icon_info (w);
3766 if (info && info->using_default_icon)
3768 gtk_window_unrealize_icon (w);
3769 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3770 gtk_window_realize_icon (w);
3773 tmp_list = tmp_list->next;
3775 g_list_free (toplevels);
3779 * gtk_window_set_default_icon:
3782 * Sets an icon to be used as fallback for windows that haven't
3783 * had gtk_window_set_icon() called on them from a pixbuf.
3788 gtk_window_set_default_icon (GdkPixbuf *icon)
3792 g_return_if_fail (GDK_IS_PIXBUF (icon));
3794 list = g_list_prepend (NULL, icon);
3795 gtk_window_set_default_icon_list (list);
3800 * gtk_window_set_default_icon_name:
3801 * @name: the name of the themed icon
3803 * Sets an icon to be used as fallback for windows that haven't
3804 * had gtk_window_set_icon_list() called on them from a named
3805 * themed icon, see gtk_window_set_icon_name().
3810 gtk_window_set_default_icon_name (const gchar *name)
3815 /* Update serial so we don't used cached pixmaps/masks
3817 default_icon_serial++;
3819 g_free (default_icon_name);
3820 default_icon_name = g_strdup (name);
3822 g_list_foreach (default_icon_list,
3823 (GFunc) g_object_unref, NULL);
3825 g_list_free (default_icon_list);
3826 default_icon_list = NULL;
3828 /* Update all toplevels */
3829 toplevels = gtk_window_list_toplevels ();
3830 tmp_list = toplevels;
3831 while (tmp_list != NULL)
3833 GtkWindowIconInfo *info;
3834 GtkWindow *w = tmp_list->data;
3836 info = get_icon_info (w);
3837 if (info && info->using_default_icon && info->using_themed_icon)
3839 gtk_window_unrealize_icon (w);
3840 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3841 gtk_window_realize_icon (w);
3844 tmp_list = tmp_list->next;
3846 g_list_free (toplevels);
3850 * gtk_window_get_default_icon_name:
3852 * Returns the fallback icon name for windows that has been set
3853 * with gtk_window_set_default_icon_name(). The returned
3854 * string is owned by GTK+ and should not be modified. It
3855 * is only valid until the next call to
3856 * gtk_window_set_default_icon_name().
3858 * Returns: the fallback icon name for windows
3863 gtk_window_get_default_icon_name (void)
3865 return default_icon_name;
3869 * gtk_window_set_default_icon_from_file:
3870 * @filename: (type filename): location of icon file
3871 * @err: (allow-none): location to store error, or %NULL.
3873 * Sets an icon to be used as fallback for windows that haven't
3874 * had gtk_window_set_icon_list() called on them from a file
3875 * on disk. Warns on failure if @err is %NULL.
3877 * Returns: %TRUE if setting the icon succeeded.
3882 gtk_window_set_default_icon_from_file (const gchar *filename,
3885 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3889 gtk_window_set_default_icon (pixbuf);
3890 g_object_unref (pixbuf);
3899 * gtk_window_get_default_icon_list:
3901 * Gets the value set by gtk_window_set_default_icon_list().
3902 * The list is a copy and should be freed with g_list_free(),
3903 * but the pixbufs in the list have not had their reference count
3906 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3909 gtk_window_get_default_icon_list (void)
3911 return g_list_copy (default_icon_list);
3915 gtk_window_set_default_size_internal (GtkWindow *window,
3916 gboolean change_width,
3918 gboolean change_height,
3920 gboolean is_geometry)
3922 GtkWindowGeometryInfo *info;
3924 g_return_if_fail (change_width == FALSE || width >= -1);
3925 g_return_if_fail (change_height == FALSE || height >= -1);
3927 info = gtk_window_get_geometry_info (window, TRUE);
3929 g_object_freeze_notify (G_OBJECT (window));
3931 info->default_is_geometry = is_geometry != FALSE;
3941 info->default_width = width;
3943 g_object_notify (G_OBJECT (window), "default-width");
3954 info->default_height = height;
3956 g_object_notify (G_OBJECT (window), "default-height");
3959 g_object_thaw_notify (G_OBJECT (window));
3961 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3965 * gtk_window_set_default_size:
3966 * @window: a #GtkWindow
3967 * @width: width in pixels, or -1 to unset the default width
3968 * @height: height in pixels, or -1 to unset the default height
3970 * Sets the default size of a window. If the window's "natural" size
3971 * (its size request) is larger than the default, the default will be
3972 * ignored. More generally, if the default size does not obey the
3973 * geometry hints for the window (gtk_window_set_geometry_hints() can
3974 * be used to set these explicitly), the default size will be clamped
3975 * to the nearest permitted size.
3977 * Unlike gtk_widget_set_size_request(), which sets a size request for
3978 * a widget and thus would keep users from shrinking the window, this
3979 * function only sets the initial size, just as if the user had
3980 * resized the window themselves. Users can still shrink the window
3981 * again as they normally would. Setting a default size of -1 means to
3982 * use the "natural" default size (the size request of the window).
3984 * For more control over a window's initial size and how resizing works,
3985 * investigate gtk_window_set_geometry_hints().
3987 * For some uses, gtk_window_resize() is a more appropriate function.
3988 * gtk_window_resize() changes the current size of the window, rather
3989 * than the size to be used on initial display. gtk_window_resize() always
3990 * affects the window itself, not the geometry widget.
3992 * The default size of a window only affects the first time a window is
3993 * shown; if a window is hidden and re-shown, it will remember the size
3994 * it had prior to hiding, rather than using the default size.
3996 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3997 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4000 gtk_window_set_default_size (GtkWindow *window,
4004 g_return_if_fail (GTK_IS_WINDOW (window));
4005 g_return_if_fail (width >= -1);
4006 g_return_if_fail (height >= -1);
4008 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4012 * gtk_window_set_default_geometry:
4013 * @window: a #GtkWindow
4014 * @width: width in resize increments, or -1 to unset the default width
4015 * @height: height in resize increments, or -1 to unset the default height
4017 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4018 * in terms of the base size and increment set with
4019 * gtk_window_set_geometry_hints.
4024 gtk_window_set_default_geometry (GtkWindow *window,
4028 g_return_if_fail (GTK_IS_WINDOW (window));
4029 g_return_if_fail (width >= -1);
4030 g_return_if_fail (height >= -1);
4032 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4036 * gtk_window_get_default_size:
4037 * @window: a #GtkWindow
4038 * @width: (out) (allow-none): location to store the default width, or %NULL
4039 * @height: (out) (allow-none): location to store the default height, or %NULL
4041 * Gets the default size of the window. A value of -1 for the width or
4042 * height indicates that a default size has not been explicitly set
4043 * for that dimension, so the "natural" size of the window will be
4048 gtk_window_get_default_size (GtkWindow *window,
4052 GtkWindowGeometryInfo *info;
4054 g_return_if_fail (GTK_IS_WINDOW (window));
4056 info = gtk_window_get_geometry_info (window, FALSE);
4059 *width = info ? info->default_width : -1;
4062 *height = info ? info->default_height : -1;
4066 * gtk_window_resize:
4067 * @window: a #GtkWindow
4068 * @width: width in pixels to resize the window to
4069 * @height: height in pixels to resize the window to
4071 * Resizes the window as if the user had done so, obeying geometry
4072 * constraints. The default geometry constraint is that windows may
4073 * not be smaller than their size request; to override this
4074 * constraint, call gtk_widget_set_size_request() to set the window's
4075 * request to a smaller value.
4077 * If gtk_window_resize() is called before showing a window for the
4078 * first time, it overrides any default size set with
4079 * gtk_window_set_default_size().
4081 * Windows may not be resized smaller than 1 by 1 pixels.
4085 gtk_window_resize (GtkWindow *window,
4089 GtkWindowGeometryInfo *info;
4091 g_return_if_fail (GTK_IS_WINDOW (window));
4092 g_return_if_fail (width > 0);
4093 g_return_if_fail (height > 0);
4095 info = gtk_window_get_geometry_info (window, TRUE);
4097 info->resize_width = width;
4098 info->resize_height = height;
4099 info->resize_is_geometry = FALSE;
4101 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4105 * gtk_window_resize_to_geometry:
4106 * @window: a #GtkWindow
4107 * @width: width in resize increments to resize the window to
4108 * @height: height in resize increments to resize the window to
4110 * Like gtk_window_resize(), but @width and @height are interpreted
4111 * in terms of the base size and increment set with
4112 * gtk_window_set_geometry_hints.
4117 gtk_window_resize_to_geometry (GtkWindow *window,
4121 GtkWindowGeometryInfo *info;
4123 g_return_if_fail (GTK_IS_WINDOW (window));
4124 g_return_if_fail (width > 0);
4125 g_return_if_fail (height > 0);
4127 info = gtk_window_get_geometry_info (window, TRUE);
4129 info->resize_width = width;
4130 info->resize_height = height;
4131 info->resize_is_geometry = TRUE;
4133 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4137 * gtk_window_get_size:
4138 * @window: a #GtkWindow
4139 * @width: (out) (allow-none): return location for width, or %NULL
4140 * @height: (out) (allow-none): return location for height, or %NULL
4142 * Obtains the current size of @window. If @window is not onscreen,
4143 * it returns the size GTK+ will suggest to the <link
4144 * linkend="gtk-X11-arch">window manager</link> for the initial window
4145 * size (but this is not reliably the same as the size the window
4146 * manager will actually select). The size obtained by
4147 * gtk_window_get_size() is the last size received in a
4148 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4149 * rather than querying the X server for the size. As a result, if you
4150 * call gtk_window_resize() then immediately call
4151 * gtk_window_get_size(), the size won't have taken effect yet. After
4152 * the window manager processes the resize request, GTK+ receives
4153 * notification that the size has changed via a configure event, and
4154 * the size of the window gets updated.
4156 * Note 1: Nearly any use of this function creates a race condition,
4157 * because the size of the window may change between the time that you
4158 * get the size and the time that you perform some action assuming
4159 * that size is the current size. To avoid race conditions, connect to
4160 * "configure-event" on the window and adjust your size-dependent
4161 * state to match the size delivered in the #GdkEventConfigure.
4163 * Note 2: The returned size does <emphasis>not</emphasis> include the
4164 * size of the window manager decorations (aka the window frame or
4165 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4166 * method of determining their size.
4168 * Note 3: If you are getting a window size in order to position
4169 * the window onscreen, there may be a better way. The preferred
4170 * way is to simply set the window's semantic type with
4171 * gtk_window_set_type_hint(), which allows the window manager to
4172 * e.g. center dialogs. Also, if you set the transient parent of
4173 * dialogs with gtk_window_set_transient_for() window managers
4174 * will often center the dialog over its parent window. It's
4175 * much preferred to let the window manager handle these
4176 * things rather than doing it yourself, because all apps will
4177 * behave consistently and according to user prefs if the window
4178 * manager handles it. Also, the window manager can take the size
4179 * of the window decorations/border into account, while your
4180 * application cannot.
4182 * In any case, if you insist on application-specified window
4183 * positioning, there's <emphasis>still</emphasis> a better way than
4184 * doing it yourself - gtk_window_set_position() will frequently
4185 * handle the details for you.
4189 gtk_window_get_size (GtkWindow *window,
4195 g_return_if_fail (GTK_IS_WINDOW (window));
4197 if (width == NULL && height == NULL)
4200 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4202 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4203 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4207 GdkRectangle configure_request;
4209 gtk_window_compute_configure_request (window,
4213 w = configure_request.width;
4214 h = configure_request.height;
4225 * @window: a #GtkWindow
4226 * @x: X coordinate to move window to
4227 * @y: Y coordinate to move window to
4229 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4230 * @window to the given position. Window managers are free to ignore
4231 * this; most window managers ignore requests for initial window
4232 * positions (instead using a user-defined placement algorithm) and
4233 * honor requests after the window has already been shown.
4235 * Note: the position is the position of the gravity-determined
4236 * reference point for the window. The gravity determines two things:
4237 * first, the location of the reference point in root window
4238 * coordinates; and second, which point on the window is positioned at
4239 * the reference point.
4241 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4242 * point is simply the @x, @y supplied to gtk_window_move(). The
4243 * top-left corner of the window decorations (aka window frame or
4244 * border) will be placed at @x, @y. Therefore, to position a window
4245 * at the top left of the screen, you want to use the default gravity
4246 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4248 * To position a window at the bottom right corner of the screen, you
4249 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4250 * point is at @x + the window width and @y + the window height, and
4251 * the bottom-right corner of the window border will be placed at that
4252 * reference point. So, to place a window in the bottom right corner
4253 * you would first set gravity to south east, then write:
4254 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4255 * gdk_screen_height () - window_height)</literal> (note that this
4256 * example does not take multi-head scenarios into account).
4258 * The Extended Window Manager Hints specification at <ulink
4259 * url="http://www.freedesktop.org/Standards/wm-spec">
4260 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4261 * nice table of gravities in the "implementation notes" section.
4263 * The gtk_window_get_position() documentation may also be relevant.
4266 gtk_window_move (GtkWindow *window,
4270 GtkWindowGeometryInfo *info;
4273 g_return_if_fail (GTK_IS_WINDOW (window));
4275 widget = GTK_WIDGET (window);
4277 info = gtk_window_get_geometry_info (window, TRUE);
4279 if (gtk_widget_get_mapped (widget))
4281 GtkAllocation allocation;
4283 gtk_widget_get_allocation (widget, &allocation);
4285 /* we have now sent a request with this position
4286 * with currently-active constraints, so toggle flag.
4288 info->position_constraints_changed = FALSE;
4290 /* we only constrain if mapped - if not mapped,
4291 * then gtk_window_compute_configure_request()
4292 * will apply the constraints later, and we
4293 * don't want to lose information about
4294 * what position the user set before then.
4295 * i.e. if you do a move() then turn off POS_CENTER
4296 * then show the window, your move() will work.
4298 gtk_window_constrain_position (window,
4299 allocation.width, allocation.height,
4302 /* Note that this request doesn't go through our standard request
4303 * framework, e.g. doesn't increment configure_request_count,
4304 * doesn't set info->last, etc.; that's because
4305 * we don't save the info needed to arrive at this same request
4308 * To gtk_window_move_resize(), this will end up looking exactly
4309 * the same as the position being changed by the window
4312 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4316 /* Save this position to apply on mapping */
4317 info->initial_x = x;
4318 info->initial_y = y;
4319 info->initial_pos_set = TRUE;
4324 * gtk_window_get_position:
4325 * @window: a #GtkWindow
4326 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4327 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4329 * This function returns the position you need to pass to
4330 * gtk_window_move() to keep @window in its current position. This
4331 * means that the meaning of the returned value varies with window
4332 * gravity. See gtk_window_move() for more details.
4334 * If you haven't changed the window gravity, its gravity will be
4335 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4336 * gets the position of the top-left corner of the window manager
4337 * frame for the window. gtk_window_move() sets the position of this
4338 * same top-left corner.
4340 * gtk_window_get_position() is not 100% reliable because the X Window System
4341 * does not specify a way to obtain the geometry of the
4342 * decorations placed on a window by the window manager.
4343 * Thus GTK+ is using a "best guess" that works with most
4346 * Moreover, nearly all window managers are historically broken with
4347 * respect to their handling of window gravity. So moving a window to
4348 * its current position as returned by gtk_window_get_position() tends
4349 * to result in moving the window slightly. Window managers are
4350 * slowly getting better over time.
4352 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4353 * frame is not relevant, and thus gtk_window_get_position() will
4354 * always produce accurate results. However you can't use static
4355 * gravity to do things like place a window in a corner of the screen,
4356 * because static gravity ignores the window manager decorations.
4358 * If you are saving and restoring your application's window
4359 * positions, you should know that it's impossible for applications to
4360 * do this without getting it somewhat wrong because applications do
4361 * not have sufficient knowledge of window manager state. The Correct
4362 * Mechanism is to support the session management protocol (see the
4363 * "GnomeClient" object in the GNOME libraries for example) and allow
4364 * the window manager to save your window sizes and positions.
4369 gtk_window_get_position (GtkWindow *window,
4373 GtkWindowPrivate *priv;
4375 GdkWindow *gdk_window;
4377 g_return_if_fail (GTK_IS_WINDOW (window));
4379 priv = window->priv;
4380 widget = GTK_WIDGET (window);
4381 gdk_window = gtk_widget_get_window (widget);
4383 if (priv->gravity == GDK_GRAVITY_STATIC)
4385 if (gtk_widget_get_mapped (widget))
4387 /* This does a server round-trip, which is sort of wrong;
4388 * but a server round-trip is inevitable for
4389 * gdk_window_get_frame_extents() in the usual
4390 * NorthWestGravity case below, so not sure what else to
4391 * do. We should likely be consistent about whether we get
4392 * the client-side info or the server-side info.
4394 gdk_window_get_origin (gdk_window, root_x, root_y);
4398 GdkRectangle configure_request;
4400 gtk_window_compute_configure_request (window,
4404 *root_x = configure_request.x;
4405 *root_y = configure_request.y;
4410 GdkRectangle frame_extents;
4415 if (gtk_widget_get_mapped (widget))
4417 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4418 x = frame_extents.x;
4419 y = frame_extents.y;
4420 gtk_window_get_size (window, &w, &h);
4424 /* We just say the frame has 0 size on all sides.
4425 * Not sure what else to do.
4427 gtk_window_compute_configure_request (window,
4430 x = frame_extents.x;
4431 y = frame_extents.y;
4432 w = frame_extents.width;
4433 h = frame_extents.height;
4436 switch (priv->gravity)
4438 case GDK_GRAVITY_NORTH:
4439 case GDK_GRAVITY_CENTER:
4440 case GDK_GRAVITY_SOUTH:
4441 /* Find center of frame. */
4442 x += frame_extents.width / 2;
4443 /* Center client window on that point. */
4447 case GDK_GRAVITY_SOUTH_EAST:
4448 case GDK_GRAVITY_EAST:
4449 case GDK_GRAVITY_NORTH_EAST:
4450 /* Find right edge of frame */
4451 x += frame_extents.width;
4452 /* Align left edge of client at that point. */
4459 switch (priv->gravity)
4461 case GDK_GRAVITY_WEST:
4462 case GDK_GRAVITY_CENTER:
4463 case GDK_GRAVITY_EAST:
4464 /* Find center of frame. */
4465 y += frame_extents.height / 2;
4466 /* Center client window there. */
4469 case GDK_GRAVITY_SOUTH_WEST:
4470 case GDK_GRAVITY_SOUTH:
4471 case GDK_GRAVITY_SOUTH_EAST:
4472 /* Find south edge of frame */
4473 y += frame_extents.height;
4474 /* Place bottom edge of client there */
4489 * gtk_window_reshow_with_initial_size:
4490 * @window: a #GtkWindow
4492 * Hides @window, then reshows it, resetting the
4493 * default size and position of the window. Used
4494 * by GUI builders only.
4497 gtk_window_reshow_with_initial_size (GtkWindow *window)
4501 g_return_if_fail (GTK_IS_WINDOW (window));
4503 widget = GTK_WIDGET (window);
4505 gtk_widget_hide (widget);
4506 gtk_widget_unrealize (widget);
4507 gtk_widget_show (widget);
4511 gtk_window_destroy (GtkWidget *widget)
4513 GtkWindow *window = GTK_WINDOW (widget);
4514 GtkWindowPrivate *priv = window->priv;
4516 gtk_window_release_application (window);
4518 toplevel_list = g_slist_remove (toplevel_list, window);
4520 if (priv->transient_parent)
4521 gtk_window_set_transient_for (window, NULL);
4523 /* frees the icons */
4524 gtk_window_set_icon_list (window, NULL);
4526 if (priv->has_user_ref_count)
4528 priv->has_user_ref_count = FALSE;
4529 g_object_unref (window);
4533 gtk_window_group_remove_window (priv->group, window);
4535 gtk_window_free_key_hash (window);
4537 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4541 gtk_window_finalize (GObject *object)
4543 GtkWindow *window = GTK_WINDOW (object);
4544 GtkWindowPrivate *priv = window->priv;
4545 GtkMnemonicHash *mnemonic_hash;
4547 g_free (priv->title);
4548 g_free (priv->wmclass_name);
4549 g_free (priv->wmclass_class);
4550 g_free (priv->wm_role);
4551 gtk_window_release_application (window);
4553 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4555 _gtk_mnemonic_hash_free (mnemonic_hash);
4557 if (priv->geometry_info)
4559 if (priv->geometry_info->widget)
4560 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4561 gtk_widget_destroyed,
4562 &priv->geometry_info->widget);
4563 g_free (priv->geometry_info);
4566 if (priv->keys_changed_handler)
4568 g_source_remove (priv->keys_changed_handler);
4569 priv->keys_changed_handler = 0;
4573 g_signal_handlers_disconnect_by_func (priv->screen,
4574 gtk_window_on_composited_changed, window);
4576 g_free (priv->startup_id);
4578 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4582 gtk_window_show (GtkWidget *widget)
4584 GtkWindow *window = GTK_WINDOW (widget);
4585 GtkWindowPrivate *priv = window->priv;
4586 GtkContainer *container = GTK_CONTAINER (window);
4587 gboolean need_resize;
4589 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4591 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4595 _gtk_widget_set_visible_flag (widget, TRUE);
4597 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4598 _gtk_container_set_need_resize (container, FALSE);
4602 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4603 GtkAllocation allocation = { 0, 0 };
4604 GdkRectangle configure_request;
4605 GdkGeometry new_geometry;
4607 gboolean was_realized;
4609 /* We are going to go ahead and perform this configure request
4610 * and then emulate a configure notify by going ahead and
4611 * doing a size allocate. Sort of a synchronous
4612 * mini-copy of gtk_window_move_resize() here.
4614 gtk_window_compute_configure_request (window,
4619 /* We update this because we are going to go ahead
4620 * and gdk_window_resize() below, rather than
4623 info->last.configure_request.width = configure_request.width;
4624 info->last.configure_request.height = configure_request.height;
4626 /* and allocate the window - this is normally done
4627 * in move_resize in response to configure notify
4629 allocation.width = configure_request.width;
4630 allocation.height = configure_request.height;
4631 gtk_widget_size_allocate (widget, &allocation);
4633 /* Then we guarantee we have a realize */
4634 was_realized = FALSE;
4635 if (!gtk_widget_get_realized (widget))
4637 gtk_widget_realize (widget);
4638 was_realized = TRUE;
4641 /* We only send configure request if we didn't just finish
4642 * creating the window; if we just created the window
4643 * then we created it with widget->allocation anyhow.
4646 gdk_window_move_resize (gtk_widget_get_window (widget),
4647 configure_request.x,
4648 configure_request.y,
4649 configure_request.width,
4650 configure_request.height);
4653 gtk_container_check_resize (container);
4655 gtk_widget_map (widget);
4657 /* Try to make sure that we have some focused widget
4659 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4660 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4663 gtk_grab_add (widget);
4667 gtk_window_hide (GtkWidget *widget)
4669 GtkWindow *window = GTK_WINDOW (widget);
4670 GtkWindowPrivate *priv = window->priv;
4672 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4674 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4678 _gtk_widget_set_visible_flag (widget, FALSE);
4679 gtk_widget_unmap (widget);
4682 gtk_grab_remove (widget);
4686 gtk_window_map (GtkWidget *widget)
4689 GtkWindow *window = GTK_WINDOW (widget);
4690 GtkWindowPrivate *priv = window->priv;
4691 GdkWindow *toplevel;
4692 GdkWindow *gdk_window;
4693 gboolean auto_mnemonics;
4695 gdk_window = gtk_widget_get_window (widget);
4697 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4699 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4703 gtk_widget_set_mapped (widget, TRUE);
4705 child = gtk_bin_get_child (&(window->bin));
4707 gtk_widget_get_visible (child) &&
4708 !gtk_widget_get_mapped (child))
4709 gtk_widget_map (child);
4711 toplevel = gdk_window;
4713 if (priv->maximize_initially)
4714 gdk_window_maximize (toplevel);
4716 gdk_window_unmaximize (toplevel);
4718 if (priv->stick_initially)
4719 gdk_window_stick (toplevel);
4721 gdk_window_unstick (toplevel);
4723 if (priv->iconify_initially)
4724 gdk_window_iconify (toplevel);
4726 gdk_window_deiconify (toplevel);
4728 if (priv->fullscreen_initially)
4729 gdk_window_fullscreen (toplevel);
4731 gdk_window_unfullscreen (toplevel);
4733 gdk_window_set_keep_above (toplevel, priv->above_initially);
4735 gdk_window_set_keep_below (toplevel, priv->below_initially);
4737 /* No longer use the default settings */
4738 priv->need_default_size = FALSE;
4739 priv->need_default_position = FALSE;
4741 if (priv->reset_type_hint)
4743 /* We should only reset the type hint when the application
4744 * used gtk_window_set_type_hint() to change the hint.
4745 * Some applications use X directly to change the properties;
4746 * in that case, we shouldn't overwrite what they did.
4748 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4749 priv->reset_type_hint = FALSE;
4752 gdk_window_show (gdk_window);
4754 if (priv->grip_window)
4755 gdk_window_show (priv->grip_window);
4757 if (!disable_startup_notification)
4759 /* Do we have a custom startup-notification id? */
4760 if (priv->startup_id != NULL)
4762 /* Make sure we have a "real" id */
4763 if (!startup_id_is_fake (priv->startup_id))
4764 gdk_notify_startup_complete_with_id (priv->startup_id);
4766 g_free (priv->startup_id);
4767 priv->startup_id = NULL;
4769 else if (!sent_startup_notification)
4771 sent_startup_notification = TRUE;
4772 gdk_notify_startup_complete ();
4776 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4777 * (as in the case of popup menus), then hide mnemonics initially
4779 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4780 &auto_mnemonics, NULL);
4781 if (auto_mnemonics && !priv->mnemonics_visible_set)
4782 gtk_window_set_mnemonics_visible (window, FALSE);
4786 gtk_window_map_event (GtkWidget *widget,
4789 if (!gtk_widget_get_mapped (widget))
4791 /* we should be be unmapped, but are getting a MapEvent, this may happen
4792 * to toplevel XWindows if mapping was intercepted by a window manager
4793 * and an unmap request occoured while the MapRequestEvent was still
4794 * being handled. we work around this situaiton here by re-requesting
4795 * the window being unmapped. more details can be found in:
4796 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4798 gdk_window_hide (gtk_widget_get_window (widget));
4804 gtk_window_unmap (GtkWidget *widget)
4806 GtkWindow *window = GTK_WINDOW (widget);
4807 GtkWindowPrivate *priv = window->priv;
4809 GtkWindowGeometryInfo *info;
4810 GdkWindow *gdk_window;
4811 GdkWindowState state;
4813 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4815 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
4819 gdk_window = gtk_widget_get_window (widget);
4821 gtk_widget_set_mapped (widget, FALSE);
4822 gdk_window_withdraw (gdk_window);
4824 priv->configure_request_count = 0;
4825 priv->configure_notify_received = FALSE;
4827 /* on unmap, we reset the default positioning of the window,
4828 * so it's placed again, but we don't reset the default
4829 * size of the window, so it's remembered.
4831 priv->need_default_position = TRUE;
4833 info = gtk_window_get_geometry_info (window, FALSE);
4836 info->initial_pos_set = FALSE;
4837 info->position_constraints_changed = FALSE;
4840 state = gdk_window_get_state (gdk_window);
4841 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4842 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4843 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4844 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4845 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4847 child = gtk_bin_get_child (&(window->bin));
4849 gtk_widget_unmap (child);
4853 gtk_window_realize (GtkWidget *widget)
4855 GtkAllocation allocation;
4857 GdkWindow *parent_window;
4858 GdkWindow *gdk_window;
4859 GdkWindowAttr attributes;
4860 gint attributes_mask;
4861 GtkWindowPrivate *priv;
4862 GtkStyleContext *context;
4864 window = GTK_WINDOW (widget);
4865 priv = window->priv;
4867 gtk_widget_get_allocation (widget, &allocation);
4869 if (gtk_widget_get_parent_window (widget))
4871 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
4873 gtk_widget_set_realized (widget, TRUE);
4875 attributes.x = allocation.x;
4876 attributes.y = allocation.y;
4877 attributes.width = allocation.width;
4878 attributes.height = allocation.height;
4879 attributes.window_type = GDK_WINDOW_CHILD;
4881 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
4883 attributes.visual = gtk_widget_get_visual (widget);
4884 attributes.wclass = GDK_INPUT_OUTPUT;
4886 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
4888 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
4889 &attributes, attributes_mask);
4890 gtk_widget_set_window (widget, gdk_window);
4891 gdk_window_set_user_data (gdk_window, widget);
4893 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
4895 gdk_window_enable_synchronized_configure (gdk_window);
4899 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
4901 /* ensure widget tree is properly size allocated */
4902 if (allocation.x == -1 &&
4903 allocation.y == -1 &&
4904 allocation.width == 1 &&
4905 allocation.height == 1)
4907 GtkRequisition requisition;
4911 allocation.width = 200;
4912 allocation.height = 200;
4914 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4915 if (requisition.width || requisition.height)
4917 /* non-empty window */
4918 allocation.width = requisition.width;
4919 allocation.height = requisition.height;
4921 gtk_widget_size_allocate (widget, &allocation);
4923 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4925 g_return_if_fail (!gtk_widget_get_realized (widget));
4928 gtk_widget_set_realized (widget, TRUE);
4932 case GTK_WINDOW_TOPLEVEL:
4933 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4935 case GTK_WINDOW_POPUP:
4936 attributes.window_type = GDK_WINDOW_TEMP;
4939 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4943 attributes.title = priv->title;
4944 attributes.wmclass_name = priv->wmclass_name;
4945 attributes.wmclass_class = priv->wmclass_class;
4946 attributes.wclass = GDK_INPUT_OUTPUT;
4947 attributes.visual = gtk_widget_get_visual (widget);
4949 attributes_mask = 0;
4950 parent_window = gtk_widget_get_root_window (widget);
4952 gtk_widget_get_allocation (widget, &allocation);
4953 attributes.width = allocation.width;
4954 attributes.height = allocation.height;
4955 attributes.event_mask = gtk_widget_get_events (widget);
4956 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4957 GDK_KEY_PRESS_MASK |
4958 GDK_KEY_RELEASE_MASK |
4959 GDK_ENTER_NOTIFY_MASK |
4960 GDK_LEAVE_NOTIFY_MASK |
4961 GDK_FOCUS_CHANGE_MASK |
4962 GDK_STRUCTURE_MASK);
4963 attributes.type_hint = priv->type_hint;
4965 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4966 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4967 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4969 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4970 gtk_widget_set_window (widget, gdk_window);
4972 if (priv->opacity_set)
4973 gdk_window_set_opacity (gdk_window, priv->opacity);
4975 gdk_window_enable_synchronized_configure (gdk_window);
4977 gdk_window_set_user_data (gdk_window, window);
4979 context = gtk_widget_get_style_context (widget);
4980 gtk_style_context_set_background (context, gdk_window);
4983 if (priv->transient_parent &&
4984 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
4985 gdk_window_set_transient_for (gdk_window,
4986 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
4989 gdk_window_set_role (gdk_window, priv->wm_role);
4991 if (!priv->decorated)
4992 gdk_window_set_decorations (gdk_window, 0);
4994 if (!priv->deletable)
4995 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4997 if (gtk_window_get_skip_pager_hint (window))
4998 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5000 if (gtk_window_get_skip_taskbar_hint (window))
5001 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5003 if (gtk_window_get_accept_focus (window))
5004 gdk_window_set_accept_focus (gdk_window, TRUE);
5006 gdk_window_set_accept_focus (gdk_window, FALSE);
5008 if (gtk_window_get_focus_on_map (window))
5009 gdk_window_set_focus_on_map (gdk_window, TRUE);
5011 gdk_window_set_focus_on_map (gdk_window, FALSE);
5014 gdk_window_set_modal_hint (gdk_window, TRUE);
5016 gdk_window_set_modal_hint (gdk_window, FALSE);
5018 if (priv->startup_id)
5020 #ifdef GDK_WINDOWING_X11
5021 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5022 if (timestamp != GDK_CURRENT_TIME)
5023 gdk_x11_window_set_user_time (gdk_window, timestamp);
5025 if (!startup_id_is_fake (priv->startup_id))
5026 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5030 gtk_window_realize_icon (window);
5032 if (priv->has_resize_grip)
5033 resize_grip_create_window (window);
5037 gtk_window_unrealize (GtkWidget *widget)
5039 GtkWindow *window = GTK_WINDOW (widget);
5040 GtkWindowPrivate *priv = window->priv;
5041 GtkWindowGeometryInfo *info;
5043 /* On unrealize, we reset the size of the window such
5044 * that we will re-apply the default sizing stuff
5045 * next time we show the window.
5047 * Default positioning is reset on unmap, instead of unrealize.
5049 priv->need_default_size = TRUE;
5050 info = gtk_window_get_geometry_info (window, FALSE);
5053 info->resize_width = -1;
5054 info->resize_height = -1;
5055 info->last.configure_request.x = 0;
5056 info->last.configure_request.y = 0;
5057 info->last.configure_request.width = -1;
5058 info->last.configure_request.height = -1;
5059 /* be sure we reset geom hints on re-realize */
5060 info->last.flags = 0;
5064 gtk_window_unrealize_icon (window);
5066 if (priv->grip_window != NULL)
5067 resize_grip_destroy_window (window);
5069 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5072 static GtkJunctionSides
5073 get_grip_junction (GtkWidget *widget)
5075 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5076 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5078 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5082 get_drag_edge (GtkWidget *widget,
5083 GdkWindowEdge *edge)
5085 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5086 gboolean hresizable;
5087 gboolean vresizable;
5088 GtkTextDirection dir;
5089 GtkWindowGeometryInfo *info;
5094 info = priv->geometry_info;
5097 GdkWindowHints flags = info->last.flags;
5098 GdkGeometry *geometry = &info->last.geometry;
5100 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5102 hresizable = geometry->min_width < geometry->max_width;
5103 vresizable = geometry->min_height < geometry->max_height;
5107 dir = gtk_widget_get_direction (widget);
5109 if (hresizable && vresizable)
5110 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5111 else if (hresizable)
5112 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5113 else if (vresizable)
5114 *edge = GDK_WINDOW_EDGE_SOUTH;
5122 set_grip_cursor (GtkWindow *window)
5124 GtkWidget *widget = GTK_WIDGET (window);
5125 GtkWindowPrivate *priv = window->priv;
5127 if (priv->grip_window == NULL)
5130 if (gtk_widget_is_sensitive (widget))
5133 GdkDisplay *display;
5134 GdkCursorType cursor_type;
5137 cursor_type = GDK_LEFT_PTR;
5139 if (get_drag_edge (widget, &edge))
5143 case GDK_WINDOW_EDGE_EAST:
5144 cursor_type = GDK_RIGHT_SIDE;
5146 case GDK_WINDOW_EDGE_SOUTH_EAST:
5147 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5149 case GDK_WINDOW_EDGE_SOUTH:
5150 cursor_type = GDK_BOTTOM_SIDE;
5152 case GDK_WINDOW_EDGE_SOUTH_WEST:
5153 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5155 case GDK_WINDOW_EDGE_WEST:
5156 cursor_type = GDK_LEFT_SIDE;
5162 display = gtk_widget_get_display (widget);
5163 cursor = gdk_cursor_new_for_display (display, cursor_type);
5164 gdk_window_set_cursor (priv->grip_window, cursor);
5165 g_object_unref (cursor);
5168 gdk_window_set_cursor (priv->grip_window, NULL);
5172 set_grip_shape (GtkWindow *window)
5174 GtkWindowPrivate *priv = window->priv;
5175 cairo_region_t *region;
5176 cairo_surface_t *surface;
5178 double width, height;
5180 if (priv->grip_window == NULL)
5183 width = gdk_window_get_width (priv->grip_window);
5184 height = gdk_window_get_height (priv->grip_window);
5185 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5187 cr = cairo_create (surface);
5188 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5190 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5191 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5193 cairo_move_to (cr, width, 0.0);
5194 cairo_line_to (cr, width, height);
5195 cairo_line_to (cr, 0.0, height);
5199 cairo_move_to (cr, 0.0, 0.0);
5200 cairo_line_to (cr, width, height);
5201 cairo_line_to (cr, 0.0, height);
5203 cairo_close_path (cr);
5206 region = gdk_cairo_region_create_from_surface (surface);
5207 cairo_surface_destroy (surface);
5209 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5210 cairo_region_destroy (region);
5214 set_grip_position (GtkWindow *window)
5216 GtkWindowPrivate *priv = window->priv;
5219 if (priv->grip_window == NULL)
5222 gtk_window_get_resize_grip_area (window, &rect);
5223 gdk_window_raise (priv->grip_window);
5224 gdk_window_move_resize (priv->grip_window,
5226 rect.width, rect.height);
5230 gtk_window_size_allocate (GtkWidget *widget,
5231 GtkAllocation *allocation)
5233 GtkWindow *window = GTK_WINDOW (widget);
5234 GtkAllocation child_allocation;
5238 gtk_widget_set_allocation (widget, allocation);
5240 if (gtk_widget_get_realized (widget))
5242 /* If it's not a toplevel we're embedded, we need to resize the window's
5243 * window and skip the grip.
5245 if (!gtk_widget_is_toplevel (widget))
5247 gdk_window_move_resize (gtk_widget_get_window (widget),
5248 allocation->x, allocation->y,
5249 allocation->width, allocation->height);
5253 update_grip_visibility (window);
5254 set_grip_position (window);
5258 child = gtk_bin_get_child (&(window->bin));
5259 if (child && gtk_widget_get_visible (child))
5261 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5262 child_allocation.x = border_width;
5263 child_allocation.y = border_width;
5264 child_allocation.width =
5265 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5266 child_allocation.height =
5267 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5269 gtk_widget_size_allocate (child, &child_allocation);
5274 gtk_window_configure_event (GtkWidget *widget,
5275 GdkEventConfigure *event)
5277 GtkAllocation allocation;
5278 GtkWindow *window = GTK_WINDOW (widget);
5279 GtkWindowPrivate *priv = window->priv;
5280 gboolean expected_reply = priv->configure_request_count > 0;
5282 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5284 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5285 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5287 gdk_window_configure_finished (gtk_widget_get_window (widget));
5291 /* priv->configure_request_count incremented for each
5292 * configure request, and decremented to a min of 0 for
5293 * each configure notify.
5295 * All it means is that we know we will get at least
5296 * priv->configure_request_count more configure notifies.
5297 * We could get more configure notifies than that; some
5298 * of the configure notifies we get may be unrelated to
5299 * the configure requests. But we will get at least
5300 * priv->configure_request_count notifies.
5303 if (priv->configure_request_count > 0)
5305 priv->configure_request_count -= 1;
5306 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5309 /* As an optimization, we avoid a resize when possible.
5311 * The only times we can avoid a resize are:
5312 * - we know only the position changed, not the size
5313 * - we know we have made more requests and so will get more
5314 * notifies and can wait to resize when we get them
5316 gtk_widget_get_allocation (widget, &allocation);
5317 if (!expected_reply &&
5318 (allocation.width == event->width &&
5319 allocation.height == event->height))
5321 gdk_window_configure_finished (gtk_widget_get_window (widget));
5326 * If we do need to resize, we do that by:
5327 * - filling in widget->allocation with the new size
5328 * - setting configure_notify_received to TRUE
5329 * for use in gtk_window_move_resize()
5330 * - queueing a resize, leading to invocation of
5331 * gtk_window_move_resize() in an idle handler
5335 priv->configure_notify_received = TRUE;
5337 allocation.width = event->width;
5338 allocation.height = event->height;
5339 gtk_widget_set_allocation (widget, &allocation);
5341 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5343 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5349 gtk_window_state_event (GtkWidget *widget,
5350 GdkEventWindowState *event)
5352 update_grip_visibility (GTK_WINDOW (widget));
5358 gtk_window_direction_changed (GtkWidget *widget,
5359 GtkTextDirection prev_dir)
5361 GtkWindow *window = GTK_WINDOW (widget);
5363 set_grip_cursor (window);
5364 set_grip_position (window);
5365 set_grip_shape (window);
5369 gtk_window_state_changed (GtkWidget *widget,
5370 GtkStateType previous_state)
5372 GtkWindow *window = GTK_WINDOW (widget);
5374 update_grip_visibility (window);
5378 gtk_window_style_updated (GtkWidget *widget)
5380 GtkWindow *window = GTK_WINDOW (widget);
5381 GtkWindowPrivate *priv = window->priv;
5384 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5386 gdk_window_move_resize (priv->grip_window,
5388 rect.width, rect.height);
5390 set_grip_shape (window);
5391 gtk_widget_queue_resize (widget);
5396 resize_grip_create_window (GtkWindow *window)
5399 GtkWindowPrivate *priv;
5400 GdkWindowAttr attributes;
5401 gint attributes_mask;
5404 priv = window->priv;
5405 widget = GTK_WIDGET (window);
5407 g_return_if_fail (gtk_widget_get_realized (widget));
5408 g_return_if_fail (priv->grip_window == NULL);
5410 gtk_window_get_resize_grip_area (window, &rect);
5412 attributes.x = rect.x;
5413 attributes.y = rect.y;
5414 attributes.width = rect.width;
5415 attributes.height = rect.height;
5416 attributes.window_type = GDK_WINDOW_CHILD;
5417 attributes.wclass = GDK_INPUT_OUTPUT;
5418 attributes.event_mask = gtk_widget_get_events (widget) |
5420 GDK_BUTTON_PRESS_MASK;
5422 attributes_mask = GDK_WA_X | GDK_WA_Y;
5424 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5428 gdk_window_set_user_data (priv->grip_window, widget);
5430 gdk_window_raise (priv->grip_window);
5432 set_grip_shape (window);
5433 update_grip_visibility (window);
5437 resize_grip_destroy_window (GtkWindow *window)
5439 GtkWindowPrivate *priv = window->priv;
5441 gdk_window_set_user_data (priv->grip_window, NULL);
5442 gdk_window_destroy (priv->grip_window);
5443 priv->grip_window = NULL;
5444 update_grip_visibility (window);
5448 * gtk_window_set_has_resize_grip:
5449 * @window: a #GtkWindow
5450 * @value: %TRUE to allow a resize grip
5452 * Sets whether @window has a corner resize grip.
5454 * Note that the resize grip is only shown if the window
5455 * is actually resizable and not maximized. Use
5456 * gtk_window_resize_grip_is_visible() to find out if the
5457 * resize grip is currently shown.
5462 gtk_window_set_has_resize_grip (GtkWindow *window,
5465 GtkWidget *widget = GTK_WIDGET (window);
5466 GtkWindowPrivate *priv = window->priv;
5468 value = value != FALSE;
5470 if (value != priv->has_resize_grip)
5472 priv->has_resize_grip = value;
5473 gtk_widget_queue_draw (widget);
5475 if (gtk_widget_get_realized (widget) &&
5476 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5478 if (priv->has_resize_grip && priv->grip_window == NULL)
5479 resize_grip_create_window (window);
5480 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5481 resize_grip_destroy_window (window);
5484 g_object_notify (G_OBJECT (window), "has-resize-grip");
5489 update_grip_visibility (GtkWindow *window)
5491 GtkWindowPrivate *priv = window->priv;
5494 val = gtk_window_resize_grip_is_visible (window);
5496 if (priv->grip_window != NULL)
5500 gdk_window_show (priv->grip_window);
5501 set_grip_cursor (window);
5505 gdk_window_hide (priv->grip_window);
5509 if (priv->resize_grip_visible != val)
5511 priv->resize_grip_visible = val;
5513 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5518 * gtk_window_resize_grip_is_visible:
5519 * @window: a #GtkWindow
5521 * Determines whether a resize grip is visible for the specified window.
5523 * Returns: %TRUE if a resize grip exists and is visible
5528 gtk_window_resize_grip_is_visible (GtkWindow *window)
5531 GtkWindowPrivate *priv;
5534 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5536 priv = window->priv;
5537 widget = GTK_WIDGET (window);
5539 if (priv->type == GTK_WINDOW_POPUP)
5542 if (!priv->resizable)
5545 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5548 if (gtk_widget_get_realized (widget))
5550 GdkWindowState state;
5552 state = gdk_window_get_state (gtk_widget_get_window (widget));
5554 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5558 if (!get_drag_edge (widget, &edge))
5561 return window->priv->has_resize_grip;
5565 * gtk_window_get_has_resize_grip:
5566 * @window: a #GtkWindow
5568 * Determines whether the window may have a resize grip.
5570 * Returns: %TRUE if the window has a resize grip
5575 gtk_window_get_has_resize_grip (GtkWindow *window)
5577 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5579 return window->priv->has_resize_grip;
5583 * gtk_window_get_resize_grip_area:
5584 * @window: a #GtkWindow
5585 * @rect: (out): a pointer to a #GdkRectangle which we should store
5586 * the resize grip area
5588 * If a window has a resize grip, this will retrieve the grip
5589 * position, width and height into the specified #GdkRectangle.
5591 * Returns: %TRUE if the resize grip's area was retrieved
5596 gtk_window_get_resize_grip_area (GtkWindow *window,
5599 GtkWidget *widget = GTK_WIDGET (window);
5600 GtkAllocation allocation;
5604 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5606 if (!window->priv->has_resize_grip)
5609 gtk_widget_get_allocation (widget, &allocation);
5611 gtk_widget_style_get (widget,
5612 "resize-grip-width", &grip_width,
5613 "resize-grip-height", &grip_height,
5616 if (grip_width > allocation.width)
5617 grip_width = allocation.width;
5619 if (grip_height > allocation.height)
5620 grip_height = allocation.height;
5622 rect->width = grip_width;
5623 rect->height = grip_height;
5624 rect->y = allocation.y + allocation.height - grip_height;
5626 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5627 rect->x = allocation.x + allocation.width - grip_width;
5629 rect->x = allocation.x;
5634 /* the accel_key and accel_mods fields of the key have to be setup
5635 * upon calling this function. it'll then return whether that key
5636 * is at all used as accelerator, and if so will OR in the
5637 * accel_flags member of the key.
5640 _gtk_window_query_nonaccels (GtkWindow *window,
5642 GdkModifierType accel_mods)
5644 GtkWindowPrivate *priv;
5646 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5648 priv = window->priv;
5650 /* movement keys are considered locked accels */
5653 static const guint bindings[] = {
5654 GDK_KEY_space, GDK_KEY_KP_Space, GDK_KEY_Return, GDK_KEY_ISO_Enter, GDK_KEY_KP_Enter, GDK_KEY_Up, GDK_KEY_KP_Up, GDK_KEY_Down, GDK_KEY_KP_Down,
5655 GDK_KEY_Left, GDK_KEY_KP_Left, GDK_KEY_Right, GDK_KEY_KP_Right, GDK_KEY_Tab, GDK_KEY_KP_Tab, GDK_KEY_ISO_Left_Tab,
5659 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5660 if (bindings[i] == accel_key)
5664 /* mnemonics are considered locked accels */
5665 if (accel_mods == priv->mnemonic_modifier)
5667 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5668 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5676 * gtk_window_propagate_key_event:
5677 * @window: a #GtkWindow
5678 * @event: a #GdkEventKey
5680 * Propagate a key press or release event to the focus widget and
5681 * up the focus container chain until a widget handles @event.
5682 * This is normally called by the default ::key_press_event and
5683 * ::key_release_event handlers for toplevel windows,
5684 * however in some cases it may be useful to call this directly when
5685 * overriding the standard key handling for a toplevel window.
5687 * Return value: %TRUE if a widget in the focus chain handled the event.
5692 gtk_window_propagate_key_event (GtkWindow *window,
5695 GtkWindowPrivate *priv;
5696 gboolean handled = FALSE;
5697 GtkWidget *widget, *focus;
5699 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5701 priv = window->priv;
5702 widget = GTK_WIDGET (window);
5704 focus = priv->focus_widget;
5706 g_object_ref (focus);
5709 focus && focus != widget &&
5710 gtk_widget_get_toplevel (focus) == widget)
5714 if (gtk_widget_is_sensitive (focus))
5715 handled = gtk_widget_event (focus, (GdkEvent*) event);
5717 parent = gtk_widget_get_parent (focus);
5719 g_object_ref (parent);
5721 g_object_unref (focus);
5727 g_object_unref (focus);
5733 gtk_window_key_press_event (GtkWidget *widget,
5736 GtkWindow *window = GTK_WINDOW (widget);
5737 gboolean handled = FALSE;
5739 /* handle mnemonics and accelerators */
5741 handled = gtk_window_activate_key (window, event);
5743 /* handle focus widget key events */
5745 handled = gtk_window_propagate_key_event (window, event);
5747 /* Chain up, invokes binding set */
5749 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5755 gtk_window_key_release_event (GtkWidget *widget,
5758 GtkWindow *window = GTK_WINDOW (widget);
5759 gboolean handled = FALSE;
5761 /* handle focus widget key events */
5763 handled = gtk_window_propagate_key_event (window, event);
5765 /* Chain up, invokes binding set */
5767 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5773 gtk_window_button_press_event (GtkWidget *widget,
5774 GdkEventButton *event)
5776 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5779 if (event->window == priv->grip_window)
5781 if (get_drag_edge (widget, &edge))
5782 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5796 gtk_window_real_activate_default (GtkWindow *window)
5798 gtk_window_activate_default (window);
5802 gtk_window_real_activate_focus (GtkWindow *window)
5804 gtk_window_activate_focus (window);
5808 gtk_window_enter_notify_event (GtkWidget *widget,
5809 GdkEventCrossing *event)
5815 gtk_window_leave_notify_event (GtkWidget *widget,
5816 GdkEventCrossing *event)
5822 do_focus_change (GtkWidget *widget,
5826 GdkDeviceManager *device_manager;
5829 g_object_ref (widget);
5831 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5832 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5833 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5834 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5836 for (d = devices; d; d = d->next)
5838 GdkDevice *dev = d->data;
5841 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5844 /* Skip non-master keyboards that haven't
5845 * selected for events from this window
5847 window = gtk_widget_get_window (widget);
5848 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5849 window && !gdk_window_get_device_events (window, dev))
5852 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5854 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5855 fevent->focus_change.window = window;
5857 g_object_ref (window);
5858 fevent->focus_change.in = in;
5859 gdk_event_set_device (fevent, dev);
5861 gtk_widget_send_focus_change (widget, fevent);
5863 gdk_event_free (fevent);
5866 g_list_free (devices);
5867 g_object_unref (widget);
5871 gtk_window_focus_in_event (GtkWidget *widget,
5872 GdkEventFocus *event)
5874 GtkWindow *window = GTK_WINDOW (widget);
5876 /* It appears spurious focus in events can occur when
5877 * the window is hidden. So we'll just check to see if
5878 * the window is visible before actually handling the
5881 if (gtk_widget_get_visible (widget))
5883 _gtk_window_set_has_toplevel_focus (window, TRUE);
5884 _gtk_window_set_is_active (window, TRUE);
5891 gtk_window_focus_out_event (GtkWidget *widget,
5892 GdkEventFocus *event)
5894 GtkWindow *window = GTK_WINDOW (widget);
5895 gboolean auto_mnemonics;
5897 _gtk_window_set_has_toplevel_focus (window, FALSE);
5898 _gtk_window_set_is_active (window, FALSE);
5900 /* set the mnemonic-visible property to false */
5901 g_object_get (gtk_widget_get_settings (widget),
5902 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5904 gtk_window_set_mnemonics_visible (window, FALSE);
5909 static GdkAtom atom_rcfiles = GDK_NONE;
5910 static GdkAtom atom_iconthemes = GDK_NONE;
5913 send_client_message_to_embedded_windows (GtkWidget *widget,
5914 GdkAtom message_type)
5916 GList *embedded_windows;
5918 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5919 if (embedded_windows)
5921 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5924 for (i = 0; i < 5; i++)
5925 send_event->client.data.l[i] = 0;
5926 send_event->client.data_format = 32;
5927 send_event->client.message_type = message_type;
5929 while (embedded_windows)
5931 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
5932 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5933 embedded_windows = embedded_windows->next;
5936 gdk_event_free (send_event);
5941 gtk_window_client_event (GtkWidget *widget,
5942 GdkEventClient *event)
5946 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5947 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5950 if (event->message_type == atom_rcfiles)
5952 send_client_message_to_embedded_windows (widget, atom_rcfiles);
5953 gtk_style_context_reset_widgets (gtk_widget_get_screen (widget));
5956 if (event->message_type == atom_iconthemes)
5958 send_client_message_to_embedded_windows (widget, atom_iconthemes);
5959 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
5966 gtk_window_check_resize (GtkContainer *container)
5968 /* If the window is not toplevel anymore than it's embedded somewhere,
5969 * so handle it like a normal window */
5970 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
5971 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
5972 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
5973 gtk_window_move_resize (GTK_WINDOW (container));
5977 gtk_window_focus (GtkWidget *widget,
5978 GtkDirectionType direction)
5980 GtkWindowPrivate *priv;
5983 GtkContainer *container;
5985 GtkWidget *old_focus_child;
5988 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5989 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
5991 container = GTK_CONTAINER (widget);
5992 window = GTK_WINDOW (widget);
5993 priv = window->priv;
5994 bin = GTK_BIN (widget);
5996 old_focus_child = gtk_container_get_focus_child (container);
5998 /* We need a special implementation here to deal properly with wrapping
5999 * around in the tab chain without the danger of going into an
6002 if (old_focus_child)
6004 if (gtk_widget_child_focus (old_focus_child, direction))
6008 if (priv->focus_widget)
6010 if (direction == GTK_DIR_LEFT ||
6011 direction == GTK_DIR_RIGHT ||
6012 direction == GTK_DIR_UP ||
6013 direction == GTK_DIR_DOWN)
6018 /* Wrapped off the end, clear the focus setting for the toplpevel */
6019 parent = gtk_widget_get_parent (priv->focus_widget);
6022 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6023 parent = gtk_widget_get_parent (parent);
6026 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6029 /* Now try to focus the first widget in the window */
6030 child = gtk_bin_get_child (bin);
6033 if (gtk_widget_child_focus (child, direction))
6041 gtk_window_move_focus (GtkWidget *widget,
6042 GtkDirectionType dir)
6044 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6046 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6050 gtk_widget_child_focus (widget, dir);
6052 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6053 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6057 gtk_window_real_set_focus (GtkWindow *window,
6060 GtkWindowPrivate *priv = window->priv;
6061 GtkWidget *old_focus = priv->focus_widget;
6062 gboolean had_default = FALSE;
6063 gboolean focus_had_default = FALSE;
6064 gboolean old_focus_had_default = FALSE;
6068 g_object_ref (old_focus);
6069 g_object_freeze_notify (G_OBJECT (old_focus));
6070 old_focus_had_default = gtk_widget_has_default (old_focus);
6074 g_object_ref (focus);
6075 g_object_freeze_notify (G_OBJECT (focus));
6076 focus_had_default = gtk_widget_has_default (focus);
6079 if (priv->default_widget)
6080 had_default = gtk_widget_has_default (priv->default_widget);
6082 if (priv->focus_widget)
6084 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6085 (priv->focus_widget != priv->default_widget))
6087 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6088 gtk_widget_queue_draw (priv->focus_widget);
6090 if (priv->default_widget)
6091 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6094 priv->focus_widget = NULL;
6096 if (priv->has_focus)
6097 do_focus_change (old_focus, FALSE);
6099 g_object_notify (G_OBJECT (old_focus), "is-focus");
6102 /* The above notifications may have set a new focus widget,
6103 * if so, we don't want to override it.
6105 if (focus && !priv->focus_widget)
6107 priv->focus_widget = focus;
6109 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6110 (priv->focus_widget != priv->default_widget))
6112 if (gtk_widget_get_can_default (priv->focus_widget))
6113 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6115 if (priv->default_widget)
6116 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6119 if (priv->has_focus)
6120 do_focus_change (priv->focus_widget, TRUE);
6122 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6125 /* If the default widget changed, a redraw will have been queued
6126 * on the old and new default widgets by gtk_window_set_default(), so
6127 * we only have to worry about the case where it didn't change.
6128 * We'll sometimes queue a draw twice on the new widget but that
6131 if (priv->default_widget &&
6132 (had_default != gtk_widget_has_default (priv->default_widget)))
6133 gtk_widget_queue_draw (priv->default_widget);
6137 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6138 gtk_widget_queue_draw (old_focus);
6140 g_object_thaw_notify (G_OBJECT (old_focus));
6141 g_object_unref (old_focus);
6145 if (focus_had_default != gtk_widget_has_default (focus))
6146 gtk_widget_queue_draw (focus);
6148 g_object_thaw_notify (G_OBJECT (focus));
6149 g_object_unref (focus);
6155 gtk_window_get_preferred_width (GtkWidget *widget,
6163 window = GTK_WINDOW (widget);
6164 child = gtk_bin_get_child (GTK_BIN (window));
6166 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6167 *minimum_size = border_width * 2;
6168 *natural_size = border_width * 2;
6170 if (child && gtk_widget_get_visible (child))
6172 gint child_min, child_nat;
6173 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6175 *minimum_size += child_min;
6176 *natural_size += child_nat;
6181 gtk_window_get_preferred_height (GtkWidget *widget,
6189 window = GTK_WINDOW (widget);
6190 child = gtk_bin_get_child (GTK_BIN (window));
6192 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6193 *minimum_size = border_width * 2;
6194 *natural_size = border_width * 2;
6196 if (child && gtk_widget_get_visible (child))
6198 gint child_min, child_nat;
6199 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6201 *minimum_size += child_min;
6202 *natural_size += child_nat;
6208 * _gtk_window_unset_focus_and_default:
6209 * @window: a #GtkWindow
6210 * @widget: a widget inside of @window
6212 * Checks whether the focus and default widgets of @window are
6213 * @widget or a descendent of @widget, and if so, unset them.
6216 _gtk_window_unset_focus_and_default (GtkWindow *window,
6220 GtkWindowPrivate *priv = window->priv;
6224 g_object_ref (window);
6225 g_object_ref (widget);
6227 parent = gtk_widget_get_parent (widget);
6228 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6230 child = priv->focus_widget;
6232 while (child && child != widget)
6233 child = gtk_widget_get_parent (child);
6235 if (child == widget)
6236 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6239 child = priv->default_widget;
6241 while (child && child != widget)
6242 child = gtk_widget_get_parent (child);
6244 if (child == widget)
6245 gtk_window_set_default (window, NULL);
6247 g_object_unref (widget);
6248 g_object_unref (window);
6251 /*********************************
6252 * Functions related to resizing *
6253 *********************************/
6256 geometry_size_to_pixels (GdkGeometry *geometry,
6261 gint base_width = 0;
6262 gint base_height = 0;
6264 gint min_height = 0;
6266 gint height_inc = 1;
6268 if (flags & GDK_HINT_BASE_SIZE)
6270 base_width = geometry->base_width;
6271 base_height = geometry->base_height;
6273 if (flags & GDK_HINT_MIN_SIZE)
6275 min_width = geometry->min_width;
6276 min_height = geometry->min_height;
6278 if (flags & GDK_HINT_RESIZE_INC)
6280 width_inc = geometry->width_inc;
6281 height_inc = geometry->height_inc;
6285 *width = MAX (*width * width_inc + base_width, min_width);
6287 *height = MAX (*height * height_inc + base_height, min_height);
6290 /* This function doesn't constrain to geometry hints */
6292 gtk_window_compute_configure_request_size (GtkWindow *window,
6293 GdkGeometry *geometry,
6298 GtkWindowPrivate *priv = window->priv;
6299 GtkRequisition requisition;
6300 GtkWindowGeometryInfo *info;
6304 * - we've done a size request
6307 widget = GTK_WIDGET (window);
6309 info = gtk_window_get_geometry_info (window, FALSE);
6311 if (priv->need_default_size)
6313 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6315 /* Default to requisition */
6316 *width = requisition.width;
6317 *height = requisition.height;
6319 /* If window is empty so requests 0, default to random nonzero size */
6320 if (*width == 0 && *height == 0)
6326 /* Override requisition with default size */
6330 if (info->default_width > 0)
6331 *width = info->default_width;
6332 if (info->default_height > 0)
6333 *height = info->default_height;
6335 if (info->default_is_geometry)
6336 geometry_size_to_pixels (geometry, flags,
6337 info->default_width > 0 ? width : NULL,
6338 info->default_height > 0 ? height : NULL);
6343 GtkAllocation allocation;
6345 gtk_widget_get_allocation (widget, &allocation);
6347 /* Default to keeping current size */
6348 *width = allocation.width;
6349 *height = allocation.height;
6352 /* Override any size with gtk_window_resize() values */
6355 if (info->resize_width > 0)
6356 *width = info->resize_width;
6357 if (info->resize_height > 0)
6358 *height = info->resize_height;
6360 if (info->resize_is_geometry)
6361 geometry_size_to_pixels (geometry, flags,
6362 info->resize_width > 0 ? width : NULL,
6363 info->resize_height > 0 ? height : NULL);
6366 /* Don't ever request zero width or height, its not supported by
6367 gdk. The size allocation code will round it to 1 anyway but if
6368 we do it then the value returned from this function will is
6369 not comparable to the size allocation read from the GtkWindow. */
6370 *width = MAX (*width, 1);
6371 *height = MAX (*height, 1);
6374 static GtkWindowPosition
6375 get_effective_position (GtkWindow *window)
6377 GtkWindowPrivate *priv = window->priv;
6378 GtkWindowPosition pos = priv->position;
6380 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6381 (priv->transient_parent == NULL ||
6382 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6383 pos = GTK_WIN_POS_NONE;
6389 get_center_monitor_of_window (GtkWindow *window)
6391 /* We could try to sort out the relative positions of the monitors and
6392 * stuff, or we could just be losers and assume you have a row
6393 * or column of monitors.
6395 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6399 get_monitor_containing_pointer (GtkWindow *window)
6403 GdkScreen *window_screen;
6404 GdkScreen *pointer_screen;
6405 GdkDisplay *display;
6406 GdkDeviceManager *device_manager;
6409 window_screen = gtk_window_check_screen (window);
6410 display = gdk_screen_get_display (window_screen);
6411 device_manager = gdk_display_get_device_manager (display);
6412 pointer = gdk_device_manager_get_client_pointer (device_manager);
6414 gdk_device_get_position (pointer,
6418 if (pointer_screen == window_screen)
6419 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6427 center_window_on_monitor (GtkWindow *window,
6433 GdkRectangle monitor;
6436 monitor_num = get_monitor_containing_pointer (window);
6438 if (monitor_num == -1)
6439 monitor_num = get_center_monitor_of_window (window);
6441 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6442 monitor_num, &monitor);
6444 *x = (monitor.width - w) / 2 + monitor.x;
6445 *y = (monitor.height - h) / 2 + monitor.y;
6447 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6448 * and WM decorations.
6462 if (extent > clamp_extent)
6464 *base = clamp_base + clamp_extent/2 - extent/2;
6465 else if (*base < clamp_base)
6467 else if (*base + extent > clamp_base + clamp_extent)
6468 *base = clamp_base + clamp_extent - extent;
6472 clamp_window_to_rectangle (gint *x,
6476 const GdkRectangle *rect)
6478 #ifdef DEBUGGING_OUTPUT
6479 g_print ("%s: %+d%+d %dx%d: %+d%+d: %dx%d", G_STRFUNC, rect->x, rect->y, rect->width, rect->height, *x, *y, w, h);
6482 /* If it is too large, center it. If it fits on the monitor but is
6483 * partially outside, move it to the closest edge. Do this
6484 * separately in x and y directions.
6486 clamp (x, w, rect->x, rect->width);
6487 clamp (y, h, rect->y, rect->height);
6488 #ifdef DEBUGGING_OUTPUT
6489 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6495 gtk_window_compute_configure_request (GtkWindow *window,
6496 GdkRectangle *request,
6497 GdkGeometry *geometry,
6500 GtkWindowPrivate *priv = window->priv;
6501 GdkGeometry new_geometry;
6504 GtkWindowPosition pos;
6505 GtkWidget *parent_widget;
6506 GtkWindowGeometryInfo *info;
6510 screen = gtk_window_check_screen (window);
6512 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6513 gtk_window_compute_configure_request_size (window,
6514 &new_geometry, new_flags,
6515 (guint *)&w, (guint *)&h);
6517 gtk_window_constrain_size (window,
6518 &new_geometry, new_flags,
6522 parent_widget = (GtkWidget*) priv->transient_parent;
6524 pos = get_effective_position (window);
6525 info = gtk_window_get_geometry_info (window, FALSE);
6527 /* by default, don't change position requested */
6530 x = info->last.configure_request.x;
6531 y = info->last.configure_request.y;
6540 if (priv->need_default_position)
6543 /* FIXME this all interrelates with window gravity.
6544 * For most of them I think we want to set GRAVITY_CENTER.
6546 * Not sure how to go about that.
6550 /* here we are only handling CENTER_ALWAYS
6551 * as it relates to default positioning,
6552 * where it's equivalent to simply CENTER
6554 case GTK_WIN_POS_CENTER_ALWAYS:
6555 case GTK_WIN_POS_CENTER:
6556 center_window_on_monitor (window, w, h, &x, &y);
6559 case GTK_WIN_POS_CENTER_ON_PARENT:
6561 GtkAllocation allocation;
6562 GdkWindow *gdk_window;
6564 GdkRectangle monitor;
6567 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6569 gdk_window = gtk_widget_get_window (parent_widget);
6571 if (gdk_window != NULL)
6572 monitor_num = gdk_screen_get_monitor_at_window (screen,
6577 gdk_window_get_origin (gdk_window,
6580 gtk_widget_get_allocation (parent_widget, &allocation);
6581 x = ox + (allocation.width - w) / 2;
6582 y = oy + (allocation.height - h) / 2;
6584 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6585 * WM decorations. If parent wasn't on a monitor, just
6588 if (monitor_num >= 0)
6590 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6591 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6596 case GTK_WIN_POS_MOUSE:
6598 gint screen_width = gdk_screen_get_width (screen);
6599 gint screen_height = gdk_screen_get_height (screen);
6601 GdkRectangle monitor;
6602 GdkDisplay *display;
6603 GdkDeviceManager *device_manager;
6605 GdkScreen *pointer_screen;
6608 display = gdk_screen_get_display (screen);
6609 device_manager = gdk_display_get_device_manager (display);
6610 pointer = gdk_device_manager_get_client_pointer (device_manager);
6612 gdk_device_get_position (pointer,
6616 if (pointer_screen == screen)
6617 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6623 x = CLAMP (x, 0, screen_width - w);
6624 y = CLAMP (y, 0, screen_height - h);
6626 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6627 * WM decorations. Don't try to figure out what's going
6628 * on if the mouse wasn't inside a monitor.
6630 if (monitor_num >= 0)
6632 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6633 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6641 } /* if (priv->need_default_position) */
6643 if (priv->need_default_position && info &&
6644 info->initial_pos_set)
6646 x = info->initial_x;
6647 y = info->initial_y;
6648 gtk_window_constrain_position (window, w, h, &x, &y);
6654 request->height = h;
6657 *geometry = new_geometry;
6663 gtk_window_constrain_position (GtkWindow *window,
6669 GtkWindowPrivate *priv = window->priv;
6671 /* See long comments in gtk_window_move_resize()
6672 * on when it's safe to call this function.
6674 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6676 gint center_x, center_y;
6678 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6686 gtk_window_move_resize (GtkWindow *window)
6690 * First we determine whether any information has changed that would
6691 * cause us to revise our last configure request. If we would send
6692 * a different configure request from last time, then
6693 * configure_request_size_changed = TRUE or
6694 * configure_request_pos_changed = TRUE. configure_request_size_changed
6695 * may be true due to new hints, a gtk_window_resize(), or whatever.
6696 * configure_request_pos_changed may be true due to gtk_window_set_position()
6697 * or gtk_window_move().
6699 * If the configure request has changed, we send off a new one. To
6700 * ensure GTK+ invariants are maintained (resize queue does what it
6701 * should), we go ahead and size_allocate the requested size in this
6704 * If the configure request has not changed, we don't ever resend
6705 * it, because it could mean fighting the user or window manager.
6708 * To prepare the configure request, we come up with a base size/pos:
6709 * - the one from gtk_window_move()/gtk_window_resize()
6710 * - else default_width, default_height if we haven't ever
6712 * - else the size request if we haven't ever been mapped,
6713 * as a substitute default size
6714 * - else the current size of the window, as received from
6715 * configure notifies (i.e. the current allocation)
6717 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6718 * the position request to be centered.
6720 GtkWindowPrivate *priv = window->priv;
6721 GtkAllocation allocation;
6723 GtkContainer *container;
6724 GtkWindowGeometryInfo *info;
6725 GdkGeometry new_geometry;
6726 GdkWindow *gdk_window;
6728 GdkRectangle new_request;
6729 gboolean configure_request_size_changed;
6730 gboolean configure_request_pos_changed;
6731 gboolean hints_changed; /* do we need to send these again */
6732 GtkWindowLastGeometryInfo saved_last_info;
6734 widget = GTK_WIDGET (window);
6736 gdk_window = gtk_widget_get_window (widget);
6737 container = GTK_CONTAINER (widget);
6738 info = gtk_window_get_geometry_info (window, TRUE);
6740 configure_request_size_changed = FALSE;
6741 configure_request_pos_changed = FALSE;
6743 gtk_window_compute_configure_request (window, &new_request,
6744 &new_geometry, &new_flags);
6746 /* This check implies the invariant that we never set info->last
6747 * without setting the hints and sending off a configure request.
6749 * If we change info->last without sending the request, we may
6752 if (info->last.configure_request.x != new_request.x ||
6753 info->last.configure_request.y != new_request.y)
6754 configure_request_pos_changed = TRUE;
6756 if ((info->last.configure_request.width != new_request.width ||
6757 info->last.configure_request.height != new_request.height))
6758 configure_request_size_changed = TRUE;
6760 hints_changed = FALSE;
6762 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6763 &new_geometry, new_flags))
6765 hints_changed = TRUE;
6768 /* Position Constraints
6769 * ====================
6771 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6772 * a default. The other POS_ values are used only when the
6773 * window is shown, not after that.
6775 * However, we can't implement a position constraint as
6776 * "anytime the window size changes, center the window"
6777 * because this may well end up fighting the WM or user. In
6778 * fact it gets in an infinite loop with at least one WM.
6780 * Basically, applications are in no way in a position to
6781 * constrain the position of a window, with one exception:
6782 * override redirect windows. (Really the intended purpose
6783 * of CENTER_ALWAYS anyhow, I would think.)
6785 * So the way we implement this "constraint" is to say that when WE
6786 * cause a move or resize, i.e. we make a configure request changing
6787 * window size, we recompute the CENTER_ALWAYS position to reflect
6788 * the new window size, and include it in our request. Also, if we
6789 * just turned on CENTER_ALWAYS we snap to center with a new
6790 * request. Otherwise, if we are just NOTIFIED of a move or resize
6791 * done by someone else e.g. the window manager, we do NOT send a
6792 * new configure request.
6794 * For override redirect windows, this works fine; all window
6795 * sizes are from our configure requests. For managed windows,
6796 * it is at least semi-sane, though who knows what the
6797 * app author is thinking.
6800 /* This condition should be kept in sync with the condition later on
6801 * that determines whether we send a configure request. i.e. we
6802 * should do this position constraining anytime we were going to
6803 * send a configure request anyhow, plus when constraints have
6806 if (configure_request_pos_changed ||
6807 configure_request_size_changed ||
6809 info->position_constraints_changed)
6811 /* We request the constrained position if:
6812 * - we were changing position, and need to clamp
6813 * the change to the constraint
6814 * - we're changing the size anyway
6815 * - set_position() was called to toggle CENTER_ALWAYS on
6818 gtk_window_constrain_position (window,
6824 /* Update whether we need to request a move */
6825 if (info->last.configure_request.x != new_request.x ||
6826 info->last.configure_request.y != new_request.y)
6827 configure_request_pos_changed = TRUE;
6829 configure_request_pos_changed = FALSE;
6833 if (priv->type == GTK_WINDOW_TOPLEVEL)
6835 int notify_x, notify_y;
6837 /* this is the position from the last configure notify */
6838 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6840 g_message ("--- %s ---\n"
6841 "last : %d,%d\t%d x %d\n"
6842 "this : %d,%d\t%d x %d\n"
6843 "alloc : %d,%d\t%d x %d\n"
6845 "resize: \t%d x %d\n"
6846 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6847 "configure_notify_received: %d\n"
6848 "configure_request_count: %d\n"
6849 "position_constraints_changed: %d\n",
6850 priv->title ? priv->title : "(no title)",
6851 info->last.configure_request.x,
6852 info->last.configure_request.y,
6853 info->last.configure_request.width,
6854 info->last.configure_request.height,
6860 widget->allocation.width,
6861 widget->allocation.height,
6862 widget->requisition.width,
6863 widget->requisition.height,
6865 info->resize_height,
6866 configure_request_pos_changed,
6867 configure_request_size_changed,
6869 priv->configure_notify_received,
6870 priv->configure_request_count,
6871 info->position_constraints_changed);
6875 saved_last_info = info->last;
6876 info->last.geometry = new_geometry;
6877 info->last.flags = new_flags;
6878 info->last.configure_request = new_request;
6880 /* need to set PPosition so the WM will look at our position,
6881 * but we don't want to count PPosition coming and going as a hints
6882 * change for future iterations. So we saved info->last prior to
6886 /* Also, if the initial position was explicitly set, then we always
6887 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6891 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6892 * this is an initial map
6895 if ((configure_request_pos_changed ||
6896 info->initial_pos_set ||
6897 (priv->need_default_position &&
6898 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6899 (new_flags & GDK_HINT_POS) == 0)
6901 new_flags |= GDK_HINT_POS;
6902 hints_changed = TRUE;
6905 /* Set hints if necessary
6908 gdk_window_set_geometry_hints (gdk_window,
6912 gtk_widget_get_allocation (widget, &allocation);
6914 /* handle resizing/moving and widget tree allocation
6916 if (priv->configure_notify_received)
6918 /* If we have received a configure event since
6919 * the last time in this function, we need to
6920 * accept our new size and size_allocate child widgets.
6921 * (see gtk_window_configure_event() for more details).
6923 * 1 or more configure notifies may have been received.
6924 * Also, configure_notify_received will only be TRUE
6925 * if all expected configure notifies have been received
6926 * (one per configure request), as an optimization.
6929 priv->configure_notify_received = FALSE;
6931 /* gtk_window_configure_event() filled in widget->allocation */
6932 gtk_widget_size_allocate (widget, &allocation);
6934 set_grip_position (window);
6935 update_grip_visibility (window);
6937 gdk_window_process_updates (gdk_window, TRUE);
6939 gdk_window_configure_finished (gdk_window);
6941 /* If the configure request changed, it means that
6943 * 1) coincidentally changed hints or widget properties
6944 * impacting the configure request before getting
6945 * a configure notify, or
6946 * 2) some broken widget is changing its size request
6947 * during size allocation, resulting in
6948 * a false appearance of changed configure request.
6950 * For 1), we could just go ahead and ask for the
6951 * new size right now, but doing that for 2)
6952 * might well be fighting the user (and can even
6953 * trigger a loop). Since we really don't want to
6954 * do that, we requeue a resize in hopes that
6955 * by the time it gets handled, the child has seen
6956 * the light and is willing to go along with the
6957 * new size. (this happens for the zvt widget, since
6958 * the size_allocate() above will have stored the
6959 * requisition corresponding to the new size in the
6962 * This doesn't buy us anything for 1), but it shouldn't
6963 * hurt us too badly, since it is what would have
6964 * happened if we had gotten the configure event before
6965 * the new size had been set.
6968 if (configure_request_size_changed ||
6969 configure_request_pos_changed)
6971 /* Don't change the recorded last info after all, because we
6972 * haven't actually updated to the new info yet - we decided
6973 * to postpone our configure request until later.
6975 info->last = saved_last_info;
6977 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6980 return; /* Bail out, we didn't really process the move/resize */
6982 else if ((configure_request_size_changed || hints_changed) &&
6983 (allocation.width != new_request.width || allocation.height != new_request.height))
6986 /* We are in one of the following situations:
6987 * A. configure_request_size_changed
6988 * our requisition has changed and we need a different window size,
6989 * so we request it from the window manager.
6990 * B. !configure_request_size_changed && hints_changed
6991 * the window manager rejects our size, but we have just changed the
6992 * window manager hints, so there's a chance our request will
6993 * be honoured this time, so we try again.
6995 * However, if the new requisition is the same as the current allocation,
6996 * we don't request it again, since we won't get a ConfigureNotify back from
6997 * the window manager unless it decides to change our requisition. If
6998 * we don't get the ConfigureNotify back, the resize queue will never be run.
7001 /* Now send the configure request */
7002 if (configure_request_pos_changed)
7004 gdk_window_move_resize (gdk_window,
7005 new_request.x, new_request.y,
7006 new_request.width, new_request.height);
7008 else /* only size changed */
7010 gdk_window_resize (gdk_window,
7011 new_request.width, new_request.height);
7014 if (priv->type == GTK_WINDOW_POPUP)
7016 GtkAllocation allocation;
7018 /* Directly size allocate for override redirect (popup) windows. */
7021 allocation.width = new_request.width;
7022 allocation.height = new_request.height;
7024 gtk_widget_size_allocate (widget, &allocation);
7026 gdk_window_process_updates (gdk_window, TRUE);
7028 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7029 gtk_widget_queue_draw (widget);
7033 /* Increment the number of have-not-yet-received-notify requests */
7034 priv->configure_request_count += 1;
7035 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7037 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7038 * configure event in response to our resizing request.
7039 * the configure event will cause a new resize with
7040 * ->configure_notify_received=TRUE.
7041 * until then, we want to
7042 * - discard expose events
7043 * - coalesce resizes for our children
7044 * - defer any window resizes until the configure event arrived
7045 * to achieve this, we queue a resize for the window, but remove its
7046 * resizing handler, so resizing will not be handled from the next
7047 * idle handler but when the configure event arrives.
7049 * FIXME: we should also dequeue the pending redraws here, since
7050 * we handle those ourselves upon ->configure_notify_received==TRUE.
7052 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7054 gtk_widget_queue_resize_no_redraw (widget);
7055 _gtk_container_dequeue_resize_handler (container);
7061 /* Handle any position changes.
7063 if (configure_request_pos_changed)
7065 gdk_window_move (gdk_window,
7066 new_request.x, new_request.y);
7069 /* And run the resize queue.
7071 gtk_container_resize_children (container);
7074 /* We have now processed a move/resize since the last position
7075 * constraint change, setting of the initial position, or resize.
7076 * (Not resetting these flags here can lead to infinite loops for
7077 * GTK_RESIZE_IMMEDIATE containers)
7079 info->position_constraints_changed = FALSE;
7080 info->initial_pos_set = FALSE;
7081 info->resize_width = -1;
7082 info->resize_height = -1;
7085 /* Compare two sets of Geometry hints for equality.
7088 gtk_window_compare_hints (GdkGeometry *geometry_a,
7090 GdkGeometry *geometry_b,
7093 if (flags_a != flags_b)
7096 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7097 (geometry_a->min_width != geometry_b->min_width ||
7098 geometry_a->min_height != geometry_b->min_height))
7101 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7102 (geometry_a->max_width != geometry_b->max_width ||
7103 geometry_a->max_height != geometry_b->max_height))
7106 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7107 (geometry_a->base_width != geometry_b->base_width ||
7108 geometry_a->base_height != geometry_b->base_height))
7111 if ((flags_a & GDK_HINT_ASPECT) &&
7112 (geometry_a->min_aspect != geometry_b->min_aspect ||
7113 geometry_a->max_aspect != geometry_b->max_aspect))
7116 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7117 (geometry_a->width_inc != geometry_b->width_inc ||
7118 geometry_a->height_inc != geometry_b->height_inc))
7121 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7122 geometry_a->win_gravity != geometry_b->win_gravity)
7129 _gtk_window_constrain_size (GtkWindow *window,
7135 GtkWindowPrivate *priv;
7136 GtkWindowGeometryInfo *info;
7138 g_return_if_fail (GTK_IS_WINDOW (window));
7140 priv = window->priv;
7142 info = priv->geometry_info;
7145 GdkWindowHints flags = info->last.flags;
7146 GdkGeometry *geometry = &info->last.geometry;
7148 gtk_window_constrain_size (window,
7159 gtk_window_constrain_size (GtkWindow *window,
7160 GdkGeometry *geometry,
7167 gdk_window_constrain_size (geometry, flags, width, height,
7168 new_width, new_height);
7171 /* Compute the set of geometry hints and flags for a window
7172 * based on the application set geometry, and requisition
7173 * of the window. gtk_widget_get_preferred_size() must have been
7177 gtk_window_compute_hints (GtkWindow *window,
7178 GdkGeometry *new_geometry,
7181 GtkWindowPrivate *priv = window->priv;
7183 gint extra_width = 0;
7184 gint extra_height = 0;
7185 GtkWindowGeometryInfo *geometry_info;
7186 GtkRequisition requisition;
7188 widget = GTK_WIDGET (window);
7190 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7191 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7195 *new_flags = geometry_info->mask;
7196 *new_geometry = geometry_info->geometry;
7203 if (geometry_info && geometry_info->widget)
7205 /* If the geometry widget is set, then the hints really apply to that
7206 * widget. This is pretty much meaningless unless the window layout
7207 * is such that the rest of the window adds fixed size borders to
7208 * the geometry widget. Our job is to figure the size of the borders;
7209 * We do that by asking how big the toplevel would be if the
7210 * geometry widget was *really big*.
7213 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7214 * |GGGGG B| in the border can confuse things
7220 * |AAAAAAAAA | When the geometry widget is large, things are
7221 * |GGGGGGGGGGB| clearer.
7226 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7227 GtkRequisition requisition;
7228 int current_width, current_height;
7230 _gtk_widget_override_size_request (geometry_info->widget,
7231 TEMPORARY_SIZE, TEMPORARY_SIZE,
7232 ¤t_width, ¤t_height);
7233 gtk_widget_get_preferred_size (widget,
7234 &requisition, NULL);
7235 _gtk_widget_restore_size_request (geometry_info->widget,
7236 current_width, current_height);
7238 extra_width = requisition.width - TEMPORARY_SIZE;
7239 extra_height = requisition.height - TEMPORARY_SIZE;
7241 if (extra_width < 0 || extra_width < 0)
7243 g_warning("Toplevel size doesn't seem to directly depend on the "
7244 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7245 "The geometry widget might not be in the window, or it might not "
7246 "be packed into the window appropriately");
7247 extra_width = MAX(extra_width, 0);
7248 extra_height = MAX(extra_height, 0);
7250 #undef TEMPORARY_SIZE
7253 /* We don't want to set GDK_HINT_POS in here, we just set it
7254 * in gtk_window_move_resize() when we want the position
7258 if (*new_flags & GDK_HINT_BASE_SIZE)
7260 new_geometry->base_width += extra_width;
7261 new_geometry->base_height += extra_height;
7265 /* For simplicity, we always set the base hint, even when we
7266 * don't expect it to have any visible effect.
7267 * (Note: geometry_size_to_pixels() depends on this.)
7269 *new_flags |= GDK_HINT_BASE_SIZE;
7271 new_geometry->base_width = extra_width;
7272 new_geometry->base_height = extra_height;
7274 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7275 * base size is the minimum size */
7276 if (*new_flags & GDK_HINT_MIN_SIZE)
7278 if (new_geometry->min_width > 0)
7279 new_geometry->base_width += new_geometry->min_width;
7280 if (new_geometry->min_height > 0)
7281 new_geometry->base_height += new_geometry->min_height;
7285 if (*new_flags & GDK_HINT_MIN_SIZE)
7287 if (new_geometry->min_width < 0)
7288 new_geometry->min_width = requisition.width;
7290 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7292 if (new_geometry->min_height < 0)
7293 new_geometry->min_height = requisition.height;
7295 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7299 *new_flags |= GDK_HINT_MIN_SIZE;
7301 new_geometry->min_width = requisition.width;
7302 new_geometry->min_height = requisition.height;
7305 if (*new_flags & GDK_HINT_MAX_SIZE)
7307 if (new_geometry->max_width < 0)
7308 new_geometry->max_width = requisition.width;
7310 new_geometry->max_width += extra_width;
7312 if (new_geometry->max_height < 0)
7313 new_geometry->max_height = requisition.height;
7315 new_geometry->max_height += extra_height;
7317 else if (!priv->resizable)
7319 *new_flags |= GDK_HINT_MAX_SIZE;
7321 new_geometry->max_width = requisition.width;
7322 new_geometry->max_height = requisition.height;
7325 *new_flags |= GDK_HINT_WIN_GRAVITY;
7326 new_geometry->win_gravity = priv->gravity;
7329 /***********************
7330 * Redrawing functions *
7331 ***********************/
7334 gtk_window_draw (GtkWidget *widget,
7337 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7338 GtkStyleContext *context;
7339 gboolean ret = FALSE;
7341 context = gtk_widget_get_style_context (widget);
7343 gtk_style_context_save (context);
7345 if (!gtk_widget_get_app_paintable (widget))
7347 GtkStateFlags state;
7349 state = gtk_widget_get_state_flags (widget);
7351 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7352 state |= GTK_STATE_FLAG_FOCUSED;
7354 gtk_style_context_set_state (context, state);
7355 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7356 gtk_render_background (context, cr, 0, 0,
7357 gtk_widget_get_allocated_width (widget),
7358 gtk_widget_get_allocated_height (widget));
7361 gtk_style_context_restore (context);
7363 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7364 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7366 if (priv->grip_window != NULL &&
7367 gtk_cairo_should_draw_window (cr, priv->grip_window))
7371 gtk_style_context_save (context);
7374 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7375 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7377 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7378 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7379 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7382 gtk_style_context_restore (context);
7389 * gtk_window_present:
7390 * @window: a #GtkWindow
7392 * Presents a window to the user. This may mean raising the window
7393 * in the stacking order, deiconifying it, moving it to the current
7394 * desktop, and/or giving it the keyboard focus, possibly dependent
7395 * on the user's platform, window manager, and preferences.
7397 * If @window is hidden, this function calls gtk_widget_show()
7400 * This function should be used when the user tries to open a window
7401 * that's already open. Say for example the preferences dialog is
7402 * currently open, and the user chooses Preferences from the menu
7403 * a second time; use gtk_window_present() to move the already-open dialog
7404 * where the user can see it.
7406 * If you are calling this function in response to a user interaction,
7407 * it is preferable to use gtk_window_present_with_time().
7411 gtk_window_present (GtkWindow *window)
7413 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7417 * gtk_window_present_with_time:
7418 * @window: a #GtkWindow
7419 * @timestamp: the timestamp of the user interaction (typically a
7420 * button or key press event) which triggered this call
7422 * Presents a window to the user in response to a user interaction.
7423 * If you need to present a window without a timestamp, use
7424 * gtk_window_present(). See gtk_window_present() for details.
7429 gtk_window_present_with_time (GtkWindow *window,
7433 GdkWindow *gdk_window;
7435 g_return_if_fail (GTK_IS_WINDOW (window));
7437 widget = GTK_WIDGET (window);
7439 if (gtk_widget_get_visible (widget))
7441 gdk_window = gtk_widget_get_window (widget);
7443 g_assert (gdk_window != NULL);
7445 gdk_window_show (gdk_window);
7447 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7448 if (timestamp == GDK_CURRENT_TIME)
7450 #ifdef GDK_WINDOWING_X11
7451 GdkDisplay *display;
7453 display = gtk_widget_get_display (GTK_WIDGET (window));
7454 timestamp = gdk_x11_display_get_user_time (display);
7456 timestamp = gtk_get_current_event_time ();
7460 gdk_window_focus (gdk_window, timestamp);
7464 gtk_widget_show (widget);
7469 * gtk_window_iconify:
7470 * @window: a #GtkWindow
7472 * Asks to iconify (i.e. minimize) the specified @window. Note that
7473 * you shouldn't assume the window is definitely iconified afterward,
7474 * because other entities (e.g. the user or <link
7475 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7476 * again, or there may not be a window manager in which case
7477 * iconification isn't possible, etc. But normally the window will end
7478 * up iconified. Just don't write code that crashes if not.
7480 * It's permitted to call this function before showing a window,
7481 * in which case the window will be iconified before it ever appears
7484 * You can track iconification via the "window-state-event" signal
7489 gtk_window_iconify (GtkWindow *window)
7491 GtkWindowPrivate *priv;
7493 GdkWindow *toplevel;
7495 g_return_if_fail (GTK_IS_WINDOW (window));
7497 priv = window->priv;
7498 widget = GTK_WIDGET (window);
7500 priv->iconify_initially = TRUE;
7502 toplevel = gtk_widget_get_window (widget);
7504 if (toplevel != NULL)
7505 gdk_window_iconify (toplevel);
7509 * gtk_window_deiconify:
7510 * @window: a #GtkWindow
7512 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7513 * that you shouldn't assume the window is definitely deiconified
7514 * afterward, because other entities (e.g. the user or <link
7515 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7516 * again before your code which assumes deiconification gets to run.
7518 * You can track iconification via the "window-state-event" signal
7522 gtk_window_deiconify (GtkWindow *window)
7524 GtkWindowPrivate *priv;
7526 GdkWindow *toplevel;
7528 g_return_if_fail (GTK_IS_WINDOW (window));
7530 priv = window->priv;
7531 widget = GTK_WIDGET (window);
7533 priv->iconify_initially = FALSE;
7535 toplevel = gtk_widget_get_window (widget);
7537 if (toplevel != NULL)
7538 gdk_window_deiconify (toplevel);
7543 * @window: a #GtkWindow
7545 * Asks to stick @window, which means that it will appear on all user
7546 * desktops. Note that you shouldn't assume the window is definitely
7547 * stuck afterward, because other entities (e.g. the user or <link
7548 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7549 * again, and some window managers do not support sticking
7550 * windows. But normally the window will end up stuck. Just don't
7551 * write code that crashes if not.
7553 * It's permitted to call this function before showing a window.
7555 * You can track stickiness via the "window-state-event" signal
7560 gtk_window_stick (GtkWindow *window)
7562 GtkWindowPrivate *priv;
7564 GdkWindow *toplevel;
7566 g_return_if_fail (GTK_IS_WINDOW (window));
7568 priv = window->priv;
7569 widget = GTK_WIDGET (window);
7571 priv->stick_initially = TRUE;
7573 toplevel = gtk_widget_get_window (widget);
7575 if (toplevel != NULL)
7576 gdk_window_stick (toplevel);
7580 * gtk_window_unstick:
7581 * @window: a #GtkWindow
7583 * Asks to unstick @window, which means that it will appear on only
7584 * one of the user's desktops. Note that you shouldn't assume the
7585 * window is definitely unstuck afterward, because other entities
7586 * (e.g. the user or <link linkend="gtk-X11-arch">window
7587 * manager</link>) could stick it again. But normally the window will
7588 * end up stuck. Just don't write code that crashes if not.
7590 * You can track stickiness via the "window-state-event" signal
7595 gtk_window_unstick (GtkWindow *window)
7597 GtkWindowPrivate *priv;
7599 GdkWindow *toplevel;
7601 g_return_if_fail (GTK_IS_WINDOW (window));
7603 priv = window->priv;
7604 widget = GTK_WIDGET (window);
7606 priv->stick_initially = FALSE;
7608 toplevel = gtk_widget_get_window (widget);
7610 if (toplevel != NULL)
7611 gdk_window_unstick (toplevel);
7615 * gtk_window_maximize:
7616 * @window: a #GtkWindow
7618 * Asks to maximize @window, so that it becomes full-screen. Note that
7619 * you shouldn't assume the window is definitely maximized afterward,
7620 * because other entities (e.g. the user or <link
7621 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7622 * again, and not all window managers support maximization. But
7623 * normally the window will end up maximized. Just don't write code
7624 * that crashes if not.
7626 * It's permitted to call this function before showing a window,
7627 * in which case the window will be maximized when it appears onscreen
7630 * You can track maximization via the "window-state-event" signal
7635 gtk_window_maximize (GtkWindow *window)
7637 GtkWindowPrivate *priv;
7639 GdkWindow *toplevel;
7641 g_return_if_fail (GTK_IS_WINDOW (window));
7643 priv = window->priv;
7644 widget = GTK_WIDGET (window);
7646 priv->maximize_initially = TRUE;
7648 toplevel = gtk_widget_get_window (widget);
7650 if (toplevel != NULL)
7651 gdk_window_maximize (toplevel);
7655 * gtk_window_unmaximize:
7656 * @window: a #GtkWindow
7658 * Asks to unmaximize @window. Note that you shouldn't assume the
7659 * window is definitely unmaximized afterward, because other entities
7660 * (e.g. the user or <link linkend="gtk-X11-arch">window
7661 * manager</link>) could maximize it again, and not all window
7662 * managers honor requests to unmaximize. But normally the window will
7663 * end up unmaximized. Just don't write code that crashes if not.
7665 * You can track maximization via the "window-state-event" signal
7670 gtk_window_unmaximize (GtkWindow *window)
7672 GtkWindowPrivate *priv;
7674 GdkWindow *toplevel;
7676 g_return_if_fail (GTK_IS_WINDOW (window));
7678 priv = window->priv;
7679 widget = GTK_WIDGET (window);
7681 priv->maximize_initially = FALSE;
7683 toplevel = gtk_widget_get_window (widget);
7685 if (toplevel != NULL)
7686 gdk_window_unmaximize (toplevel);
7690 * gtk_window_fullscreen:
7691 * @window: a #GtkWindow
7693 * Asks to place @window in the fullscreen state. Note that you
7694 * shouldn't assume the window is definitely full screen afterward,
7695 * because other entities (e.g. the user or <link
7696 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7697 * again, and not all window managers honor requests to fullscreen
7698 * windows. But normally the window will end up fullscreen. Just
7699 * don't write code that crashes if not.
7701 * You can track the fullscreen state via the "window-state-event" signal
7707 gtk_window_fullscreen (GtkWindow *window)
7709 GtkWindowPrivate *priv;
7711 GdkWindow *toplevel;
7713 g_return_if_fail (GTK_IS_WINDOW (window));
7715 priv = window->priv;
7716 widget = GTK_WIDGET (window);
7718 priv->fullscreen_initially = TRUE;
7720 toplevel = gtk_widget_get_window (widget);
7722 if (toplevel != NULL)
7723 gdk_window_fullscreen (toplevel);
7727 * gtk_window_unfullscreen:
7728 * @window: a #GtkWindow
7730 * Asks to toggle off the fullscreen state for @window. Note that you
7731 * shouldn't assume the window is definitely not full screen
7732 * afterward, because other entities (e.g. the user or <link
7733 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7734 * again, and not all window managers honor requests to unfullscreen
7735 * windows. But normally the window will end up restored to its normal
7736 * state. Just don't write code that crashes if not.
7738 * You can track the fullscreen state via the "window-state-event" signal
7744 gtk_window_unfullscreen (GtkWindow *window)
7747 GdkWindow *toplevel;
7748 GtkWindowPrivate *priv;
7750 g_return_if_fail (GTK_IS_WINDOW (window));
7752 priv = window->priv;
7753 widget = GTK_WIDGET (window);
7755 priv->fullscreen_initially = FALSE;
7757 toplevel = gtk_widget_get_window (widget);
7759 if (toplevel != NULL)
7760 gdk_window_unfullscreen (toplevel);
7764 * gtk_window_set_keep_above:
7765 * @window: a #GtkWindow
7766 * @setting: whether to keep @window above other windows
7768 * Asks to keep @window above, so that it stays on top. Note that
7769 * you shouldn't assume the window is definitely above afterward,
7770 * because other entities (e.g. the user or <link
7771 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7772 * and not all window managers support keeping windows above. But
7773 * normally the window will end kept above. Just don't write code
7774 * that crashes if not.
7776 * It's permitted to call this function before showing a window,
7777 * in which case the window will be kept above when it appears onscreen
7780 * You can track the above state via the "window-state-event" signal
7783 * Note that, according to the <ulink
7784 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7785 * Manager Hints</ulink> specification, the above state is mainly meant
7786 * for user preferences and should not be used by applications e.g. for
7787 * drawing attention to their dialogs.
7792 gtk_window_set_keep_above (GtkWindow *window,
7796 GtkWindowPrivate *priv;
7797 GdkWindow *toplevel;
7799 g_return_if_fail (GTK_IS_WINDOW (window));
7801 priv = window->priv;
7802 widget = GTK_WIDGET (window);
7804 priv->above_initially = setting != FALSE;
7806 priv->below_initially = FALSE;
7808 toplevel = gtk_widget_get_window (widget);
7810 if (toplevel != NULL)
7811 gdk_window_set_keep_above (toplevel, setting);
7815 * gtk_window_set_keep_below:
7816 * @window: a #GtkWindow
7817 * @setting: whether to keep @window below other windows
7819 * Asks to keep @window below, so that it stays in bottom. Note that
7820 * you shouldn't assume the window is definitely below afterward,
7821 * because other entities (e.g. the user or <link
7822 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7823 * and not all window managers support putting windows below. But
7824 * normally the window will be kept below. Just don't write code
7825 * that crashes if not.
7827 * It's permitted to call this function before showing a window,
7828 * in which case the window will be kept below when it appears onscreen
7831 * You can track the below state via the "window-state-event" signal
7834 * Note that, according to the <ulink
7835 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7836 * Manager Hints</ulink> specification, the above state is mainly meant
7837 * for user preferences and should not be used by applications e.g. for
7838 * drawing attention to their dialogs.
7843 gtk_window_set_keep_below (GtkWindow *window,
7847 GtkWindowPrivate *priv;
7848 GdkWindow *toplevel;
7850 g_return_if_fail (GTK_IS_WINDOW (window));
7852 priv = window->priv;
7853 widget = GTK_WIDGET (window);
7855 priv->below_initially = setting != FALSE;
7857 priv->above_initially = FALSE;
7859 toplevel = gtk_widget_get_window (widget);
7861 if (toplevel != NULL)
7862 gdk_window_set_keep_below (toplevel, setting);
7866 * gtk_window_set_resizable:
7867 * @window: a #GtkWindow
7868 * @resizable: %TRUE if the user can resize this window
7870 * Sets whether the user can resize a window. Windows are user resizable
7874 gtk_window_set_resizable (GtkWindow *window,
7877 GtkWindowPrivate *priv;
7879 g_return_if_fail (GTK_IS_WINDOW (window));
7881 priv = window->priv;
7883 resizable = (resizable != FALSE);
7885 if (priv->resizable != resizable)
7887 priv->resizable = (resizable != FALSE);
7889 update_grip_visibility (window);
7891 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7893 g_object_notify (G_OBJECT (window), "resizable");
7898 * gtk_window_get_resizable:
7899 * @window: a #GtkWindow
7901 * Gets the value set by gtk_window_set_resizable().
7903 * Return value: %TRUE if the user can resize the window
7906 gtk_window_get_resizable (GtkWindow *window)
7908 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7910 return window->priv->resizable;
7914 * gtk_window_set_gravity:
7915 * @window: a #GtkWindow
7916 * @gravity: window gravity
7918 * Window gravity defines the meaning of coordinates passed to
7919 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7922 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7923 * typically "do what you mean."
7927 gtk_window_set_gravity (GtkWindow *window,
7930 GtkWindowPrivate *priv;
7932 g_return_if_fail (GTK_IS_WINDOW (window));
7934 priv = window->priv;
7936 if (gravity != priv->gravity)
7938 priv->gravity = gravity;
7940 /* gtk_window_move_resize() will adapt gravity
7942 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7944 g_object_notify (G_OBJECT (window), "gravity");
7949 * gtk_window_get_gravity:
7950 * @window: a #GtkWindow
7952 * Gets the value set by gtk_window_set_gravity().
7954 * Return value: (transfer none): window gravity
7957 gtk_window_get_gravity (GtkWindow *window)
7959 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7961 return window->priv->gravity;
7965 * gtk_window_begin_resize_drag:
7966 * @window: a #GtkWindow
7967 * @button: mouse button that initiated the drag
7968 * @edge: position of the resize control
7969 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7970 * @root_y: Y position where the user clicked to initiate the drag
7971 * @timestamp: timestamp from the click event that initiated the drag
7973 * Starts resizing a window. This function is used if an application
7974 * has window resizing controls. When GDK can support it, the resize
7975 * will be done using the standard mechanism for the <link
7976 * linkend="gtk-X11-arch">window manager</link> or windowing
7977 * system. Otherwise, GDK will try to emulate window resizing,
7978 * potentially not all that well, depending on the windowing system.
7982 gtk_window_begin_resize_drag (GtkWindow *window,
7990 GdkWindow *toplevel;
7992 g_return_if_fail (GTK_IS_WINDOW (window));
7993 widget = GTK_WIDGET (window);
7994 g_return_if_fail (gtk_widget_get_visible (widget));
7996 toplevel = gtk_widget_get_window (widget);
7998 gdk_window_begin_resize_drag (toplevel,
8005 * gtk_window_begin_move_drag:
8006 * @window: a #GtkWindow
8007 * @button: mouse button that initiated the drag
8008 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8009 * @root_y: Y position where the user clicked to initiate the drag
8010 * @timestamp: timestamp from the click event that initiated the drag
8012 * Starts moving a window. This function is used if an application has
8013 * window movement grips. When GDK can support it, the window movement
8014 * will be done using the standard mechanism for the <link
8015 * linkend="gtk-X11-arch">window manager</link> or windowing
8016 * system. Otherwise, GDK will try to emulate window movement,
8017 * potentially not all that well, depending on the windowing system.
8021 gtk_window_begin_move_drag (GtkWindow *window,
8028 GdkWindow *toplevel;
8030 g_return_if_fail (GTK_IS_WINDOW (window));
8031 widget = GTK_WIDGET (window);
8032 g_return_if_fail (gtk_widget_get_visible (widget));
8034 toplevel = gtk_widget_get_window (widget);
8036 gdk_window_begin_move_drag (toplevel,
8043 * gtk_window_set_screen:
8044 * @window: a #GtkWindow.
8045 * @screen: a #GdkScreen.
8047 * Sets the #GdkScreen where the @window is displayed; if
8048 * the window is already mapped, it will be unmapped, and
8049 * then remapped on the new screen.
8054 gtk_window_set_screen (GtkWindow *window,
8057 GtkWindowPrivate *priv;
8059 GdkScreen *previous_screen;
8060 gboolean was_mapped;
8062 g_return_if_fail (GTK_IS_WINDOW (window));
8063 g_return_if_fail (GDK_IS_SCREEN (screen));
8065 priv = window->priv;
8067 if (screen == priv->screen)
8070 widget = GTK_WIDGET (window);
8072 previous_screen = priv->screen;
8073 was_mapped = gtk_widget_get_mapped (widget);
8076 gtk_widget_unmap (widget);
8077 if (gtk_widget_get_realized (widget))
8078 gtk_widget_unrealize (widget);
8080 gtk_window_free_key_hash (window);
8081 priv->screen = screen;
8082 gtk_widget_reset_rc_styles (widget);
8083 if (screen != previous_screen)
8085 g_signal_handlers_disconnect_by_func (previous_screen,
8086 gtk_window_on_composited_changed, window);
8087 g_signal_connect (screen, "composited-changed",
8088 G_CALLBACK (gtk_window_on_composited_changed), window);
8090 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8091 _gtk_widget_propagate_composited_changed (widget);
8093 g_object_notify (G_OBJECT (window), "screen");
8096 gtk_widget_map (widget);
8100 gtk_window_on_composited_changed (GdkScreen *screen,
8103 gtk_widget_queue_draw (GTK_WIDGET (window));
8105 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8109 gtk_window_check_screen (GtkWindow *window)
8111 GtkWindowPrivate *priv = window->priv;
8114 return priv->screen;
8117 g_warning ("Screen for GtkWindow not set; you must always set\n"
8118 "a screen for a GtkWindow before using the window");
8124 * gtk_window_get_screen:
8125 * @window: a #GtkWindow.
8127 * Returns the #GdkScreen associated with @window.
8129 * Return value: (transfer none): a #GdkScreen.
8134 gtk_window_get_screen (GtkWindow *window)
8136 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8138 return window->priv->screen;
8142 * gtk_window_is_active:
8143 * @window: a #GtkWindow
8145 * Returns whether the window is part of the current active toplevel.
8146 * (That is, the toplevel window receiving keystrokes.)
8147 * The return value is %TRUE if the window is active toplevel
8148 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8149 * You might use this function if you wanted to draw a widget
8150 * differently in an active window from a widget in an inactive window.
8151 * See gtk_window_has_toplevel_focus()
8153 * Return value: %TRUE if the window part of the current active window.
8158 gtk_window_is_active (GtkWindow *window)
8160 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8162 return window->priv->is_active;
8166 * gtk_window_has_toplevel_focus:
8167 * @window: a #GtkWindow
8169 * Returns whether the input focus is within this GtkWindow.
8170 * For real toplevel windows, this is identical to gtk_window_is_active(),
8171 * but for embedded windows, like #GtkPlug, the results will differ.
8173 * Return value: %TRUE if the input focus is within this GtkWindow
8178 gtk_window_has_toplevel_focus (GtkWindow *window)
8180 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8182 return window->priv->has_toplevel_focus;
8185 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8188 gtk_window_group_init (GtkWindowGroup *group)
8190 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8191 GTK_TYPE_WINDOW_GROUP,
8192 GtkWindowGroupPrivate);
8196 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8198 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8202 * gtk_window_group_new:
8204 * Creates a new #GtkWindowGroup object. Grabs added with
8205 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8207 * Return value: a new #GtkWindowGroup.
8210 gtk_window_group_new (void)
8212 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8216 window_group_cleanup_grabs (GtkWindowGroup *group,
8219 GtkWindowGroupPrivate *priv;
8220 GtkDeviceGrabInfo *info;
8222 GSList *to_remove = NULL;
8226 tmp_list = priv->grabs;
8229 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8230 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8231 tmp_list = tmp_list->next;
8236 gtk_grab_remove (to_remove->data);
8237 g_object_unref (to_remove->data);
8238 to_remove = g_slist_delete_link (to_remove, to_remove);
8241 tmp_list = priv->device_grabs;
8245 info = tmp_list->data;
8247 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8248 to_remove = g_slist_prepend (to_remove, info);
8250 tmp_list = tmp_list->next;
8255 info = to_remove->data;
8257 gtk_device_grab_remove (info->widget, info->device);
8258 to_remove = g_slist_delete_link (to_remove, to_remove);
8263 * gtk_window_group_add_window:
8264 * @window_group: a #GtkWindowGroup
8265 * @window: the #GtkWindow to add
8267 * Adds a window to a #GtkWindowGroup.
8270 gtk_window_group_add_window (GtkWindowGroup *window_group,
8273 GtkWindowPrivate *priv;
8275 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8276 g_return_if_fail (GTK_IS_WINDOW (window));
8278 priv = window->priv;
8280 if (priv->group != window_group)
8282 g_object_ref (window);
8283 g_object_ref (window_group);
8286 gtk_window_group_remove_window (priv->group, window);
8288 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8290 priv->group = window_group;
8292 g_object_unref (window);
8297 * gtk_window_group_remove_window:
8298 * @window_group: a #GtkWindowGroup
8299 * @window: the #GtkWindow to remove
8301 * Removes a window from a #GtkWindowGroup.
8304 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8307 GtkWindowPrivate *priv;
8309 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8310 g_return_if_fail (GTK_IS_WINDOW (window));
8311 priv = window->priv;
8312 g_return_if_fail (priv->group == window_group);
8314 g_object_ref (window);
8316 window_group_cleanup_grabs (window_group, window);
8319 g_object_unref (window_group);
8320 g_object_unref (window);
8324 * gtk_window_group_list_windows:
8325 * @window_group: a #GtkWindowGroup
8327 * Returns a list of the #GtkWindows that belong to @window_group.
8329 * Returns: (element-type GtkWindow) (transfer container): A
8330 * newly-allocated list of windows inside the group.
8335 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8337 GList *toplevels, *toplevel, *group_windows;
8339 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8341 group_windows = NULL;
8342 toplevels = gtk_window_list_toplevels ();
8344 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8346 GtkWindow *window = toplevel->data;
8348 if (window_group == window->priv->group)
8349 group_windows = g_list_prepend (group_windows, window);
8352 g_list_free (toplevels);
8354 return g_list_reverse (group_windows);
8358 * gtk_window_get_group:
8359 * @window: (allow-none): a #GtkWindow, or %NULL
8361 * Returns the group for @window or the default group, if
8362 * @window is %NULL or if @window does not have an explicit
8365 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8370 gtk_window_get_group (GtkWindow *window)
8372 if (window && window->priv->group)
8373 return window->priv->group;
8376 static GtkWindowGroup *default_group = NULL;
8379 default_group = gtk_window_group_new ();
8381 return default_group;
8386 * gtk_window_has_group:
8387 * @window: a #GtkWindow
8389 * Returns whether @window has an explicit window group.
8391 * Return value: %TRUE if @window has an explicit window group.
8396 gtk_window_has_group (GtkWindow *window)
8398 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8400 return window->priv->group != NULL;
8404 * gtk_window_group_get_current_grab:
8405 * @window_group: a #GtkWindowGroup
8407 * Gets the current grab widget of the given group,
8408 * see gtk_grab_add().
8410 * Returns: (transfer none): the current grab widget of the group
8415 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8417 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8419 if (window_group->priv->grabs)
8420 return GTK_WIDGET (window_group->priv->grabs->data);
8425 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8428 GtkWindowGroupPrivate *priv;
8430 priv = window_group->priv;
8431 priv->grabs = g_slist_prepend (priv->grabs, widget);
8435 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8438 GtkWindowGroupPrivate *priv;
8440 priv = window_group->priv;
8441 priv->grabs = g_slist_remove (priv->grabs, widget);
8446 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8449 gboolean block_others)
8451 GtkWindowGroupPrivate *priv;
8452 GtkDeviceGrabInfo *info;
8454 priv = window_group->priv;
8456 info = g_slice_new0 (GtkDeviceGrabInfo);
8457 info->widget = widget;
8458 info->device = device;
8459 info->block_others = block_others;
8461 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8465 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8469 GtkWindowGroupPrivate *priv;
8470 GtkDeviceGrabInfo *info;
8471 GSList *list, *node = NULL;
8472 GdkDevice *other_device;
8474 priv = window_group->priv;
8475 other_device = gdk_device_get_associated_device (device);
8476 list = priv->device_grabs;
8482 if (info->widget == widget &&
8483 (info->device == device ||
8484 info->device == other_device))
8497 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8498 g_slice_free (GtkDeviceGrabInfo, info);
8503 * gtk_window_group_get_current_device_grab:
8504 * @window_group: a #GtkWindowGroup
8505 * @device: a #GdkDevice
8507 * Returns the current grab widget for @device, or %NULL if none.
8509 * Returns: (transfer none): The grab widget, or %NULL
8514 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8517 GtkWindowGroupPrivate *priv;
8518 GtkDeviceGrabInfo *info;
8519 GdkDevice *other_device;
8522 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8523 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8525 priv = window_group->priv;
8526 list = priv->device_grabs;
8527 other_device = gdk_device_get_associated_device (device);
8534 if (info->device == device ||
8535 info->device == other_device)
8536 return info->widget;
8543 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8547 GtkWindowGroupPrivate *priv;
8548 GtkDeviceGrabInfo *info;
8549 GdkDevice *other_device;
8552 priv = window_group->priv;
8553 other_device = gdk_device_get_associated_device (device);
8554 list = priv->device_grabs;
8561 /* Look for blocking grabs on other device pairs
8562 * that have the passed widget within the GTK+ grab.
8564 if (info->block_others &&
8565 info->device != device &&
8566 info->device != other_device &&
8567 (info->widget == widget ||
8568 gtk_widget_is_ancestor (widget, info->widget)))
8576 Derived from XParseGeometry() in XFree86
8578 Copyright 1985, 1986, 1987,1998 The Open Group
8580 All Rights Reserved.
8582 The above copyright notice and this permission notice shall be included
8583 in all copies or substantial portions of the Software.
8585 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8586 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8587 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8588 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8589 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8590 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8591 OTHER DEALINGS IN THE SOFTWARE.
8593 Except as contained in this notice, the name of The Open Group shall
8594 not be used in advertising or otherwise to promote the sale, use or
8595 other dealings in this Software without prior written authorization
8596 from The Open Group.
8601 * XParseGeometry parses strings of the form
8602 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8603 * width, height, xoffset, and yoffset are unsigned integers.
8604 * Example: "=80x24+300-49"
8605 * The equal sign is optional.
8606 * It returns a bitmask that indicates which of the four values
8607 * were actually found in the string. For each value found,
8608 * the corresponding argument is updated; for each value
8609 * not found, the corresponding argument is left unchanged.
8612 /* The following code is from Xlib, and is minimally modified, so we
8613 * can track any upstream changes if required. Don't change this
8614 * code. Or if you do, put in a huge comment marking which thing
8619 read_int (gchar *string,
8627 else if (*string == '-')
8633 for (; (*string >= '0') && (*string <= '9'); string++)
8635 result = (result * 10) + (*string - '0');
8647 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8648 * value (x, y, width, height) was found in the parsed string.
8650 #define NoValue 0x0000
8651 #define XValue 0x0001
8652 #define YValue 0x0002
8653 #define WidthValue 0x0004
8654 #define HeightValue 0x0008
8655 #define AllValues 0x000F
8656 #define XNegative 0x0010
8657 #define YNegative 0x0020
8659 /* Try not to reformat/modify, so we can compare/sync with X sources */
8661 gtk_XParseGeometry (const char *string,
8664 unsigned int *width,
8665 unsigned int *height)
8669 unsigned int tempWidth, tempHeight;
8671 char *nextCharacter;
8673 /* These initializations are just to silence gcc */
8679 if ( (string == NULL) || (*string == '\0')) return(mask);
8681 string++; /* ignore possible '=' at beg of geometry spec */
8683 strind = (char *)string;
8684 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8685 tempWidth = read_int(strind, &nextCharacter);
8686 if (strind == nextCharacter)
8688 strind = nextCharacter;
8692 if (*strind == 'x' || *strind == 'X') {
8694 tempHeight = read_int(strind, &nextCharacter);
8695 if (strind == nextCharacter)
8697 strind = nextCharacter;
8698 mask |= HeightValue;
8701 if ((*strind == '+') || (*strind == '-')) {
8702 if (*strind == '-') {
8704 tempX = -read_int(strind, &nextCharacter);
8705 if (strind == nextCharacter)
8707 strind = nextCharacter;
8713 tempX = read_int(strind, &nextCharacter);
8714 if (strind == nextCharacter)
8716 strind = nextCharacter;
8719 if ((*strind == '+') || (*strind == '-')) {
8720 if (*strind == '-') {
8722 tempY = -read_int(strind, &nextCharacter);
8723 if (strind == nextCharacter)
8725 strind = nextCharacter;
8732 tempY = read_int(strind, &nextCharacter);
8733 if (strind == nextCharacter)
8735 strind = nextCharacter;
8741 /* If strind isn't at the end of the string the it's an invalid
8742 geometry specification. */
8744 if (*strind != '\0') return (0);
8750 if (mask & WidthValue)
8752 if (mask & HeightValue)
8753 *height = tempHeight;
8758 * gtk_window_parse_geometry:
8759 * @window: a #GtkWindow
8760 * @geometry: geometry string
8762 * Parses a standard X Window System geometry string - see the
8763 * manual page for X (type 'man X') for details on this.
8764 * gtk_window_parse_geometry() does work on all GTK+ ports
8765 * including Win32 but is primarily intended for an X environment.
8767 * If either a size or a position can be extracted from the
8768 * geometry string, gtk_window_parse_geometry() returns %TRUE
8769 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8770 * to resize/move the window.
8772 * If gtk_window_parse_geometry() returns %TRUE, it will also
8773 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8774 * indicating to the window manager that the size/position of
8775 * the window was user-specified. This causes most window
8776 * managers to honor the geometry.
8778 * Note that for gtk_window_parse_geometry() to work as expected, it has
8779 * to be called when the window has its "final" size, i.e. after calling
8780 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8783 * #include <gtk/gtk.h>
8786 * fill_with_content (GtkWidget *vbox)
8788 * /* fill with content... */
8792 * main (int argc, char *argv[])
8794 * GtkWidget *window, *vbox;
8795 * GdkGeometry size_hints = {
8796 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8799 * gtk_init (&argc, &argv);
8801 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8802 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
8804 * gtk_container_add (GTK_CONTAINER (window), vbox);
8805 * fill_with_content (vbox);
8806 * gtk_widget_show_all (vbox);
8808 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8811 * GDK_HINT_MIN_SIZE |
8812 * GDK_HINT_BASE_SIZE |
8813 * GDK_HINT_RESIZE_INC);
8817 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8818 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8821 * gtk_widget_show_all (window);
8828 * Return value: %TRUE if string was parsed successfully
8831 gtk_window_parse_geometry (GtkWindow *window,
8832 const gchar *geometry)
8834 gint result, x = 0, y = 0;
8838 gboolean size_set, pos_set;
8841 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8842 g_return_val_if_fail (geometry != NULL, FALSE);
8844 child = gtk_bin_get_child (GTK_BIN (window));
8845 if (!child || !gtk_widget_get_visible (child))
8846 g_warning ("gtk_window_parse_geometry() called on a window with no "
8847 "visible children; the window should be set up before "
8848 "gtk_window_parse_geometry() is called.");
8850 screen = gtk_window_check_screen (window);
8852 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8855 if ((result & WidthValue) || (result & HeightValue))
8857 gtk_window_set_default_size_internal (window,
8858 TRUE, result & WidthValue ? w : -1,
8859 TRUE, result & HeightValue ? h : -1,
8864 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8866 grav = GDK_GRAVITY_NORTH_WEST;
8868 if ((result & XNegative) && (result & YNegative))
8869 grav = GDK_GRAVITY_SOUTH_EAST;
8870 else if (result & XNegative)
8871 grav = GDK_GRAVITY_NORTH_EAST;
8872 else if (result & YNegative)
8873 grav = GDK_GRAVITY_SOUTH_WEST;
8875 if ((result & XValue) == 0)
8878 if ((result & YValue) == 0)
8881 if (grav == GDK_GRAVITY_SOUTH_WEST ||
8882 grav == GDK_GRAVITY_SOUTH_EAST)
8883 y = gdk_screen_get_height (screen) - h + y;
8885 if (grav == GDK_GRAVITY_SOUTH_EAST ||
8886 grav == GDK_GRAVITY_NORTH_EAST)
8887 x = gdk_screen_get_width (screen) - w + x;
8889 /* we don't let you put a window offscreen; maybe some people would
8890 * prefer to be able to, but it's kind of a bogus thing to do.
8899 if ((result & XValue) || (result & YValue))
8901 gtk_window_set_gravity (window, grav);
8902 gtk_window_move (window, x, y);
8906 if (size_set || pos_set)
8908 /* Set USSize, USPosition hints */
8909 GtkWindowGeometryInfo *info;
8911 info = gtk_window_get_geometry_info (window, TRUE);
8914 info->mask |= GDK_HINT_USER_POS;
8916 info->mask |= GDK_HINT_USER_SIZE;
8923 gtk_window_mnemonic_hash_foreach (guint keyval,
8929 GtkWindowKeysForeachFunc func;
8933 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
8937 _gtk_window_keys_foreach (GtkWindow *window,
8938 GtkWindowKeysForeachFunc func,
8942 GtkMnemonicHash *mnemonic_hash;
8946 GtkWindowKeysForeachFunc func;
8950 info.window = window;
8952 info.func_data = func_data;
8954 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8956 _gtk_mnemonic_hash_foreach (mnemonic_hash,
8957 gtk_window_mnemonic_hash_foreach, &info);
8959 groups = gtk_accel_groups_from_object (G_OBJECT (window));
8962 GtkAccelGroup *group = groups->data;
8965 for (i = 0; i < group->priv->n_accels; i++)
8967 GtkAccelKey *key = &group->priv->priv_accels[i].key;
8970 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8973 groups = groups->next;
8978 gtk_window_keys_changed (GtkWindow *window)
8980 gtk_window_free_key_hash (window);
8981 gtk_window_get_key_hash (window);
8984 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8986 struct _GtkWindowKeyEntry
8990 guint is_mnemonic : 1;
8994 window_key_entry_destroy (gpointer data)
8996 g_slice_free (GtkWindowKeyEntry, data);
9000 add_to_key_hash (GtkWindow *window,
9002 GdkModifierType modifiers,
9003 gboolean is_mnemonic,
9006 GtkKeyHash *key_hash = data;
9008 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9010 entry->keyval = keyval;
9011 entry->modifiers = modifiers;
9012 entry->is_mnemonic = is_mnemonic;
9014 /* GtkAccelGroup stores lowercased accelerators. To deal
9015 * with this, if <Shift> was specified, uppercase.
9017 if (modifiers & GDK_SHIFT_MASK)
9019 if (keyval == GDK_KEY_Tab)
9020 keyval = GDK_KEY_ISO_Left_Tab;
9022 keyval = gdk_keyval_to_upper (keyval);
9025 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9029 gtk_window_get_key_hash (GtkWindow *window)
9031 GdkScreen *screen = gtk_window_check_screen (window);
9032 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9037 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9038 (GDestroyNotify)window_key_entry_destroy);
9039 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9040 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9046 gtk_window_free_key_hash (GtkWindow *window)
9048 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9051 _gtk_key_hash_free (key_hash);
9052 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9057 * gtk_window_activate_key:
9058 * @window: a #GtkWindow
9059 * @event: a #GdkEventKey
9061 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9062 * called by the default ::key_press_event handler for toplevel windows,
9063 * however in some cases it may be useful to call this directly when
9064 * overriding the standard key handling for a toplevel window.
9066 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9071 gtk_window_activate_key (GtkWindow *window,
9074 GtkKeyHash *key_hash;
9075 GtkWindowKeyEntry *found_entry = NULL;
9076 gboolean enable_mnemonics;
9077 gboolean enable_accels;
9079 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9080 g_return_val_if_fail (event != NULL, FALSE);
9082 key_hash = gtk_window_get_key_hash (window);
9087 GSList *entries = _gtk_key_hash_lookup (key_hash,
9088 event->hardware_keycode,
9090 gtk_accelerator_get_default_mod_mask (),
9093 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9094 "gtk-enable-mnemonics", &enable_mnemonics,
9095 "gtk-enable-accels", &enable_accels,
9098 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9100 GtkWindowKeyEntry *entry = tmp_list->data;
9101 if (entry->is_mnemonic)
9103 if (enable_mnemonics)
9105 found_entry = entry;
9111 if (enable_accels && !found_entry)
9113 found_entry = entry;
9118 g_slist_free (entries);
9123 if (found_entry->is_mnemonic)
9125 if (enable_mnemonics)
9126 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9127 found_entry->modifiers);
9132 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9133 found_entry->modifiers);
9141 window_update_has_focus (GtkWindow *window)
9143 GtkWindowPrivate *priv = window->priv;
9144 GtkWidget *widget = GTK_WIDGET (window);
9145 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9147 if (has_focus != priv->has_focus)
9149 priv->has_focus = has_focus;
9153 if (priv->focus_widget &&
9154 priv->focus_widget != widget &&
9155 !gtk_widget_has_focus (priv->focus_widget))
9156 do_focus_change (priv->focus_widget, TRUE);
9160 if (priv->focus_widget &&
9161 priv->focus_widget != widget &&
9162 gtk_widget_has_focus (priv->focus_widget))
9163 do_focus_change (priv->focus_widget, FALSE);
9169 * _gtk_window_set_is_active:
9170 * @window: a #GtkWindow
9171 * @is_active: %TRUE if the window is in the currently active toplevel
9173 * Internal function that sets whether the #GtkWindow is part
9174 * of the currently active toplevel window (taking into account inter-process
9178 _gtk_window_set_is_active (GtkWindow *window,
9181 GtkWindowPrivate *priv;
9183 g_return_if_fail (GTK_IS_WINDOW (window));
9185 priv = window->priv;
9187 is_active = is_active != FALSE;
9189 if (is_active != priv->is_active)
9191 priv->is_active = is_active;
9192 window_update_has_focus (window);
9194 g_object_notify (G_OBJECT (window), "is-active");
9199 * _gtk_window_set_is_toplevel:
9200 * @window: a #GtkWindow
9201 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9202 * child of the root window); %FALSE if it is not (for example, for an
9203 * in-process, parented GtkPlug)
9205 * Internal function used by #GtkPlug when it gets parented/unparented by a
9206 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9207 * global list of toplevel windows.
9210 _gtk_window_set_is_toplevel (GtkWindow *window,
9211 gboolean is_toplevel)
9214 GtkWidget *toplevel;
9216 widget = GTK_WIDGET (window);
9218 if (gtk_widget_is_toplevel (widget))
9219 g_assert (g_slist_find (toplevel_list, window) != NULL);
9221 g_assert (g_slist_find (toplevel_list, window) == NULL);
9223 if (is_toplevel == gtk_widget_is_toplevel (widget))
9228 /* Pass through regular pathways of an embedded toplevel
9229 * to go through unmapping and hiding the widget before
9230 * becomming a toplevel again.
9232 * We remain hidden after becomming toplevel in order to
9233 * avoid problems during an embedded toplevel's dispose cycle
9234 * (When a toplevel window is shown it tries to grab focus again,
9235 * this causes problems while disposing).
9237 gtk_widget_hide (widget);
9239 /* Save the toplevel this widget was previously anchored into before
9240 * propagating a hierarchy-changed.
9242 * Usually this happens by way of gtk_widget_unparent() and we are
9243 * already unanchored at this point, just adding this clause incase
9244 * things happen differently.
9246 toplevel = gtk_widget_get_toplevel (widget);
9247 if (!gtk_widget_is_toplevel (toplevel))
9250 _gtk_widget_set_is_toplevel (widget, TRUE);
9252 /* When a window becomes toplevel after being embedded and anchored
9253 * into another window we need to unset it's anchored flag so that
9254 * the hierarchy changed signal kicks in properly.
9256 _gtk_widget_set_anchored (widget, FALSE);
9257 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9259 toplevel_list = g_slist_prepend (toplevel_list, window);
9263 _gtk_widget_set_is_toplevel (widget, FALSE);
9264 toplevel_list = g_slist_remove (toplevel_list, window);
9266 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9271 * _gtk_window_set_has_toplevel_focus:
9272 * @window: a #GtkWindow
9273 * @has_toplevel_focus: %TRUE if the in
9275 * Internal function that sets whether the keyboard focus for the
9276 * toplevel window (taking into account inter-process embedding.)
9279 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9280 gboolean has_toplevel_focus)
9282 GtkWindowPrivate *priv;
9284 g_return_if_fail (GTK_IS_WINDOW (window));
9286 priv = window->priv;
9288 has_toplevel_focus = has_toplevel_focus != FALSE;
9290 if (has_toplevel_focus != priv->has_toplevel_focus)
9292 priv->has_toplevel_focus = has_toplevel_focus;
9293 window_update_has_focus (window);
9295 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9300 * gtk_window_set_auto_startup_notification:
9301 * @setting: %TRUE to automatically do startup notification
9303 * By default, after showing the first #GtkWindow, GTK+ calls
9304 * gdk_notify_startup_complete(). Call this function to disable
9305 * the automatic startup notification. You might do this if your
9306 * first window is a splash screen, and you want to delay notification
9307 * until after your real main window has been shown, for example.
9309 * In that example, you would disable startup notification
9310 * temporarily, show your splash screen, then re-enable it so that
9311 * showing the main window would automatically result in notification.
9316 gtk_window_set_auto_startup_notification (gboolean setting)
9318 disable_startup_notification = !setting;
9322 * gtk_window_get_window_type:
9323 * @window: a #GtkWindow
9325 * Gets the type of the window. See #GtkWindowType.
9327 * Return value: the type of the window
9332 gtk_window_get_window_type (GtkWindow *window)
9334 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9336 return window->priv->type;
9340 * gtk_window_get_mnemonics_visible:
9341 * @window: a #GtkWindow
9343 * Gets the value of the #GtkWindow:mnemonics-visible property.
9345 * Returns: %TRUE if mnemonics are supposed to be visible
9351 gtk_window_get_mnemonics_visible (GtkWindow *window)
9353 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9355 return window->priv->mnemonics_visible;
9359 * gtk_window_set_mnemonics_visible:
9360 * @window: a #GtkWindow
9361 * @setting: the new value
9363 * Sets the #GtkWindow:mnemonics-visible property.
9368 gtk_window_set_mnemonics_visible (GtkWindow *window,
9371 GtkWindowPrivate *priv;
9373 g_return_if_fail (GTK_IS_WINDOW (window));
9375 priv = window->priv;
9377 setting = setting != FALSE;
9379 if (priv->mnemonics_visible != setting)
9381 priv->mnemonics_visible = setting;
9382 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9385 priv->mnemonics_visible_set = TRUE;
9389 _gtk_window_get_wmclass (GtkWindow *window,
9390 gchar **wmclass_name,
9391 gchar **wmclass_class)
9393 GtkWindowPrivate *priv = window->priv;
9395 *wmclass_name = priv->wmclass_name;
9396 *wmclass_class = priv->wmclass_class;
9400 * gtk_window_set_has_user_ref_count:
9401 * @window: a #GtkWindow
9402 * @setting: the new value
9404 * Tells GTK+ whether to drop its extra reference to the window
9405 * when gtk_window_destroy() is called.
9407 * This function is only exported for the benefit of language
9408 * bindings which may need to keep the window alive until their
9409 * wrapper object is garbage collected. There is no justification
9410 * for ever calling this function in an application.
9415 gtk_window_set_has_user_ref_count (GtkWindow *window,
9418 g_return_if_fail (GTK_IS_WINDOW (window));
9420 window->priv->has_user_ref_count = setting;