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/.
33 #include "gdk/gdkkeysyms.h"
37 #include "gtkprivate.h"
39 #include "gtkwindow.h"
40 #include "gtkwindow-decorate.h"
41 #include "gtkbindings.h"
42 #include "gtkkeyhash.h"
44 #include "gtkmnemonichash.h"
45 #include "gtkmenubar.h"
46 #include "gtkiconfactory.h"
47 #include "gtkicontheme.h"
48 #include "gtkmarshalers.h"
50 #include "gtkprivate.h"
51 #include "gtkbuildable.h"
53 #ifdef GDK_WINDOWING_X11
60 * @short_description: Toplevel which can contain other widgets
62 * A GtkWindow is a toplevel window which can contain other widgets.
63 * Windows normally have decorations that are under the control
64 * of the windowing system and allow the user to manipulate the window
65 * (resize it, move it, close it,...).
67 * GTK+ also allows windows to have a resize grip (a small area in the lower
68 * right or left corner) which can be clicked to reszie the window. To
69 * control whether a window has a resize grip, use
70 * gtk_window_set_has_resize_grip().
72 * <refsect2 id="GtkWindow-BUILDER-UI">
73 * <title>GtkWindow as GtkBuildable</title>
75 * The GtkWindow implementation of the GtkBuildable interface supports a
76 * custom <tag class="starttag">accel-groups</tag> element, which supports
77 * any number of <tag class="starttag">group</tag> elements representing the
78 * #GtkAccelGroup objects you want to add to your window (synonymous with
79 * gtk_window_add_accel_group().
82 * <title>A UI definition fragment with accel groups</title>
83 * <programlisting><![CDATA[
84 * <object class="GtkWindow">
86 * <group name="accelgroup1"/>
92 * <object class="GtkAccelGroup" id="accelgroup1"/>
93 * ]]></programlisting>
98 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
99 typedef struct _GtkWindowGroupPrivate GtkWindowGroupPrivate;
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;
114 GdkWindowTypeHint gdk_type_hint;
118 gboolean has_resize_grip;
119 GdkWindow *grip_window;
123 gchar *wmclass_class;
131 guint keys_changed_handler;
133 /* Don't use this value, it's only used for determining when
134 * to fire notify events on the "resize-grip-visible" property.
136 gboolean resize_grip_visible;
138 guint16 configure_request_count;
140 /* The following flags are initially TRUE (before a window is mapped).
141 * They cause us to compute a configure request that involves
142 * default-only parameters. Once mapped, we set them to FALSE.
143 * Then we set them to TRUE again on unmap (for position)
144 * and on unrealize (for size).
146 guint need_default_position : 1;
147 guint need_default_size : 1;
149 guint above_initially : 1;
150 guint accept_focus : 1;
151 guint below_initially : 1;
152 guint builder_visible : 1;
153 guint configure_notify_received : 1;
156 guint destroy_with_parent : 1;
157 guint focus_on_map : 1;
158 guint fullscreen_initially : 1;
159 guint gravity : 5; /* GdkGravity */
161 guint has_user_ref_count : 1;
163 guint has_toplevel_focus : 1;
164 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
166 guint maximize_initially : 1;
167 guint mnemonics_visible : 1;
168 guint mnemonics_visible_set : 1;
170 guint opacity_set : 1;
172 guint reset_type_hint : 1;
174 guint skips_pager : 1;
175 guint skips_taskbar : 1;
176 guint stick_initially : 1;
177 guint transient_parent_group : 1;
178 guint type : 4; /* GtkWindowType */
179 guint type_hint : 3; /* GdkWindowTypeHint if the hint is one of the original eight. If not, then
180 * it contains GDK_WINDOW_TYPE_HINT_NORMAL */
207 PROP_DESTROY_WITH_PARENT,
212 PROP_SKIP_TASKBAR_HINT,
213 PROP_SKIP_PAGER_HINT,
222 PROP_HAS_RESIZE_GRIP,
223 PROP_RESIZE_GRIP_VISIBLE,
225 /* Readonly properties */
227 PROP_HAS_TOPLEVEL_FOCUS,
229 /* Writeonly properties */
232 PROP_MNEMONICS_VISIBLE,
242 guint using_default_icon : 1;
243 guint using_parent_icon : 1;
244 guint using_themed_icon : 1;
248 GdkGeometry geometry; /* Last set of geometry hints we set */
249 GdkWindowHints flags;
250 GdkRectangle configure_request;
251 } GtkWindowLastGeometryInfo;
253 struct _GtkWindowGeometryInfo
255 /* Properties that the app has set on the window
257 GdkGeometry geometry; /* Geometry hints */
259 GtkWidget *widget; /* subwidget to which hints apply */
260 /* from last gtk_window_resize () - if > 0, indicates that
261 * we should resize to this size.
266 /* From last gtk_window_move () prior to mapping -
267 * only used if initial_pos_set
272 /* Default size - used only the FIRST time we map a window,
277 /* whether to use initial_x, initial_y */
278 guint initial_pos_set : 1;
279 /* CENTER_ALWAYS or other position constraint changed since
280 * we sent the last configure request.
282 guint position_constraints_changed : 1;
284 /* if true, default_width, height come from gtk_window_parse_geometry,
285 * and thus should be multiplied by the increments and affect the
286 * geometry widget only
288 guint default_is_geometry : 1;
290 GtkWindowLastGeometryInfo last;
293 #define GTK_WINDOW_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW_GROUP, GtkWindowGroupPrivate))
295 struct _GtkDeviceGrabInfo
299 guint block_others : 1;
302 struct _GtkWindowGroupPrivate
304 GSList *device_grabs;
307 static void gtk_window_dispose (GObject *object);
308 static void gtk_window_finalize (GObject *object);
309 static void gtk_window_destroy (GtkWidget *widget);
310 static void gtk_window_show (GtkWidget *widget);
311 static void gtk_window_hide (GtkWidget *widget);
312 static void gtk_window_map (GtkWidget *widget);
313 static void gtk_window_unmap (GtkWidget *widget);
314 static void gtk_window_realize (GtkWidget *widget);
315 static void gtk_window_unrealize (GtkWidget *widget);
316 static void gtk_window_size_allocate (GtkWidget *widget,
317 GtkAllocation *allocation);
318 static gint gtk_window_event (GtkWidget *widget,
320 static gboolean gtk_window_map_event (GtkWidget *widget,
322 static gboolean gtk_window_frame_event (GtkWindow *window,
324 static gint gtk_window_configure_event (GtkWidget *widget,
325 GdkEventConfigure *event);
326 static gint gtk_window_key_press_event (GtkWidget *widget,
328 static gint gtk_window_key_release_event (GtkWidget *widget,
330 static gint gtk_window_button_press_event (GtkWidget *widget,
331 GdkEventButton *event);
332 static gint gtk_window_enter_notify_event (GtkWidget *widget,
333 GdkEventCrossing *event);
334 static gint gtk_window_leave_notify_event (GtkWidget *widget,
335 GdkEventCrossing *event);
336 static gint gtk_window_focus_in_event (GtkWidget *widget,
337 GdkEventFocus *event);
338 static gint gtk_window_focus_out_event (GtkWidget *widget,
339 GdkEventFocus *event);
340 static gint gtk_window_client_event (GtkWidget *widget,
341 GdkEventClient *event);
342 static gboolean gtk_window_state_event (GtkWidget *widget,
343 GdkEventWindowState *event);
344 static void gtk_window_check_resize (GtkContainer *container);
345 static gint gtk_window_focus (GtkWidget *widget,
346 GtkDirectionType direction);
347 static void gtk_window_real_set_focus (GtkWindow *window,
349 static void gtk_window_direction_changed (GtkWidget *widget,
350 GtkTextDirection prev_dir);
351 static void gtk_window_state_changed (GtkWidget *widget,
352 GtkStateType previous_state);
354 static void gtk_window_real_activate_default (GtkWindow *window);
355 static void gtk_window_real_activate_focus (GtkWindow *window);
356 static void gtk_window_move_focus (GtkWindow *window,
357 GtkDirectionType dir);
358 static void gtk_window_keys_changed (GtkWindow *window);
359 static gint gtk_window_draw (GtkWidget *widget,
361 static void gtk_window_unset_transient_for (GtkWindow *window);
362 static void gtk_window_transient_parent_realized (GtkWidget *parent,
364 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
367 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
369 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
372 static void gtk_window_move_resize (GtkWindow *window);
373 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
375 GdkGeometry *geometry_b,
377 static void gtk_window_constrain_size (GtkWindow *window,
378 GdkGeometry *geometry,
384 static void gtk_window_constrain_position (GtkWindow *window,
389 static void gtk_window_compute_hints (GtkWindow *window,
390 GdkGeometry *new_geometry,
392 static void gtk_window_compute_configure_request (GtkWindow *window,
393 GdkRectangle *request,
394 GdkGeometry *geometry,
397 static void gtk_window_set_default_size_internal (GtkWindow *window,
398 gboolean change_width,
400 gboolean change_height,
402 gboolean is_geometry);
404 static void update_themed_icon (GtkIconTheme *theme,
406 static GList *icon_list_from_theme (GtkWidget *widget,
408 static void gtk_window_realize_icon (GtkWindow *window);
409 static void gtk_window_unrealize_icon (GtkWindow *window);
410 static void resize_grip_create_window (GtkWindow *window);
411 static void resize_grip_destroy_window (GtkWindow *window);
412 static void update_grip_visibility (GtkWindow *window);
414 static void gtk_window_notify_keys_changed (GtkWindow *window);
415 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
416 static void gtk_window_free_key_hash (GtkWindow *window);
417 static void gtk_window_on_composited_changed (GdkScreen *screen,
420 static GSList *toplevel_list = NULL;
421 static guint window_signals[LAST_SIGNAL] = { 0 };
422 static GList *default_icon_list = NULL;
423 static gchar *default_icon_name = NULL;
424 static guint default_icon_serial = 0;
425 static gboolean disable_startup_notification = FALSE;
426 static gboolean sent_startup_notification = FALSE;
428 static GQuark quark_gtk_embedded = 0;
429 static GQuark quark_gtk_window_key_hash = 0;
430 static GQuark quark_gtk_window_icon_info = 0;
431 static GQuark quark_gtk_buildable_accels = 0;
433 static GtkBuildableIface *parent_buildable_iface;
435 static void gtk_window_set_property (GObject *object,
439 static void gtk_window_get_property (GObject *object,
445 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
446 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
449 const GValue *value);
450 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
451 GtkBuilder *builder);
452 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
455 const gchar *tagname,
456 GMarkupParser *parser,
458 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
461 const gchar *tagname,
465 static void gtk_window_get_preferred_width (GtkWidget *widget,
468 static void gtk_window_get_preferred_height (GtkWidget *widget,
472 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
473 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
474 gtk_window_buildable_interface_init))
477 add_tab_bindings (GtkBindingSet *binding_set,
478 GdkModifierType modifiers,
479 GtkDirectionType direction)
481 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
483 GTK_TYPE_DIRECTION_TYPE, direction);
484 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
486 GTK_TYPE_DIRECTION_TYPE, direction);
490 add_arrow_bindings (GtkBindingSet *binding_set,
492 GtkDirectionType direction)
494 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
496 gtk_binding_entry_add_signal (binding_set, keysym, 0,
498 GTK_TYPE_DIRECTION_TYPE, direction);
499 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
501 GTK_TYPE_DIRECTION_TYPE, direction);
502 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
504 GTK_TYPE_DIRECTION_TYPE, direction);
505 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
507 GTK_TYPE_DIRECTION_TYPE, direction);
511 extract_time_from_startup_id (const gchar* startup_id)
513 gchar *timestr = g_strrstr (startup_id, "_TIME");
514 guint32 retval = GDK_CURRENT_TIME;
521 /* Skip past the "_TIME" part */
525 timestamp = strtoul (timestr, &end, 0);
526 if (end != timestr && errno == 0)
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->draw = gtk_window_draw;
581 widget_class->get_preferred_width = gtk_window_get_preferred_width;
582 widget_class->get_preferred_height = gtk_window_get_preferred_height;
583 widget_class->window_state_event = gtk_window_state_event;
584 widget_class->direction_changed = gtk_window_direction_changed;
585 widget_class->state_changed = gtk_window_state_changed;
587 container_class->check_resize = gtk_window_check_resize;
589 klass->set_focus = gtk_window_real_set_focus;
590 klass->frame_event = gtk_window_frame_event;
592 klass->activate_default = gtk_window_real_activate_default;
593 klass->activate_focus = gtk_window_real_activate_focus;
594 klass->move_focus = gtk_window_move_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));
934 gtk_widget_class_install_style_property (widget_class,
935 g_param_spec_int ("resize-grip-width",
936 P_("Width of resize grip"),
937 P_("Width of resize grip"),
938 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
940 gtk_widget_class_install_style_property (widget_class,
941 g_param_spec_int ("resize-grip-height",
942 P_("Height of resize grip"),
943 P_("Height of resize grip"),
944 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
949 window_signals[SET_FOCUS] =
950 g_signal_new (I_("set-focus"),
951 G_TYPE_FROM_CLASS (gobject_class),
953 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
955 _gtk_marshal_VOID__OBJECT,
959 window_signals[FRAME_EVENT] =
960 g_signal_new (I_("frame-event"),
961 G_TYPE_FROM_CLASS (gobject_class),
963 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
964 _gtk_boolean_handled_accumulator, NULL,
965 _gtk_marshal_BOOLEAN__BOXED,
970 * GtkWindow::activate-focus:
971 * @window: the window which received the signal
973 * The ::activate-focus signal is a
974 * <link linkend="keybinding-signals">keybinding signal</link>
975 * which gets emitted when the user activates the currently
976 * focused widget of @window.
978 window_signals[ACTIVATE_FOCUS] =
979 g_signal_new (I_("activate-focus"),
980 G_TYPE_FROM_CLASS (gobject_class),
981 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
982 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
984 _gtk_marshal_VOID__VOID,
989 * GtkWindow::activate-default:
990 * @window: the window which received the signal
992 * The ::activate-default signal is a
993 * <link linkend="keybinding-signals">keybinding signal</link>
994 * which gets emitted when the user activates the default widget
997 window_signals[ACTIVATE_DEFAULT] =
998 g_signal_new (I_("activate-default"),
999 G_TYPE_FROM_CLASS (gobject_class),
1000 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1001 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1003 _gtk_marshal_VOID__VOID,
1008 * GtkWindow::keys-changed:
1009 * @window: the window which received the signal
1011 * The ::keys-changed signal gets emitted when the set of accelerators
1012 * or mnemonics that are associated with @window changes.
1014 window_signals[KEYS_CHANGED] =
1015 g_signal_new (I_("keys-changed"),
1016 G_TYPE_FROM_CLASS (gobject_class),
1018 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1020 _gtk_marshal_VOID__VOID,
1028 binding_set = gtk_binding_set_by_class (klass);
1030 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1031 "activate-focus", 0);
1032 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1033 "activate-focus", 0);
1035 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1036 "activate-default", 0);
1037 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1038 "activate-default", 0);
1039 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1040 "activate-default", 0);
1042 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1043 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1044 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1045 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1047 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1048 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1049 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1050 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1054 gtk_window_init (GtkWindow *window)
1056 GtkWindowPrivate *priv;
1058 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1061 priv = window->priv;
1063 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1064 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1066 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1068 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1071 priv->wmclass_name = g_strdup (g_get_prgname ());
1072 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1073 priv->wm_role = NULL;
1074 priv->geometry_info = NULL;
1075 priv->type = GTK_WINDOW_TOPLEVEL;
1076 priv->focus_widget = NULL;
1077 priv->default_widget = NULL;
1078 priv->configure_request_count = 0;
1079 priv->resizable = TRUE;
1080 priv->configure_notify_received = FALSE;
1081 priv->position = GTK_WIN_POS_NONE;
1082 priv->need_default_size = TRUE;
1083 priv->need_default_position = TRUE;
1084 priv->modal = FALSE;
1086 priv->has_frame = FALSE;
1087 priv->frame_left = 0;
1088 priv->frame_right = 0;
1089 priv->frame_top = 0;
1090 priv->frame_bottom = 0;
1091 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1092 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1093 priv->decorated = TRUE;
1094 priv->mnemonic_modifier = GDK_MOD1_MASK;
1095 priv->screen = gdk_screen_get_default ();
1097 priv->accept_focus = TRUE;
1098 priv->focus_on_map = TRUE;
1099 priv->deletable = TRUE;
1100 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1101 priv->opacity = 1.0;
1102 priv->startup_id = NULL;
1103 priv->has_resize_grip = TRUE;
1104 priv->mnemonics_visible = TRUE;
1106 g_object_ref_sink (window);
1107 priv->has_user_ref_count = TRUE;
1108 toplevel_list = g_slist_prepend (toplevel_list, window);
1110 gtk_decorated_window_init (window);
1112 g_signal_connect (priv->screen, "composited-changed",
1113 G_CALLBACK (gtk_window_on_composited_changed), window);
1117 gtk_window_set_property (GObject *object,
1119 const GValue *value,
1122 GtkWindow *window = GTK_WINDOW (object);
1123 GtkWindowPrivate *priv = window->priv;
1128 priv->type = g_value_get_enum (value);
1131 gtk_window_set_title (window, g_value_get_string (value));
1134 gtk_window_set_role (window, g_value_get_string (value));
1136 case PROP_STARTUP_ID:
1137 gtk_window_set_startup_id (window, g_value_get_string (value));
1139 case PROP_RESIZABLE:
1140 gtk_window_set_resizable (window, g_value_get_boolean (value));
1143 gtk_window_set_modal (window, g_value_get_boolean (value));
1146 gtk_window_set_position (window, g_value_get_enum (value));
1148 case PROP_DEFAULT_WIDTH:
1149 gtk_window_set_default_size_internal (window,
1150 TRUE, g_value_get_int (value),
1153 case PROP_DEFAULT_HEIGHT:
1154 gtk_window_set_default_size_internal (window,
1156 TRUE, g_value_get_int (value), FALSE);
1158 case PROP_DESTROY_WITH_PARENT:
1159 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1162 gtk_window_set_icon (window,
1163 g_value_get_object (value));
1165 case PROP_ICON_NAME:
1166 gtk_window_set_icon_name (window, g_value_get_string (value));
1169 gtk_window_set_screen (window, g_value_get_object (value));
1171 case PROP_TYPE_HINT:
1172 gtk_window_set_type_hint (window,
1173 g_value_get_enum (value));
1175 case PROP_SKIP_TASKBAR_HINT:
1176 gtk_window_set_skip_taskbar_hint (window,
1177 g_value_get_boolean (value));
1179 case PROP_SKIP_PAGER_HINT:
1180 gtk_window_set_skip_pager_hint (window,
1181 g_value_get_boolean (value));
1183 case PROP_URGENCY_HINT:
1184 gtk_window_set_urgency_hint (window,
1185 g_value_get_boolean (value));
1187 case PROP_ACCEPT_FOCUS:
1188 gtk_window_set_accept_focus (window,
1189 g_value_get_boolean (value));
1191 case PROP_FOCUS_ON_MAP:
1192 gtk_window_set_focus_on_map (window,
1193 g_value_get_boolean (value));
1195 case PROP_DECORATED:
1196 gtk_window_set_decorated (window, g_value_get_boolean (value));
1198 case PROP_DELETABLE:
1199 gtk_window_set_deletable (window, g_value_get_boolean (value));
1202 gtk_window_set_gravity (window, g_value_get_enum (value));
1204 case PROP_TRANSIENT_FOR:
1205 gtk_window_set_transient_for (window, g_value_get_object (value));
1208 gtk_window_set_opacity (window, g_value_get_double (value));
1210 case PROP_HAS_RESIZE_GRIP:
1211 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1213 case PROP_MNEMONICS_VISIBLE:
1214 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1217 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1223 gtk_window_get_property (GObject *object,
1228 GtkWindow *window = GTK_WINDOW (object);
1229 GtkWindowPrivate *priv = window->priv;
1233 GtkWindowGeometryInfo *info;
1235 g_value_set_enum (value, priv->type);
1238 g_value_set_string (value, priv->wm_role);
1241 g_value_set_string (value, priv->title);
1243 case PROP_RESIZABLE:
1244 g_value_set_boolean (value, priv->resizable);
1247 g_value_set_boolean (value, priv->modal);
1250 g_value_set_enum (value, priv->position);
1252 case PROP_DEFAULT_WIDTH:
1253 info = gtk_window_get_geometry_info (window, FALSE);
1255 g_value_set_int (value, -1);
1257 g_value_set_int (value, info->default_width);
1259 case PROP_DEFAULT_HEIGHT:
1260 info = gtk_window_get_geometry_info (window, FALSE);
1262 g_value_set_int (value, -1);
1264 g_value_set_int (value, info->default_height);
1266 case PROP_DESTROY_WITH_PARENT:
1267 g_value_set_boolean (value, priv->destroy_with_parent);
1270 g_value_set_object (value, gtk_window_get_icon (window));
1272 case PROP_ICON_NAME:
1273 g_value_set_string (value, gtk_window_get_icon_name (window));
1276 g_value_set_object (value, priv->screen);
1278 case PROP_IS_ACTIVE:
1279 g_value_set_boolean (value, priv->is_active);
1281 case PROP_HAS_TOPLEVEL_FOCUS:
1282 g_value_set_boolean (value, priv->has_toplevel_focus);
1284 case PROP_TYPE_HINT:
1285 g_value_set_enum (value, priv->type_hint);
1287 case PROP_SKIP_TASKBAR_HINT:
1288 g_value_set_boolean (value,
1289 gtk_window_get_skip_taskbar_hint (window));
1291 case PROP_SKIP_PAGER_HINT:
1292 g_value_set_boolean (value,
1293 gtk_window_get_skip_pager_hint (window));
1295 case PROP_URGENCY_HINT:
1296 g_value_set_boolean (value,
1297 gtk_window_get_urgency_hint (window));
1299 case PROP_ACCEPT_FOCUS:
1300 g_value_set_boolean (value,
1301 gtk_window_get_accept_focus (window));
1303 case PROP_FOCUS_ON_MAP:
1304 g_value_set_boolean (value,
1305 gtk_window_get_focus_on_map (window));
1307 case PROP_DECORATED:
1308 g_value_set_boolean (value, gtk_window_get_decorated (window));
1310 case PROP_DELETABLE:
1311 g_value_set_boolean (value, gtk_window_get_deletable (window));
1314 g_value_set_enum (value, gtk_window_get_gravity (window));
1316 case PROP_TRANSIENT_FOR:
1317 g_value_set_object (value, gtk_window_get_transient_for (window));
1320 g_value_set_double (value, gtk_window_get_opacity (window));
1322 case PROP_HAS_RESIZE_GRIP:
1323 g_value_set_boolean (value, priv->has_resize_grip);
1325 case PROP_RESIZE_GRIP_VISIBLE:
1326 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1328 case PROP_MNEMONICS_VISIBLE:
1329 g_value_set_boolean (value, priv->mnemonics_visible);
1332 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1338 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1340 parent_buildable_iface = g_type_interface_peek_parent (iface);
1341 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1342 iface->parser_finished = gtk_window_buildable_parser_finished;
1343 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1344 iface->custom_finished = gtk_window_buildable_custom_finished;
1348 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1349 GtkBuilder *builder,
1351 const GValue *value)
1353 GtkWindow *window = GTK_WINDOW (buildable);
1354 GtkWindowPrivate *priv = window->priv;
1356 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1357 priv->builder_visible = TRUE;
1359 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1363 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1364 GtkBuilder *builder)
1366 GtkWindow *window = GTK_WINDOW (buildable);
1367 GtkWindowPrivate *priv = window->priv;
1371 if (priv->builder_visible)
1372 gtk_widget_show (GTK_WIDGET (buildable));
1374 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1375 for (l = accels; l; l = l->next)
1377 object = gtk_builder_get_object (builder, l->data);
1380 g_warning ("Unknown accel group %s specified in window %s",
1381 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1384 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1385 GTK_ACCEL_GROUP (object));
1389 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1391 parent_buildable_iface->parser_finished (buildable, builder);
1397 } GSListSubParserData;
1400 window_start_element (GMarkupParseContext *context,
1401 const gchar *element_name,
1402 const gchar **names,
1403 const gchar **values,
1408 GSListSubParserData *data = (GSListSubParserData*)user_data;
1410 if (strcmp (element_name, "group") == 0)
1412 for (i = 0; names[i]; i++)
1414 if (strcmp (names[i], "name") == 0)
1415 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1418 else if (strcmp (element_name, "accel-groups") == 0)
1421 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1426 static const GMarkupParser window_parser =
1428 window_start_element
1432 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1433 GtkBuilder *builder,
1435 const gchar *tagname,
1436 GMarkupParser *parser,
1439 GSListSubParserData *parser_data;
1441 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1442 tagname, parser, data))
1445 if (strcmp (tagname, "accel-groups") == 0)
1447 parser_data = g_slice_new0 (GSListSubParserData);
1448 parser_data->items = NULL;
1449 parser_data->object = G_OBJECT (buildable);
1451 *parser = window_parser;
1452 *data = parser_data;
1460 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1461 GtkBuilder *builder,
1463 const gchar *tagname,
1466 GSListSubParserData *data;
1468 parent_buildable_iface->custom_finished (buildable, builder, child,
1469 tagname, user_data);
1471 if (strcmp (tagname, "accel-groups") != 0)
1474 data = (GSListSubParserData*)user_data;
1476 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1477 data->items, (GDestroyNotify) g_slist_free);
1479 g_slice_free (GSListSubParserData, data);
1484 * @type: type of window
1486 * Creates a new #GtkWindow, which is a toplevel window that can
1487 * contain other widgets. Nearly always, the type of the window should
1488 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1489 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1490 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1491 * dialogs, though in some other toolkits dialogs are called "popups".
1492 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1493 * On X11, popup windows are not controlled by the <link
1494 * linkend="gtk-X11-arch">window manager</link>.
1496 * If you simply want an undecorated window (no window borders), use
1497 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1499 * Return value: a new #GtkWindow.
1502 gtk_window_new (GtkWindowType type)
1504 GtkWindowPrivate *priv;
1507 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1509 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1510 priv = window->priv;
1514 return GTK_WIDGET (window);
1518 * gtk_window_set_title:
1519 * @window: a #GtkWindow
1520 * @title: title of the window
1522 * Sets the title of the #GtkWindow. The title of a window will be
1523 * displayed in its title bar; on the X Window System, the title bar
1524 * is rendered by the <link linkend="gtk-X11-arch">window
1525 * manager</link>, so exactly how the title appears to users may vary
1526 * according to a user's exact configuration. The title should help a
1527 * user distinguish this window from other windows they may have
1528 * open. A good title might include the application name and current
1529 * document filename, for example.
1533 gtk_window_set_title (GtkWindow *window,
1536 GtkWindowPrivate *priv;
1540 g_return_if_fail (GTK_IS_WINDOW (window));
1542 priv = window->priv;
1543 widget = GTK_WIDGET (window);
1545 new_title = g_strdup (title);
1546 g_free (priv->title);
1547 priv->title = new_title;
1549 if (gtk_widget_get_realized (widget))
1551 gdk_window_set_title (gtk_widget_get_window (widget),
1554 gtk_decorated_window_set_title (window, title);
1557 g_object_notify (G_OBJECT (window), "title");
1561 * gtk_window_get_title:
1562 * @window: a #GtkWindow
1564 * Retrieves the title of the window. See gtk_window_set_title().
1566 * Return value: the title of the window, or %NULL if none has
1567 * been set explicitely. The returned string is owned by the widget
1568 * and must not be modified or freed.
1570 G_CONST_RETURN gchar *
1571 gtk_window_get_title (GtkWindow *window)
1573 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1575 return window->priv->title;
1579 * gtk_window_set_wmclass:
1580 * @window: a #GtkWindow
1581 * @wmclass_name: window name hint
1582 * @wmclass_class: window class hint
1584 * Don't use this function. It sets the X Window System "class" and
1585 * "name" hints for a window. According to the ICCCM, you should
1586 * always set these to the same value for all windows in an
1587 * application, and GTK+ sets them to that value by default, so calling
1588 * this function is sort of pointless. However, you may want to call
1589 * gtk_window_set_role() on each window in your application, for the
1590 * benefit of the session manager. Setting the role allows the window
1591 * manager to restore window positions when loading a saved session.
1595 gtk_window_set_wmclass (GtkWindow *window,
1596 const gchar *wmclass_name,
1597 const gchar *wmclass_class)
1599 GtkWindowPrivate *priv;
1601 g_return_if_fail (GTK_IS_WINDOW (window));
1603 priv = window->priv;
1605 g_free (priv->wmclass_name);
1606 priv->wmclass_name = g_strdup (wmclass_name);
1608 g_free (priv->wmclass_class);
1609 priv->wmclass_class = g_strdup (wmclass_class);
1611 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1612 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1616 * gtk_window_set_role:
1617 * @window: a #GtkWindow
1618 * @role: unique identifier for the window to be used when restoring a session
1620 * This function is only useful on X11, not with other GTK+ targets.
1622 * In combination with the window title, the window role allows a
1623 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1624 * same" window when an application is restarted. So for example you
1625 * might set the "toolbox" role on your app's toolbox window, so that
1626 * when the user restarts their session, the window manager can put
1627 * the toolbox back in the same place.
1629 * If a window already has a unique title, you don't need to set the
1630 * role, since the WM can use the title to identify the window when
1631 * restoring the session.
1635 gtk_window_set_role (GtkWindow *window,
1638 GtkWindowPrivate *priv;
1641 g_return_if_fail (GTK_IS_WINDOW (window));
1643 priv = window->priv;
1645 new_role = g_strdup (role);
1646 g_free (priv->wm_role);
1647 priv->wm_role = new_role;
1649 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1650 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1653 g_object_notify (G_OBJECT (window), "role");
1657 * gtk_window_set_startup_id:
1658 * @window: a #GtkWindow
1659 * @startup_id: a string with startup-notification identifier
1661 * Startup notification identifiers are used by desktop environment to
1662 * track application startup, to provide user feedback and other
1663 * features. This function changes the corresponding property on the
1664 * underlying GdkWindow. Normally, startup identifier is managed
1665 * automatically and you should only use this function in special cases
1666 * like transferring focus from other processes. You should use this
1667 * function before calling gtk_window_present() or any equivalent
1668 * function generating a window map event.
1670 * This function is only useful on X11, not with other GTK+ targets.
1675 gtk_window_set_startup_id (GtkWindow *window,
1676 const gchar *startup_id)
1678 GtkWindowPrivate *priv;
1681 g_return_if_fail (GTK_IS_WINDOW (window));
1683 priv = window->priv;
1684 widget = GTK_WIDGET (window);
1686 g_free (priv->startup_id);
1687 priv->startup_id = g_strdup (startup_id);
1689 if (gtk_widget_get_realized (widget))
1691 GdkWindow *gdk_window;
1692 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1694 gdk_window = gtk_widget_get_window (widget);
1696 #ifdef GDK_WINDOWING_X11
1697 if (timestamp != GDK_CURRENT_TIME)
1698 gdk_x11_window_set_user_time (gdk_window, timestamp);
1701 /* Here we differentiate real and "fake" startup notification IDs,
1702 * constructed on purpose just to pass interaction timestamp
1704 if (startup_id_is_fake (priv->startup_id))
1705 gtk_window_present_with_time (window, timestamp);
1708 gdk_window_set_startup_id (gdk_window,
1711 /* If window is mapped, terminate the startup-notification too */
1712 if (gtk_widget_get_mapped (widget) &&
1713 !disable_startup_notification)
1714 gdk_notify_startup_complete_with_id (priv->startup_id);
1718 g_object_notify (G_OBJECT (window), "startup-id");
1722 * gtk_window_get_role:
1723 * @window: a #GtkWindow
1725 * Returns the role of the window. See gtk_window_set_role() for
1726 * further explanation.
1728 * Return value: the role of the window if set, or %NULL. The
1729 * returned is owned by the widget and must not be modified
1732 G_CONST_RETURN gchar *
1733 gtk_window_get_role (GtkWindow *window)
1735 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1737 return window->priv->wm_role;
1741 * gtk_window_set_focus:
1742 * @window: a #GtkWindow
1743 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1744 * any focus widget for the toplevel window.
1746 * If @focus is not the current focus widget, and is focusable, sets
1747 * it as the focus widget for the window. If @focus is %NULL, unsets
1748 * the focus widget for this window. To set the focus to a particular
1749 * widget in the toplevel, it is usually more convenient to use
1750 * gtk_widget_grab_focus() instead of this function.
1753 gtk_window_set_focus (GtkWindow *window,
1756 GtkWindowPrivate *priv;
1759 g_return_if_fail (GTK_IS_WINDOW (window));
1761 priv = window->priv;
1765 g_return_if_fail (GTK_IS_WIDGET (focus));
1766 g_return_if_fail (gtk_widget_get_can_focus (focus));
1770 gtk_widget_grab_focus (focus);
1773 /* Clear the existing focus chain, so that when we focus into
1774 * the window again, we start at the beginnning.
1776 GtkWidget *widget = priv->focus_widget;
1779 while ((parent = gtk_widget_get_parent (widget)))
1782 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1786 _gtk_window_internal_set_focus (window, NULL);
1791 _gtk_window_internal_set_focus (GtkWindow *window,
1794 GtkWindowPrivate *priv;
1796 g_return_if_fail (GTK_IS_WINDOW (window));
1798 priv = window->priv;
1800 if ((priv->focus_widget != focus) ||
1801 (focus && !gtk_widget_has_focus (focus)))
1802 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1806 * gtk_window_set_default:
1807 * @window: a #GtkWindow
1808 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1809 * default widget for the toplevel.
1811 * The default widget is the widget that's activated when the user
1812 * presses Enter in a dialog (for example). This function sets or
1813 * unsets the default widget for a #GtkWindow about. When setting
1814 * (rather than unsetting) the default widget it's generally easier to
1815 * call gtk_widget_grab_focus() on the widget. Before making a widget
1816 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1817 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1820 gtk_window_set_default (GtkWindow *window,
1821 GtkWidget *default_widget)
1823 GtkWindowPrivate *priv;
1825 g_return_if_fail (GTK_IS_WINDOW (window));
1827 priv = window->priv;
1830 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1832 if (priv->default_widget != default_widget)
1834 GtkWidget *old_default_widget = NULL;
1837 g_object_ref (default_widget);
1839 if (priv->default_widget)
1841 old_default_widget = priv->default_widget;
1843 if (priv->focus_widget != priv->default_widget ||
1844 !gtk_widget_get_receives_default (priv->default_widget))
1845 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1847 gtk_widget_queue_draw (priv->default_widget);
1850 priv->default_widget = default_widget;
1852 if (priv->default_widget)
1854 if (priv->focus_widget == NULL ||
1855 !gtk_widget_get_receives_default (priv->focus_widget))
1856 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1858 gtk_widget_queue_draw (priv->default_widget);
1861 if (old_default_widget)
1862 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1866 g_object_notify (G_OBJECT (default_widget), "has-default");
1867 g_object_unref (default_widget);
1873 * gtk_window_get_default_widget:
1874 * @window: a #GtkWindow
1876 * Returns the default widget for @window. See gtk_window_set_default()
1879 * Returns: (transfer none): the default widget, or %NULL if there is none.
1884 gtk_window_get_default_widget (GtkWindow *window)
1886 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1888 return window->priv->default_widget;
1892 handle_keys_changed (gpointer data)
1894 GtkWindow *window = GTK_WINDOW (data);
1895 GtkWindowPrivate *priv = window->priv;
1897 if (priv->keys_changed_handler)
1899 g_source_remove (priv->keys_changed_handler);
1900 priv->keys_changed_handler = 0;
1903 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1909 gtk_window_notify_keys_changed (GtkWindow *window)
1911 GtkWindowPrivate *priv = window->priv;
1913 if (!priv->keys_changed_handler)
1914 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1918 * gtk_window_add_accel_group:
1919 * @window: window to attach accelerator group to
1920 * @accel_group: a #GtkAccelGroup
1922 * Associate @accel_group with @window, such that calling
1923 * gtk_accel_groups_activate() on @window will activate accelerators
1927 gtk_window_add_accel_group (GtkWindow *window,
1928 GtkAccelGroup *accel_group)
1930 g_return_if_fail (GTK_IS_WINDOW (window));
1931 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1933 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1934 g_signal_connect_object (accel_group, "accel-changed",
1935 G_CALLBACK (gtk_window_notify_keys_changed),
1936 window, G_CONNECT_SWAPPED);
1937 gtk_window_notify_keys_changed (window);
1941 * gtk_window_remove_accel_group:
1942 * @window: a #GtkWindow
1943 * @accel_group: a #GtkAccelGroup
1945 * Reverses the effects of gtk_window_add_accel_group().
1948 gtk_window_remove_accel_group (GtkWindow *window,
1949 GtkAccelGroup *accel_group)
1951 g_return_if_fail (GTK_IS_WINDOW (window));
1952 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1954 g_signal_handlers_disconnect_by_func (accel_group,
1955 gtk_window_notify_keys_changed,
1957 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1958 gtk_window_notify_keys_changed (window);
1961 static GtkMnemonicHash *
1962 gtk_window_get_mnemonic_hash (GtkWindow *window,
1965 GtkWindowPrivate *private = window->priv;
1967 if (!private->mnemonic_hash && create)
1968 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1970 return private->mnemonic_hash;
1974 * gtk_window_add_mnemonic:
1975 * @window: a #GtkWindow
1976 * @keyval: the mnemonic
1977 * @target: the widget that gets activated by the mnemonic
1979 * Adds a mnemonic to this window.
1982 gtk_window_add_mnemonic (GtkWindow *window,
1986 g_return_if_fail (GTK_IS_WINDOW (window));
1987 g_return_if_fail (GTK_IS_WIDGET (target));
1989 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1991 gtk_window_notify_keys_changed (window);
1995 * gtk_window_remove_mnemonic:
1996 * @window: a #GtkWindow
1997 * @keyval: the mnemonic
1998 * @target: the widget that gets activated by the mnemonic
2000 * Removes a mnemonic from this window.
2003 gtk_window_remove_mnemonic (GtkWindow *window,
2007 g_return_if_fail (GTK_IS_WINDOW (window));
2008 g_return_if_fail (GTK_IS_WIDGET (target));
2010 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2012 gtk_window_notify_keys_changed (window);
2016 * gtk_window_mnemonic_activate:
2017 * @window: a #GtkWindow
2018 * @keyval: the mnemonic
2019 * @modifier: the modifiers
2020 * @returns: %TRUE if the activation is done.
2022 * Activates the targets associated with the mnemonic.
2025 gtk_window_mnemonic_activate (GtkWindow *window,
2027 GdkModifierType modifier)
2029 GtkWindowPrivate *priv;
2031 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2033 priv = window->priv;
2035 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2037 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2039 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2046 * gtk_window_set_mnemonic_modifier:
2047 * @window: a #GtkWindow
2048 * @modifier: the modifier mask used to activate
2049 * mnemonics on this window.
2051 * Sets the mnemonic modifier for this window.
2054 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2055 GdkModifierType modifier)
2057 GtkWindowPrivate *priv;
2059 g_return_if_fail (GTK_IS_WINDOW (window));
2060 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2062 priv = window->priv;
2064 priv->mnemonic_modifier = modifier;
2065 gtk_window_notify_keys_changed (window);
2069 * gtk_window_get_mnemonic_modifier:
2070 * @window: a #GtkWindow
2072 * Returns the mnemonic modifier for this window. See
2073 * gtk_window_set_mnemonic_modifier().
2075 * Return value: the modifier mask used to activate
2076 * mnemonics on this window.
2079 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2081 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2083 return window->priv->mnemonic_modifier;
2087 * gtk_window_set_position:
2088 * @window: a #GtkWindow.
2089 * @position: a position constraint.
2091 * Sets a position constraint for this window. If the old or new
2092 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2093 * the window to be repositioned to satisfy the new constraint.
2096 gtk_window_set_position (GtkWindow *window,
2097 GtkWindowPosition position)
2099 GtkWindowPrivate *priv;
2101 g_return_if_fail (GTK_IS_WINDOW (window));
2103 priv = window->priv;
2105 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2106 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2108 GtkWindowGeometryInfo *info;
2110 info = gtk_window_get_geometry_info (window, TRUE);
2112 /* this flag causes us to re-request the CENTER_ALWAYS
2113 * constraint in gtk_window_move_resize(), see
2114 * comment in that function.
2116 info->position_constraints_changed = TRUE;
2118 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2121 priv->position = position;
2123 g_object_notify (G_OBJECT (window), "window-position");
2127 * gtk_window_activate_focus:
2128 * @window: a #GtkWindow
2130 * Activates the current focused widget within the window.
2132 * Return value: %TRUE if a widget got activated.
2135 gtk_window_activate_focus (GtkWindow *window)
2137 GtkWindowPrivate *priv;
2139 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2141 priv = window->priv;
2143 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2144 return gtk_widget_activate (priv->focus_widget);
2150 * gtk_window_get_focus:
2151 * @window: a #GtkWindow
2153 * Retrieves the current focused widget within the window.
2154 * Note that this is the widget that would have the focus
2155 * if the toplevel window focused; if the toplevel window
2156 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2157 * not be %TRUE for the widget.
2159 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2162 gtk_window_get_focus (GtkWindow *window)
2164 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2166 return window->priv->focus_widget;
2170 * gtk_window_activate_default:
2171 * @window: a #GtkWindow
2173 * Activates the default widget for the window, unless the current
2174 * focused widget has been configured to receive the default action
2175 * (see gtk_widget_set_receives_default()), in which case the
2176 * focused widget is activated.
2178 * Return value: %TRUE if a widget got activated.
2181 gtk_window_activate_default (GtkWindow *window)
2183 GtkWindowPrivate *priv;
2185 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2187 priv = window->priv;
2189 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2190 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2191 return gtk_widget_activate (priv->default_widget);
2192 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2193 return gtk_widget_activate (priv->focus_widget);
2199 * gtk_window_set_modal:
2200 * @window: a #GtkWindow
2201 * @modal: whether the window is modal
2203 * Sets a window modal or non-modal. Modal windows prevent interaction
2204 * with other windows in the same application. To keep modal dialogs
2205 * on top of main application windows, use
2206 * gtk_window_set_transient_for() to make the dialog transient for the
2207 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2208 * will then disallow lowering the dialog below the parent.
2213 gtk_window_set_modal (GtkWindow *window,
2216 GtkWindowPrivate *priv;
2219 g_return_if_fail (GTK_IS_WINDOW (window));
2221 priv = window->priv;
2223 modal = modal != FALSE;
2224 if (priv->modal == modal)
2227 priv->modal = modal;
2228 widget = GTK_WIDGET (window);
2230 /* adjust desired modality state */
2231 if (gtk_widget_get_realized (widget))
2234 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2236 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2239 if (gtk_widget_get_visible (widget))
2242 gtk_grab_add (widget);
2244 gtk_grab_remove (widget);
2247 g_object_notify (G_OBJECT (window), "modal");
2251 * gtk_window_get_modal:
2252 * @window: a #GtkWindow
2254 * Returns whether the window is modal. See gtk_window_set_modal().
2256 * Return value: %TRUE if the window is set to be modal and
2257 * establishes a grab when shown
2260 gtk_window_get_modal (GtkWindow *window)
2262 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2264 return window->priv->modal;
2268 * gtk_window_list_toplevels:
2270 * Returns a list of all existing toplevel windows. The widgets
2271 * in the list are not individually referenced. If you want
2272 * to iterate through the list and perform actions involving
2273 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2274 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2275 * then unref all the widgets afterwards.
2277 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2280 gtk_window_list_toplevels (void)
2285 for (slist = toplevel_list; slist; slist = slist->next)
2286 list = g_list_prepend (list, slist->data);
2292 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2294 GList *embedded_windows;
2296 g_return_if_fail (GTK_IS_WINDOW (window));
2298 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2299 if (embedded_windows)
2300 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2301 embedded_windows = g_list_prepend (embedded_windows,
2302 GUINT_TO_POINTER (xid));
2304 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2307 (GDestroyNotify) g_list_free : NULL);
2311 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2313 GList *embedded_windows;
2316 g_return_if_fail (GTK_IS_WINDOW (window));
2318 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2319 if (embedded_windows)
2320 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2322 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2325 embedded_windows = g_list_remove_link (embedded_windows, node);
2326 g_list_free_1 (node);
2329 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2332 (GDestroyNotify) g_list_free : NULL);
2336 gtk_window_dispose (GObject *object)
2338 GtkWindow *window = GTK_WINDOW (object);
2340 gtk_window_set_focus (window, NULL);
2341 gtk_window_set_default (window, NULL);
2343 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2347 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2349 gtk_widget_destroy (GTK_WIDGET (child));
2353 connect_parent_destroyed (GtkWindow *window)
2355 GtkWindowPrivate *priv = window->priv;
2357 if (priv->transient_parent)
2359 g_signal_connect (priv->transient_parent,
2361 G_CALLBACK (parent_destroyed_callback),
2367 disconnect_parent_destroyed (GtkWindow *window)
2369 GtkWindowPrivate *priv = window->priv;
2371 if (priv->transient_parent)
2373 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2374 parent_destroyed_callback,
2380 gtk_window_transient_parent_realized (GtkWidget *parent,
2383 if (gtk_widget_get_realized (window))
2384 gdk_window_set_transient_for (gtk_widget_get_window (window),
2385 gtk_widget_get_window (parent));
2389 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2392 if (gtk_widget_get_realized (window))
2393 gdk_property_delete (gtk_widget_get_window (window),
2394 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2398 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2402 gtk_window_set_screen (window, parent->priv->screen);
2406 gtk_window_unset_transient_for (GtkWindow *window)
2408 GtkWindowPrivate *priv = window->priv;
2410 if (priv->transient_parent)
2412 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2413 gtk_window_transient_parent_realized,
2415 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2416 gtk_window_transient_parent_unrealized,
2418 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2419 gtk_window_transient_parent_screen_changed,
2421 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2422 gtk_widget_destroyed,
2423 &priv->transient_parent);
2425 if (priv->destroy_with_parent)
2426 disconnect_parent_destroyed (window);
2428 priv->transient_parent = NULL;
2430 if (priv->transient_parent_group)
2432 priv->transient_parent_group = FALSE;
2433 gtk_window_group_remove_window (priv->group,
2440 * gtk_window_set_transient_for:
2441 * @window: a #GtkWindow
2442 * @parent: (allow-none): parent window, or %NULL
2444 * Dialog windows should be set transient for the main application
2445 * window they were spawned from. This allows <link
2446 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2447 * dialog on top of the main window, or center the dialog over the
2448 * main window. gtk_dialog_new_with_buttons() and other convenience
2449 * functions in GTK+ will sometimes call
2450 * gtk_window_set_transient_for() on your behalf.
2452 * Passing %NULL for @parent unsets the current transient window.
2454 * On Windows, this function puts the child window on top of the parent,
2455 * much as the window manager would have done on X.
2458 gtk_window_set_transient_for (GtkWindow *window,
2461 GtkWindowPrivate *priv;
2463 g_return_if_fail (GTK_IS_WINDOW (window));
2464 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2465 g_return_if_fail (window != parent);
2467 priv = window->priv;
2469 if (priv->transient_parent)
2471 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2472 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2473 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2474 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2475 GTK_WIDGET (window));
2477 gtk_window_unset_transient_for (window);
2480 priv->transient_parent = parent;
2484 g_signal_connect (parent, "destroy",
2485 G_CALLBACK (gtk_widget_destroyed),
2486 &priv->transient_parent);
2487 g_signal_connect (parent, "realize",
2488 G_CALLBACK (gtk_window_transient_parent_realized),
2490 g_signal_connect (parent, "unrealize",
2491 G_CALLBACK (gtk_window_transient_parent_unrealized),
2493 g_signal_connect (parent, "notify::screen",
2494 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2497 gtk_window_set_screen (window, parent->priv->screen);
2499 if (priv->destroy_with_parent)
2500 connect_parent_destroyed (window);
2502 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2503 gtk_widget_get_realized (GTK_WIDGET (parent)))
2504 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2505 GTK_WIDGET (window));
2507 if (parent->priv->group)
2509 gtk_window_group_add_window (parent->priv->group, window);
2510 priv->transient_parent_group = TRUE;
2516 * gtk_window_get_transient_for:
2517 * @window: a #GtkWindow
2519 * Fetches the transient parent for this window. See
2520 * gtk_window_set_transient_for().
2522 * Return value: (transfer none): the transient parent for this window, or %NULL
2523 * if no transient parent has been set.
2526 gtk_window_get_transient_for (GtkWindow *window)
2528 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2530 return window->priv->transient_parent;
2534 * gtk_window_set_opacity:
2535 * @window: a #GtkWindow
2536 * @opacity: desired opacity, between 0 and 1
2538 * Request the windowing system to make @window partially transparent,
2539 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2540 * of the opacity parameter are clamped to the [0,1] range.) On X11
2541 * this has any effect only on X screens with a compositing manager
2542 * running. See gtk_widget_is_composited(). On Windows it should work
2545 * Note that setting a window's opacity after the window has been
2546 * shown causes it to flicker once on Windows.
2551 gtk_window_set_opacity (GtkWindow *window,
2554 GtkWindowPrivate *priv;
2556 g_return_if_fail (GTK_IS_WINDOW (window));
2558 priv = window->priv;
2562 else if (opacity > 1.0)
2565 priv->opacity_set = TRUE;
2566 priv->opacity = opacity;
2568 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2569 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2574 * gtk_window_get_opacity:
2575 * @window: a #GtkWindow
2577 * Fetches the requested opacity for this window. See
2578 * gtk_window_set_opacity().
2580 * Return value: the requested opacity for this window.
2585 gtk_window_get_opacity (GtkWindow *window)
2587 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2589 return window->priv->opacity;
2593 * gtk_window_set_type_hint:
2594 * @window: a #GtkWindow
2595 * @hint: the window type
2597 * By setting the type hint for the window, you allow the window
2598 * manager to decorate and handle the window in a way which is
2599 * suitable to the function of the window in your application.
2601 * This function should be called before the window becomes visible.
2603 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2604 * will sometimes call gtk_window_set_type_hint() on your behalf.
2608 gtk_window_set_type_hint (GtkWindow *window,
2609 GdkWindowTypeHint hint)
2611 GtkWindowPrivate *priv;
2613 g_return_if_fail (GTK_IS_WINDOW (window));
2614 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2616 priv = window->priv;
2618 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2619 priv->gdk_type_hint = hint;
2621 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2623 priv->reset_type_hint = TRUE;
2624 priv->type_hint = hint;
2628 * gtk_window_get_type_hint:
2629 * @window: a #GtkWindow
2631 * Gets the type hint for this window. See gtk_window_set_type_hint().
2633 * Return value: the type hint for @window.
2636 gtk_window_get_type_hint (GtkWindow *window)
2638 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2640 return window->priv->type_hint;
2644 * gtk_window_set_skip_taskbar_hint:
2645 * @window: a #GtkWindow
2646 * @setting: %TRUE to keep this window from appearing in the task bar
2648 * Windows may set a hint asking the desktop environment not to display
2649 * the window in the task bar. This function sets this hint.
2654 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2657 GtkWindowPrivate *priv;
2659 g_return_if_fail (GTK_IS_WINDOW (window));
2661 priv = window->priv;
2663 setting = setting != FALSE;
2665 if (priv->skips_taskbar != setting)
2667 priv->skips_taskbar = setting;
2668 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2669 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2670 priv->skips_taskbar);
2671 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2676 * gtk_window_get_skip_taskbar_hint:
2677 * @window: a #GtkWindow
2679 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2681 * Return value: %TRUE if window shouldn't be in taskbar
2686 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2688 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2690 return window->priv->skips_taskbar;
2694 * gtk_window_set_skip_pager_hint:
2695 * @window: a #GtkWindow
2696 * @setting: %TRUE to keep this window from appearing in the pager
2698 * Windows may set a hint asking the desktop environment not to display
2699 * the window in the pager. This function sets this hint.
2700 * (A "pager" is any desktop navigation tool such as a workspace
2701 * switcher that displays a thumbnail representation of the windows
2707 gtk_window_set_skip_pager_hint (GtkWindow *window,
2710 GtkWindowPrivate *priv;
2712 g_return_if_fail (GTK_IS_WINDOW (window));
2714 priv = window->priv;
2716 setting = setting != FALSE;
2718 if (priv->skips_pager != setting)
2720 priv->skips_pager = setting;
2721 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2722 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2724 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2729 * gtk_window_get_skip_pager_hint:
2730 * @window: a #GtkWindow
2732 * Gets the value set by gtk_window_set_skip_pager_hint().
2734 * Return value: %TRUE if window shouldn't be in pager
2739 gtk_window_get_skip_pager_hint (GtkWindow *window)
2741 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2743 return window->priv->skips_pager;
2747 * gtk_window_set_urgency_hint:
2748 * @window: a #GtkWindow
2749 * @setting: %TRUE to mark this window as urgent
2751 * Windows may set a hint asking the desktop environment to draw
2752 * the users attention to the window. This function sets this hint.
2757 gtk_window_set_urgency_hint (GtkWindow *window,
2760 GtkWindowPrivate *priv;
2762 g_return_if_fail (GTK_IS_WINDOW (window));
2764 priv = window->priv;
2766 setting = setting != FALSE;
2768 if (priv->urgent != setting)
2770 priv->urgent = setting;
2771 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2772 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2774 g_object_notify (G_OBJECT (window), "urgency-hint");
2779 * gtk_window_get_urgency_hint:
2780 * @window: a #GtkWindow
2782 * Gets the value set by gtk_window_set_urgency_hint()
2784 * Return value: %TRUE if window is urgent
2789 gtk_window_get_urgency_hint (GtkWindow *window)
2791 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2793 return window->priv->urgent;
2797 * gtk_window_set_accept_focus:
2798 * @window: a #GtkWindow
2799 * @setting: %TRUE to let this window receive input focus
2801 * Windows may set a hint asking the desktop environment not to receive
2802 * the input focus. This function sets this hint.
2807 gtk_window_set_accept_focus (GtkWindow *window,
2810 GtkWindowPrivate *priv;
2812 g_return_if_fail (GTK_IS_WINDOW (window));
2814 priv = window->priv;
2816 setting = setting != FALSE;
2818 if (priv->accept_focus != setting)
2820 priv->accept_focus = setting;
2821 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2822 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2823 priv->accept_focus);
2824 g_object_notify (G_OBJECT (window), "accept-focus");
2829 * gtk_window_get_accept_focus:
2830 * @window: a #GtkWindow
2832 * Gets the value set by gtk_window_set_accept_focus().
2834 * Return value: %TRUE if window should receive the input focus
2839 gtk_window_get_accept_focus (GtkWindow *window)
2841 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2843 return window->priv->accept_focus;
2847 * gtk_window_set_focus_on_map:
2848 * @window: a #GtkWindow
2849 * @setting: %TRUE to let this window receive input focus on map
2851 * Windows may set a hint asking the desktop environment not to receive
2852 * the input focus when the window is mapped. This function sets this
2858 gtk_window_set_focus_on_map (GtkWindow *window,
2861 GtkWindowPrivate *priv;
2863 g_return_if_fail (GTK_IS_WINDOW (window));
2865 priv = window->priv;
2867 setting = setting != FALSE;
2869 if (priv->focus_on_map != setting)
2871 priv->focus_on_map = setting;
2872 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2873 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2874 priv->focus_on_map);
2875 g_object_notify (G_OBJECT (window), "focus-on-map");
2880 * gtk_window_get_focus_on_map:
2881 * @window: a #GtkWindow
2883 * Gets the value set by gtk_window_set_focus_on_map().
2885 * Return value: %TRUE if window should receive the input focus when
2891 gtk_window_get_focus_on_map (GtkWindow *window)
2893 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2895 return window->priv->focus_on_map;
2899 * gtk_window_set_destroy_with_parent:
2900 * @window: a #GtkWindow
2901 * @setting: whether to destroy @window with its transient parent
2903 * If @setting is %TRUE, then destroying the transient parent of @window
2904 * will also destroy @window itself. This is useful for dialogs that
2905 * shouldn't persist beyond the lifetime of the main window they're
2906 * associated with, for example.
2909 gtk_window_set_destroy_with_parent (GtkWindow *window,
2912 GtkWindowPrivate *priv;
2914 g_return_if_fail (GTK_IS_WINDOW (window));
2916 priv = window->priv;
2918 if (priv->destroy_with_parent == (setting != FALSE))
2921 if (priv->destroy_with_parent)
2923 disconnect_parent_destroyed (window);
2927 connect_parent_destroyed (window);
2930 priv->destroy_with_parent = setting;
2932 g_object_notify (G_OBJECT (window), "destroy-with-parent");
2936 * gtk_window_get_destroy_with_parent:
2937 * @window: a #GtkWindow
2939 * Returns whether the window will be destroyed with its transient parent. See
2940 * gtk_window_set_destroy_with_parent ().
2942 * Return value: %TRUE if the window will be destroyed with its transient parent.
2945 gtk_window_get_destroy_with_parent (GtkWindow *window)
2947 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2949 return window->priv->destroy_with_parent;
2952 static GtkWindowGeometryInfo*
2953 gtk_window_get_geometry_info (GtkWindow *window,
2956 GtkWindowPrivate *priv = window->priv;
2957 GtkWindowGeometryInfo *info;
2959 info = priv->geometry_info;
2960 if (!info && create)
2962 info = g_new0 (GtkWindowGeometryInfo, 1);
2964 info->default_width = -1;
2965 info->default_height = -1;
2966 info->resize_width = -1;
2967 info->resize_height = -1;
2968 info->initial_x = 0;
2969 info->initial_y = 0;
2970 info->initial_pos_set = FALSE;
2971 info->default_is_geometry = FALSE;
2972 info->position_constraints_changed = FALSE;
2973 info->last.configure_request.x = 0;
2974 info->last.configure_request.y = 0;
2975 info->last.configure_request.width = -1;
2976 info->last.configure_request.height = -1;
2977 info->widget = NULL;
2979 priv->geometry_info = info;
2986 * gtk_window_set_geometry_hints:
2987 * @window: a #GtkWindow
2988 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
2989 * @geometry: (allow-none): struct containing geometry information or %NULL
2990 * @geom_mask: mask indicating which struct fields should be paid attention to
2992 * This function sets up hints about how a window can be resized by
2993 * the user. You can set a minimum and maximum size; allowed resize
2994 * increments (e.g. for xterm, you can only resize by the size of a
2995 * character); aspect ratios; and more. See the #GdkGeometry struct.
2999 gtk_window_set_geometry_hints (GtkWindow *window,
3000 GtkWidget *geometry_widget,
3001 GdkGeometry *geometry,
3002 GdkWindowHints geom_mask)
3004 GtkWindowGeometryInfo *info;
3006 g_return_if_fail (GTK_IS_WINDOW (window));
3007 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3009 info = gtk_window_get_geometry_info (window, TRUE);
3012 g_signal_handlers_disconnect_by_func (info->widget,
3013 gtk_widget_destroyed,
3016 info->widget = geometry_widget;
3018 g_signal_connect (geometry_widget, "destroy",
3019 G_CALLBACK (gtk_widget_destroyed),
3023 info->geometry = *geometry;
3025 /* We store gravity in priv->gravity not in the hints. */
3026 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3028 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3030 gtk_window_set_gravity (window, geometry->win_gravity);
3033 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3037 * gtk_window_set_decorated:
3038 * @window: a #GtkWindow
3039 * @setting: %TRUE to decorate the window
3041 * By default, windows are decorated with a title bar, resize
3042 * controls, etc. Some <link linkend="gtk-X11-arch">window
3043 * managers</link> allow GTK+ to disable these decorations, creating a
3044 * borderless window. If you set the decorated property to %FALSE
3045 * using this function, GTK+ will do its best to convince the window
3046 * manager not to decorate the window. Depending on the system, this
3047 * function may not have any effect when called on a window that is
3048 * already visible, so you should call it before calling gtk_window_show().
3050 * On Windows, this function always works, since there's no window manager
3055 gtk_window_set_decorated (GtkWindow *window,
3058 GtkWindowPrivate *priv;
3059 GdkWindow *gdk_window;
3061 g_return_if_fail (GTK_IS_WINDOW (window));
3063 priv = window->priv;
3065 setting = setting != FALSE;
3067 if (setting == priv->decorated)
3070 priv->decorated = setting;
3072 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3075 if (priv->decorated)
3076 gdk_window_set_decorations (gdk_window,
3079 gdk_window_set_decorations (gdk_window,
3083 g_object_notify (G_OBJECT (window), "decorated");
3087 * gtk_window_get_decorated:
3088 * @window: a #GtkWindow
3090 * Returns whether the window has been set to have decorations
3091 * such as a title bar via gtk_window_set_decorated().
3093 * Return value: %TRUE if the window has been set to have decorations
3096 gtk_window_get_decorated (GtkWindow *window)
3098 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3100 return window->priv->decorated;
3104 * gtk_window_set_deletable:
3105 * @window: a #GtkWindow
3106 * @setting: %TRUE to decorate the window as deletable
3108 * By default, windows have a close button in the window frame. Some
3109 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3110 * disable this button. If you set the deletable property to %FALSE
3111 * using this function, GTK+ will do its best to convince the window
3112 * manager not to show a close button. Depending on the system, this
3113 * function may not have any effect when called on a window that is
3114 * already visible, so you should call it before calling gtk_window_show().
3116 * On Windows, this function always works, since there's no window manager
3122 gtk_window_set_deletable (GtkWindow *window,
3125 GtkWindowPrivate *priv;
3126 GdkWindow *gdk_window;
3128 g_return_if_fail (GTK_IS_WINDOW (window));
3130 priv = window->priv;
3132 setting = setting != FALSE;
3134 if (setting == priv->deletable)
3137 priv->deletable = setting;
3139 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3142 if (priv->deletable)
3143 gdk_window_set_functions (gdk_window,
3146 gdk_window_set_functions (gdk_window,
3147 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3150 g_object_notify (G_OBJECT (window), "deletable");
3154 * gtk_window_get_deletable:
3155 * @window: a #GtkWindow
3157 * Returns whether the window has been set to have a close button
3158 * via gtk_window_set_deletable().
3160 * Return value: %TRUE if the window has been set to have a close button
3165 gtk_window_get_deletable (GtkWindow *window)
3167 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3169 return window->priv->deletable;
3172 static GtkWindowIconInfo*
3173 get_icon_info (GtkWindow *window)
3175 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3179 free_icon_info (GtkWindowIconInfo *info)
3181 g_free (info->icon_name);
3182 g_slice_free (GtkWindowIconInfo, info);
3186 static GtkWindowIconInfo*
3187 ensure_icon_info (GtkWindow *window)
3189 GtkWindowIconInfo *info;
3191 info = get_icon_info (window);
3195 info = g_slice_new0 (GtkWindowIconInfo);
3196 g_object_set_qdata_full (G_OBJECT (window),
3197 quark_gtk_window_icon_info,
3199 (GDestroyNotify)free_icon_info);
3206 icon_list_from_theme (GtkWidget *widget,
3211 GtkIconTheme *icon_theme;
3216 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3218 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3221 for (i = 0; sizes[i]; i++)
3224 * We need an EWMH extension to handle scalable icons
3225 * by passing their name to the WM. For now just use a
3229 icon = gtk_icon_theme_load_icon (icon_theme, name,
3232 icon = gtk_icon_theme_load_icon (icon_theme, name,
3235 list = g_list_append (list, icon);
3245 gtk_window_realize_icon (GtkWindow *window)
3247 GtkWindowPrivate *priv = window->priv;
3249 GtkWindowIconInfo *info;
3250 GdkWindow *gdk_window;
3253 widget = GTK_WIDGET (window);
3254 gdk_window = gtk_widget_get_window (widget);
3256 g_return_if_fail (gdk_window != NULL);
3258 /* no point setting an icon on override-redirect */
3259 if (priv->type == GTK_WINDOW_POPUP)
3264 info = ensure_icon_info (window);
3269 info->using_default_icon = FALSE;
3270 info->using_parent_icon = FALSE;
3271 info->using_themed_icon = FALSE;
3273 icon_list = info->icon_list;
3275 /* Look up themed icon */
3276 if (icon_list == NULL && info->icon_name)
3278 icon_list = icon_list_from_theme (widget, info->icon_name);
3280 info->using_themed_icon = TRUE;
3283 /* Inherit from transient parent */
3284 if (icon_list == NULL && priv->transient_parent)
3286 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3288 info->using_parent_icon = TRUE;
3291 /* Inherit from default */
3292 if (icon_list == NULL)
3294 icon_list = default_icon_list;
3296 info->using_default_icon = TRUE;
3299 /* Look up themed icon */
3300 if (icon_list == NULL && default_icon_name)
3302 icon_list = icon_list_from_theme (widget, default_icon_name);
3303 info->using_default_icon = TRUE;
3304 info->using_themed_icon = TRUE;
3307 info->realized = TRUE;
3309 if (info->using_themed_icon)
3311 GtkIconTheme *icon_theme;
3313 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3314 g_list_free (icon_list);
3316 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3317 g_signal_connect (icon_theme, "changed",
3318 G_CALLBACK (update_themed_icon), window);
3323 gtk_window_unrealize_icon (GtkWindow *window)
3325 GtkWindowIconInfo *info;
3327 info = get_icon_info (window);
3332 if (info->using_themed_icon)
3334 GtkIconTheme *icon_theme;
3336 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3338 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3341 /* We don't clear the properties on the window, just figure the
3342 * window is going away.
3345 info->realized = FALSE;
3350 * gtk_window_set_icon_list:
3351 * @window: a #GtkWindow
3352 * @list: (element-type GdkPixbuf) (transfer container): list of #GdkPixbuf
3354 * Sets up the icon representing a #GtkWindow. The icon is used when
3355 * the window is minimized (also known as iconified). Some window
3356 * managers or desktop environments may also place it in the window
3357 * frame, or display it in other contexts.
3359 * gtk_window_set_icon_list() allows you to pass in the same icon in
3360 * several hand-drawn sizes. The list should contain the natural sizes
3361 * your icon is available in; that is, don't scale the image before
3362 * passing it to GTK+. Scaling is postponed until the last minute,
3363 * when the desired final size is known, to allow best quality.
3365 * By passing several sizes, you may improve the final image quality
3366 * of the icon, by reducing or eliminating automatic image scaling.
3368 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3369 * larger images (64x64, 128x128) if you have them.
3371 * See also gtk_window_set_default_icon_list() to set the icon
3372 * for all windows in your application in one go.
3374 * Note that transient windows (those who have been set transient for another
3375 * window using gtk_window_set_transient_for()) will inherit their
3376 * icon from their transient parent. So there's no need to explicitly
3377 * set the icon on transient windows.
3380 gtk_window_set_icon_list (GtkWindow *window,
3383 GtkWindowIconInfo *info;
3385 g_return_if_fail (GTK_IS_WINDOW (window));
3387 info = ensure_icon_info (window);
3389 if (info->icon_list == list) /* check for NULL mostly */
3392 g_list_foreach (list,
3393 (GFunc) g_object_ref, NULL);
3395 g_list_foreach (info->icon_list,
3396 (GFunc) g_object_unref, NULL);
3398 g_list_free (info->icon_list);
3400 info->icon_list = g_list_copy (list);
3402 g_object_notify (G_OBJECT (window), "icon");
3404 gtk_window_unrealize_icon (window);
3406 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3407 gtk_window_realize_icon (window);
3409 /* We could try to update our transient children, but I don't think
3410 * it's really worth it. If we did it, the best way would probably
3411 * be to have children connect to notify::icon-list
3416 * gtk_window_get_icon_list:
3417 * @window: a #GtkWindow
3419 * Retrieves the list of icons set by gtk_window_set_icon_list().
3420 * The list is copied, but the reference count on each
3421 * member won't be incremented.
3423 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3426 gtk_window_get_icon_list (GtkWindow *window)
3428 GtkWindowIconInfo *info;
3430 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3432 info = get_icon_info (window);
3435 return g_list_copy (info->icon_list);
3441 * gtk_window_set_icon:
3442 * @window: a #GtkWindow
3443 * @icon: (allow-none): icon image, or %NULL
3445 * Sets up the icon representing a #GtkWindow. This icon is used when
3446 * the window is minimized (also known as iconified). Some window
3447 * managers or desktop environments may also place it in the window
3448 * frame, or display it in other contexts.
3450 * The icon should be provided in whatever size it was naturally
3451 * drawn; that is, don't scale the image before passing it to
3452 * GTK+. Scaling is postponed until the last minute, when the desired
3453 * final size is known, to allow best quality.
3455 * If you have your icon hand-drawn in multiple sizes, use
3456 * gtk_window_set_icon_list(). Then the best size will be used.
3458 * This function is equivalent to calling gtk_window_set_icon_list()
3459 * with a 1-element list.
3461 * See also gtk_window_set_default_icon_list() to set the icon
3462 * for all windows in your application in one go.
3465 gtk_window_set_icon (GtkWindow *window,
3470 g_return_if_fail (GTK_IS_WINDOW (window));
3471 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3476 list = g_list_append (list, icon);
3478 gtk_window_set_icon_list (window, list);
3484 update_themed_icon (GtkIconTheme *icon_theme,
3487 g_object_notify (G_OBJECT (window), "icon");
3489 gtk_window_unrealize_icon (window);
3491 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3492 gtk_window_realize_icon (window);
3496 * gtk_window_set_icon_name:
3497 * @window: a #GtkWindow
3498 * @name: (allow-none): the name of the themed icon
3500 * Sets the icon for the window from a named themed icon. See
3501 * the docs for #GtkIconTheme for more details.
3503 * Note that this has nothing to do with the WM_ICON_NAME
3504 * property which is mentioned in the ICCCM.
3509 gtk_window_set_icon_name (GtkWindow *window,
3512 GtkWindowIconInfo *info;
3515 g_return_if_fail (GTK_IS_WINDOW (window));
3517 info = ensure_icon_info (window);
3519 if (g_strcmp0 (info->icon_name, name) == 0)
3522 tmp = info->icon_name;
3523 info->icon_name = g_strdup (name);
3526 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3527 g_list_free (info->icon_list);
3528 info->icon_list = NULL;
3530 update_themed_icon (NULL, window);
3532 g_object_notify (G_OBJECT (window), "icon-name");
3536 * gtk_window_get_icon_name:
3537 * @window: a #GtkWindow
3539 * Returns the name of the themed icon for the window,
3540 * see gtk_window_set_icon_name().
3542 * Returns: the icon name or %NULL if the window has
3548 gtk_window_get_icon_name (GtkWindow *window)
3550 GtkWindowIconInfo *info;
3552 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3554 info = ensure_icon_info (window);
3556 return info->icon_name;
3560 * gtk_window_get_icon:
3561 * @window: a #GtkWindow
3563 * Gets the value set by gtk_window_set_icon() (or if you've
3564 * called gtk_window_set_icon_list(), gets the first icon in
3567 * Return value: (transfer none): icon for window
3570 gtk_window_get_icon (GtkWindow *window)
3572 GtkWindowIconInfo *info;
3574 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3576 info = get_icon_info (window);
3577 if (info && info->icon_list)
3578 return GDK_PIXBUF (info->icon_list->data);
3583 /* Load pixbuf, printing warning on failure if error == NULL
3586 load_pixbuf_verbosely (const char *filename,
3589 GError *local_err = NULL;
3592 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3600 g_warning ("Error loading icon from file '%s':\n\t%s",
3601 filename, local_err->message);
3602 g_error_free (local_err);
3610 * gtk_window_set_icon_from_file:
3611 * @window: a #GtkWindow
3612 * @filename: location of icon file
3613 * @err: (allow-none): location to store error, or %NULL.
3615 * Sets the icon for @window.
3616 * Warns on failure if @err is %NULL.
3618 * This function is equivalent to calling gtk_window_set_icon()
3619 * with a pixbuf created by loading the image from @filename.
3621 * Returns: %TRUE if setting the icon succeeded.
3626 gtk_window_set_icon_from_file (GtkWindow *window,
3627 const gchar *filename,
3630 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3634 gtk_window_set_icon (window, pixbuf);
3635 g_object_unref (pixbuf);
3644 * gtk_window_set_default_icon_list:
3645 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3647 * Sets an icon list to be used as fallback for windows that haven't
3648 * had gtk_window_set_icon_list() called on them to set up a
3649 * window-specific icon list. This function allows you to set up the
3650 * icon for all windows in your app at once.
3652 * See gtk_window_set_icon_list() for more details.
3656 gtk_window_set_default_icon_list (GList *list)
3660 if (list == default_icon_list)
3663 /* Update serial so we don't used cached pixmaps/masks
3665 default_icon_serial++;
3667 g_list_foreach (list,
3668 (GFunc) g_object_ref, NULL);
3670 g_list_foreach (default_icon_list,
3671 (GFunc) g_object_unref, NULL);
3673 g_list_free (default_icon_list);
3675 default_icon_list = g_list_copy (list);
3677 /* Update all toplevels */
3678 toplevels = gtk_window_list_toplevels ();
3679 tmp_list = toplevels;
3680 while (tmp_list != NULL)
3682 GtkWindowIconInfo *info;
3683 GtkWindow *w = tmp_list->data;
3685 info = get_icon_info (w);
3686 if (info && info->using_default_icon)
3688 gtk_window_unrealize_icon (w);
3689 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3690 gtk_window_realize_icon (w);
3693 tmp_list = tmp_list->next;
3695 g_list_free (toplevels);
3699 * gtk_window_set_default_icon:
3702 * Sets an icon to be used as fallback for windows that haven't
3703 * had gtk_window_set_icon() called on them from a pixbuf.
3708 gtk_window_set_default_icon (GdkPixbuf *icon)
3712 g_return_if_fail (GDK_IS_PIXBUF (icon));
3714 list = g_list_prepend (NULL, icon);
3715 gtk_window_set_default_icon_list (list);
3720 * gtk_window_set_default_icon_name:
3721 * @name: the name of the themed icon
3723 * Sets an icon to be used as fallback for windows that haven't
3724 * had gtk_window_set_icon_list() called on them from a named
3725 * themed icon, see gtk_window_set_icon_name().
3730 gtk_window_set_default_icon_name (const gchar *name)
3735 /* Update serial so we don't used cached pixmaps/masks
3737 default_icon_serial++;
3739 g_free (default_icon_name);
3740 default_icon_name = g_strdup (name);
3742 g_list_foreach (default_icon_list,
3743 (GFunc) g_object_unref, NULL);
3745 g_list_free (default_icon_list);
3746 default_icon_list = NULL;
3748 /* Update all toplevels */
3749 toplevels = gtk_window_list_toplevels ();
3750 tmp_list = toplevels;
3751 while (tmp_list != NULL)
3753 GtkWindowIconInfo *info;
3754 GtkWindow *w = tmp_list->data;
3756 info = get_icon_info (w);
3757 if (info && info->using_default_icon && info->using_themed_icon)
3759 gtk_window_unrealize_icon (w);
3760 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3761 gtk_window_realize_icon (w);
3764 tmp_list = tmp_list->next;
3766 g_list_free (toplevels);
3770 * gtk_window_get_default_icon_name:
3772 * Returns the fallback icon name for windows that has been set
3773 * with gtk_window_set_default_icon_name(). The returned
3774 * string is owned by GTK+ and should not be modified. It
3775 * is only valid until the next call to
3776 * gtk_window_set_default_icon_name().
3778 * Returns: the fallback icon name for windows
3783 gtk_window_get_default_icon_name (void)
3785 return default_icon_name;
3789 * gtk_window_set_default_icon_from_file:
3790 * @filename: location of icon file
3791 * @err: (allow-none): location to store error, or %NULL.
3793 * Sets an icon to be used as fallback for windows that haven't
3794 * had gtk_window_set_icon_list() called on them from a file
3795 * on disk. Warns on failure if @err is %NULL.
3797 * Returns: %TRUE if setting the icon succeeded.
3802 gtk_window_set_default_icon_from_file (const gchar *filename,
3805 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3809 gtk_window_set_default_icon (pixbuf);
3810 g_object_unref (pixbuf);
3819 * gtk_window_get_default_icon_list:
3821 * Gets the value set by gtk_window_set_default_icon_list().
3822 * The list is a copy and should be freed with g_list_free(),
3823 * but the pixbufs in the list have not had their reference count
3826 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3829 gtk_window_get_default_icon_list (void)
3831 return g_list_copy (default_icon_list);
3835 gtk_window_set_default_size_internal (GtkWindow *window,
3836 gboolean change_width,
3838 gboolean change_height,
3840 gboolean is_geometry)
3842 GtkWindowGeometryInfo *info;
3844 g_return_if_fail (change_width == FALSE || width >= -1);
3845 g_return_if_fail (change_height == FALSE || height >= -1);
3847 info = gtk_window_get_geometry_info (window, TRUE);
3849 g_object_freeze_notify (G_OBJECT (window));
3851 info->default_is_geometry = is_geometry != FALSE;
3861 info->default_width = width;
3863 g_object_notify (G_OBJECT (window), "default-width");
3874 info->default_height = height;
3876 g_object_notify (G_OBJECT (window), "default-height");
3879 g_object_thaw_notify (G_OBJECT (window));
3881 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3885 * gtk_window_set_default_size:
3886 * @window: a #GtkWindow
3887 * @width: width in pixels, or -1 to unset the default width
3888 * @height: height in pixels, or -1 to unset the default height
3890 * Sets the default size of a window. If the window's "natural" size
3891 * (its size request) is larger than the default, the default will be
3892 * ignored. More generally, if the default size does not obey the
3893 * geometry hints for the window (gtk_window_set_geometry_hints() can
3894 * be used to set these explicitly), the default size will be clamped
3895 * to the nearest permitted size.
3897 * Unlike gtk_widget_set_size_request(), which sets a size request for
3898 * a widget and thus would keep users from shrinking the window, this
3899 * function only sets the initial size, just as if the user had
3900 * resized the window themselves. Users can still shrink the window
3901 * again as they normally would. Setting a default size of -1 means to
3902 * use the "natural" default size (the size request of the window).
3904 * For more control over a window's initial size and how resizing works,
3905 * investigate gtk_window_set_geometry_hints().
3907 * For some uses, gtk_window_resize() is a more appropriate function.
3908 * gtk_window_resize() changes the current size of the window, rather
3909 * than the size to be used on initial display. gtk_window_resize() always
3910 * affects the window itself, not the geometry widget.
3912 * The default size of a window only affects the first time a window is
3913 * shown; if a window is hidden and re-shown, it will remember the size
3914 * it had prior to hiding, rather than using the default size.
3916 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3917 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3920 gtk_window_set_default_size (GtkWindow *window,
3924 g_return_if_fail (GTK_IS_WINDOW (window));
3925 g_return_if_fail (width >= -1);
3926 g_return_if_fail (height >= -1);
3928 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3932 * gtk_window_get_default_size:
3933 * @window: a #GtkWindow
3934 * @width: (out) (allow-none): location to store the default width, or %NULL
3935 * @height: (out) (allow-none): location to store the default height, or %NULL
3937 * Gets the default size of the window. A value of -1 for the width or
3938 * height indicates that a default size has not been explicitly set
3939 * for that dimension, so the "natural" size of the window will be
3944 gtk_window_get_default_size (GtkWindow *window,
3948 GtkWindowGeometryInfo *info;
3950 g_return_if_fail (GTK_IS_WINDOW (window));
3952 info = gtk_window_get_geometry_info (window, FALSE);
3955 *width = info ? info->default_width : -1;
3958 *height = info ? info->default_height : -1;
3962 * gtk_window_resize:
3963 * @window: a #GtkWindow
3964 * @width: width in pixels to resize the window to
3965 * @height: height in pixels to resize the window to
3967 * Resizes the window as if the user had done so, obeying geometry
3968 * constraints. The default geometry constraint is that windows may
3969 * not be smaller than their size request; to override this
3970 * constraint, call gtk_widget_set_size_request() to set the window's
3971 * request to a smaller value.
3973 * If gtk_window_resize() is called before showing a window for the
3974 * first time, it overrides any default size set with
3975 * gtk_window_set_default_size().
3977 * Windows may not be resized smaller than 1 by 1 pixels.
3981 gtk_window_resize (GtkWindow *window,
3985 GtkWindowGeometryInfo *info;
3987 g_return_if_fail (GTK_IS_WINDOW (window));
3988 g_return_if_fail (width > 0);
3989 g_return_if_fail (height > 0);
3991 info = gtk_window_get_geometry_info (window, TRUE);
3993 info->resize_width = width;
3994 info->resize_height = height;
3996 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4000 * gtk_window_get_size:
4001 * @window: a #GtkWindow
4002 * @width: (out) (allow-none): return location for width, or %NULL
4003 * @height: (out) (allow-none): return location for height, or %NULL
4005 * Obtains the current size of @window. If @window is not onscreen,
4006 * it returns the size GTK+ will suggest to the <link
4007 * linkend="gtk-X11-arch">window manager</link> for the initial window
4008 * size (but this is not reliably the same as the size the window
4009 * manager will actually select). The size obtained by
4010 * gtk_window_get_size() is the last size received in a
4011 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4012 * rather than querying the X server for the size. As a result, if you
4013 * call gtk_window_resize() then immediately call
4014 * gtk_window_get_size(), the size won't have taken effect yet. After
4015 * the window manager processes the resize request, GTK+ receives
4016 * notification that the size has changed via a configure event, and
4017 * the size of the window gets updated.
4019 * Note 1: Nearly any use of this function creates a race condition,
4020 * because the size of the window may change between the time that you
4021 * get the size and the time that you perform some action assuming
4022 * that size is the current size. To avoid race conditions, connect to
4023 * "configure-event" on the window and adjust your size-dependent
4024 * state to match the size delivered in the #GdkEventConfigure.
4026 * Note 2: The returned size does <emphasis>not</emphasis> include the
4027 * size of the window manager decorations (aka the window frame or
4028 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4029 * method of determining their size.
4031 * Note 3: If you are getting a window size in order to position
4032 * the window onscreen, there may be a better way. The preferred
4033 * way is to simply set the window's semantic type with
4034 * gtk_window_set_type_hint(), which allows the window manager to
4035 * e.g. center dialogs. Also, if you set the transient parent of
4036 * dialogs with gtk_window_set_transient_for() window managers
4037 * will often center the dialog over its parent window. It's
4038 * much preferred to let the window manager handle these
4039 * things rather than doing it yourself, because all apps will
4040 * behave consistently and according to user prefs if the window
4041 * manager handles it. Also, the window manager can take the size
4042 * of the window decorations/border into account, while your
4043 * application cannot.
4045 * In any case, if you insist on application-specified window
4046 * positioning, there's <emphasis>still</emphasis> a better way than
4047 * doing it yourself - gtk_window_set_position() will frequently
4048 * handle the details for you.
4052 gtk_window_get_size (GtkWindow *window,
4058 g_return_if_fail (GTK_IS_WINDOW (window));
4060 if (width == NULL && height == NULL)
4063 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4065 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4066 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4070 GdkRectangle configure_request;
4072 gtk_window_compute_configure_request (window,
4076 w = configure_request.width;
4077 h = configure_request.height;
4088 * @window: a #GtkWindow
4089 * @x: X coordinate to move window to
4090 * @y: Y coordinate to move window to
4092 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4093 * @window to the given position. Window managers are free to ignore
4094 * this; most window managers ignore requests for initial window
4095 * positions (instead using a user-defined placement algorithm) and
4096 * honor requests after the window has already been shown.
4098 * Note: the position is the position of the gravity-determined
4099 * reference point for the window. The gravity determines two things:
4100 * first, the location of the reference point in root window
4101 * coordinates; and second, which point on the window is positioned at
4102 * the reference point.
4104 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4105 * point is simply the @x, @y supplied to gtk_window_move(). The
4106 * top-left corner of the window decorations (aka window frame or
4107 * border) will be placed at @x, @y. Therefore, to position a window
4108 * at the top left of the screen, you want to use the default gravity
4109 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4111 * To position a window at the bottom right corner of the screen, you
4112 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4113 * point is at @x + the window width and @y + the window height, and
4114 * the bottom-right corner of the window border will be placed at that
4115 * reference point. So, to place a window in the bottom right corner
4116 * you would first set gravity to south east, then write:
4117 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4118 * gdk_screen_height () - window_height)</literal> (note that this
4119 * example does not take multi-head scenarios into account).
4121 * The Extended Window Manager Hints specification at <ulink
4122 * url="http://www.freedesktop.org/Standards/wm-spec">
4123 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4124 * nice table of gravities in the "implementation notes" section.
4126 * The gtk_window_get_position() documentation may also be relevant.
4129 gtk_window_move (GtkWindow *window,
4133 GtkWindowPrivate *priv;
4134 GtkWindowGeometryInfo *info;
4137 g_return_if_fail (GTK_IS_WINDOW (window));
4139 priv = window->priv;
4140 widget = GTK_WIDGET (window);
4142 info = gtk_window_get_geometry_info (window, TRUE);
4144 if (gtk_widget_get_mapped (widget))
4146 GtkAllocation allocation;
4148 gtk_widget_get_allocation (widget, &allocation);
4150 /* we have now sent a request with this position
4151 * with currently-active constraints, so toggle flag.
4153 info->position_constraints_changed = FALSE;
4155 /* we only constrain if mapped - if not mapped,
4156 * then gtk_window_compute_configure_request()
4157 * will apply the constraints later, and we
4158 * don't want to lose information about
4159 * what position the user set before then.
4160 * i.e. if you do a move() then turn off POS_CENTER
4161 * then show the window, your move() will work.
4163 gtk_window_constrain_position (window,
4164 allocation.width, allocation.height,
4167 /* Note that this request doesn't go through our standard request
4168 * framework, e.g. doesn't increment configure_request_count,
4169 * doesn't set info->last, etc.; that's because
4170 * we don't save the info needed to arrive at this same request
4173 * To gtk_window_move_resize(), this will end up looking exactly
4174 * the same as the position being changed by the window
4178 /* FIXME are we handling gravity properly for framed windows? */
4180 gdk_window_move (priv->frame,
4181 x - priv->frame_left,
4182 y - priv->frame_top);
4184 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)),
4189 /* Save this position to apply on mapping */
4190 info->initial_x = x;
4191 info->initial_y = y;
4192 info->initial_pos_set = TRUE;
4197 * gtk_window_get_position:
4198 * @window: a #GtkWindow
4199 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4200 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4202 * This function returns the position you need to pass to
4203 * gtk_window_move() to keep @window in its current position. This
4204 * means that the meaning of the returned value varies with window
4205 * gravity. See gtk_window_move() for more details.
4207 * If you haven't changed the window gravity, its gravity will be
4208 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4209 * gets the position of the top-left corner of the window manager
4210 * frame for the window. gtk_window_move() sets the position of this
4211 * same top-left corner.
4213 * gtk_window_get_position() is not 100% reliable because the X Window System
4214 * does not specify a way to obtain the geometry of the
4215 * decorations placed on a window by the window manager.
4216 * Thus GTK+ is using a "best guess" that works with most
4219 * Moreover, nearly all window managers are historically broken with
4220 * respect to their handling of window gravity. So moving a window to
4221 * its current position as returned by gtk_window_get_position() tends
4222 * to result in moving the window slightly. Window managers are
4223 * slowly getting better over time.
4225 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4226 * frame is not relevant, and thus gtk_window_get_position() will
4227 * always produce accurate results. However you can't use static
4228 * gravity to do things like place a window in a corner of the screen,
4229 * because static gravity ignores the window manager decorations.
4231 * If you are saving and restoring your application's window
4232 * positions, you should know that it's impossible for applications to
4233 * do this without getting it somewhat wrong because applications do
4234 * not have sufficient knowledge of window manager state. The Correct
4235 * Mechanism is to support the session management protocol (see the
4236 * "GnomeClient" object in the GNOME libraries for example) and allow
4237 * the window manager to save your window sizes and positions.
4242 gtk_window_get_position (GtkWindow *window,
4246 GtkWindowPrivate *priv;
4248 GdkWindow *gdk_window;
4250 g_return_if_fail (GTK_IS_WINDOW (window));
4252 priv = window->priv;
4253 widget = GTK_WIDGET (window);
4254 gdk_window = gtk_widget_get_window (widget);
4256 if (priv->gravity == GDK_GRAVITY_STATIC)
4258 if (gtk_widget_get_mapped (widget))
4260 /* This does a server round-trip, which is sort of wrong;
4261 * but a server round-trip is inevitable for
4262 * gdk_window_get_frame_extents() in the usual
4263 * NorthWestGravity case below, so not sure what else to
4264 * do. We should likely be consistent about whether we get
4265 * the client-side info or the server-side info.
4267 gdk_window_get_origin (gdk_window, root_x, root_y);
4271 GdkRectangle configure_request;
4273 gtk_window_compute_configure_request (window,
4277 *root_x = configure_request.x;
4278 *root_y = configure_request.y;
4283 GdkRectangle frame_extents;
4288 if (gtk_widget_get_mapped (widget))
4291 gdk_window_get_frame_extents (priv->frame, &frame_extents);
4293 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4294 x = frame_extents.x;
4295 y = frame_extents.y;
4296 gtk_window_get_size (window, &w, &h);
4300 /* We just say the frame has 0 size on all sides.
4301 * Not sure what else to do.
4303 gtk_window_compute_configure_request (window,
4306 x = frame_extents.x;
4307 y = frame_extents.y;
4308 w = frame_extents.width;
4309 h = frame_extents.height;
4312 switch (priv->gravity)
4314 case GDK_GRAVITY_NORTH:
4315 case GDK_GRAVITY_CENTER:
4316 case GDK_GRAVITY_SOUTH:
4317 /* Find center of frame. */
4318 x += frame_extents.width / 2;
4319 /* Center client window on that point. */
4323 case GDK_GRAVITY_SOUTH_EAST:
4324 case GDK_GRAVITY_EAST:
4325 case GDK_GRAVITY_NORTH_EAST:
4326 /* Find right edge of frame */
4327 x += frame_extents.width;
4328 /* Align left edge of client at that point. */
4335 switch (priv->gravity)
4337 case GDK_GRAVITY_WEST:
4338 case GDK_GRAVITY_CENTER:
4339 case GDK_GRAVITY_EAST:
4340 /* Find center of frame. */
4341 y += frame_extents.height / 2;
4342 /* Center client window there. */
4345 case GDK_GRAVITY_SOUTH_WEST:
4346 case GDK_GRAVITY_SOUTH:
4347 case GDK_GRAVITY_SOUTH_EAST:
4348 /* Find south edge of frame */
4349 y += frame_extents.height;
4350 /* Place bottom edge of client there */
4365 * gtk_window_reshow_with_initial_size:
4366 * @window: a #GtkWindow
4368 * Hides @window, then reshows it, resetting the
4369 * default size and position of the window. Used
4370 * by GUI builders only.
4373 gtk_window_reshow_with_initial_size (GtkWindow *window)
4377 g_return_if_fail (GTK_IS_WINDOW (window));
4379 widget = GTK_WIDGET (window);
4381 gtk_widget_hide (widget);
4382 gtk_widget_unrealize (widget);
4383 gtk_widget_show (widget);
4387 gtk_window_destroy (GtkWidget *widget)
4389 GtkWindow *window = GTK_WINDOW (widget);
4390 GtkWindowPrivate *priv = window->priv;
4392 toplevel_list = g_slist_remove (toplevel_list, window);
4394 if (priv->transient_parent)
4395 gtk_window_set_transient_for (window, NULL);
4397 /* frees the icons */
4398 gtk_window_set_icon_list (window, NULL);
4400 if (priv->has_user_ref_count)
4402 priv->has_user_ref_count = FALSE;
4403 g_object_unref (window);
4407 gtk_window_group_remove_window (priv->group, window);
4409 gtk_window_free_key_hash (window);
4411 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4415 gtk_window_finalize (GObject *object)
4417 GtkWindow *window = GTK_WINDOW (object);
4418 GtkWindowPrivate *priv = window->priv;
4419 GtkMnemonicHash *mnemonic_hash;
4421 g_free (priv->title);
4422 g_free (priv->wmclass_name);
4423 g_free (priv->wmclass_class);
4424 g_free (priv->wm_role);
4426 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4428 _gtk_mnemonic_hash_free (mnemonic_hash);
4430 if (priv->geometry_info)
4432 if (priv->geometry_info->widget)
4433 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4434 gtk_widget_destroyed,
4435 &priv->geometry_info->widget);
4436 g_free (priv->geometry_info);
4439 if (priv->keys_changed_handler)
4441 g_source_remove (priv->keys_changed_handler);
4442 priv->keys_changed_handler = 0;
4446 g_signal_handlers_disconnect_by_func (priv->screen,
4447 gtk_window_on_composited_changed, window);
4449 g_free (priv->startup_id);
4451 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4455 gtk_window_show (GtkWidget *widget)
4457 GtkWindow *window = GTK_WINDOW (widget);
4458 GtkWindowPrivate *priv = window->priv;
4459 GtkContainer *container = GTK_CONTAINER (window);
4460 gboolean need_resize;
4462 _gtk_widget_set_visible_flag (widget, TRUE);
4464 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4465 _gtk_container_set_need_resize (container, FALSE);
4469 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4470 GtkAllocation allocation = { 0, 0 };
4471 GdkRectangle configure_request;
4472 GdkGeometry new_geometry;
4474 gboolean was_realized;
4476 /* We are going to go ahead and perform this configure request
4477 * and then emulate a configure notify by going ahead and
4478 * doing a size allocate. Sort of a synchronous
4479 * mini-copy of gtk_window_move_resize() here.
4481 gtk_window_compute_configure_request (window,
4486 /* We update this because we are going to go ahead
4487 * and gdk_window_resize() below, rather than
4490 info->last.configure_request.width = configure_request.width;
4491 info->last.configure_request.height = configure_request.height;
4493 /* and allocate the window - this is normally done
4494 * in move_resize in response to configure notify
4496 allocation.width = configure_request.width;
4497 allocation.height = configure_request.height;
4498 gtk_widget_size_allocate (widget, &allocation);
4500 /* Then we guarantee we have a realize */
4501 was_realized = FALSE;
4502 if (!gtk_widget_get_realized (widget))
4504 gtk_widget_realize (widget);
4505 was_realized = TRUE;
4508 /* Must be done after the windows are realized,
4509 * so that the decorations can be read
4511 gtk_decorated_window_calculate_frame_size (window);
4513 /* We only send configure request if we didn't just finish
4514 * creating the window; if we just created the window
4515 * then we created it with widget->allocation anyhow.
4518 gdk_window_move_resize (gtk_widget_get_window (widget),
4519 configure_request.x,
4520 configure_request.y,
4521 configure_request.width,
4522 configure_request.height);
4525 gtk_container_check_resize (container);
4527 gtk_widget_map (widget);
4529 /* Try to make sure that we have some focused widget
4531 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4532 gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4535 gtk_grab_add (widget);
4539 gtk_window_hide (GtkWidget *widget)
4541 GtkWindow *window = GTK_WINDOW (widget);
4542 GtkWindowPrivate *priv = window->priv;
4544 _gtk_widget_set_visible_flag (widget, FALSE);
4545 gtk_widget_unmap (widget);
4548 gtk_grab_remove (widget);
4552 gtk_window_map (GtkWidget *widget)
4555 GtkWindow *window = GTK_WINDOW (widget);
4556 GtkWindowPrivate *priv = window->priv;
4557 GdkWindow *toplevel;
4558 GdkWindow *gdk_window;
4559 gboolean auto_mnemonics;
4561 gdk_window = gtk_widget_get_window (widget);
4563 gtk_widget_set_mapped (widget, TRUE);
4565 child = gtk_bin_get_child (&(window->bin));
4567 gtk_widget_get_visible (child) &&
4568 !gtk_widget_get_mapped (child))
4569 gtk_widget_map (child);
4572 toplevel = priv->frame;
4574 toplevel = gdk_window;
4576 if (priv->maximize_initially)
4577 gdk_window_maximize (toplevel);
4579 gdk_window_unmaximize (toplevel);
4581 if (priv->stick_initially)
4582 gdk_window_stick (toplevel);
4584 gdk_window_unstick (toplevel);
4586 if (priv->iconify_initially)
4587 gdk_window_iconify (toplevel);
4589 gdk_window_deiconify (toplevel);
4591 if (priv->fullscreen_initially)
4592 gdk_window_fullscreen (toplevel);
4594 gdk_window_unfullscreen (toplevel);
4596 gdk_window_set_keep_above (toplevel, priv->above_initially);
4598 gdk_window_set_keep_below (toplevel, priv->below_initially);
4600 /* No longer use the default settings */
4601 priv->need_default_size = FALSE;
4602 priv->need_default_position = FALSE;
4604 if (priv->reset_type_hint)
4606 /* We should only reset the type hint when the application
4607 * used gtk_window_set_type_hint() to change the hint.
4608 * Some applications use X directly to change the properties;
4609 * in that case, we shouldn't overwrite what they did.
4611 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4612 priv->reset_type_hint = FALSE;
4615 gdk_window_show (gdk_window);
4618 gdk_window_show (priv->frame);
4620 if (priv->grip_window)
4621 gdk_window_show (priv->grip_window);
4623 if (!disable_startup_notification)
4625 /* Do we have a custom startup-notification id? */
4626 if (priv->startup_id != NULL)
4628 /* Make sure we have a "real" id */
4629 if (!startup_id_is_fake (priv->startup_id))
4630 gdk_notify_startup_complete_with_id (priv->startup_id);
4632 g_free (priv->startup_id);
4633 priv->startup_id = NULL;
4635 else if (!sent_startup_notification)
4637 sent_startup_notification = TRUE;
4638 gdk_notify_startup_complete ();
4642 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4643 * (as in the case of popup menus), then hide mnemonics initially
4645 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4646 &auto_mnemonics, NULL);
4647 if (auto_mnemonics && !priv->mnemonics_visible_set)
4648 gtk_window_set_mnemonics_visible (window, FALSE);
4652 gtk_window_map_event (GtkWidget *widget,
4655 if (!gtk_widget_get_mapped (widget))
4657 /* we should be be unmapped, but are getting a MapEvent, this may happen
4658 * to toplevel XWindows if mapping was intercepted by a window manager
4659 * and an unmap request occoured while the MapRequestEvent was still
4660 * being handled. we work around this situaiton here by re-requesting
4661 * the window being unmapped. more details can be found in:
4662 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4664 gdk_window_hide (gtk_widget_get_window (widget));
4670 gtk_window_unmap (GtkWidget *widget)
4672 GtkWindow *window = GTK_WINDOW (widget);
4673 GtkWindowPrivate *priv = window->priv;
4674 GtkWindowGeometryInfo *info;
4675 GdkWindow *gdk_window;
4676 GdkWindowState state;
4678 gdk_window = gtk_widget_get_window (widget);
4680 gtk_widget_set_mapped (widget, FALSE);
4682 gdk_window_withdraw (priv->frame);
4684 gdk_window_withdraw (gdk_window);
4686 priv->configure_request_count = 0;
4687 priv->configure_notify_received = FALSE;
4689 /* on unmap, we reset the default positioning of the window,
4690 * so it's placed again, but we don't reset the default
4691 * size of the window, so it's remembered.
4693 priv->need_default_position = TRUE;
4695 info = gtk_window_get_geometry_info (window, FALSE);
4698 info->initial_pos_set = FALSE;
4699 info->position_constraints_changed = FALSE;
4702 state = gdk_window_get_state (gdk_window);
4703 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4704 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4705 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4706 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4707 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4711 gtk_window_realize (GtkWidget *widget)
4713 GtkAllocation allocation;
4716 GdkWindow *parent_window;
4717 GdkWindow *gdk_window;
4718 GdkWindowAttr attributes;
4719 gint attributes_mask;
4720 GtkWindowPrivate *priv;
4722 window = GTK_WINDOW (widget);
4723 priv = window->priv;
4725 gtk_widget_get_allocation (widget, &allocation);
4727 /* ensure widget tree is properly size allocated */
4728 if (allocation.x == -1 &&
4729 allocation.y == -1 &&
4730 allocation.width == 1 &&
4731 allocation.height == 1)
4733 GtkRequisition requisition;
4737 allocation.width = 200;
4738 allocation.height = 200;
4740 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4741 if (requisition.width || requisition.height)
4743 /* non-empty window */
4744 allocation.width = requisition.width;
4745 allocation.height = requisition.height;
4747 gtk_widget_size_allocate (widget, &allocation);
4749 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4751 g_return_if_fail (!gtk_widget_get_realized (widget));
4754 gtk_widget_set_realized (widget, TRUE);
4758 case GTK_WINDOW_TOPLEVEL:
4759 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4761 case GTK_WINDOW_POPUP:
4762 attributes.window_type = GDK_WINDOW_TEMP;
4765 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4769 attributes.title = priv->title;
4770 attributes.wmclass_name = priv->wmclass_name;
4771 attributes.wmclass_class = priv->wmclass_class;
4772 attributes.wclass = GDK_INPUT_OUTPUT;
4773 attributes.visual = gtk_widget_get_visual (widget);
4775 if (priv->has_frame)
4777 gtk_widget_get_allocation (widget, &allocation);
4778 attributes.width = allocation.width + priv->frame_left + priv->frame_right;
4779 attributes.height = allocation.height + priv->frame_top + priv->frame_bottom;
4780 attributes.event_mask = (GDK_EXPOSURE_MASK |
4781 GDK_KEY_PRESS_MASK |
4782 GDK_ENTER_NOTIFY_MASK |
4783 GDK_LEAVE_NOTIFY_MASK |
4784 GDK_FOCUS_CHANGE_MASK |
4785 GDK_STRUCTURE_MASK |
4786 GDK_BUTTON_MOTION_MASK |
4787 GDK_POINTER_MOTION_HINT_MASK |
4788 GDK_BUTTON_PRESS_MASK |
4789 GDK_BUTTON_RELEASE_MASK);
4791 attributes_mask = GDK_WA_VISUAL;
4793 priv->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4794 &attributes, attributes_mask);
4796 if (priv->opacity_set)
4797 gdk_window_set_opacity (priv->frame, priv->opacity);
4799 gdk_window_set_user_data (priv->frame, widget);
4801 attributes.window_type = GDK_WINDOW_CHILD;
4802 attributes.x = priv->frame_left;
4803 attributes.y = priv->frame_top;
4805 attributes_mask = GDK_WA_X | GDK_WA_Y;
4807 parent_window = priv->frame;
4809 g_signal_connect (window,
4811 G_CALLBACK (gtk_window_event),
4816 attributes_mask = 0;
4817 parent_window = gtk_widget_get_root_window (widget);
4820 gtk_widget_get_allocation (widget, &allocation);
4821 attributes.width = allocation.width;
4822 attributes.height = allocation.height;
4823 attributes.event_mask = gtk_widget_get_events (widget);
4824 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4825 GDK_KEY_PRESS_MASK |
4826 GDK_KEY_RELEASE_MASK |
4827 GDK_ENTER_NOTIFY_MASK |
4828 GDK_LEAVE_NOTIFY_MASK |
4829 GDK_FOCUS_CHANGE_MASK |
4830 GDK_STRUCTURE_MASK);
4831 attributes.type_hint = priv->type_hint;
4833 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4834 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4835 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4837 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4838 gtk_widget_set_window (widget, gdk_window);
4840 if (!priv->has_frame && priv->opacity_set)
4841 gdk_window_set_opacity (gdk_window, priv->opacity);
4843 gdk_window_enable_synchronized_configure (gdk_window);
4845 gdk_window_set_user_data (gdk_window, window);
4847 gtk_widget_style_attach (widget);
4848 style = gtk_widget_get_style (widget);
4849 gtk_style_set_background (style, gdk_window, GTK_STATE_NORMAL);
4851 gtk_style_set_background (style, priv->frame, GTK_STATE_NORMAL);
4853 if (priv->transient_parent &&
4854 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
4855 gdk_window_set_transient_for (gdk_window,
4856 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
4859 gdk_window_set_role (gdk_window, priv->wm_role);
4861 if (!priv->decorated)
4862 gdk_window_set_decorations (gdk_window, 0);
4864 if (!priv->deletable)
4865 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4867 if (gtk_window_get_skip_pager_hint (window))
4868 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
4870 if (gtk_window_get_skip_taskbar_hint (window))
4871 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
4873 if (gtk_window_get_accept_focus (window))
4874 gdk_window_set_accept_focus (gdk_window, TRUE);
4876 gdk_window_set_accept_focus (gdk_window, FALSE);
4878 if (gtk_window_get_focus_on_map (window))
4879 gdk_window_set_focus_on_map (gdk_window, TRUE);
4881 gdk_window_set_focus_on_map (gdk_window, FALSE);
4884 gdk_window_set_modal_hint (gdk_window, TRUE);
4886 gdk_window_set_modal_hint (gdk_window, FALSE);
4888 if (priv->startup_id)
4890 #ifdef GDK_WINDOWING_X11
4891 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4892 if (timestamp != GDK_CURRENT_TIME)
4893 gdk_x11_window_set_user_time (gdk_window, timestamp);
4895 if (!startup_id_is_fake (priv->startup_id))
4896 gdk_window_set_startup_id (gdk_window, priv->startup_id);
4900 gtk_window_realize_icon (window);
4902 if (priv->has_resize_grip)
4903 resize_grip_create_window (window);
4907 gtk_window_unrealize (GtkWidget *widget)
4909 GtkWindow *window = GTK_WINDOW (widget);
4910 GtkWindowPrivate *priv = window->priv;
4911 GtkWindowGeometryInfo *info;
4913 /* On unrealize, we reset the size of the window such
4914 * that we will re-apply the default sizing stuff
4915 * next time we show the window.
4917 * Default positioning is reset on unmap, instead of unrealize.
4919 priv->need_default_size = TRUE;
4920 info = gtk_window_get_geometry_info (window, FALSE);
4923 info->resize_width = -1;
4924 info->resize_height = -1;
4925 info->last.configure_request.x = 0;
4926 info->last.configure_request.y = 0;
4927 info->last.configure_request.width = -1;
4928 info->last.configure_request.height = -1;
4929 /* be sure we reset geom hints on re-realize */
4930 info->last.flags = 0;
4935 gdk_window_set_user_data (priv->frame, NULL);
4936 gdk_window_destroy (priv->frame);
4941 gtk_window_unrealize_icon (window);
4943 if (priv->grip_window != NULL)
4944 resize_grip_destroy_window (window);
4946 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
4949 static GdkWindowEdge
4950 get_grip_edge (GtkWidget *widget)
4952 return gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
4956 set_grip_cursor (GtkWindow *window)
4958 GtkWidget *widget = GTK_WIDGET (window);
4959 GtkWindowPrivate *priv = window->priv;
4961 GdkDisplay *display;
4962 GdkCursorType cursor_type;
4965 if (priv->grip_window == NULL)
4968 if (gtk_widget_is_sensitive (widget))
4970 edge = get_grip_edge (widget);
4972 if (edge == GDK_WINDOW_EDGE_SOUTH_EAST)
4973 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
4975 cursor_type = GDK_BOTTOM_LEFT_CORNER;
4977 display = gtk_widget_get_display (widget);
4978 cursor = gdk_cursor_new_for_display (display, cursor_type);
4979 gdk_window_set_cursor (priv->grip_window, cursor);
4980 gdk_cursor_unref (cursor);
4983 gdk_window_set_cursor (priv->grip_window, NULL);
4987 set_grip_shape (GtkWindow *window)
4989 GtkWindowPrivate *priv = window->priv;
4990 cairo_region_t *region;
4991 cairo_surface_t *surface;
4993 double width, height;
4995 if (priv->grip_window == NULL)
4998 width = gdk_window_get_width (priv->grip_window);
4999 height = gdk_window_get_height (priv->grip_window);
5000 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5002 cr = cairo_create (surface);
5003 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5005 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5006 if (get_grip_edge (GTK_WIDGET (window)) == GDK_WINDOW_EDGE_SOUTH_EAST)
5008 cairo_move_to (cr, width, 0.0);
5009 cairo_line_to (cr, width, height);
5010 cairo_line_to (cr, 0.0, height);
5014 cairo_move_to (cr, 0.0, 0.0);
5015 cairo_line_to (cr, width, height);
5016 cairo_line_to (cr, 0.0, height);
5018 cairo_close_path (cr);
5021 region = gdk_cairo_region_create_from_surface (surface);
5022 cairo_surface_destroy (surface);
5024 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5025 cairo_region_destroy (region);
5029 set_grip_position (GtkWindow *window)
5031 GtkWindowPrivate *priv = window->priv;
5034 if (priv->grip_window == NULL)
5037 gtk_window_get_resize_grip_area (window, &rect);
5038 gdk_window_raise (priv->grip_window);
5039 gdk_window_move_resize (priv->grip_window,
5041 rect.width, rect.height);
5045 gtk_window_size_allocate (GtkWidget *widget,
5046 GtkAllocation *allocation)
5048 GtkWindow *window = GTK_WINDOW (widget);
5049 GtkWindowPrivate *priv = window->priv;
5050 GtkAllocation child_allocation;
5054 gtk_widget_set_allocation (widget, allocation);
5056 child = gtk_bin_get_child (&(window->bin));
5057 if (child && gtk_widget_get_visible (child))
5059 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5060 child_allocation.x = border_width;
5061 child_allocation.y = border_width;
5062 child_allocation.width =
5063 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5064 child_allocation.height =
5065 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5067 gtk_widget_size_allocate (child, &child_allocation);
5070 if (gtk_widget_get_realized (widget))
5073 gdk_window_resize (priv->frame,
5074 allocation->width + priv->frame_left + priv->frame_right,
5075 allocation->height + priv->frame_top + priv->frame_bottom);
5076 set_grip_position (window);
5081 gtk_window_event (GtkWidget *widget, GdkEvent *event)
5083 GtkWindow *window = GTK_WINDOW (widget);
5084 GtkWindowPrivate *priv = window->priv;
5085 gboolean return_val;
5087 if (priv->frame && (event->any.window == priv->frame))
5089 if ((event->type != GDK_KEY_PRESS) &&
5090 (event->type != GDK_KEY_RELEASE) &&
5091 (event->type != GDK_FOCUS_CHANGE))
5093 g_signal_stop_emission_by_name (widget, "event");
5095 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
5100 g_object_unref (event->any.window);
5101 event->any.window = g_object_ref (gtk_widget_get_window (widget));
5109 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
5111 GtkWindowPrivate *priv = window->priv;
5112 GdkEventConfigure *configure_event;
5115 switch (event->type)
5118 configure_event = (GdkEventConfigure *)event;
5120 /* Invalidate the decorations */
5123 rect.width = configure_event->width;
5124 rect.height = configure_event->height;
5126 gdk_window_invalidate_rect (priv->frame, &rect, FALSE);
5128 /* Pass on the (modified) configure event */
5129 configure_event->width -= priv->frame_left + priv->frame_right;
5130 configure_event->height -= priv->frame_top + priv->frame_bottom;
5131 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
5140 gtk_window_configure_event (GtkWidget *widget,
5141 GdkEventConfigure *event)
5143 GtkAllocation allocation;
5144 GtkWindow *window = GTK_WINDOW (widget);
5145 GtkWindowPrivate *priv = window->priv;
5146 gboolean expected_reply = priv->configure_request_count > 0;
5148 /* priv->configure_request_count incremented for each
5149 * configure request, and decremented to a min of 0 for
5150 * each configure notify.
5152 * All it means is that we know we will get at least
5153 * priv->configure_request_count more configure notifies.
5154 * We could get more configure notifies than that; some
5155 * of the configure notifies we get may be unrelated to
5156 * the configure requests. But we will get at least
5157 * priv->configure_request_count notifies.
5160 if (priv->configure_request_count > 0)
5162 priv->configure_request_count -= 1;
5163 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5166 /* As an optimization, we avoid a resize when possible.
5168 * The only times we can avoid a resize are:
5169 * - we know only the position changed, not the size
5170 * - we know we have made more requests and so will get more
5171 * notifies and can wait to resize when we get them
5173 gtk_widget_get_allocation (widget, &allocation);
5174 if (!expected_reply &&
5175 (allocation.width == event->width &&
5176 allocation.height == event->height))
5178 gdk_window_configure_finished (gtk_widget_get_window (widget));
5183 * If we do need to resize, we do that by:
5184 * - filling in widget->allocation with the new size
5185 * - setting configure_notify_received to TRUE
5186 * for use in gtk_window_move_resize()
5187 * - queueing a resize, leading to invocation of
5188 * gtk_window_move_resize() in an idle handler
5192 priv->configure_notify_received = TRUE;
5194 allocation.width = event->width;
5195 allocation.height = event->height;
5196 gtk_widget_set_allocation (widget, &allocation);
5198 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5200 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5206 gtk_window_state_event (GtkWidget *widget,
5207 GdkEventWindowState *event)
5209 update_grip_visibility (GTK_WINDOW (widget));
5215 gtk_window_direction_changed (GtkWidget *widget,
5216 GtkTextDirection prev_dir)
5218 GtkWindow *window = GTK_WINDOW (widget);
5220 set_grip_cursor (window);
5221 set_grip_position (window);
5222 set_grip_shape (window);
5226 gtk_window_state_changed (GtkWidget *widget,
5227 GtkStateType previous_state)
5229 GtkWindow *window = GTK_WINDOW (widget);
5231 set_grip_cursor (window);
5232 update_grip_visibility (window);
5236 resize_grip_create_window (GtkWindow *window)
5239 GtkWindowPrivate *priv;
5240 GdkWindowAttr attributes;
5241 gint attributes_mask;
5244 priv = window->priv;
5245 widget = GTK_WIDGET (window);
5247 g_return_if_fail (gtk_widget_get_realized (widget));
5248 g_return_if_fail (priv->grip_window == NULL);
5250 gtk_window_get_resize_grip_area (window, &rect);
5252 attributes.x = rect.x;
5253 attributes.y = rect.y;
5254 attributes.width = rect.width;
5255 attributes.height = rect.height;
5256 attributes.window_type = GDK_WINDOW_CHILD;
5257 attributes.wclass = GDK_INPUT_OUTPUT;
5258 attributes.event_mask = gtk_widget_get_events (widget) |
5260 GDK_BUTTON_PRESS_MASK;
5262 attributes_mask = GDK_WA_X | GDK_WA_Y;
5264 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5268 gdk_window_set_user_data (priv->grip_window, widget);
5270 gdk_window_raise (priv->grip_window);
5272 set_grip_cursor (window);
5273 set_grip_shape (window);
5274 update_grip_visibility (window);
5278 resize_grip_destroy_window (GtkWindow *window)
5280 GtkWindowPrivate *priv = window->priv;
5282 gdk_window_set_user_data (priv->grip_window, NULL);
5283 gdk_window_destroy (priv->grip_window);
5284 priv->grip_window = NULL;
5285 update_grip_visibility (window);
5289 * gtk_window_set_has_resize_grip:
5290 * @window: a #GtkWindow
5291 * @value: %TRUE to allow a resize grip
5293 * Sets whether @window has a corner resize grip.
5295 * Note that the resize grip is only shown if the window
5296 * is actually resizable and not maximized. Use
5297 * gtk_window_resize_grip_is_visible() to find out if the
5298 * resize grip is currently shown.
5303 gtk_window_set_has_resize_grip (GtkWindow *window,
5306 GtkWidget *widget = GTK_WIDGET (window);
5307 GtkWindowPrivate *priv = window->priv;
5309 value = value != FALSE;
5311 if (value != priv->has_resize_grip)
5313 priv->has_resize_grip = value;
5314 gtk_widget_queue_draw (widget);
5316 if (gtk_widget_get_realized (widget))
5318 if (priv->has_resize_grip && priv->grip_window == NULL)
5319 resize_grip_create_window (window);
5320 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5321 resize_grip_destroy_window (window);
5324 g_object_notify (G_OBJECT (window), "has-resize-grip");
5329 update_grip_visibility (GtkWindow *window)
5331 GtkWindowPrivate *priv = window->priv;
5334 val = gtk_window_resize_grip_is_visible (window);
5336 if (priv->grip_window != NULL)
5339 gdk_window_show (priv->grip_window);
5341 gdk_window_hide (priv->grip_window);
5344 if (priv->resize_grip_visible != val)
5346 priv->resize_grip_visible = val;
5348 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5353 * gtk_window_resize_grip_is_visible:
5354 * @window: a #GtkWindow
5356 * Determines whether a resize grip is visible for the specified window.
5358 * Returns %TRUE if a resize grip exists and is visible.
5363 gtk_window_resize_grip_is_visible (GtkWindow *window)
5365 GtkWindowPrivate *priv;
5367 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5369 priv = window->priv;
5371 if (priv->type == GTK_WINDOW_POPUP)
5374 if (!priv->resizable)
5377 if (gtk_widget_get_realized (GTK_WIDGET (window)))
5379 GdkWindowState state;
5381 state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)));
5383 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5387 return window->priv->has_resize_grip;
5391 * gtk_window_get_has_resize_grip:
5392 * @window: a #GtkWindow
5394 * Determines whether the window may has a resize grip.
5396 * Returns: %TRUE if the window has a resize grip.
5401 gtk_window_get_has_resize_grip (GtkWindow *window)
5403 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5405 return window->priv->has_resize_grip;
5409 * gtk_window_get_resize_grip_area:
5410 * @window: a #GtkWindow
5411 * @rect: a pointer to a #GdkRectangle which we should store the
5414 * If a window has a resize grip, this will retrieve the grip
5415 * position, width and height into the specified #GdkRectangle.
5417 * Returns: %TRUE if the resize grip's area was retrieved.
5422 gtk_window_get_resize_grip_area (GtkWindow *window,
5425 GtkWidget *widget = GTK_WIDGET (window);
5426 GtkAllocation allocation;
5431 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5433 if (!window->priv->has_resize_grip)
5436 gtk_widget_get_allocation (widget, &allocation);
5437 style = gtk_widget_get_style (widget);
5439 gtk_widget_style_get (widget,
5440 "resize-grip-width", &grip_width,
5441 "resize-grip-height", &grip_height,
5444 if (grip_width > allocation.width)
5445 grip_width = allocation.width;
5447 if (grip_height > allocation.height)
5448 grip_height = allocation.height;
5450 rect->width = grip_width;
5451 rect->height = grip_height;
5452 rect->y = allocation.y + allocation.height - grip_height;
5454 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5455 rect->x = allocation.x + allocation.width - grip_width;
5457 rect->x = allocation.x;
5462 /* the accel_key and accel_mods fields of the key have to be setup
5463 * upon calling this function. it'll then return whether that key
5464 * is at all used as accelerator, and if so will OR in the
5465 * accel_flags member of the key.
5468 _gtk_window_query_nonaccels (GtkWindow *window,
5470 GdkModifierType accel_mods)
5472 GtkWindowPrivate *priv;
5474 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5476 priv = window->priv;
5478 /* movement keys are considered locked accels */
5481 static const guint bindings[] = {
5482 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,
5483 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,
5487 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5488 if (bindings[i] == accel_key)
5492 /* mnemonics are considered locked accels */
5493 if (accel_mods == priv->mnemonic_modifier)
5495 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5496 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5504 * gtk_window_propagate_key_event:
5505 * @window: a #GtkWindow
5506 * @event: a #GdkEventKey
5508 * Propagate a key press or release event to the focus widget and
5509 * up the focus container chain until a widget handles @event.
5510 * This is normally called by the default ::key_press_event and
5511 * ::key_release_event handlers for toplevel windows,
5512 * however in some cases it may be useful to call this directly when
5513 * overriding the standard key handling for a toplevel window.
5515 * Return value: %TRUE if a widget in the focus chain handled the event.
5520 gtk_window_propagate_key_event (GtkWindow *window,
5523 GtkWindowPrivate *priv;
5524 gboolean handled = FALSE;
5525 GtkWidget *widget, *focus;
5527 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5529 priv = window->priv;
5530 widget = GTK_WIDGET (window);
5532 focus = priv->focus_widget;
5534 g_object_ref (focus);
5537 focus && focus != widget &&
5538 gtk_widget_get_toplevel (focus) == widget)
5542 if (gtk_widget_is_sensitive (focus))
5543 handled = gtk_widget_event (focus, (GdkEvent*) event);
5545 parent = gtk_widget_get_parent (focus);
5547 g_object_ref (parent);
5549 g_object_unref (focus);
5555 g_object_unref (focus);
5561 gtk_window_key_press_event (GtkWidget *widget,
5564 GtkWindow *window = GTK_WINDOW (widget);
5565 gboolean handled = FALSE;
5567 /* handle mnemonics and accelerators */
5569 handled = gtk_window_activate_key (window, event);
5571 /* handle focus widget key events */
5573 handled = gtk_window_propagate_key_event (window, event);
5575 /* Chain up, invokes binding set */
5577 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5583 gtk_window_key_release_event (GtkWidget *widget,
5586 GtkWindow *window = GTK_WINDOW (widget);
5587 gboolean handled = FALSE;
5589 /* handle focus widget key events */
5591 handled = gtk_window_propagate_key_event (window, event);
5593 /* Chain up, invokes binding set */
5595 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5601 gtk_window_button_press_event (GtkWidget *widget,
5602 GdkEventButton *event)
5604 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5606 if (event->window == priv->grip_window)
5607 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5608 get_grip_edge (widget),
5618 gtk_window_real_activate_default (GtkWindow *window)
5620 gtk_window_activate_default (window);
5624 gtk_window_real_activate_focus (GtkWindow *window)
5626 gtk_window_activate_focus (window);
5630 gtk_window_move_focus (GtkWindow *window,
5631 GtkDirectionType dir)
5633 gtk_widget_child_focus (GTK_WIDGET (window), dir);
5635 if (!gtk_container_get_focus_child (GTK_CONTAINER (window)))
5636 gtk_window_set_focus (window, NULL);
5640 gtk_window_enter_notify_event (GtkWidget *widget,
5641 GdkEventCrossing *event)
5647 gtk_window_leave_notify_event (GtkWidget *widget,
5648 GdkEventCrossing *event)
5654 do_focus_change (GtkWidget *widget,
5658 GdkDeviceManager *device_manager;
5661 g_object_ref (widget);
5663 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5664 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5665 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5666 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5668 for (d = devices; d; d = d->next)
5670 GdkDevice *dev = d->data;
5673 if (dev->source != GDK_SOURCE_KEYBOARD)
5676 /* Skip non-master keyboards that haven't
5677 * selected for events from this window
5679 window = gtk_widget_get_window (widget);
5680 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5681 window && !gdk_window_get_device_events (window, dev))
5684 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5686 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5687 fevent->focus_change.window = window;
5689 g_object_ref (window);
5690 fevent->focus_change.in = in;
5691 gdk_event_set_device (fevent, dev);
5693 gtk_widget_send_focus_change (widget, fevent);
5695 gdk_event_free (fevent);
5698 g_list_free (devices);
5699 g_object_unref (widget);
5703 gtk_window_focus_in_event (GtkWidget *widget,
5704 GdkEventFocus *event)
5706 GtkWindow *window = GTK_WINDOW (widget);
5708 /* It appears spurious focus in events can occur when
5709 * the window is hidden. So we'll just check to see if
5710 * the window is visible before actually handling the
5713 if (gtk_widget_get_visible (widget))
5715 _gtk_window_set_has_toplevel_focus (window, TRUE);
5716 _gtk_window_set_is_active (window, TRUE);
5723 gtk_window_focus_out_event (GtkWidget *widget,
5724 GdkEventFocus *event)
5726 GtkWindow *window = GTK_WINDOW (widget);
5727 gboolean auto_mnemonics;
5729 _gtk_window_set_has_toplevel_focus (window, FALSE);
5730 _gtk_window_set_is_active (window, FALSE);
5732 /* set the mnemonic-visible property to false */
5733 g_object_get (gtk_widget_get_settings (widget),
5734 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5736 gtk_window_set_mnemonics_visible (window, FALSE);
5741 static GdkAtom atom_rcfiles = GDK_NONE;
5742 static GdkAtom atom_iconthemes = GDK_NONE;
5745 send_client_message_to_embedded_windows (GtkWidget *widget,
5746 GdkAtom message_type)
5748 GList *embedded_windows;
5750 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5751 if (embedded_windows)
5753 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5756 for (i = 0; i < 5; i++)
5757 send_event->client.data.l[i] = 0;
5758 send_event->client.data_format = 32;
5759 send_event->client.message_type = message_type;
5761 while (embedded_windows)
5763 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
5764 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5765 embedded_windows = embedded_windows->next;
5768 gdk_event_free (send_event);
5773 gtk_window_client_event (GtkWidget *widget,
5774 GdkEventClient *event)
5778 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5779 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5782 if (event->message_type == atom_rcfiles)
5784 send_client_message_to_embedded_windows (widget, atom_rcfiles);
5785 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
5788 if (event->message_type == atom_iconthemes)
5790 send_client_message_to_embedded_windows (widget, atom_iconthemes);
5791 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
5798 gtk_window_check_resize (GtkContainer *container)
5800 if (gtk_widget_get_visible (GTK_WIDGET (container)))
5801 gtk_window_move_resize (GTK_WINDOW (container));
5805 gtk_window_focus (GtkWidget *widget,
5806 GtkDirectionType direction)
5808 GtkWindowPrivate *priv;
5811 GtkContainer *container;
5813 GtkWidget *old_focus_child;
5816 container = GTK_CONTAINER (widget);
5817 window = GTK_WINDOW (widget);
5818 priv = window->priv;
5819 bin = GTK_BIN (widget);
5821 old_focus_child = gtk_container_get_focus_child (container);
5823 /* We need a special implementation here to deal properly with wrapping
5824 * around in the tab chain without the danger of going into an
5827 if (old_focus_child)
5829 if (gtk_widget_child_focus (old_focus_child, direction))
5833 if (priv->focus_widget)
5835 if (direction == GTK_DIR_LEFT ||
5836 direction == GTK_DIR_RIGHT ||
5837 direction == GTK_DIR_UP ||
5838 direction == GTK_DIR_DOWN)
5843 /* Wrapped off the end, clear the focus setting for the toplpevel */
5844 parent = gtk_widget_get_parent (priv->focus_widget);
5847 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5848 parent = gtk_widget_get_parent (parent);
5851 gtk_window_set_focus (GTK_WINDOW (container), NULL);
5854 /* Now try to focus the first widget in the window */
5855 child = gtk_bin_get_child (bin);
5858 if (gtk_widget_child_focus (child, direction))
5866 gtk_window_real_set_focus (GtkWindow *window,
5869 GtkWindowPrivate *priv = window->priv;
5870 GtkWidget *old_focus = priv->focus_widget;
5871 gboolean had_default = FALSE;
5872 gboolean focus_had_default = FALSE;
5873 gboolean old_focus_had_default = FALSE;
5877 g_object_ref (old_focus);
5878 g_object_freeze_notify (G_OBJECT (old_focus));
5879 old_focus_had_default = gtk_widget_has_default (old_focus);
5883 g_object_ref (focus);
5884 g_object_freeze_notify (G_OBJECT (focus));
5885 focus_had_default = gtk_widget_has_default (focus);
5888 if (priv->default_widget)
5889 had_default = gtk_widget_has_default (priv->default_widget);
5891 if (priv->focus_widget)
5893 if (gtk_widget_get_receives_default (priv->focus_widget) &&
5894 (priv->focus_widget != priv->default_widget))
5896 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
5897 gtk_widget_queue_draw (priv->focus_widget);
5899 if (priv->default_widget)
5900 _gtk_widget_set_has_default (priv->default_widget, TRUE);
5903 priv->focus_widget = NULL;
5905 if (priv->has_focus)
5906 do_focus_change (old_focus, FALSE);
5908 g_object_notify (G_OBJECT (old_focus), "is-focus");
5911 /* The above notifications may have set a new focus widget,
5912 * if so, we don't want to override it.
5914 if (focus && !priv->focus_widget)
5916 priv->focus_widget = focus;
5918 if (gtk_widget_get_receives_default (priv->focus_widget) &&
5919 (priv->focus_widget != priv->default_widget))
5921 if (gtk_widget_get_can_default (priv->focus_widget))
5922 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
5924 if (priv->default_widget)
5925 _gtk_widget_set_has_default (priv->default_widget, FALSE);
5928 if (priv->has_focus)
5929 do_focus_change (priv->focus_widget, TRUE);
5931 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
5934 /* If the default widget changed, a redraw will have been queued
5935 * on the old and new default widgets by gtk_window_set_default(), so
5936 * we only have to worry about the case where it didn't change.
5937 * We'll sometimes queue a draw twice on the new widget but that
5940 if (priv->default_widget &&
5941 (had_default != gtk_widget_has_default (priv->default_widget)))
5942 gtk_widget_queue_draw (priv->default_widget);
5946 if (old_focus_had_default != gtk_widget_has_default (old_focus))
5947 gtk_widget_queue_draw (old_focus);
5949 g_object_thaw_notify (G_OBJECT (old_focus));
5950 g_object_unref (old_focus);
5954 if (focus_had_default != gtk_widget_has_default (focus))
5955 gtk_widget_queue_draw (focus);
5957 g_object_thaw_notify (G_OBJECT (focus));
5958 g_object_unref (focus);
5964 gtk_window_get_preferred_width (GtkWidget *widget,
5972 window = GTK_WINDOW (widget);
5973 child = gtk_bin_get_child (GTK_BIN (window));
5975 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5976 *minimum_size = border_width * 2;
5977 *natural_size = border_width * 2;
5979 if (child && gtk_widget_get_visible (child))
5981 gint child_min, child_nat;
5982 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
5984 *minimum_size += child_min;
5985 *natural_size += child_nat;
5990 gtk_window_get_preferred_height (GtkWidget *widget,
5998 window = GTK_WINDOW (widget);
5999 child = gtk_bin_get_child (GTK_BIN (window));
6001 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6002 *minimum_size = border_width * 2;
6003 *natural_size = border_width * 2;
6005 if (child && gtk_widget_get_visible (child))
6007 gint child_min, child_nat;
6008 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6010 *minimum_size += child_min;
6011 *natural_size += child_nat;
6017 * _gtk_window_unset_focus_and_default:
6018 * @window: a #GtkWindow
6019 * @widget: a widget inside of @window
6021 * Checks whether the focus and default widgets of @window are
6022 * @widget or a descendent of @widget, and if so, unset them.
6025 _gtk_window_unset_focus_and_default (GtkWindow *window,
6029 GtkWindowPrivate *priv = window->priv;
6033 g_object_ref (window);
6034 g_object_ref (widget);
6036 parent = gtk_widget_get_parent (widget);
6037 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6039 child = priv->focus_widget;
6041 while (child && child != widget)
6042 child = gtk_widget_get_parent (child);
6044 if (child == widget)
6045 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6048 child = priv->default_widget;
6050 while (child && child != widget)
6051 child = gtk_widget_get_parent (child);
6053 if (child == widget)
6054 gtk_window_set_default (window, NULL);
6056 g_object_unref (widget);
6057 g_object_unref (window);
6060 /*********************************
6061 * Functions related to resizing *
6062 *********************************/
6064 /* This function doesn't constrain to geometry hints */
6066 gtk_window_compute_configure_request_size (GtkWindow *window,
6070 GtkWindowPrivate *priv = window->priv;
6071 GtkRequisition requisition;
6072 GtkWindowGeometryInfo *info;
6076 * - we've done a size request
6079 widget = GTK_WIDGET (window);
6081 info = gtk_window_get_geometry_info (window, FALSE);
6083 if (priv->need_default_size)
6085 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6087 /* Default to requisition */
6088 *width = requisition.width;
6089 *height = requisition.height;
6091 /* If window is empty so requests 0, default to random nonzero size */
6092 if (*width == 0 && *height == 0)
6098 /* Override requisition with default size */
6102 gint base_width = 0;
6103 gint base_height = 0;
6105 gint min_height = 0;
6107 gint height_inc = 1;
6109 if (info->default_is_geometry &&
6110 (info->default_width > 0 || info->default_height > 0))
6112 GdkGeometry geometry;
6115 gtk_window_compute_hints (window, &geometry, &flags);
6117 if (flags & GDK_HINT_BASE_SIZE)
6119 base_width = geometry.base_width;
6120 base_height = geometry.base_height;
6122 if (flags & GDK_HINT_MIN_SIZE)
6124 min_width = geometry.min_width;
6125 min_height = geometry.min_height;
6127 if (flags & GDK_HINT_RESIZE_INC)
6129 width_inc = geometry.width_inc;
6130 height_inc = geometry.height_inc;
6134 if (info->default_width > 0)
6135 *width = MAX (info->default_width * width_inc + base_width, min_width);
6137 if (info->default_height > 0)
6138 *height = MAX (info->default_height * height_inc + base_height, min_height);
6143 GtkAllocation allocation;
6145 gtk_widget_get_allocation (widget, &allocation);
6147 /* Default to keeping current size */
6148 *width = allocation.width;
6149 *height = allocation.height;
6152 /* Override any size with gtk_window_resize() values */
6155 if (info->resize_width > 0)
6156 *width = info->resize_width;
6158 if (info->resize_height > 0)
6159 *height = info->resize_height;
6162 /* Don't ever request zero width or height, its not supported by
6163 gdk. The size allocation code will round it to 1 anyway but if
6164 we do it then the value returned from this function will is
6165 not comparable to the size allocation read from the GtkWindow. */
6166 *width = MAX (*width, 1);
6167 *height = MAX (*height, 1);
6170 static GtkWindowPosition
6171 get_effective_position (GtkWindow *window)
6173 GtkWindowPrivate *priv = window->priv;
6174 GtkWindowPosition pos = priv->position;
6176 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6177 (priv->transient_parent == NULL ||
6178 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6179 pos = GTK_WIN_POS_NONE;
6185 get_center_monitor_of_window (GtkWindow *window)
6187 /* We could try to sort out the relative positions of the monitors and
6188 * stuff, or we could just be losers and assume you have a row
6189 * or column of monitors.
6191 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6195 get_monitor_containing_pointer (GtkWindow *window)
6199 GdkScreen *window_screen;
6200 GdkScreen *pointer_screen;
6201 GdkDisplay *display;
6202 GdkDeviceManager *device_manager;
6205 window_screen = gtk_window_check_screen (window);
6206 display = gdk_screen_get_display (window_screen);
6207 device_manager = gdk_display_get_device_manager (display);
6208 pointer = gdk_device_manager_get_client_pointer (device_manager);
6210 gdk_display_get_device_state (display, pointer,
6214 if (pointer_screen == window_screen)
6215 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6223 center_window_on_monitor (GtkWindow *window,
6229 GdkRectangle monitor;
6232 monitor_num = get_monitor_containing_pointer (window);
6234 if (monitor_num == -1)
6235 monitor_num = get_center_monitor_of_window (window);
6237 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6238 monitor_num, &monitor);
6240 *x = (monitor.width - w) / 2 + monitor.x;
6241 *y = (monitor.height - h) / 2 + monitor.y;
6243 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6244 * and WM decorations.
6258 if (extent > clamp_extent)
6260 *base = clamp_base + clamp_extent/2 - extent/2;
6261 else if (*base < clamp_base)
6263 else if (*base + extent > clamp_base + clamp_extent)
6264 *base = clamp_base + clamp_extent - extent;
6268 clamp_window_to_rectangle (gint *x,
6272 const GdkRectangle *rect)
6274 #ifdef DEBUGGING_OUTPUT
6275 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);
6278 /* If it is too large, center it. If it fits on the monitor but is
6279 * partially outside, move it to the closest edge. Do this
6280 * separately in x and y directions.
6282 clamp (x, w, rect->x, rect->width);
6283 clamp (y, h, rect->y, rect->height);
6284 #ifdef DEBUGGING_OUTPUT
6285 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6291 gtk_window_compute_configure_request (GtkWindow *window,
6292 GdkRectangle *request,
6293 GdkGeometry *geometry,
6296 GtkWindowPrivate *priv = window->priv;
6297 GdkGeometry new_geometry;
6301 GtkWindowPosition pos;
6302 GtkWidget *parent_widget;
6303 GtkWindowGeometryInfo *info;
6307 widget = GTK_WIDGET (window);
6309 screen = gtk_window_check_screen (window);
6311 gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
6313 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6314 gtk_window_constrain_size (window,
6315 &new_geometry, new_flags,
6319 parent_widget = (GtkWidget*) priv->transient_parent;
6321 pos = get_effective_position (window);
6322 info = gtk_window_get_geometry_info (window, FALSE);
6324 /* by default, don't change position requested */
6327 x = info->last.configure_request.x;
6328 y = info->last.configure_request.y;
6337 if (priv->need_default_position)
6340 /* FIXME this all interrelates with window gravity.
6341 * For most of them I think we want to set GRAVITY_CENTER.
6343 * Not sure how to go about that.
6348 /* here we are only handling CENTER_ALWAYS
6349 * as it relates to default positioning,
6350 * where it's equivalent to simply CENTER
6352 case GTK_WIN_POS_CENTER_ALWAYS:
6353 case GTK_WIN_POS_CENTER:
6354 center_window_on_monitor (window, w, h, &x, &y);
6357 case GTK_WIN_POS_CENTER_ON_PARENT:
6359 GtkAllocation allocation;
6360 GdkWindow *gdk_window;
6362 GdkRectangle monitor;
6365 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6367 gdk_window = gtk_widget_get_window (parent_widget);
6369 if (gdk_window != NULL)
6370 monitor_num = gdk_screen_get_monitor_at_window (screen,
6375 gdk_window_get_origin (gdk_window,
6378 gtk_widget_get_allocation (parent_widget, &allocation);
6379 x = ox + (allocation.width - w) / 2;
6380 y = oy + (allocation.height - h) / 2;
6382 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6383 * WM decorations. If parent wasn't on a monitor, just
6386 if (monitor_num >= 0)
6388 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6389 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6394 case GTK_WIN_POS_MOUSE:
6396 gint screen_width = gdk_screen_get_width (screen);
6397 gint screen_height = gdk_screen_get_height (screen);
6399 GdkRectangle monitor;
6400 GdkDisplay *display;
6401 GdkDeviceManager *device_manager;
6403 GdkScreen *pointer_screen;
6406 display = gdk_screen_get_display (screen);
6407 device_manager = gdk_display_get_device_manager (display);
6408 pointer = gdk_device_manager_get_client_pointer (device_manager);
6410 gdk_display_get_device_state (display, pointer,
6414 if (pointer_screen == screen)
6415 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6421 x = CLAMP (x, 0, screen_width - w);
6422 y = CLAMP (y, 0, screen_height - h);
6424 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6425 * WM decorations. Don't try to figure out what's going
6426 * on if the mouse wasn't inside a monitor.
6428 if (monitor_num >= 0)
6430 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6431 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6439 } /* if (priv->need_default_position) */
6441 if (priv->need_default_position && info &&
6442 info->initial_pos_set)
6444 x = info->initial_x;
6445 y = info->initial_y;
6446 gtk_window_constrain_position (window, w, h, &x, &y);
6452 request->height = h;
6455 *geometry = new_geometry;
6461 gtk_window_constrain_position (GtkWindow *window,
6467 GtkWindowPrivate *priv = window->priv;
6469 /* See long comments in gtk_window_move_resize()
6470 * on when it's safe to call this function.
6472 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6474 gint center_x, center_y;
6476 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6484 gtk_window_move_resize (GtkWindow *window)
6488 * First we determine whether any information has changed that would
6489 * cause us to revise our last configure request. If we would send
6490 * a different configure request from last time, then
6491 * configure_request_size_changed = TRUE or
6492 * configure_request_pos_changed = TRUE. configure_request_size_changed
6493 * may be true due to new hints, a gtk_window_resize(), or whatever.
6494 * configure_request_pos_changed may be true due to gtk_window_set_position()
6495 * or gtk_window_move().
6497 * If the configure request has changed, we send off a new one. To
6498 * ensure GTK+ invariants are maintained (resize queue does what it
6499 * should), we go ahead and size_allocate the requested size in this
6502 * If the configure request has not changed, we don't ever resend
6503 * it, because it could mean fighting the user or window manager.
6506 * To prepare the configure request, we come up with a base size/pos:
6507 * - the one from gtk_window_move()/gtk_window_resize()
6508 * - else default_width, default_height if we haven't ever
6510 * - else the size request if we haven't ever been mapped,
6511 * as a substitute default size
6512 * - else the current size of the window, as received from
6513 * configure notifies (i.e. the current allocation)
6515 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6516 * the position request to be centered.
6518 GtkWindowPrivate *priv = window->priv;
6519 GtkAllocation allocation;
6521 GtkContainer *container;
6522 GtkWindowGeometryInfo *info;
6523 GdkGeometry new_geometry;
6524 GdkWindow *gdk_window;
6526 GdkRectangle new_request;
6527 gboolean configure_request_size_changed;
6528 gboolean configure_request_pos_changed;
6529 gboolean hints_changed; /* do we need to send these again */
6530 GtkWindowLastGeometryInfo saved_last_info;
6532 widget = GTK_WIDGET (window);
6533 gdk_window = gtk_widget_get_window (widget);
6534 container = GTK_CONTAINER (widget);
6535 info = gtk_window_get_geometry_info (window, TRUE);
6537 configure_request_size_changed = FALSE;
6538 configure_request_pos_changed = FALSE;
6540 gtk_window_compute_configure_request (window, &new_request,
6541 &new_geometry, &new_flags);
6543 /* This check implies the invariant that we never set info->last
6544 * without setting the hints and sending off a configure request.
6546 * If we change info->last without sending the request, we may
6549 if (info->last.configure_request.x != new_request.x ||
6550 info->last.configure_request.y != new_request.y)
6551 configure_request_pos_changed = TRUE;
6553 if ((info->last.configure_request.width != new_request.width ||
6554 info->last.configure_request.height != new_request.height))
6555 configure_request_size_changed = TRUE;
6557 hints_changed = FALSE;
6559 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6560 &new_geometry, new_flags))
6562 hints_changed = TRUE;
6565 /* Position Constraints
6566 * ====================
6568 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6569 * a default. The other POS_ values are used only when the
6570 * window is shown, not after that.
6572 * However, we can't implement a position constraint as
6573 * "anytime the window size changes, center the window"
6574 * because this may well end up fighting the WM or user. In
6575 * fact it gets in an infinite loop with at least one WM.
6577 * Basically, applications are in no way in a position to
6578 * constrain the position of a window, with one exception:
6579 * override redirect windows. (Really the intended purpose
6580 * of CENTER_ALWAYS anyhow, I would think.)
6582 * So the way we implement this "constraint" is to say that when WE
6583 * cause a move or resize, i.e. we make a configure request changing
6584 * window size, we recompute the CENTER_ALWAYS position to reflect
6585 * the new window size, and include it in our request. Also, if we
6586 * just turned on CENTER_ALWAYS we snap to center with a new
6587 * request. Otherwise, if we are just NOTIFIED of a move or resize
6588 * done by someone else e.g. the window manager, we do NOT send a
6589 * new configure request.
6591 * For override redirect windows, this works fine; all window
6592 * sizes are from our configure requests. For managed windows,
6593 * it is at least semi-sane, though who knows what the
6594 * app author is thinking.
6597 /* This condition should be kept in sync with the condition later on
6598 * that determines whether we send a configure request. i.e. we
6599 * should do this position constraining anytime we were going to
6600 * send a configure request anyhow, plus when constraints have
6603 if (configure_request_pos_changed ||
6604 configure_request_size_changed ||
6606 info->position_constraints_changed)
6608 /* We request the constrained position if:
6609 * - we were changing position, and need to clamp
6610 * the change to the constraint
6611 * - we're changing the size anyway
6612 * - set_position() was called to toggle CENTER_ALWAYS on
6615 gtk_window_constrain_position (window,
6621 /* Update whether we need to request a move */
6622 if (info->last.configure_request.x != new_request.x ||
6623 info->last.configure_request.y != new_request.y)
6624 configure_request_pos_changed = TRUE;
6626 configure_request_pos_changed = FALSE;
6630 if (priv->type == GTK_WINDOW_TOPLEVEL)
6632 int notify_x, notify_y;
6634 /* this is the position from the last configure notify */
6635 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6637 g_message ("--- %s ---\n"
6638 "last : %d,%d\t%d x %d\n"
6639 "this : %d,%d\t%d x %d\n"
6640 "alloc : %d,%d\t%d x %d\n"
6642 "resize: \t%d x %d\n"
6643 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6644 "configure_notify_received: %d\n"
6645 "configure_request_count: %d\n"
6646 "position_constraints_changed: %d\n",
6647 priv->title ? priv->title : "(no title)",
6648 info->last.configure_request.x,
6649 info->last.configure_request.y,
6650 info->last.configure_request.width,
6651 info->last.configure_request.height,
6657 widget->allocation.width,
6658 widget->allocation.height,
6659 widget->requisition.width,
6660 widget->requisition.height,
6662 info->resize_height,
6663 configure_request_pos_changed,
6664 configure_request_size_changed,
6666 priv->configure_notify_received,
6667 priv->configure_request_count,
6668 info->position_constraints_changed);
6672 saved_last_info = info->last;
6673 info->last.geometry = new_geometry;
6674 info->last.flags = new_flags;
6675 info->last.configure_request = new_request;
6677 /* need to set PPosition so the WM will look at our position,
6678 * but we don't want to count PPosition coming and going as a hints
6679 * change for future iterations. So we saved info->last prior to
6683 /* Also, if the initial position was explicitly set, then we always
6684 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6688 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6689 * this is an initial map
6692 if ((configure_request_pos_changed ||
6693 info->initial_pos_set ||
6694 (priv->need_default_position &&
6695 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6696 (new_flags & GDK_HINT_POS) == 0)
6698 new_flags |= GDK_HINT_POS;
6699 hints_changed = TRUE;
6702 /* Set hints if necessary
6705 gdk_window_set_geometry_hints (gdk_window,
6709 gtk_widget_get_allocation (widget, &allocation);
6711 /* handle resizing/moving and widget tree allocation
6713 if (priv->configure_notify_received)
6715 /* If we have received a configure event since
6716 * the last time in this function, we need to
6717 * accept our new size and size_allocate child widgets.
6718 * (see gtk_window_configure_event() for more details).
6720 * 1 or more configure notifies may have been received.
6721 * Also, configure_notify_received will only be TRUE
6722 * if all expected configure notifies have been received
6723 * (one per configure request), as an optimization.
6726 priv->configure_notify_received = FALSE;
6728 /* gtk_window_configure_event() filled in widget->allocation */
6729 gtk_widget_size_allocate (widget, &allocation);
6731 set_grip_position (window);
6732 set_grip_cursor (window);
6733 set_grip_shape (window);
6735 gdk_window_process_updates (gdk_window, TRUE);
6737 gdk_window_configure_finished (gdk_window);
6739 /* If the configure request changed, it means that
6741 * 1) coincidentally changed hints or widget properties
6742 * impacting the configure request before getting
6743 * a configure notify, or
6744 * 2) some broken widget is changing its size request
6745 * during size allocation, resulting in
6746 * a false appearance of changed configure request.
6748 * For 1), we could just go ahead and ask for the
6749 * new size right now, but doing that for 2)
6750 * might well be fighting the user (and can even
6751 * trigger a loop). Since we really don't want to
6752 * do that, we requeue a resize in hopes that
6753 * by the time it gets handled, the child has seen
6754 * the light and is willing to go along with the
6755 * new size. (this happens for the zvt widget, since
6756 * the size_allocate() above will have stored the
6757 * requisition corresponding to the new size in the
6760 * This doesn't buy us anything for 1), but it shouldn't
6761 * hurt us too badly, since it is what would have
6762 * happened if we had gotten the configure event before
6763 * the new size had been set.
6766 if (configure_request_size_changed ||
6767 configure_request_pos_changed)
6769 /* Don't change the recorded last info after all, because we
6770 * haven't actually updated to the new info yet - we decided
6771 * to postpone our configure request until later.
6773 info->last = saved_last_info;
6775 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6778 return; /* Bail out, we didn't really process the move/resize */
6780 else if ((configure_request_size_changed || hints_changed) &&
6781 (allocation.width != new_request.width || allocation.height != new_request.height))
6784 /* We are in one of the following situations:
6785 * A. configure_request_size_changed
6786 * our requisition has changed and we need a different window size,
6787 * so we request it from the window manager.
6788 * B. !configure_request_size_changed && hints_changed
6789 * the window manager rejects our size, but we have just changed the
6790 * window manager hints, so there's a chance our request will
6791 * be honoured this time, so we try again.
6793 * However, if the new requisition is the same as the current allocation,
6794 * we don't request it again, since we won't get a ConfigureNotify back from
6795 * the window manager unless it decides to change our requisition. If
6796 * we don't get the ConfigureNotify back, the resize queue will never be run.
6799 /* Now send the configure request */
6800 if (configure_request_pos_changed)
6804 gdk_window_move_resize (priv->frame,
6805 new_request.x - priv->frame_left,
6806 new_request.y - priv->frame_top,
6807 new_request.width + priv->frame_left + priv->frame_right,
6808 new_request.height + priv->frame_top + priv->frame_bottom);
6809 gdk_window_resize (gdk_window,
6810 new_request.width, new_request.height);
6813 gdk_window_move_resize (gdk_window,
6814 new_request.x, new_request.y,
6815 new_request.width, new_request.height);
6817 else /* only size changed */
6820 gdk_window_resize (priv->frame,
6821 new_request.width + priv->frame_left + priv->frame_right,
6822 new_request.height + priv->frame_top + priv->frame_bottom);
6823 gdk_window_resize (gdk_window,
6824 new_request.width, new_request.height);
6827 if (priv->type == GTK_WINDOW_POPUP)
6829 GtkAllocation allocation;
6831 /* Directly size allocate for override redirect (popup) windows. */
6834 allocation.width = new_request.width;
6835 allocation.height = new_request.height;
6837 gtk_widget_size_allocate (widget, &allocation);
6839 gdk_window_process_updates (gdk_window, TRUE);
6841 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6842 gtk_widget_queue_draw (widget);
6846 /* Increment the number of have-not-yet-received-notify requests */
6847 priv->configure_request_count += 1;
6848 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
6850 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6851 * configure event in response to our resizing request.
6852 * the configure event will cause a new resize with
6853 * ->configure_notify_received=TRUE.
6854 * until then, we want to
6855 * - discard expose events
6856 * - coalesce resizes for our children
6857 * - defer any window resizes until the configure event arrived
6858 * to achieve this, we queue a resize for the window, but remove its
6859 * resizing handler, so resizing will not be handled from the next
6860 * idle handler but when the configure event arrives.
6862 * FIXME: we should also dequeue the pending redraws here, since
6863 * we handle those ourselves upon ->configure_notify_received==TRUE.
6865 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6867 gtk_widget_queue_resize_no_redraw (widget);
6868 _gtk_container_dequeue_resize_handler (container);
6874 /* Handle any position changes.
6876 if (configure_request_pos_changed)
6880 gdk_window_move (priv->frame,
6881 new_request.x - priv->frame_left,
6882 new_request.y - priv->frame_top);
6885 gdk_window_move (gdk_window,
6886 new_request.x, new_request.y);
6889 /* And run the resize queue.
6891 gtk_container_resize_children (container);
6894 /* We have now processed a move/resize since the last position
6895 * constraint change, setting of the initial position, or resize.
6896 * (Not resetting these flags here can lead to infinite loops for
6897 * GTK_RESIZE_IMMEDIATE containers)
6899 info->position_constraints_changed = FALSE;
6900 info->initial_pos_set = FALSE;
6901 info->resize_width = -1;
6902 info->resize_height = -1;
6905 /* Compare two sets of Geometry hints for equality.
6908 gtk_window_compare_hints (GdkGeometry *geometry_a,
6910 GdkGeometry *geometry_b,
6913 if (flags_a != flags_b)
6916 if ((flags_a & GDK_HINT_MIN_SIZE) &&
6917 (geometry_a->min_width != geometry_b->min_width ||
6918 geometry_a->min_height != geometry_b->min_height))
6921 if ((flags_a & GDK_HINT_MAX_SIZE) &&
6922 (geometry_a->max_width != geometry_b->max_width ||
6923 geometry_a->max_height != geometry_b->max_height))
6926 if ((flags_a & GDK_HINT_BASE_SIZE) &&
6927 (geometry_a->base_width != geometry_b->base_width ||
6928 geometry_a->base_height != geometry_b->base_height))
6931 if ((flags_a & GDK_HINT_ASPECT) &&
6932 (geometry_a->min_aspect != geometry_b->min_aspect ||
6933 geometry_a->max_aspect != geometry_b->max_aspect))
6936 if ((flags_a & GDK_HINT_RESIZE_INC) &&
6937 (geometry_a->width_inc != geometry_b->width_inc ||
6938 geometry_a->height_inc != geometry_b->height_inc))
6941 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
6942 geometry_a->win_gravity != geometry_b->win_gravity)
6949 _gtk_window_constrain_size (GtkWindow *window,
6955 GtkWindowPrivate *priv;
6956 GtkWindowGeometryInfo *info;
6958 g_return_if_fail (GTK_IS_WINDOW (window));
6960 priv = window->priv;
6962 info = priv->geometry_info;
6965 GdkWindowHints flags = info->last.flags;
6966 GdkGeometry *geometry = &info->last.geometry;
6968 gtk_window_constrain_size (window,
6979 gtk_window_constrain_size (GtkWindow *window,
6980 GdkGeometry *geometry,
6987 gdk_window_constrain_size (geometry, flags, width, height,
6988 new_width, new_height);
6991 /* Compute the set of geometry hints and flags for a window
6992 * based on the application set geometry, and requisition
6993 * of the window. gtk_widget_get_preferred_size() must have been
6997 gtk_window_compute_hints (GtkWindow *window,
6998 GdkGeometry *new_geometry,
7001 GtkWindowPrivate *priv = window->priv;
7003 gint extra_width = 0;
7004 gint extra_height = 0;
7005 GtkWindowGeometryInfo *geometry_info;
7006 GtkRequisition requisition;
7008 widget = GTK_WIDGET (window);
7010 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7011 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7015 *new_flags = geometry_info->mask;
7016 *new_geometry = geometry_info->geometry;
7023 if (geometry_info && geometry_info->widget)
7025 /* If the geometry widget is set, then the hints really apply to that
7026 * widget. This is pretty much meaningless unless the window layout
7027 * is such that the rest of the window adds fixed size borders to
7028 * the geometry widget. Our job is to figure the size of the borders;
7029 * We do that by asking how big the toplevel would be if the
7030 * geometry widget was *really big*.
7033 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7034 * |GGGGG B| in the border can confuse things
7040 * |AAAAAAAAA | When the geometry widget is large, things are
7041 * |GGGGGGGGGGB| clearer.
7046 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7047 GtkRequisition requisition;
7048 int current_width, current_height;
7050 _gtk_widget_override_size_request (geometry_info->widget,
7051 TEMPORARY_SIZE, TEMPORARY_SIZE,
7052 ¤t_width, ¤t_height);
7053 gtk_widget_get_preferred_size (widget,
7054 &requisition, NULL);
7055 _gtk_widget_restore_size_request (geometry_info->widget,
7056 current_width, current_height);
7058 extra_width = requisition.width - TEMPORARY_SIZE;
7059 extra_height = requisition.height - TEMPORARY_SIZE;
7061 if (extra_width < 0 || extra_width < 0)
7063 g_warning("Toplevel size doesn't seem to directly depend on the "
7064 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7065 "The geometry widget might not be in the window, or it might not "
7066 "be packed into the window appropriately");
7067 extra_width = MAX(extra_width, 0);
7068 extra_height = MAX(extra_height, 0);
7070 #undef TEMPORARY_SIZE
7073 /* We don't want to set GDK_HINT_POS in here, we just set it
7074 * in gtk_window_move_resize() when we want the position
7078 if (*new_flags & GDK_HINT_BASE_SIZE)
7080 new_geometry->base_width += extra_width;
7081 new_geometry->base_height += extra_height;
7085 /* For simplicity, we always set the base hint, even when we
7086 * don't expect it to have any visible effect.
7088 *new_flags |= GDK_HINT_BASE_SIZE;
7090 new_geometry->base_width = extra_width;
7091 new_geometry->base_height = extra_height;
7093 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7094 * base size is the minimum size */
7095 if (*new_flags & GDK_HINT_MIN_SIZE)
7097 if (new_geometry->min_width > 0)
7098 new_geometry->base_width += new_geometry->min_width;
7099 if (new_geometry->min_height > 0)
7100 new_geometry->base_height += new_geometry->min_height;
7104 if (*new_flags & GDK_HINT_MIN_SIZE)
7106 if (new_geometry->min_width < 0)
7107 new_geometry->min_width = requisition.width;
7109 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7111 if (new_geometry->min_height < 0)
7112 new_geometry->min_height = requisition.height;
7114 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7118 *new_flags |= GDK_HINT_MIN_SIZE;
7120 new_geometry->min_width = requisition.width;
7121 new_geometry->min_height = requisition.height;
7124 if (*new_flags & GDK_HINT_MAX_SIZE)
7126 if (new_geometry->max_width < 0)
7127 new_geometry->max_width = requisition.width;
7129 new_geometry->max_width += extra_width;
7131 if (new_geometry->max_height < 0)
7132 new_geometry->max_height = requisition.height;
7134 new_geometry->max_height += extra_height;
7136 else if (!priv->resizable)
7138 *new_flags |= GDK_HINT_MAX_SIZE;
7140 new_geometry->max_width = requisition.width;
7141 new_geometry->max_height = requisition.height;
7144 *new_flags |= GDK_HINT_WIN_GRAVITY;
7145 new_geometry->win_gravity = priv->gravity;
7148 /***********************
7149 * Redrawing functions *
7150 ***********************/
7153 gtk_window_draw (GtkWidget *widget,
7156 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7157 gboolean ret = FALSE;
7159 if (!gtk_widget_get_app_paintable (widget))
7160 gtk_paint_flat_box (gtk_widget_get_style (widget),
7163 GTK_SHADOW_NONE, widget, "base",
7165 gtk_widget_get_allocated_width (widget),
7166 gtk_widget_get_allocated_height (widget));
7168 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7169 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7171 if (priv->grip_window != NULL &&
7172 gtk_cairo_should_draw_window (cr, priv->grip_window))
7177 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7178 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7179 gtk_paint_resize_grip (gtk_widget_get_style (widget),
7181 gtk_widget_get_state (widget),
7184 get_grip_edge (widget),
7186 rect.width, rect.height);
7194 * gtk_window_set_has_frame:
7195 * @window: a #GtkWindow
7196 * @setting: a boolean
7198 * (Note: this is a special-purpose function for the framebuffer port,
7199 * that causes GTK+ to draw its own window border. For most applications,
7200 * you want gtk_window_set_decorated() instead, which tells the window
7201 * manager whether to draw the window border.)
7203 * If this function is called on a window with setting of %TRUE, before
7204 * it is realized or showed, it will have a "frame" window around
7205 * @window->window, accessible in @window->frame. Using the signal
7206 * frame_event you can receive all events targeted at the frame.
7208 * This function is used by the linux-fb port to implement managed
7209 * windows, but it could conceivably be used by X-programs that
7210 * want to do their own window decorations.
7214 gtk_window_set_has_frame (GtkWindow *window,
7217 GtkWindowPrivate *priv;
7219 g_return_if_fail (GTK_IS_WINDOW (window));
7220 g_return_if_fail (!gtk_widget_get_realized (GTK_WIDGET (window)));
7222 priv = window->priv;
7224 priv->has_frame = setting != FALSE;
7228 * gtk_window_get_has_frame:
7229 * @window: a #GtkWindow
7231 * Accessor for whether the window has a frame window exterior to
7232 * @window->window. Gets the value set by gtk_window_set_has_frame ().
7234 * Return value: %TRUE if a frame has been added to the window
7235 * via gtk_window_set_has_frame().
7238 gtk_window_get_has_frame (GtkWindow *window)
7240 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7242 return window->priv->has_frame;
7246 * gtk_window_set_frame_dimensions:
7247 * @window: a #GtkWindow that has a frame
7248 * @left: The width of the left border
7249 * @top: The height of the top border
7250 * @right: The width of the right border
7251 * @bottom: The height of the bottom border
7253 * (Note: this is a special-purpose function intended for the framebuffer
7254 * port; see gtk_window_set_has_frame(). It will have no effect on the
7255 * window border drawn by the window manager, which is the normal
7256 * case when using the X Window system.)
7258 * For windows with frames (see gtk_window_set_has_frame()) this function
7259 * can be used to change the size of the frame border.
7262 gtk_window_set_frame_dimensions (GtkWindow *window,
7268 GtkWindowPrivate *priv;
7269 GtkAllocation allocation;
7272 g_return_if_fail (GTK_IS_WINDOW (window));
7274 priv = window->priv;
7275 widget = GTK_WIDGET (window);
7277 if (priv->frame_left == left &&
7278 priv->frame_top == top &&
7279 priv->frame_right == right &&
7280 priv->frame_bottom == bottom)
7283 priv->frame_left = left;
7284 priv->frame_top = top;
7285 priv->frame_right = right;
7286 priv->frame_bottom = bottom;
7288 if (gtk_widget_get_realized (widget) && priv->frame)
7290 gtk_widget_get_allocation (widget, &allocation);
7292 gint width = allocation.width + left + right;
7293 gint height = allocation.height + top + bottom;
7294 gdk_window_resize (priv->frame, width, height);
7295 gtk_decorated_window_move_resize_window (window,
7303 * gtk_window_present:
7304 * @window: a #GtkWindow
7306 * Presents a window to the user. This may mean raising the window
7307 * in the stacking order, deiconifying it, moving it to the current
7308 * desktop, and/or giving it the keyboard focus, possibly dependent
7309 * on the user's platform, window manager, and preferences.
7311 * If @window is hidden, this function calls gtk_widget_show()
7314 * This function should be used when the user tries to open a window
7315 * that's already open. Say for example the preferences dialog is
7316 * currently open, and the user chooses Preferences from the menu
7317 * a second time; use gtk_window_present() to move the already-open dialog
7318 * where the user can see it.
7320 * If you are calling this function in response to a user interaction,
7321 * it is preferable to use gtk_window_present_with_time().
7325 gtk_window_present (GtkWindow *window)
7327 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7331 * gtk_window_present_with_time:
7332 * @window: a #GtkWindow
7333 * @timestamp: the timestamp of the user interaction (typically a
7334 * button or key press event) which triggered this call
7336 * Presents a window to the user in response to a user interaction.
7337 * If you need to present a window without a timestamp, use
7338 * gtk_window_present(). See gtk_window_present() for details.
7343 gtk_window_present_with_time (GtkWindow *window,
7347 GdkWindow *gdk_window;
7349 g_return_if_fail (GTK_IS_WINDOW (window));
7351 widget = GTK_WIDGET (window);
7353 if (gtk_widget_get_visible (widget))
7355 gdk_window = gtk_widget_get_window (widget);
7357 g_assert (gdk_window != NULL);
7359 gdk_window_show (gdk_window);
7361 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7362 if (timestamp == GDK_CURRENT_TIME)
7364 #ifdef GDK_WINDOWING_X11
7365 GdkDisplay *display;
7367 display = gtk_widget_get_display (GTK_WIDGET (window));
7368 timestamp = gdk_x11_display_get_user_time (display);
7370 timestamp = gtk_get_current_event_time ();
7374 gdk_window_focus (gdk_window, timestamp);
7378 gtk_widget_show (widget);
7383 * gtk_window_iconify:
7384 * @window: a #GtkWindow
7386 * Asks to iconify (i.e. minimize) the specified @window. Note that
7387 * you shouldn't assume the window is definitely iconified afterward,
7388 * because other entities (e.g. the user or <link
7389 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7390 * again, or there may not be a window manager in which case
7391 * iconification isn't possible, etc. But normally the window will end
7392 * up iconified. Just don't write code that crashes if not.
7394 * It's permitted to call this function before showing a window,
7395 * in which case the window will be iconified before it ever appears
7398 * You can track iconification via the "window-state-event" signal
7403 gtk_window_iconify (GtkWindow *window)
7405 GtkWindowPrivate *priv;
7407 GdkWindow *toplevel;
7409 g_return_if_fail (GTK_IS_WINDOW (window));
7411 priv = window->priv;
7412 widget = GTK_WIDGET (window);
7414 priv->iconify_initially = TRUE;
7417 toplevel = priv->frame;
7419 toplevel = gtk_widget_get_window (widget);
7421 if (toplevel != NULL)
7422 gdk_window_iconify (toplevel);
7426 * gtk_window_deiconify:
7427 * @window: a #GtkWindow
7429 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7430 * that you shouldn't assume the window is definitely deiconified
7431 * afterward, because other entities (e.g. the user or <link
7432 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7433 * again before your code which assumes deiconification gets to run.
7435 * You can track iconification via the "window-state-event" signal
7439 gtk_window_deiconify (GtkWindow *window)
7441 GtkWindowPrivate *priv;
7443 GdkWindow *toplevel;
7445 g_return_if_fail (GTK_IS_WINDOW (window));
7447 priv = window->priv;
7448 widget = GTK_WIDGET (window);
7450 priv->iconify_initially = FALSE;
7453 toplevel = priv->frame;
7455 toplevel = gtk_widget_get_window (widget);
7457 if (toplevel != NULL)
7458 gdk_window_deiconify (toplevel);
7463 * @window: a #GtkWindow
7465 * Asks to stick @window, which means that it will appear on all user
7466 * desktops. Note that you shouldn't assume the window is definitely
7467 * stuck afterward, because other entities (e.g. the user or <link
7468 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7469 * again, and some window managers do not support sticking
7470 * windows. But normally the window will end up stuck. Just don't
7471 * write code that crashes if not.
7473 * It's permitted to call this function before showing a window.
7475 * You can track stickiness via the "window-state-event" signal
7480 gtk_window_stick (GtkWindow *window)
7482 GtkWindowPrivate *priv;
7484 GdkWindow *toplevel;
7486 g_return_if_fail (GTK_IS_WINDOW (window));
7488 priv = window->priv;
7489 widget = GTK_WIDGET (window);
7491 priv->stick_initially = TRUE;
7494 toplevel = priv->frame;
7496 toplevel = gtk_widget_get_window (widget);
7498 if (toplevel != NULL)
7499 gdk_window_stick (toplevel);
7503 * gtk_window_unstick:
7504 * @window: a #GtkWindow
7506 * Asks to unstick @window, which means that it will appear on only
7507 * one of the user's desktops. Note that you shouldn't assume the
7508 * window is definitely unstuck afterward, because other entities
7509 * (e.g. the user or <link linkend="gtk-X11-arch">window
7510 * manager</link>) could stick it again. But normally the window will
7511 * end up stuck. Just don't write code that crashes if not.
7513 * You can track stickiness via the "window-state-event" signal
7518 gtk_window_unstick (GtkWindow *window)
7520 GtkWindowPrivate *priv;
7522 GdkWindow *toplevel;
7524 g_return_if_fail (GTK_IS_WINDOW (window));
7526 priv = window->priv;
7527 widget = GTK_WIDGET (window);
7529 priv->stick_initially = FALSE;
7532 toplevel = priv->frame;
7534 toplevel = gtk_widget_get_window (widget);
7536 if (toplevel != NULL)
7537 gdk_window_unstick (toplevel);
7541 * gtk_window_maximize:
7542 * @window: a #GtkWindow
7544 * Asks to maximize @window, so that it becomes full-screen. Note that
7545 * you shouldn't assume the window is definitely maximized afterward,
7546 * because other entities (e.g. the user or <link
7547 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7548 * again, and not all window managers support maximization. But
7549 * normally the window will end up maximized. Just don't write code
7550 * that crashes if not.
7552 * It's permitted to call this function before showing a window,
7553 * in which case the window will be maximized when it appears onscreen
7556 * You can track maximization via the "window-state-event" signal
7561 gtk_window_maximize (GtkWindow *window)
7563 GtkWindowPrivate *priv;
7565 GdkWindow *toplevel;
7567 g_return_if_fail (GTK_IS_WINDOW (window));
7569 priv = window->priv;
7570 widget = GTK_WIDGET (window);
7572 priv->maximize_initially = TRUE;
7575 toplevel = priv->frame;
7577 toplevel = gtk_widget_get_window (widget);
7579 if (toplevel != NULL)
7580 gdk_window_maximize (toplevel);
7584 * gtk_window_unmaximize:
7585 * @window: a #GtkWindow
7587 * Asks to unmaximize @window. Note that you shouldn't assume the
7588 * window is definitely unmaximized afterward, because other entities
7589 * (e.g. the user or <link linkend="gtk-X11-arch">window
7590 * manager</link>) could maximize it again, and not all window
7591 * managers honor requests to unmaximize. But normally the window will
7592 * end up unmaximized. Just don't write code that crashes if not.
7594 * You can track maximization via the "window-state-event" signal
7599 gtk_window_unmaximize (GtkWindow *window)
7601 GtkWindowPrivate *priv;
7603 GdkWindow *toplevel;
7605 g_return_if_fail (GTK_IS_WINDOW (window));
7607 priv = window->priv;
7608 widget = GTK_WIDGET (window);
7610 priv->maximize_initially = FALSE;
7613 toplevel = priv->frame;
7615 toplevel = gtk_widget_get_window (widget);
7617 if (toplevel != NULL)
7618 gdk_window_unmaximize (toplevel);
7622 * gtk_window_fullscreen:
7623 * @window: a #GtkWindow
7625 * Asks to place @window in the fullscreen state. Note that you
7626 * shouldn't assume the window is definitely full screen afterward,
7627 * because other entities (e.g. the user or <link
7628 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7629 * again, and not all window managers honor requests to fullscreen
7630 * windows. But normally the window will end up fullscreen. Just
7631 * don't write code that crashes if not.
7633 * You can track the fullscreen state via the "window-state-event" signal
7639 gtk_window_fullscreen (GtkWindow *window)
7641 GtkWindowPrivate *priv;
7643 GdkWindow *toplevel;
7645 g_return_if_fail (GTK_IS_WINDOW (window));
7647 priv = window->priv;
7648 widget = GTK_WIDGET (window);
7650 priv->fullscreen_initially = TRUE;
7653 toplevel = priv->frame;
7655 toplevel = gtk_widget_get_window (widget);
7657 if (toplevel != NULL)
7658 gdk_window_fullscreen (toplevel);
7662 * gtk_window_unfullscreen:
7663 * @window: a #GtkWindow
7665 * Asks to toggle off the fullscreen state for @window. Note that you
7666 * shouldn't assume the window is definitely not full screen
7667 * afterward, because other entities (e.g. the user or <link
7668 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7669 * again, and not all window managers honor requests to unfullscreen
7670 * windows. But normally the window will end up restored to its normal
7671 * state. Just don't write code that crashes if not.
7673 * You can track the fullscreen state via the "window-state-event" signal
7679 gtk_window_unfullscreen (GtkWindow *window)
7682 GdkWindow *toplevel;
7683 GtkWindowPrivate *priv;
7685 g_return_if_fail (GTK_IS_WINDOW (window));
7687 priv = window->priv;
7688 widget = GTK_WIDGET (window);
7690 priv->fullscreen_initially = FALSE;
7693 toplevel = priv->frame;
7695 toplevel = gtk_widget_get_window (widget);
7697 if (toplevel != NULL)
7698 gdk_window_unfullscreen (toplevel);
7702 * gtk_window_set_keep_above:
7703 * @window: a #GtkWindow
7704 * @setting: whether to keep @window above other windows
7706 * Asks to keep @window above, so that it stays on top. Note that
7707 * you shouldn't assume the window is definitely above afterward,
7708 * because other entities (e.g. the user or <link
7709 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7710 * and not all window managers support keeping windows above. But
7711 * normally the window will end kept above. Just don't write code
7712 * that crashes if not.
7714 * It's permitted to call this function before showing a window,
7715 * in which case the window will be kept above when it appears onscreen
7718 * You can track the above state via the "window-state-event" signal
7721 * Note that, according to the <ulink
7722 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7723 * Manager Hints</ulink> specification, the above state is mainly meant
7724 * for user preferences and should not be used by applications e.g. for
7725 * drawing attention to their dialogs.
7730 gtk_window_set_keep_above (GtkWindow *window,
7734 GtkWindowPrivate *priv;
7735 GdkWindow *toplevel;
7737 g_return_if_fail (GTK_IS_WINDOW (window));
7739 priv = window->priv;
7740 widget = GTK_WIDGET (window);
7742 priv->above_initially = setting != FALSE;
7744 priv->below_initially = FALSE;
7747 toplevel = priv->frame;
7749 toplevel = gtk_widget_get_window (widget);
7751 if (toplevel != NULL)
7752 gdk_window_set_keep_above (toplevel, setting);
7756 * gtk_window_set_keep_below:
7757 * @window: a #GtkWindow
7758 * @setting: whether to keep @window below other windows
7760 * Asks to keep @window below, so that it stays in bottom. Note that
7761 * you shouldn't assume the window is definitely below afterward,
7762 * because other entities (e.g. the user or <link
7763 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7764 * and not all window managers support putting windows below. But
7765 * normally the window will be kept below. Just don't write code
7766 * that crashes if not.
7768 * It's permitted to call this function before showing a window,
7769 * in which case the window will be kept below when it appears onscreen
7772 * You can track the below state via the "window-state-event" signal
7775 * Note that, according to the <ulink
7776 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7777 * Manager Hints</ulink> specification, the above state is mainly meant
7778 * for user preferences and should not be used by applications e.g. for
7779 * drawing attention to their dialogs.
7784 gtk_window_set_keep_below (GtkWindow *window,
7788 GtkWindowPrivate *priv;
7789 GdkWindow *toplevel;
7791 g_return_if_fail (GTK_IS_WINDOW (window));
7793 priv = window->priv;
7794 widget = GTK_WIDGET (window);
7796 priv->below_initially = setting != FALSE;
7798 priv->above_initially = FALSE;
7801 toplevel = priv->frame;
7803 toplevel = gtk_widget_get_window (widget);
7805 if (toplevel != NULL)
7806 gdk_window_set_keep_below (toplevel, setting);
7810 * gtk_window_set_resizable:
7811 * @window: a #GtkWindow
7812 * @resizable: %TRUE if the user can resize this window
7814 * Sets whether the user can resize a window. Windows are user resizable
7818 gtk_window_set_resizable (GtkWindow *window,
7821 GtkWindowPrivate *priv;
7823 g_return_if_fail (GTK_IS_WINDOW (window));
7825 priv = window->priv;
7827 priv->resizable = (resizable != FALSE);
7829 g_object_notify (G_OBJECT (window), "resizable");
7831 if (priv->grip_window != NULL)
7832 update_grip_visibility (window);
7834 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7838 * gtk_window_get_resizable:
7839 * @window: a #GtkWindow
7841 * Gets the value set by gtk_window_set_resizable().
7843 * Return value: %TRUE if the user can resize the window
7846 gtk_window_get_resizable (GtkWindow *window)
7848 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7850 return window->priv->resizable;
7854 * gtk_window_set_gravity:
7855 * @window: a #GtkWindow
7856 * @gravity: window gravity
7858 * Window gravity defines the meaning of coordinates passed to
7859 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7862 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7863 * typically "do what you mean."
7867 gtk_window_set_gravity (GtkWindow *window,
7870 GtkWindowPrivate *priv;
7872 g_return_if_fail (GTK_IS_WINDOW (window));
7874 priv = window->priv;
7876 if (gravity != priv->gravity)
7878 priv->gravity = gravity;
7880 /* gtk_window_move_resize() will adapt gravity
7882 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7884 g_object_notify (G_OBJECT (window), "gravity");
7889 * gtk_window_get_gravity:
7890 * @window: a #GtkWindow
7892 * Gets the value set by gtk_window_set_gravity().
7894 * Return value: (transfer none): window gravity
7897 gtk_window_get_gravity (GtkWindow *window)
7899 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7901 return window->priv->gravity;
7905 * gtk_window_begin_resize_drag:
7906 * @window: a #GtkWindow
7907 * @button: mouse button that initiated the drag
7908 * @edge: position of the resize control
7909 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7910 * @root_y: Y position where the user clicked to initiate the drag
7911 * @timestamp: timestamp from the click event that initiated the drag
7913 * Starts resizing a window. This function is used if an application
7914 * has window resizing controls. When GDK can support it, the resize
7915 * will be done using the standard mechanism for the <link
7916 * linkend="gtk-X11-arch">window manager</link> or windowing
7917 * system. Otherwise, GDK will try to emulate window resizing,
7918 * potentially not all that well, depending on the windowing system.
7922 gtk_window_begin_resize_drag (GtkWindow *window,
7929 GtkWindowPrivate *priv;
7931 GdkWindow *toplevel;
7933 g_return_if_fail (GTK_IS_WINDOW (window));
7934 widget = GTK_WIDGET (window);
7935 g_return_if_fail (gtk_widget_get_visible (widget));
7937 priv = window->priv;
7940 toplevel = priv->frame;
7942 toplevel = gtk_widget_get_window (widget);
7944 gdk_window_begin_resize_drag (toplevel,
7951 * gtk_window_get_frame_dimensions:
7952 * @window: a #GtkWindow
7953 * @left: (out) (allow-none): location to store the width of the frame at the left, or %NULL
7954 * @top: (out) (allow-none): location to store the height of the frame at the top, or %NULL
7955 * @right: (out) (allow-none): location to store the width of the frame at the returns, or %NULL
7956 * @bottom: (out) (allow-none): location to store the height of the frame at the bottom, or %NULL
7958 * (Note: this is a special-purpose function intended for the
7959 * framebuffer port; see gtk_window_set_has_frame(). It will not
7960 * return the size of the window border drawn by the <link
7961 * linkend="gtk-X11-arch">window manager</link>, which is the normal
7962 * case when using a windowing system. See
7963 * gdk_window_get_frame_extents() to get the standard window border
7966 * Retrieves the dimensions of the frame window for this toplevel.
7967 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
7970 gtk_window_get_frame_dimensions (GtkWindow *window,
7976 GtkWindowPrivate *priv;
7978 g_return_if_fail (GTK_IS_WINDOW (window));
7980 priv = window->priv;
7983 *left = priv->frame_left;
7985 *top = priv->frame_top;
7987 *right = priv->frame_right;
7989 *bottom = priv->frame_bottom;
7993 * gtk_window_begin_move_drag:
7994 * @window: a #GtkWindow
7995 * @button: mouse button that initiated the drag
7996 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7997 * @root_y: Y position where the user clicked to initiate the drag
7998 * @timestamp: timestamp from the click event that initiated the drag
8000 * Starts moving a window. This function is used if an application has
8001 * window movement grips. When GDK can support it, the window movement
8002 * will be done using the standard mechanism for the <link
8003 * linkend="gtk-X11-arch">window manager</link> or windowing
8004 * system. Otherwise, GDK will try to emulate window movement,
8005 * potentially not all that well, depending on the windowing system.
8009 gtk_window_begin_move_drag (GtkWindow *window,
8015 GtkWindowPrivate *priv;
8017 GdkWindow *toplevel;
8019 g_return_if_fail (GTK_IS_WINDOW (window));
8020 widget = GTK_WIDGET (window);
8021 g_return_if_fail (gtk_widget_get_visible (widget));
8023 priv = window->priv;
8026 toplevel = priv->frame;
8028 toplevel = gtk_widget_get_window (widget);
8030 gdk_window_begin_move_drag (toplevel,
8037 * gtk_window_set_screen:
8038 * @window: a #GtkWindow.
8039 * @screen: a #GdkScreen.
8041 * Sets the #GdkScreen where the @window is displayed; if
8042 * the window is already mapped, it will be unmapped, and
8043 * then remapped on the new screen.
8048 gtk_window_set_screen (GtkWindow *window,
8051 GtkWindowPrivate *priv;
8053 GdkScreen *previous_screen;
8054 gboolean was_mapped;
8056 g_return_if_fail (GTK_IS_WINDOW (window));
8057 g_return_if_fail (GDK_IS_SCREEN (screen));
8059 priv = window->priv;
8061 if (screen == priv->screen)
8064 widget = GTK_WIDGET (window);
8066 previous_screen = priv->screen;
8067 was_mapped = gtk_widget_get_mapped (widget);
8070 gtk_widget_unmap (widget);
8071 if (gtk_widget_get_realized (widget))
8072 gtk_widget_unrealize (widget);
8074 gtk_window_free_key_hash (window);
8075 priv->screen = screen;
8076 gtk_widget_reset_rc_styles (widget);
8077 if (screen != previous_screen)
8079 g_signal_handlers_disconnect_by_func (previous_screen,
8080 gtk_window_on_composited_changed, window);
8081 g_signal_connect (screen, "composited-changed",
8082 G_CALLBACK (gtk_window_on_composited_changed), window);
8084 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8085 _gtk_widget_propagate_composited_changed (widget);
8087 g_object_notify (G_OBJECT (window), "screen");
8090 gtk_widget_map (widget);
8094 gtk_window_on_composited_changed (GdkScreen *screen,
8097 gtk_widget_queue_draw (GTK_WIDGET (window));
8099 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8103 gtk_window_check_screen (GtkWindow *window)
8105 GtkWindowPrivate *priv = window->priv;
8108 return priv->screen;
8111 g_warning ("Screen for GtkWindow not set; you must always set\n"
8112 "a screen for a GtkWindow before using the window");
8118 * gtk_window_get_screen:
8119 * @window: a #GtkWindow.
8121 * Returns the #GdkScreen associated with @window.
8123 * Return value: (transfer none): a #GdkScreen.
8128 gtk_window_get_screen (GtkWindow *window)
8130 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8132 return window->priv->screen;
8136 * gtk_window_is_active:
8137 * @window: a #GtkWindow
8139 * Returns whether the window is part of the current active toplevel.
8140 * (That is, the toplevel window receiving keystrokes.)
8141 * The return value is %TRUE if the window is active toplevel
8142 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8143 * You might use this function if you wanted to draw a widget
8144 * differently in an active window from a widget in an inactive window.
8145 * See gtk_window_has_toplevel_focus()
8147 * Return value: %TRUE if the window part of the current active window.
8152 gtk_window_is_active (GtkWindow *window)
8154 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8156 return window->priv->is_active;
8160 * gtk_window_has_toplevel_focus:
8161 * @window: a #GtkWindow
8163 * Returns whether the input focus is within this GtkWindow.
8164 * For real toplevel windows, this is identical to gtk_window_is_active(),
8165 * but for embedded windows, like #GtkPlug, the results will differ.
8167 * Return value: %TRUE if the input focus is within this GtkWindow
8172 gtk_window_has_toplevel_focus (GtkWindow *window)
8174 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8176 return window->priv->has_toplevel_focus;
8180 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8182 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8186 gtk_window_group_get_type (void)
8188 static GType window_group_type = 0;
8190 if (!window_group_type)
8192 const GTypeInfo window_group_info =
8194 sizeof (GtkWindowGroupClass),
8195 NULL, /* base_init */
8196 NULL, /* base_finalize */
8197 (GClassInitFunc) gtk_window_group_class_init,
8198 NULL, /* class_finalize */
8199 NULL, /* class_data */
8200 sizeof (GtkWindowGroup),
8201 0, /* n_preallocs */
8202 (GInstanceInitFunc) NULL,
8205 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
8206 &window_group_info, 0);
8209 return window_group_type;
8213 * gtk_window_group_new:
8215 * Creates a new #GtkWindowGroup object. Grabs added with
8216 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8218 * Return value: a new #GtkWindowGroup.
8221 gtk_window_group_new (void)
8223 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8227 window_group_cleanup_grabs (GtkWindowGroup *group,
8230 GtkWindowGroupPrivate *priv;
8231 GtkDeviceGrabInfo *info;
8233 GSList *to_remove = NULL;
8235 tmp_list = group->grabs;
8238 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8239 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8240 tmp_list = tmp_list->next;
8245 gtk_grab_remove (to_remove->data);
8246 g_object_unref (to_remove->data);
8247 to_remove = g_slist_delete_link (to_remove, to_remove);
8250 priv = GTK_WINDOW_GROUP_GET_PRIVATE (group);
8251 tmp_list = priv->device_grabs;
8255 info = tmp_list->data;
8257 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8258 to_remove = g_slist_prepend (to_remove, info);
8260 tmp_list = tmp_list->next;
8265 info = to_remove->data;
8267 gtk_device_grab_remove (info->widget, info->device);
8268 to_remove = g_slist_delete_link (to_remove, to_remove);
8273 * gtk_window_group_add_window:
8274 * @window_group: a #GtkWindowGroup
8275 * @window: the #GtkWindow to add
8277 * Adds a window to a #GtkWindowGroup.
8280 gtk_window_group_add_window (GtkWindowGroup *window_group,
8283 GtkWindowPrivate *priv;
8285 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8286 g_return_if_fail (GTK_IS_WINDOW (window));
8288 priv = window->priv;
8290 if (priv->group != window_group)
8292 g_object_ref (window);
8293 g_object_ref (window_group);
8296 gtk_window_group_remove_window (priv->group, window);
8298 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8300 priv->group = window_group;
8302 g_object_unref (window);
8307 * gtk_window_group_remove_window:
8308 * @window_group: a #GtkWindowGroup
8309 * @window: the #GtkWindow to remove
8311 * Removes a window from a #GtkWindowGroup.
8314 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8317 GtkWindowPrivate *priv;
8319 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8320 g_return_if_fail (GTK_IS_WINDOW (window));
8321 priv = window->priv;
8322 g_return_if_fail (priv->group == window_group);
8324 g_object_ref (window);
8326 window_group_cleanup_grabs (window_group, window);
8329 g_object_unref (window_group);
8330 g_object_unref (window);
8334 * gtk_window_group_list_windows:
8335 * @window_group: a #GtkWindowGroup
8337 * Returns a list of the #GtkWindows that belong to @window_group.
8339 * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
8340 * windows inside the group.
8345 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8347 GList *toplevels, *toplevel, *group_windows;
8349 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8351 group_windows = NULL;
8352 toplevels = gtk_window_list_toplevels ();
8354 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8356 GtkWindow *window = toplevel->data;
8358 if (window_group == window->priv->group)
8359 group_windows = g_list_prepend (group_windows, window);
8362 return g_list_reverse (group_windows);
8366 * gtk_window_get_group:
8367 * @window: (allow-none): a #GtkWindow, or %NULL
8369 * Returns the group for @window or the default group, if
8370 * @window is %NULL or if @window does not have an explicit
8373 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8378 gtk_window_get_group (GtkWindow *window)
8380 if (window && window->priv->group)
8381 return window->priv->group;
8384 static GtkWindowGroup *default_group = NULL;
8387 default_group = gtk_window_group_new ();
8389 return default_group;
8394 * gtk_window_has_group:
8395 * @window: a #GtkWindow
8397 * Returns whether @window has an explicit window group.
8399 * Return value: %TRUE if @window has an explicit window group.
8404 gtk_window_has_group (GtkWindow *window)
8406 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8408 return window->priv->group != NULL;
8412 * gtk_window_group_get_current_grab:
8413 * @window_group: a #GtkWindowGroup
8415 * Gets the current grab widget of the given group,
8416 * see gtk_grab_add().
8418 * Returns: the current grab widget of the group
8423 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8425 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8427 if (window_group->grabs)
8428 return GTK_WIDGET (window_group->grabs->data);
8433 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8436 gboolean block_others)
8438 GtkWindowGroupPrivate *priv;
8439 GtkDeviceGrabInfo *info;
8441 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8443 info = g_slice_new0 (GtkDeviceGrabInfo);
8444 info->widget = widget;
8445 info->device = device;
8446 info->block_others = block_others;
8448 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8452 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8456 GtkWindowGroupPrivate *priv;
8457 GtkDeviceGrabInfo *info;
8458 GSList *list, *node = NULL;
8459 GdkDevice *other_device;
8461 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8462 other_device = gdk_device_get_associated_device (device);
8463 list = priv->device_grabs;
8469 if (info->widget == widget &&
8470 (info->device == device ||
8471 info->device == other_device))
8484 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8485 g_slice_free (GtkDeviceGrabInfo, info);
8490 * gtk_window_group_get_current_device_grab:
8491 * @window_group: a #GtkWindowGroup
8492 * @device: a #GdkDevice
8494 * Returns the current grab widget for @device, or %NULL if none.
8496 * Returns: The grab widget, or %NULL
8501 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8504 GtkWindowGroupPrivate *priv;
8505 GtkDeviceGrabInfo *info;
8506 GdkDevice *other_device;
8509 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8510 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8512 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8513 list = priv->device_grabs;
8514 other_device = gdk_device_get_associated_device (device);
8521 if (info->device == device ||
8522 info->device == other_device)
8523 return info->widget;
8530 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8534 GtkWindowGroupPrivate *priv;
8535 GtkDeviceGrabInfo *info;
8536 GdkDevice *other_device;
8539 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8540 other_device = gdk_device_get_associated_device (device);
8541 list = priv->device_grabs;
8548 /* Look for blocking grabs on other device pairs
8549 * that have the passed widget within the GTK+ grab.
8551 if (info->block_others &&
8552 info->device != device &&
8553 info->device != other_device &&
8554 (info->widget == widget ||
8555 gtk_widget_is_ancestor (widget, info->widget)))
8563 Derived from XParseGeometry() in XFree86
8565 Copyright 1985, 1986, 1987,1998 The Open Group
8567 All Rights Reserved.
8569 The above copyright notice and this permission notice shall be included
8570 in all copies or substantial portions of the Software.
8572 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8573 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8574 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8575 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8576 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8577 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8578 OTHER DEALINGS IN THE SOFTWARE.
8580 Except as contained in this notice, the name of The Open Group shall
8581 not be used in advertising or otherwise to promote the sale, use or
8582 other dealings in this Software without prior written authorization
8583 from The Open Group.
8588 * XParseGeometry parses strings of the form
8589 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8590 * width, height, xoffset, and yoffset are unsigned integers.
8591 * Example: "=80x24+300-49"
8592 * The equal sign is optional.
8593 * It returns a bitmask that indicates which of the four values
8594 * were actually found in the string. For each value found,
8595 * the corresponding argument is updated; for each value
8596 * not found, the corresponding argument is left unchanged.
8599 /* The following code is from Xlib, and is minimally modified, so we
8600 * can track any upstream changes if required. Don't change this
8601 * code. Or if you do, put in a huge comment marking which thing
8606 read_int (gchar *string,
8614 else if (*string == '-')
8620 for (; (*string >= '0') && (*string <= '9'); string++)
8622 result = (result * 10) + (*string - '0');
8634 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8635 * value (x, y, width, height) was found in the parsed string.
8637 #define NoValue 0x0000
8638 #define XValue 0x0001
8639 #define YValue 0x0002
8640 #define WidthValue 0x0004
8641 #define HeightValue 0x0008
8642 #define AllValues 0x000F
8643 #define XNegative 0x0010
8644 #define YNegative 0x0020
8646 /* Try not to reformat/modify, so we can compare/sync with X sources */
8648 gtk_XParseGeometry (const char *string,
8651 unsigned int *width,
8652 unsigned int *height)
8656 unsigned int tempWidth, tempHeight;
8658 char *nextCharacter;
8660 /* These initializations are just to silence gcc */
8666 if ( (string == NULL) || (*string == '\0')) return(mask);
8668 string++; /* ignore possible '=' at beg of geometry spec */
8670 strind = (char *)string;
8671 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8672 tempWidth = read_int(strind, &nextCharacter);
8673 if (strind == nextCharacter)
8675 strind = nextCharacter;
8679 if (*strind == 'x' || *strind == 'X') {
8681 tempHeight = read_int(strind, &nextCharacter);
8682 if (strind == nextCharacter)
8684 strind = nextCharacter;
8685 mask |= HeightValue;
8688 if ((*strind == '+') || (*strind == '-')) {
8689 if (*strind == '-') {
8691 tempX = -read_int(strind, &nextCharacter);
8692 if (strind == nextCharacter)
8694 strind = nextCharacter;
8700 tempX = read_int(strind, &nextCharacter);
8701 if (strind == nextCharacter)
8703 strind = nextCharacter;
8706 if ((*strind == '+') || (*strind == '-')) {
8707 if (*strind == '-') {
8709 tempY = -read_int(strind, &nextCharacter);
8710 if (strind == nextCharacter)
8712 strind = nextCharacter;
8719 tempY = read_int(strind, &nextCharacter);
8720 if (strind == nextCharacter)
8722 strind = nextCharacter;
8728 /* If strind isn't at the end of the string the it's an invalid
8729 geometry specification. */
8731 if (*strind != '\0') return (0);
8737 if (mask & WidthValue)
8739 if (mask & HeightValue)
8740 *height = tempHeight;
8745 * gtk_window_parse_geometry:
8746 * @window: a #GtkWindow
8747 * @geometry: geometry string
8749 * Parses a standard X Window System geometry string - see the
8750 * manual page for X (type 'man X') for details on this.
8751 * gtk_window_parse_geometry() does work on all GTK+ ports
8752 * including Win32 but is primarily intended for an X environment.
8754 * If either a size or a position can be extracted from the
8755 * geometry string, gtk_window_parse_geometry() returns %TRUE
8756 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8757 * to resize/move the window.
8759 * If gtk_window_parse_geometry() returns %TRUE, it will also
8760 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8761 * indicating to the window manager that the size/position of
8762 * the window was user-specified. This causes most window
8763 * managers to honor the geometry.
8765 * Note that for gtk_window_parse_geometry() to work as expected, it has
8766 * to be called when the window has its "final" size, i.e. after calling
8767 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8770 * #include <gtk/gtk.h>
8773 * fill_with_content (GtkWidget *vbox)
8775 * /* fill with content... */
8779 * main (int argc, char *argv[])
8781 * GtkWidget *window, *vbox;
8782 * GdkGeometry size_hints = {
8783 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8786 * gtk_init (&argc, &argv);
8788 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8789 * vbox = gtk_vbox_new (FALSE, 0);
8791 * gtk_container_add (GTK_CONTAINER (window), vbox);
8792 * fill_with_content (vbox);
8793 * gtk_widget_show_all (vbox);
8795 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8798 * GDK_HINT_MIN_SIZE |
8799 * GDK_HINT_BASE_SIZE |
8800 * GDK_HINT_RESIZE_INC);
8804 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8805 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8808 * gtk_widget_show_all (window);
8815 * Return value: %TRUE if string was parsed successfully
8818 gtk_window_parse_geometry (GtkWindow *window,
8819 const gchar *geometry)
8821 gint result, x = 0, y = 0;
8825 gboolean size_set, pos_set;
8828 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8829 g_return_val_if_fail (geometry != NULL, FALSE);
8831 child = gtk_bin_get_child (GTK_BIN (window));
8832 if (!child || !gtk_widget_get_visible (child))
8833 g_warning ("gtk_window_parse_geometry() called on a window with no "
8834 "visible children; the window should be set up before "
8835 "gtk_window_parse_geometry() is called.");
8837 screen = gtk_window_check_screen (window);
8839 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8842 if ((result & WidthValue) || (result & HeightValue))
8844 gtk_window_set_default_size_internal (window,
8845 TRUE, result & WidthValue ? w : -1,
8846 TRUE, result & HeightValue ? h : -1,
8851 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8853 grav = GDK_GRAVITY_NORTH_WEST;
8855 if ((result & XNegative) && (result & YNegative))
8856 grav = GDK_GRAVITY_SOUTH_EAST;
8857 else if (result & XNegative)
8858 grav = GDK_GRAVITY_NORTH_EAST;
8859 else if (result & YNegative)
8860 grav = GDK_GRAVITY_SOUTH_WEST;
8862 if ((result & XValue) == 0)
8865 if ((result & YValue) == 0)
8868 if (grav == GDK_GRAVITY_SOUTH_WEST ||
8869 grav == GDK_GRAVITY_SOUTH_EAST)
8870 y = gdk_screen_get_height (screen) - h + y;
8872 if (grav == GDK_GRAVITY_SOUTH_EAST ||
8873 grav == GDK_GRAVITY_NORTH_EAST)
8874 x = gdk_screen_get_width (screen) - w + x;
8876 /* we don't let you put a window offscreen; maybe some people would
8877 * prefer to be able to, but it's kind of a bogus thing to do.
8886 if ((result & XValue) || (result & YValue))
8888 gtk_window_set_gravity (window, grav);
8889 gtk_window_move (window, x, y);
8893 if (size_set || pos_set)
8895 /* Set USSize, USPosition hints */
8896 GtkWindowGeometryInfo *info;
8898 info = gtk_window_get_geometry_info (window, TRUE);
8901 info->mask |= GDK_HINT_USER_POS;
8903 info->mask |= GDK_HINT_USER_SIZE;
8910 gtk_window_mnemonic_hash_foreach (guint keyval,
8916 GtkWindowKeysForeachFunc func;
8920 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
8924 _gtk_window_keys_foreach (GtkWindow *window,
8925 GtkWindowKeysForeachFunc func,
8929 GtkMnemonicHash *mnemonic_hash;
8933 GtkWindowKeysForeachFunc func;
8937 info.window = window;
8939 info.func_data = func_data;
8941 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8943 _gtk_mnemonic_hash_foreach (mnemonic_hash,
8944 gtk_window_mnemonic_hash_foreach, &info);
8946 groups = gtk_accel_groups_from_object (G_OBJECT (window));
8949 GtkAccelGroup *group = groups->data;
8952 for (i = 0; i < group->priv->n_accels; i++)
8954 GtkAccelKey *key = &group->priv->priv_accels[i].key;
8957 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8960 groups = groups->next;
8965 gtk_window_keys_changed (GtkWindow *window)
8967 gtk_window_free_key_hash (window);
8968 gtk_window_get_key_hash (window);
8971 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8973 struct _GtkWindowKeyEntry
8977 guint is_mnemonic : 1;
8981 window_key_entry_destroy (gpointer data)
8983 g_slice_free (GtkWindowKeyEntry, data);
8987 add_to_key_hash (GtkWindow *window,
8989 GdkModifierType modifiers,
8990 gboolean is_mnemonic,
8993 GtkKeyHash *key_hash = data;
8995 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8997 entry->keyval = keyval;
8998 entry->modifiers = modifiers;
8999 entry->is_mnemonic = is_mnemonic;
9001 /* GtkAccelGroup stores lowercased accelerators. To deal
9002 * with this, if <Shift> was specified, uppercase.
9004 if (modifiers & GDK_SHIFT_MASK)
9006 if (keyval == GDK_KEY_Tab)
9007 keyval = GDK_KEY_ISO_Left_Tab;
9009 keyval = gdk_keyval_to_upper (keyval);
9012 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9016 gtk_window_get_key_hash (GtkWindow *window)
9018 GdkScreen *screen = gtk_window_check_screen (window);
9019 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9024 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9025 (GDestroyNotify)window_key_entry_destroy);
9026 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9027 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9033 gtk_window_free_key_hash (GtkWindow *window)
9035 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9038 _gtk_key_hash_free (key_hash);
9039 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9044 * gtk_window_activate_key:
9045 * @window: a #GtkWindow
9046 * @event: a #GdkEventKey
9048 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9049 * called by the default ::key_press_event handler for toplevel windows,
9050 * however in some cases it may be useful to call this directly when
9051 * overriding the standard key handling for a toplevel window.
9053 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9058 gtk_window_activate_key (GtkWindow *window,
9061 GtkKeyHash *key_hash;
9062 GtkWindowKeyEntry *found_entry = NULL;
9063 gboolean enable_mnemonics;
9064 gboolean enable_accels;
9066 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9067 g_return_val_if_fail (event != NULL, FALSE);
9069 key_hash = gtk_window_get_key_hash (window);
9074 GSList *entries = _gtk_key_hash_lookup (key_hash,
9075 event->hardware_keycode,
9077 gtk_accelerator_get_default_mod_mask (),
9080 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9081 "gtk-enable-mnemonics", &enable_mnemonics,
9082 "gtk-enable-accels", &enable_accels,
9085 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9087 GtkWindowKeyEntry *entry = tmp_list->data;
9088 if (entry->is_mnemonic)
9090 if (enable_mnemonics)
9092 found_entry = entry;
9098 if (enable_accels && !found_entry)
9100 found_entry = entry;
9105 g_slist_free (entries);
9110 if (found_entry->is_mnemonic)
9112 if (enable_mnemonics)
9113 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9114 found_entry->modifiers);
9119 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9120 found_entry->modifiers);
9128 window_update_has_focus (GtkWindow *window)
9130 GtkWindowPrivate *priv = window->priv;
9131 GtkWidget *widget = GTK_WIDGET (window);
9132 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9134 if (has_focus != priv->has_focus)
9136 priv->has_focus = has_focus;
9140 if (priv->focus_widget &&
9141 priv->focus_widget != widget &&
9142 !gtk_widget_has_focus (priv->focus_widget))
9143 do_focus_change (priv->focus_widget, TRUE);
9147 if (priv->focus_widget &&
9148 priv->focus_widget != widget &&
9149 gtk_widget_has_focus (priv->focus_widget))
9150 do_focus_change (priv->focus_widget, FALSE);
9156 * _gtk_window_set_is_active:
9157 * @window: a #GtkWindow
9158 * @is_active: %TRUE if the window is in the currently active toplevel
9160 * Internal function that sets whether the #GtkWindow is part
9161 * of the currently active toplevel window (taking into account inter-process
9165 _gtk_window_set_is_active (GtkWindow *window,
9168 GtkWindowPrivate *priv;
9170 g_return_if_fail (GTK_IS_WINDOW (window));
9172 priv = window->priv;
9174 is_active = is_active != FALSE;
9176 if (is_active != priv->is_active)
9178 priv->is_active = is_active;
9179 window_update_has_focus (window);
9181 g_object_notify (G_OBJECT (window), "is-active");
9186 * _gtk_window_set_is_toplevel:
9187 * @window: a #GtkWindow
9188 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9189 * parent of the root window); %FALSE if it is not (for example, for an
9190 * in-process, parented GtkPlug)
9192 * Internal function used by #GtkPlug when it gets parented/unparented by a
9193 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9194 * global list of toplevel windows.
9197 _gtk_window_set_is_toplevel (GtkWindow *window,
9198 gboolean is_toplevel)
9202 widget = GTK_WIDGET (window);
9204 if (gtk_widget_is_toplevel (widget))
9205 g_assert (g_slist_find (toplevel_list, window) != NULL);
9207 g_assert (g_slist_find (toplevel_list, window) == NULL);
9209 if (is_toplevel == gtk_widget_is_toplevel (widget))
9214 _gtk_widget_set_is_toplevel (widget, TRUE);
9215 toplevel_list = g_slist_prepend (toplevel_list, window);
9219 _gtk_widget_set_is_toplevel (widget, FALSE);
9220 toplevel_list = g_slist_remove (toplevel_list, window);
9225 * _gtk_window_set_has_toplevel_focus:
9226 * @window: a #GtkWindow
9227 * @has_toplevel_focus: %TRUE if the in
9229 * Internal function that sets whether the keyboard focus for the
9230 * toplevel window (taking into account inter-process embedding.)
9233 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9234 gboolean has_toplevel_focus)
9236 GtkWindowPrivate *priv;
9238 g_return_if_fail (GTK_IS_WINDOW (window));
9240 priv = window->priv;
9242 has_toplevel_focus = has_toplevel_focus != FALSE;
9244 if (has_toplevel_focus != priv->has_toplevel_focus)
9246 priv->has_toplevel_focus = has_toplevel_focus;
9247 window_update_has_focus (window);
9249 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9254 * gtk_window_set_auto_startup_notification:
9255 * @setting: %TRUE to automatically do startup notification
9257 * By default, after showing the first #GtkWindow, GTK+ calls
9258 * gdk_notify_startup_complete(). Call this function to disable
9259 * the automatic startup notification. You might do this if your
9260 * first window is a splash screen, and you want to delay notification
9261 * until after your real main window has been shown, for example.
9263 * In that example, you would disable startup notification
9264 * temporarily, show your splash screen, then re-enable it so that
9265 * showing the main window would automatically result in notification.
9270 gtk_window_set_auto_startup_notification (gboolean setting)
9272 disable_startup_notification = !setting;
9276 * gtk_window_get_window_type:
9277 * @window: a #GtkWindow
9279 * Gets the type of the window. See #GtkWindowType.
9281 * Return value: the type of the window
9286 gtk_window_get_window_type (GtkWindow *window)
9288 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9290 return window->priv->type;
9294 * gtk_window_get_mnemonics_visible:
9295 * @window: a #GtkWindow
9297 * Gets the value of the #GtkWindow:mnemonics-visible property.
9299 * Returns: %TRUE if mnemonics are supposed to be visible
9305 gtk_window_get_mnemonics_visible (GtkWindow *window)
9307 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9309 return window->priv->mnemonics_visible;
9313 * gtk_window_set_mnemonics_visible:
9314 * @window: a #GtkWindow
9315 * @setting: the new value
9317 * Sets the #GtkWindow:mnemonics-visible property.
9322 gtk_window_set_mnemonics_visible (GtkWindow *window,
9325 GtkWindowPrivate *priv;
9327 g_return_if_fail (GTK_IS_WINDOW (window));
9329 priv = window->priv;
9331 setting = setting != FALSE;
9333 if (priv->mnemonics_visible != setting)
9335 priv->mnemonics_visible = setting;
9336 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9339 priv->mnemonics_visible_set = TRUE;
9343 _gtk_window_get_wmclass (GtkWindow *window,
9344 gchar **wmclass_name,
9345 gchar **wmclass_class)
9347 GtkWindowPrivate *priv = window->priv;
9349 *wmclass_name = priv->wmclass_name;
9350 *wmclass_class = priv->wmclass_class;