1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include "gtkwindow.h"
36 #include "gtkprivate.h"
38 #include "gtkwindowprivate.h"
39 #include "gtkaccelgroupprivate.h"
40 #include "gtkbindings.h"
41 #include "gtkkeyhash.h"
43 #include "gtkmnemonichash.h"
44 #include "gtkmenubar.h"
45 #include "gtkiconfactory.h"
46 #include "gtkicontheme.h"
47 #include "gtkmarshalers.h"
49 #include "gtkbuildable.h"
50 #include "gtkwidgetprivate.h"
52 #include "gtktypebuiltins.h"
54 #ifdef GDK_WINDOWING_X11
61 * @short_description: Toplevel which can contain other widgets
63 * A GtkWindow is a toplevel window which can contain other widgets.
64 * Windows normally have decorations that are under the control
65 * of the windowing system and allow the user to manipulate the window
66 * (resize it, move it, close it,...).
68 * GTK+ also allows windows to have a resize grip (a small area in the lower
69 * right or left corner) which can be clicked to reszie the window. To
70 * control whether a window has a resize grip, use
71 * gtk_window_set_has_resize_grip().
73 * <refsect2 id="GtkWindow-BUILDER-UI">
74 * <title>GtkWindow as GtkBuildable</title>
76 * The GtkWindow implementation of the GtkBuildable interface supports a
77 * custom <tag class="starttag">accel-groups</tag> element, which supports
78 * any number of <tag class="starttag">group</tag> elements representing the
79 * #GtkAccelGroup objects you want to add to your window (synonymous with
80 * gtk_window_add_accel_group().
83 * <title>A UI definition fragment with accel groups</title>
84 * <programlisting><![CDATA[
85 * <object class="GtkWindow">
87 * <group name="accelgroup1"/>
93 * <object class="GtkAccelGroup" id="accelgroup1"/>
94 * ]]></programlisting>
99 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
101 struct _GtkWindowPrivate
103 GtkMnemonicHash *mnemonic_hash;
105 GtkWidget *default_widget;
106 GtkWidget *focus_widget;
107 GtkWindow *transient_parent;
108 GtkWindowGeometryInfo *geometry_info;
109 GtkWindowGroup *group;
111 GdkModifierType mnemonic_modifier;
113 GdkWindowTypeHint gdk_type_hint;
115 GtkApplication *application;
119 GdkWindow *grip_window;
123 gchar *wmclass_class;
127 guint keys_changed_handler;
129 guint16 configure_request_count;
131 /* The following flags are initially TRUE (before a window is mapped).
132 * They cause us to compute a configure request that involves
133 * default-only parameters. Once mapped, we set them to FALSE.
134 * Then we set them to TRUE again on unmap (for position)
135 * and on unrealize (for size).
137 guint need_default_position : 1;
138 guint need_default_size : 1;
140 guint above_initially : 1;
141 guint accept_focus : 1;
142 guint below_initially : 1;
143 guint builder_visible : 1;
144 guint configure_notify_received : 1;
147 guint destroy_with_parent : 1;
148 guint focus_on_map : 1;
149 guint fullscreen_initially : 1;
150 guint gravity : 5; /* GdkGravity */
152 guint has_user_ref_count : 1;
153 guint has_toplevel_focus : 1;
154 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
156 guint maximize_initially : 1;
157 guint mnemonics_visible : 1;
158 guint mnemonics_visible_set : 1;
160 guint opacity_set : 1;
162 guint reset_type_hint : 1;
164 guint skips_pager : 1;
165 guint skips_taskbar : 1;
166 guint stick_initially : 1;
167 guint transient_parent_group : 1;
168 guint type : 4; /* GtkWindowType */
169 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
170 * one of the original eight. If not,
172 * GDK_WINDOW_TYPE_HINT_NORMAL
175 guint has_resize_grip : 1;
176 guint resize_grip_visible : 1; /* don't use, just for "resize-
177 * grip-visible" notification
205 PROP_DESTROY_WITH_PARENT,
210 PROP_SKIP_TASKBAR_HINT,
211 PROP_SKIP_PAGER_HINT,
220 PROP_HAS_RESIZE_GRIP,
221 PROP_RESIZE_GRIP_VISIBLE,
223 /* Readonly properties */
225 PROP_HAS_TOPLEVEL_FOCUS,
227 /* Writeonly properties */
230 PROP_MNEMONICS_VISIBLE,
240 guint using_default_icon : 1;
241 guint using_parent_icon : 1;
242 guint using_themed_icon : 1;
246 GdkGeometry geometry; /* Last set of geometry hints we set */
247 GdkWindowHints flags;
248 GdkRectangle configure_request;
249 } GtkWindowLastGeometryInfo;
251 struct _GtkWindowGeometryInfo
253 /* Properties that the app has set on the window
255 GdkGeometry geometry; /* Geometry hints */
257 GtkWidget *widget; /* subwidget to which hints apply */
258 /* from last gtk_window_resize () - if > 0, indicates that
259 * we should resize to this size.
264 /* From last gtk_window_move () prior to mapping -
265 * only used if initial_pos_set
270 /* Default size - used only the FIRST time we map a window,
275 /* whether to use initial_x, initial_y */
276 guint initial_pos_set : 1;
277 /* CENTER_ALWAYS or other position constraint changed since
278 * we sent the last configure request.
280 guint position_constraints_changed : 1;
282 /* if true, default_width, height should be multiplied by the
283 * increments and affect the geometry widget only
285 guint default_is_geometry : 1;
287 /* if true, resize_width, height should be multiplied by the
288 * increments and affect the geometry widget only
290 guint resize_is_geometry : 1;
292 GtkWindowLastGeometryInfo last;
296 struct _GtkDeviceGrabInfo
300 guint block_others : 1;
303 struct _GtkWindowGroupPrivate
306 GSList *device_grabs;
309 static void gtk_window_dispose (GObject *object);
310 static void gtk_window_finalize (GObject *object);
311 static void gtk_window_destroy (GtkWidget *widget);
312 static void gtk_window_show (GtkWidget *widget);
313 static void gtk_window_hide (GtkWidget *widget);
314 static void gtk_window_map (GtkWidget *widget);
315 static void gtk_window_unmap (GtkWidget *widget);
316 static void gtk_window_realize (GtkWidget *widget);
317 static void gtk_window_unrealize (GtkWidget *widget);
318 static void gtk_window_size_allocate (GtkWidget *widget,
319 GtkAllocation *allocation);
320 static gboolean gtk_window_map_event (GtkWidget *widget,
322 static gint gtk_window_configure_event (GtkWidget *widget,
323 GdkEventConfigure *event);
324 static gint gtk_window_key_press_event (GtkWidget *widget,
326 static gint gtk_window_key_release_event (GtkWidget *widget,
328 static gint gtk_window_button_press_event (GtkWidget *widget,
329 GdkEventButton *event);
330 static gint gtk_window_enter_notify_event (GtkWidget *widget,
331 GdkEventCrossing *event);
332 static gint gtk_window_leave_notify_event (GtkWidget *widget,
333 GdkEventCrossing *event);
334 static gint gtk_window_focus_in_event (GtkWidget *widget,
335 GdkEventFocus *event);
336 static gint gtk_window_focus_out_event (GtkWidget *widget,
337 GdkEventFocus *event);
338 static void gtk_window_style_updated (GtkWidget *widget);
339 static gint gtk_window_client_event (GtkWidget *widget,
340 GdkEventClient *event);
341 static gboolean gtk_window_state_event (GtkWidget *widget,
342 GdkEventWindowState *event);
343 static void gtk_window_check_resize (GtkContainer *container);
344 static gint gtk_window_focus (GtkWidget *widget,
345 GtkDirectionType direction);
346 static void gtk_window_move_focus (GtkWidget *widget,
347 GtkDirectionType dir);
348 static void gtk_window_real_set_focus (GtkWindow *window,
350 static void gtk_window_direction_changed (GtkWidget *widget,
351 GtkTextDirection prev_dir);
352 static void gtk_window_state_changed (GtkWidget *widget,
353 GtkStateType previous_state);
355 static void gtk_window_real_activate_default (GtkWindow *window);
356 static void gtk_window_real_activate_focus (GtkWindow *window);
357 static void gtk_window_keys_changed (GtkWindow *window);
358 static gint gtk_window_draw (GtkWidget *widget,
360 static void gtk_window_unset_transient_for (GtkWindow *window);
361 static void gtk_window_transient_parent_realized (GtkWidget *parent,
363 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
366 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
368 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
371 static void gtk_window_move_resize (GtkWindow *window);
372 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
374 GdkGeometry *geometry_b,
376 static void gtk_window_constrain_size (GtkWindow *window,
377 GdkGeometry *geometry,
383 static void gtk_window_constrain_position (GtkWindow *window,
388 static void gtk_window_compute_hints (GtkWindow *window,
389 GdkGeometry *new_geometry,
391 static void gtk_window_compute_configure_request (GtkWindow *window,
392 GdkRectangle *request,
393 GdkGeometry *geometry,
396 static void gtk_window_set_default_size_internal (GtkWindow *window,
397 gboolean change_width,
399 gboolean change_height,
401 gboolean is_geometry);
403 static void update_themed_icon (GtkIconTheme *theme,
405 static GList *icon_list_from_theme (GtkWidget *widget,
407 static void gtk_window_realize_icon (GtkWindow *window);
408 static void gtk_window_unrealize_icon (GtkWindow *window);
409 static void resize_grip_create_window (GtkWindow *window);
410 static void resize_grip_destroy_window (GtkWindow *window);
411 static void update_grip_visibility (GtkWindow *window);
413 static void gtk_window_notify_keys_changed (GtkWindow *window);
414 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
415 static void gtk_window_free_key_hash (GtkWindow *window);
416 static void gtk_window_on_composited_changed (GdkScreen *screen,
419 static GSList *toplevel_list = NULL;
420 static guint window_signals[LAST_SIGNAL] = { 0 };
421 static GList *default_icon_list = NULL;
422 static gchar *default_icon_name = NULL;
423 static guint default_icon_serial = 0;
424 static gboolean disable_startup_notification = FALSE;
425 static gboolean sent_startup_notification = FALSE;
427 static GQuark quark_gtk_embedded = 0;
428 static GQuark quark_gtk_window_key_hash = 0;
429 static GQuark quark_gtk_window_icon_info = 0;
430 static GQuark quark_gtk_buildable_accels = 0;
432 static GtkBuildableIface *parent_buildable_iface;
434 static void gtk_window_set_property (GObject *object,
438 static void gtk_window_get_property (GObject *object,
444 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
445 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
448 const GValue *value);
449 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
450 GtkBuilder *builder);
451 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
454 const gchar *tagname,
455 GMarkupParser *parser,
457 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
460 const gchar *tagname,
464 static void gtk_window_get_preferred_width (GtkWidget *widget,
467 static void gtk_window_get_preferred_height (GtkWidget *widget,
471 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
472 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
473 gtk_window_buildable_interface_init))
476 add_tab_bindings (GtkBindingSet *binding_set,
477 GdkModifierType modifiers,
478 GtkDirectionType direction)
480 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
482 GTK_TYPE_DIRECTION_TYPE, direction);
483 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
485 GTK_TYPE_DIRECTION_TYPE, direction);
489 add_arrow_bindings (GtkBindingSet *binding_set,
491 GtkDirectionType direction)
493 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
495 gtk_binding_entry_add_signal (binding_set, keysym, 0,
497 GTK_TYPE_DIRECTION_TYPE, direction);
498 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
500 GTK_TYPE_DIRECTION_TYPE, direction);
501 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
503 GTK_TYPE_DIRECTION_TYPE, direction);
504 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
506 GTK_TYPE_DIRECTION_TYPE, direction);
510 extract_time_from_startup_id (const gchar* startup_id)
512 gchar *timestr = g_strrstr (startup_id, "_TIME");
513 guint32 retval = GDK_CURRENT_TIME;
520 /* Skip past the "_TIME" part */
525 timestamp = g_ascii_strtoull (timestr, &end, 0);
526 if (errno == 0 && end != timestr)
534 startup_id_is_fake (const gchar* startup_id)
536 return strncmp (startup_id, "_TIME", 5) == 0;
540 gtk_window_class_init (GtkWindowClass *klass)
542 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
543 GtkWidgetClass *widget_class;
544 GtkContainerClass *container_class;
545 GtkBindingSet *binding_set;
547 widget_class = (GtkWidgetClass*) klass;
548 container_class = (GtkContainerClass*) klass;
550 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
551 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
552 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
553 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
555 gobject_class->dispose = gtk_window_dispose;
556 gobject_class->finalize = gtk_window_finalize;
558 gobject_class->set_property = gtk_window_set_property;
559 gobject_class->get_property = gtk_window_get_property;
561 widget_class->destroy = gtk_window_destroy;
562 widget_class->show = gtk_window_show;
563 widget_class->hide = gtk_window_hide;
564 widget_class->map = gtk_window_map;
565 widget_class->map_event = gtk_window_map_event;
566 widget_class->unmap = gtk_window_unmap;
567 widget_class->realize = gtk_window_realize;
568 widget_class->unrealize = gtk_window_unrealize;
569 widget_class->size_allocate = gtk_window_size_allocate;
570 widget_class->configure_event = gtk_window_configure_event;
571 widget_class->key_press_event = gtk_window_key_press_event;
572 widget_class->key_release_event = gtk_window_key_release_event;
573 widget_class->enter_notify_event = gtk_window_enter_notify_event;
574 widget_class->leave_notify_event = gtk_window_leave_notify_event;
575 widget_class->focus_in_event = gtk_window_focus_in_event;
576 widget_class->button_press_event = gtk_window_button_press_event;
577 widget_class->focus_out_event = gtk_window_focus_out_event;
578 widget_class->client_event = gtk_window_client_event;
579 widget_class->focus = gtk_window_focus;
580 widget_class->move_focus = gtk_window_move_focus;
581 widget_class->draw = gtk_window_draw;
582 widget_class->get_preferred_width = gtk_window_get_preferred_width;
583 widget_class->get_preferred_height = gtk_window_get_preferred_height;
584 widget_class->window_state_event = gtk_window_state_event;
585 widget_class->direction_changed = gtk_window_direction_changed;
586 widget_class->state_changed = gtk_window_state_changed;
587 widget_class->style_updated = gtk_window_style_updated;
589 container_class->check_resize = gtk_window_check_resize;
591 klass->set_focus = gtk_window_real_set_focus;
593 klass->activate_default = gtk_window_real_activate_default;
594 klass->activate_focus = gtk_window_real_activate_focus;
595 klass->keys_changed = gtk_window_keys_changed;
597 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
600 g_object_class_install_property (gobject_class,
602 g_param_spec_enum ("type",
604 P_("The type of the window"),
605 GTK_TYPE_WINDOW_TYPE,
607 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
609 g_object_class_install_property (gobject_class,
611 g_param_spec_string ("title",
613 P_("The title of the window"),
615 GTK_PARAM_READWRITE));
617 g_object_class_install_property (gobject_class,
619 g_param_spec_string ("role",
621 P_("Unique identifier for the window to be used when restoring a session"),
623 GTK_PARAM_READWRITE));
626 * GtkWindow:startup-id:
628 * The :startup-id is a write-only property for setting window's
629 * startup notification identifier. See gtk_window_set_startup_id()
634 g_object_class_install_property (gobject_class,
636 g_param_spec_string ("startup-id",
638 P_("Unique startup identifier for the window used by startup-notification"),
640 GTK_PARAM_WRITABLE));
642 g_object_class_install_property (gobject_class,
644 g_param_spec_boolean ("resizable",
646 P_("If TRUE, users can resize the window"),
648 GTK_PARAM_READWRITE));
650 g_object_class_install_property (gobject_class,
652 g_param_spec_boolean ("modal",
654 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
656 GTK_PARAM_READWRITE));
658 g_object_class_install_property (gobject_class,
660 g_param_spec_enum ("window-position",
661 P_("Window Position"),
662 P_("The initial position of the window"),
663 GTK_TYPE_WINDOW_POSITION,
665 GTK_PARAM_READWRITE));
667 g_object_class_install_property (gobject_class,
669 g_param_spec_int ("default-width",
671 P_("The default width of the window, used when initially showing the window"),
675 GTK_PARAM_READWRITE));
677 g_object_class_install_property (gobject_class,
679 g_param_spec_int ("default-height",
680 P_("Default Height"),
681 P_("The default height of the window, used when initially showing the window"),
685 GTK_PARAM_READWRITE));
687 g_object_class_install_property (gobject_class,
688 PROP_DESTROY_WITH_PARENT,
689 g_param_spec_boolean ("destroy-with-parent",
690 P_("Destroy with Parent"),
691 P_("If this window should be destroyed when the parent is destroyed"),
693 GTK_PARAM_READWRITE));
695 g_object_class_install_property (gobject_class,
697 g_param_spec_object ("icon",
699 P_("Icon for this window"),
701 GTK_PARAM_READWRITE));
702 g_object_class_install_property (gobject_class,
703 PROP_MNEMONICS_VISIBLE,
704 g_param_spec_boolean ("mnemonics-visible",
705 P_("Mnemonics Visible"),
706 P_("Whether mnemonics are currently visible in this window"),
708 GTK_PARAM_READWRITE));
711 * GtkWindow:icon-name:
713 * The :icon-name property specifies the name of the themed icon to
714 * use as the window icon. See #GtkIconTheme for more details.
718 g_object_class_install_property (gobject_class,
720 g_param_spec_string ("icon-name",
722 P_("Name of the themed icon for this window"),
724 GTK_PARAM_READWRITE));
726 g_object_class_install_property (gobject_class,
728 g_param_spec_object ("screen",
730 P_("The screen where this window will be displayed"),
732 GTK_PARAM_READWRITE));
734 g_object_class_install_property (gobject_class,
736 g_param_spec_boolean ("is-active",
738 P_("Whether the toplevel is the current active window"),
740 GTK_PARAM_READABLE));
742 g_object_class_install_property (gobject_class,
743 PROP_HAS_TOPLEVEL_FOCUS,
744 g_param_spec_boolean ("has-toplevel-focus",
745 P_("Focus in Toplevel"),
746 P_("Whether the input focus is within this GtkWindow"),
748 GTK_PARAM_READABLE));
750 g_object_class_install_property (gobject_class,
752 g_param_spec_enum ("type-hint",
754 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
755 GDK_TYPE_WINDOW_TYPE_HINT,
756 GDK_WINDOW_TYPE_HINT_NORMAL,
757 GTK_PARAM_READWRITE));
759 g_object_class_install_property (gobject_class,
760 PROP_SKIP_TASKBAR_HINT,
761 g_param_spec_boolean ("skip-taskbar-hint",
763 P_("TRUE if the window should not be in the task bar."),
765 GTK_PARAM_READWRITE));
767 g_object_class_install_property (gobject_class,
768 PROP_SKIP_PAGER_HINT,
769 g_param_spec_boolean ("skip-pager-hint",
771 P_("TRUE if the window should not be in the pager."),
773 GTK_PARAM_READWRITE));
775 g_object_class_install_property (gobject_class,
777 g_param_spec_boolean ("urgency-hint",
779 P_("TRUE if the window should be brought to the user's attention."),
781 GTK_PARAM_READWRITE));
784 * GtkWindow:accept-focus:
786 * Whether the window should receive the input focus.
790 g_object_class_install_property (gobject_class,
792 g_param_spec_boolean ("accept-focus",
794 P_("TRUE if the window should receive the input focus."),
796 GTK_PARAM_READWRITE));
799 * GtkWindow:focus-on-map:
801 * Whether the window should receive the input focus when mapped.
805 g_object_class_install_property (gobject_class,
807 g_param_spec_boolean ("focus-on-map",
809 P_("TRUE if the window should receive the input focus when mapped."),
811 GTK_PARAM_READWRITE));
814 * GtkWindow:decorated:
816 * Whether the window should be decorated by the window manager.
820 g_object_class_install_property (gobject_class,
822 g_param_spec_boolean ("decorated",
824 P_("Whether the window should be decorated by the window manager"),
826 GTK_PARAM_READWRITE));
829 * GtkWindow:deletable:
831 * Whether the window frame should have a close button.
835 g_object_class_install_property (gobject_class,
837 g_param_spec_boolean ("deletable",
839 P_("Whether the window frame should have a close button"),
841 GTK_PARAM_READWRITE));
844 * GtkWindow:has-resize-grip
846 * Whether the window has a corner resize grip.
848 * Note that the resize grip is only shown if the window is
849 * actually resizable and not maximized. Use
850 * #GtkWindow:resize-grip-visible to find out if the resize
851 * grip is currently shown.
855 g_object_class_install_property (gobject_class,
856 PROP_HAS_RESIZE_GRIP,
857 g_param_spec_boolean ("has-resize-grip",
859 P_("Specifies whether the window should have a resize grip"),
861 GTK_PARAM_READWRITE));
864 * GtkWindow:resize-grip-visible:
866 * Whether a corner resize grip is currently shown.
870 g_object_class_install_property (gobject_class,
871 PROP_RESIZE_GRIP_VISIBLE,
872 g_param_spec_boolean ("resize-grip-visible",
873 P_("Resize grip is visible"),
874 P_("Specifies whether the window's resize grip is visible."),
876 GTK_PARAM_READABLE));
882 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
883 * more details about window gravity.
887 g_object_class_install_property (gobject_class,
889 g_param_spec_enum ("gravity",
891 P_("The window gravity of the window"),
893 GDK_GRAVITY_NORTH_WEST,
894 GTK_PARAM_READWRITE));
898 * GtkWindow:transient-for:
900 * The transient parent of the window. See gtk_window_set_transient_for() for
901 * more details about transient windows.
905 g_object_class_install_property (gobject_class,
907 g_param_spec_object ("transient-for",
908 P_("Transient for Window"),
909 P_("The transient parent of the dialog"),
911 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
916 * The requested opacity of the window. See gtk_window_set_opacity() for
917 * more details about window opacity.
921 g_object_class_install_property (gobject_class,
923 g_param_spec_double ("opacity",
924 P_("Opacity for Window"),
925 P_("The opacity of the window, from 0 to 1"),
929 GTK_PARAM_READWRITE));
933 gtk_widget_class_install_style_property (widget_class,
934 g_param_spec_int ("resize-grip-width",
935 P_("Width of resize grip"),
936 P_("Width of resize grip"),
937 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
939 gtk_widget_class_install_style_property (widget_class,
940 g_param_spec_int ("resize-grip-height",
941 P_("Height of resize grip"),
942 P_("Height of resize grip"),
943 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
949 * GtkWindow:application:
951 * The #GtkApplication associated with the window.
953 * The application will be kept alive for at least as long as the
958 g_object_class_install_property (gobject_class,
960 g_param_spec_object ("application",
961 P_("GtkApplication"),
962 P_("The GtkApplication for the window"),
963 GTK_TYPE_APPLICATION,
964 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
966 window_signals[SET_FOCUS] =
967 g_signal_new (I_("set-focus"),
968 G_TYPE_FROM_CLASS (gobject_class),
970 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
972 _gtk_marshal_VOID__OBJECT,
977 * GtkWindow::activate-focus:
978 * @window: the window which received the signal
980 * The ::activate-focus signal is a
981 * <link linkend="keybinding-signals">keybinding signal</link>
982 * which gets emitted when the user activates the currently
983 * focused widget of @window.
985 window_signals[ACTIVATE_FOCUS] =
986 g_signal_new (I_("activate-focus"),
987 G_TYPE_FROM_CLASS (gobject_class),
988 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
989 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
991 _gtk_marshal_VOID__VOID,
996 * GtkWindow::activate-default:
997 * @window: the window which received the signal
999 * The ::activate-default signal is a
1000 * <link linkend="keybinding-signals">keybinding signal</link>
1001 * which gets emitted when the user activates the default widget
1004 window_signals[ACTIVATE_DEFAULT] =
1005 g_signal_new (I_("activate-default"),
1006 G_TYPE_FROM_CLASS (gobject_class),
1007 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1008 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1010 _gtk_marshal_VOID__VOID,
1015 * GtkWindow::keys-changed:
1016 * @window: the window which received the signal
1018 * The ::keys-changed signal gets emitted when the set of accelerators
1019 * or mnemonics that are associated with @window changes.
1021 window_signals[KEYS_CHANGED] =
1022 g_signal_new (I_("keys-changed"),
1023 G_TYPE_FROM_CLASS (gobject_class),
1025 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1027 _gtk_marshal_VOID__VOID,
1035 binding_set = gtk_binding_set_by_class (klass);
1037 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1038 "activate-focus", 0);
1039 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1040 "activate-focus", 0);
1042 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1043 "activate-default", 0);
1044 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1045 "activate-default", 0);
1046 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1047 "activate-default", 0);
1049 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1050 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1051 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1052 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1054 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1055 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1056 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1057 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1061 gtk_window_init (GtkWindow *window)
1063 GtkWindowPrivate *priv;
1065 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1068 priv = window->priv;
1070 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1071 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1073 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1075 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1078 priv->wmclass_name = g_strdup (g_get_prgname ());
1079 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1080 priv->wm_role = NULL;
1081 priv->geometry_info = NULL;
1082 priv->type = GTK_WINDOW_TOPLEVEL;
1083 priv->focus_widget = NULL;
1084 priv->default_widget = NULL;
1085 priv->configure_request_count = 0;
1086 priv->resizable = TRUE;
1087 priv->configure_notify_received = FALSE;
1088 priv->position = GTK_WIN_POS_NONE;
1089 priv->need_default_size = TRUE;
1090 priv->need_default_position = TRUE;
1091 priv->modal = FALSE;
1092 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1093 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1094 priv->decorated = TRUE;
1095 priv->mnemonic_modifier = GDK_MOD1_MASK;
1096 priv->screen = gdk_screen_get_default ();
1098 priv->accept_focus = TRUE;
1099 priv->focus_on_map = TRUE;
1100 priv->deletable = TRUE;
1101 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1102 priv->opacity = 1.0;
1103 priv->startup_id = NULL;
1104 priv->has_resize_grip = TRUE;
1105 priv->mnemonics_visible = TRUE;
1107 g_object_ref_sink (window);
1108 priv->has_user_ref_count = TRUE;
1109 toplevel_list = g_slist_prepend (toplevel_list, window);
1111 g_signal_connect (priv->screen, "composited-changed",
1112 G_CALLBACK (gtk_window_on_composited_changed), window);
1116 gtk_window_set_property (GObject *object,
1118 const GValue *value,
1121 GtkWindow *window = GTK_WINDOW (object);
1122 GtkWindowPrivate *priv = window->priv;
1127 priv->type = g_value_get_enum (value);
1130 gtk_window_set_title (window, g_value_get_string (value));
1133 gtk_window_set_role (window, g_value_get_string (value));
1135 case PROP_STARTUP_ID:
1136 gtk_window_set_startup_id (window, g_value_get_string (value));
1138 case PROP_RESIZABLE:
1139 gtk_window_set_resizable (window, g_value_get_boolean (value));
1142 gtk_window_set_modal (window, g_value_get_boolean (value));
1145 gtk_window_set_position (window, g_value_get_enum (value));
1147 case PROP_DEFAULT_WIDTH:
1148 gtk_window_set_default_size_internal (window,
1149 TRUE, g_value_get_int (value),
1152 case PROP_DEFAULT_HEIGHT:
1153 gtk_window_set_default_size_internal (window,
1155 TRUE, g_value_get_int (value), FALSE);
1157 case PROP_DESTROY_WITH_PARENT:
1158 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1161 gtk_window_set_icon (window,
1162 g_value_get_object (value));
1164 case PROP_ICON_NAME:
1165 gtk_window_set_icon_name (window, g_value_get_string (value));
1168 gtk_window_set_screen (window, g_value_get_object (value));
1170 case PROP_TYPE_HINT:
1171 gtk_window_set_type_hint (window,
1172 g_value_get_enum (value));
1174 case PROP_SKIP_TASKBAR_HINT:
1175 gtk_window_set_skip_taskbar_hint (window,
1176 g_value_get_boolean (value));
1178 case PROP_SKIP_PAGER_HINT:
1179 gtk_window_set_skip_pager_hint (window,
1180 g_value_get_boolean (value));
1182 case PROP_URGENCY_HINT:
1183 gtk_window_set_urgency_hint (window,
1184 g_value_get_boolean (value));
1186 case PROP_ACCEPT_FOCUS:
1187 gtk_window_set_accept_focus (window,
1188 g_value_get_boolean (value));
1190 case PROP_FOCUS_ON_MAP:
1191 gtk_window_set_focus_on_map (window,
1192 g_value_get_boolean (value));
1194 case PROP_DECORATED:
1195 gtk_window_set_decorated (window, g_value_get_boolean (value));
1197 case PROP_DELETABLE:
1198 gtk_window_set_deletable (window, g_value_get_boolean (value));
1201 gtk_window_set_gravity (window, g_value_get_enum (value));
1203 case PROP_TRANSIENT_FOR:
1204 gtk_window_set_transient_for (window, g_value_get_object (value));
1207 gtk_window_set_opacity (window, g_value_get_double (value));
1209 case PROP_HAS_RESIZE_GRIP:
1210 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1212 case PROP_APPLICATION:
1213 gtk_window_set_application (window, g_value_get_object (value));
1215 case PROP_MNEMONICS_VISIBLE:
1216 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1219 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1225 gtk_window_get_property (GObject *object,
1230 GtkWindow *window = GTK_WINDOW (object);
1231 GtkWindowPrivate *priv = window->priv;
1235 GtkWindowGeometryInfo *info;
1237 g_value_set_enum (value, priv->type);
1240 g_value_set_string (value, priv->wm_role);
1243 g_value_set_string (value, priv->title);
1245 case PROP_RESIZABLE:
1246 g_value_set_boolean (value, priv->resizable);
1249 g_value_set_boolean (value, priv->modal);
1252 g_value_set_enum (value, priv->position);
1254 case PROP_DEFAULT_WIDTH:
1255 info = gtk_window_get_geometry_info (window, FALSE);
1257 g_value_set_int (value, -1);
1259 g_value_set_int (value, info->default_width);
1261 case PROP_DEFAULT_HEIGHT:
1262 info = gtk_window_get_geometry_info (window, FALSE);
1264 g_value_set_int (value, -1);
1266 g_value_set_int (value, info->default_height);
1268 case PROP_DESTROY_WITH_PARENT:
1269 g_value_set_boolean (value, priv->destroy_with_parent);
1272 g_value_set_object (value, gtk_window_get_icon (window));
1274 case PROP_ICON_NAME:
1275 g_value_set_string (value, gtk_window_get_icon_name (window));
1278 g_value_set_object (value, priv->screen);
1280 case PROP_IS_ACTIVE:
1281 g_value_set_boolean (value, priv->is_active);
1283 case PROP_HAS_TOPLEVEL_FOCUS:
1284 g_value_set_boolean (value, priv->has_toplevel_focus);
1286 case PROP_TYPE_HINT:
1287 g_value_set_enum (value, priv->type_hint);
1289 case PROP_SKIP_TASKBAR_HINT:
1290 g_value_set_boolean (value,
1291 gtk_window_get_skip_taskbar_hint (window));
1293 case PROP_SKIP_PAGER_HINT:
1294 g_value_set_boolean (value,
1295 gtk_window_get_skip_pager_hint (window));
1297 case PROP_URGENCY_HINT:
1298 g_value_set_boolean (value,
1299 gtk_window_get_urgency_hint (window));
1301 case PROP_ACCEPT_FOCUS:
1302 g_value_set_boolean (value,
1303 gtk_window_get_accept_focus (window));
1305 case PROP_FOCUS_ON_MAP:
1306 g_value_set_boolean (value,
1307 gtk_window_get_focus_on_map (window));
1309 case PROP_DECORATED:
1310 g_value_set_boolean (value, gtk_window_get_decorated (window));
1312 case PROP_DELETABLE:
1313 g_value_set_boolean (value, gtk_window_get_deletable (window));
1316 g_value_set_enum (value, gtk_window_get_gravity (window));
1318 case PROP_TRANSIENT_FOR:
1319 g_value_set_object (value, gtk_window_get_transient_for (window));
1322 g_value_set_double (value, gtk_window_get_opacity (window));
1324 case PROP_HAS_RESIZE_GRIP:
1325 g_value_set_boolean (value, priv->has_resize_grip);
1327 case PROP_RESIZE_GRIP_VISIBLE:
1328 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1330 case PROP_APPLICATION:
1331 g_value_set_object (value, gtk_window_get_application (window));
1333 case PROP_MNEMONICS_VISIBLE:
1334 g_value_set_boolean (value, priv->mnemonics_visible);
1337 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1343 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1345 parent_buildable_iface = g_type_interface_peek_parent (iface);
1346 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1347 iface->parser_finished = gtk_window_buildable_parser_finished;
1348 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1349 iface->custom_finished = gtk_window_buildable_custom_finished;
1353 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1354 GtkBuilder *builder,
1356 const GValue *value)
1358 GtkWindow *window = GTK_WINDOW (buildable);
1359 GtkWindowPrivate *priv = window->priv;
1361 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1362 priv->builder_visible = TRUE;
1364 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1368 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1369 GtkBuilder *builder)
1371 GtkWindow *window = GTK_WINDOW (buildable);
1372 GtkWindowPrivate *priv = window->priv;
1376 if (priv->builder_visible)
1377 gtk_widget_show (GTK_WIDGET (buildable));
1379 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1380 for (l = accels; l; l = l->next)
1382 object = gtk_builder_get_object (builder, l->data);
1385 g_warning ("Unknown accel group %s specified in window %s",
1386 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1389 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1390 GTK_ACCEL_GROUP (object));
1394 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1396 parent_buildable_iface->parser_finished (buildable, builder);
1402 } GSListSubParserData;
1405 window_start_element (GMarkupParseContext *context,
1406 const gchar *element_name,
1407 const gchar **names,
1408 const gchar **values,
1413 GSListSubParserData *data = (GSListSubParserData*)user_data;
1415 if (strcmp (element_name, "group") == 0)
1417 for (i = 0; names[i]; i++)
1419 if (strcmp (names[i], "name") == 0)
1420 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1423 else if (strcmp (element_name, "accel-groups") == 0)
1426 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1431 static const GMarkupParser window_parser =
1433 window_start_element
1437 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1438 GtkBuilder *builder,
1440 const gchar *tagname,
1441 GMarkupParser *parser,
1444 GSListSubParserData *parser_data;
1446 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1447 tagname, parser, data))
1450 if (strcmp (tagname, "accel-groups") == 0)
1452 parser_data = g_slice_new0 (GSListSubParserData);
1453 parser_data->items = NULL;
1454 parser_data->object = G_OBJECT (buildable);
1456 *parser = window_parser;
1457 *data = parser_data;
1465 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1466 GtkBuilder *builder,
1468 const gchar *tagname,
1471 GSListSubParserData *data;
1473 parent_buildable_iface->custom_finished (buildable, builder, child,
1474 tagname, user_data);
1476 if (strcmp (tagname, "accel-groups") != 0)
1479 data = (GSListSubParserData*)user_data;
1481 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1482 data->items, (GDestroyNotify) g_slist_free);
1484 g_slice_free (GSListSubParserData, data);
1489 * @type: type of window
1491 * Creates a new #GtkWindow, which is a toplevel window that can
1492 * contain other widgets. Nearly always, the type of the window should
1493 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1494 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1495 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1496 * dialogs, though in some other toolkits dialogs are called "popups".
1497 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1498 * On X11, popup windows are not controlled by the <link
1499 * linkend="gtk-X11-arch">window manager</link>.
1501 * If you simply want an undecorated window (no window borders), use
1502 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1504 * Return value: a new #GtkWindow.
1507 gtk_window_new (GtkWindowType type)
1509 GtkWindowPrivate *priv;
1512 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1514 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1515 priv = window->priv;
1519 return GTK_WIDGET (window);
1523 * gtk_window_set_title:
1524 * @window: a #GtkWindow
1525 * @title: title of the window
1527 * Sets the title of the #GtkWindow. The title of a window will be
1528 * displayed in its title bar; on the X Window System, the title bar
1529 * is rendered by the <link linkend="gtk-X11-arch">window
1530 * manager</link>, so exactly how the title appears to users may vary
1531 * according to a user's exact configuration. The title should help a
1532 * user distinguish this window from other windows they may have
1533 * open. A good title might include the application name and current
1534 * document filename, for example.
1538 gtk_window_set_title (GtkWindow *window,
1541 GtkWindowPrivate *priv;
1545 g_return_if_fail (GTK_IS_WINDOW (window));
1547 priv = window->priv;
1548 widget = GTK_WIDGET (window);
1550 new_title = g_strdup (title);
1551 g_free (priv->title);
1552 priv->title = new_title;
1554 if (gtk_widget_get_realized (widget))
1556 gdk_window_set_title (gtk_widget_get_window (widget),
1560 g_object_notify (G_OBJECT (window), "title");
1564 * gtk_window_get_title:
1565 * @window: a #GtkWindow
1567 * Retrieves the title of the window. See gtk_window_set_title().
1569 * Return value: the title of the window, or %NULL if none has
1570 * been set explicitely. The returned string is owned by the widget
1571 * and must not be modified or freed.
1573 G_CONST_RETURN gchar *
1574 gtk_window_get_title (GtkWindow *window)
1576 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1578 return window->priv->title;
1582 * gtk_window_set_wmclass:
1583 * @window: a #GtkWindow
1584 * @wmclass_name: window name hint
1585 * @wmclass_class: window class hint
1587 * Don't use this function. It sets the X Window System "class" and
1588 * "name" hints for a window. According to the ICCCM, you should
1589 * always set these to the same value for all windows in an
1590 * application, and GTK+ sets them to that value by default, so calling
1591 * this function is sort of pointless. However, you may want to call
1592 * gtk_window_set_role() on each window in your application, for the
1593 * benefit of the session manager. Setting the role allows the window
1594 * manager to restore window positions when loading a saved session.
1598 gtk_window_set_wmclass (GtkWindow *window,
1599 const gchar *wmclass_name,
1600 const gchar *wmclass_class)
1602 GtkWindowPrivate *priv;
1604 g_return_if_fail (GTK_IS_WINDOW (window));
1606 priv = window->priv;
1608 g_free (priv->wmclass_name);
1609 priv->wmclass_name = g_strdup (wmclass_name);
1611 g_free (priv->wmclass_class);
1612 priv->wmclass_class = g_strdup (wmclass_class);
1614 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1615 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1619 * gtk_window_set_role:
1620 * @window: a #GtkWindow
1621 * @role: unique identifier for the window to be used when restoring a session
1623 * This function is only useful on X11, not with other GTK+ targets.
1625 * In combination with the window title, the window role allows a
1626 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1627 * same" window when an application is restarted. So for example you
1628 * might set the "toolbox" role on your app's toolbox window, so that
1629 * when the user restarts their session, the window manager can put
1630 * the toolbox back in the same place.
1632 * If a window already has a unique title, you don't need to set the
1633 * role, since the WM can use the title to identify the window when
1634 * restoring the session.
1638 gtk_window_set_role (GtkWindow *window,
1641 GtkWindowPrivate *priv;
1644 g_return_if_fail (GTK_IS_WINDOW (window));
1646 priv = window->priv;
1648 new_role = g_strdup (role);
1649 g_free (priv->wm_role);
1650 priv->wm_role = new_role;
1652 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1653 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1656 g_object_notify (G_OBJECT (window), "role");
1660 * gtk_window_set_startup_id:
1661 * @window: a #GtkWindow
1662 * @startup_id: a string with startup-notification identifier
1664 * Startup notification identifiers are used by desktop environment to
1665 * track application startup, to provide user feedback and other
1666 * features. This function changes the corresponding property on the
1667 * underlying GdkWindow. Normally, startup identifier is managed
1668 * automatically and you should only use this function in special cases
1669 * like transferring focus from other processes. You should use this
1670 * function before calling gtk_window_present() or any equivalent
1671 * function generating a window map event.
1673 * This function is only useful on X11, not with other GTK+ targets.
1678 gtk_window_set_startup_id (GtkWindow *window,
1679 const gchar *startup_id)
1681 GtkWindowPrivate *priv;
1684 g_return_if_fail (GTK_IS_WINDOW (window));
1686 priv = window->priv;
1687 widget = GTK_WIDGET (window);
1689 g_free (priv->startup_id);
1690 priv->startup_id = g_strdup (startup_id);
1692 if (gtk_widget_get_realized (widget))
1694 GdkWindow *gdk_window;
1695 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1697 gdk_window = gtk_widget_get_window (widget);
1699 #ifdef GDK_WINDOWING_X11
1700 if (timestamp != GDK_CURRENT_TIME)
1701 gdk_x11_window_set_user_time (gdk_window, timestamp);
1704 /* Here we differentiate real and "fake" startup notification IDs,
1705 * constructed on purpose just to pass interaction timestamp
1707 if (startup_id_is_fake (priv->startup_id))
1708 gtk_window_present_with_time (window, timestamp);
1711 gdk_window_set_startup_id (gdk_window,
1714 /* If window is mapped, terminate the startup-notification too */
1715 if (gtk_widget_get_mapped (widget) &&
1716 !disable_startup_notification)
1717 gdk_notify_startup_complete_with_id (priv->startup_id);
1721 g_object_notify (G_OBJECT (window), "startup-id");
1725 * gtk_window_get_role:
1726 * @window: a #GtkWindow
1728 * Returns the role of the window. See gtk_window_set_role() for
1729 * further explanation.
1731 * Return value: the role of the window if set, or %NULL. The
1732 * returned is owned by the widget and must not be modified
1735 G_CONST_RETURN gchar *
1736 gtk_window_get_role (GtkWindow *window)
1738 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1740 return window->priv->wm_role;
1744 * gtk_window_set_focus:
1745 * @window: a #GtkWindow
1746 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1747 * any focus widget for the toplevel window.
1749 * If @focus is not the current focus widget, and is focusable, sets
1750 * it as the focus widget for the window. If @focus is %NULL, unsets
1751 * the focus widget for this window. To set the focus to a particular
1752 * widget in the toplevel, it is usually more convenient to use
1753 * gtk_widget_grab_focus() instead of this function.
1756 gtk_window_set_focus (GtkWindow *window,
1759 GtkWindowPrivate *priv;
1762 g_return_if_fail (GTK_IS_WINDOW (window));
1764 priv = window->priv;
1768 g_return_if_fail (GTK_IS_WIDGET (focus));
1769 g_return_if_fail (gtk_widget_get_can_focus (focus));
1773 gtk_widget_grab_focus (focus);
1776 /* Clear the existing focus chain, so that when we focus into
1777 * the window again, we start at the beginnning.
1779 GtkWidget *widget = priv->focus_widget;
1782 while ((parent = gtk_widget_get_parent (widget)))
1785 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1789 _gtk_window_internal_set_focus (window, NULL);
1794 _gtk_window_internal_set_focus (GtkWindow *window,
1797 GtkWindowPrivate *priv;
1799 g_return_if_fail (GTK_IS_WINDOW (window));
1801 priv = window->priv;
1803 if ((priv->focus_widget != focus) ||
1804 (focus && !gtk_widget_has_focus (focus)))
1805 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1809 * gtk_window_set_default:
1810 * @window: a #GtkWindow
1811 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1812 * default widget for the toplevel.
1814 * The default widget is the widget that's activated when the user
1815 * presses Enter in a dialog (for example). This function sets or
1816 * unsets the default widget for a #GtkWindow about. When setting
1817 * (rather than unsetting) the default widget it's generally easier to
1818 * call gtk_widget_grab_focus() on the widget. Before making a widget
1819 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1820 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1823 gtk_window_set_default (GtkWindow *window,
1824 GtkWidget *default_widget)
1826 GtkWindowPrivate *priv;
1828 g_return_if_fail (GTK_IS_WINDOW (window));
1830 priv = window->priv;
1833 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1835 if (priv->default_widget != default_widget)
1837 GtkWidget *old_default_widget = NULL;
1840 g_object_ref (default_widget);
1842 if (priv->default_widget)
1844 old_default_widget = priv->default_widget;
1846 if (priv->focus_widget != priv->default_widget ||
1847 !gtk_widget_get_receives_default (priv->default_widget))
1848 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1850 gtk_widget_queue_draw (priv->default_widget);
1853 priv->default_widget = default_widget;
1855 if (priv->default_widget)
1857 if (priv->focus_widget == NULL ||
1858 !gtk_widget_get_receives_default (priv->focus_widget))
1859 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1861 gtk_widget_queue_draw (priv->default_widget);
1864 if (old_default_widget)
1865 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1869 g_object_notify (G_OBJECT (default_widget), "has-default");
1870 g_object_unref (default_widget);
1876 * gtk_window_get_default_widget:
1877 * @window: a #GtkWindow
1879 * Returns the default widget for @window. See gtk_window_set_default()
1882 * Returns: (transfer none): the default widget, or %NULL if there is none.
1887 gtk_window_get_default_widget (GtkWindow *window)
1889 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1891 return window->priv->default_widget;
1895 handle_keys_changed (gpointer data)
1897 GtkWindow *window = GTK_WINDOW (data);
1898 GtkWindowPrivate *priv = window->priv;
1900 if (priv->keys_changed_handler)
1902 g_source_remove (priv->keys_changed_handler);
1903 priv->keys_changed_handler = 0;
1906 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1912 gtk_window_notify_keys_changed (GtkWindow *window)
1914 GtkWindowPrivate *priv = window->priv;
1916 if (!priv->keys_changed_handler)
1917 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1921 * gtk_window_add_accel_group:
1922 * @window: window to attach accelerator group to
1923 * @accel_group: a #GtkAccelGroup
1925 * Associate @accel_group with @window, such that calling
1926 * gtk_accel_groups_activate() on @window will activate accelerators
1930 gtk_window_add_accel_group (GtkWindow *window,
1931 GtkAccelGroup *accel_group)
1933 g_return_if_fail (GTK_IS_WINDOW (window));
1934 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1936 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1937 g_signal_connect_object (accel_group, "accel-changed",
1938 G_CALLBACK (gtk_window_notify_keys_changed),
1939 window, G_CONNECT_SWAPPED);
1940 gtk_window_notify_keys_changed (window);
1944 * gtk_window_remove_accel_group:
1945 * @window: a #GtkWindow
1946 * @accel_group: a #GtkAccelGroup
1948 * Reverses the effects of gtk_window_add_accel_group().
1951 gtk_window_remove_accel_group (GtkWindow *window,
1952 GtkAccelGroup *accel_group)
1954 g_return_if_fail (GTK_IS_WINDOW (window));
1955 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1957 g_signal_handlers_disconnect_by_func (accel_group,
1958 gtk_window_notify_keys_changed,
1960 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1961 gtk_window_notify_keys_changed (window);
1964 static GtkMnemonicHash *
1965 gtk_window_get_mnemonic_hash (GtkWindow *window,
1968 GtkWindowPrivate *private = window->priv;
1970 if (!private->mnemonic_hash && create)
1971 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1973 return private->mnemonic_hash;
1977 * gtk_window_add_mnemonic:
1978 * @window: a #GtkWindow
1979 * @keyval: the mnemonic
1980 * @target: the widget that gets activated by the mnemonic
1982 * Adds a mnemonic to this window.
1985 gtk_window_add_mnemonic (GtkWindow *window,
1989 g_return_if_fail (GTK_IS_WINDOW (window));
1990 g_return_if_fail (GTK_IS_WIDGET (target));
1992 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1994 gtk_window_notify_keys_changed (window);
1998 * gtk_window_remove_mnemonic:
1999 * @window: a #GtkWindow
2000 * @keyval: the mnemonic
2001 * @target: the widget that gets activated by the mnemonic
2003 * Removes a mnemonic from this window.
2006 gtk_window_remove_mnemonic (GtkWindow *window,
2010 g_return_if_fail (GTK_IS_WINDOW (window));
2011 g_return_if_fail (GTK_IS_WIDGET (target));
2013 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2015 gtk_window_notify_keys_changed (window);
2019 * gtk_window_mnemonic_activate:
2020 * @window: a #GtkWindow
2021 * @keyval: the mnemonic
2022 * @modifier: the modifiers
2023 * @returns: %TRUE if the activation is done.
2025 * Activates the targets associated with the mnemonic.
2028 gtk_window_mnemonic_activate (GtkWindow *window,
2030 GdkModifierType modifier)
2032 GtkWindowPrivate *priv;
2034 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2036 priv = window->priv;
2038 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2040 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2042 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2049 * gtk_window_set_mnemonic_modifier:
2050 * @window: a #GtkWindow
2051 * @modifier: the modifier mask used to activate
2052 * mnemonics on this window.
2054 * Sets the mnemonic modifier for this window.
2057 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2058 GdkModifierType modifier)
2060 GtkWindowPrivate *priv;
2062 g_return_if_fail (GTK_IS_WINDOW (window));
2063 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2065 priv = window->priv;
2067 priv->mnemonic_modifier = modifier;
2068 gtk_window_notify_keys_changed (window);
2072 * gtk_window_get_mnemonic_modifier:
2073 * @window: a #GtkWindow
2075 * Returns the mnemonic modifier for this window. See
2076 * gtk_window_set_mnemonic_modifier().
2078 * Return value: the modifier mask used to activate
2079 * mnemonics on this window.
2082 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2084 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2086 return window->priv->mnemonic_modifier;
2090 * gtk_window_set_position:
2091 * @window: a #GtkWindow.
2092 * @position: a position constraint.
2094 * Sets a position constraint for this window. If the old or new
2095 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2096 * the window to be repositioned to satisfy the new constraint.
2099 gtk_window_set_position (GtkWindow *window,
2100 GtkWindowPosition position)
2102 GtkWindowPrivate *priv;
2104 g_return_if_fail (GTK_IS_WINDOW (window));
2106 priv = window->priv;
2108 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2109 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2111 GtkWindowGeometryInfo *info;
2113 info = gtk_window_get_geometry_info (window, TRUE);
2115 /* this flag causes us to re-request the CENTER_ALWAYS
2116 * constraint in gtk_window_move_resize(), see
2117 * comment in that function.
2119 info->position_constraints_changed = TRUE;
2121 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2124 priv->position = position;
2126 g_object_notify (G_OBJECT (window), "window-position");
2130 * gtk_window_activate_focus:
2131 * @window: a #GtkWindow
2133 * Activates the current focused widget within the window.
2135 * Return value: %TRUE if a widget got activated.
2138 gtk_window_activate_focus (GtkWindow *window)
2140 GtkWindowPrivate *priv;
2142 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2144 priv = window->priv;
2146 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2147 return gtk_widget_activate (priv->focus_widget);
2153 * gtk_window_get_focus:
2154 * @window: a #GtkWindow
2156 * Retrieves the current focused widget within the window.
2157 * Note that this is the widget that would have the focus
2158 * if the toplevel window focused; if the toplevel window
2159 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2160 * not be %TRUE for the widget.
2162 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2165 gtk_window_get_focus (GtkWindow *window)
2167 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2169 return window->priv->focus_widget;
2173 * gtk_window_activate_default:
2174 * @window: a #GtkWindow
2176 * Activates the default widget for the window, unless the current
2177 * focused widget has been configured to receive the default action
2178 * (see gtk_widget_set_receives_default()), in which case the
2179 * focused widget is activated.
2181 * Return value: %TRUE if a widget got activated.
2184 gtk_window_activate_default (GtkWindow *window)
2186 GtkWindowPrivate *priv;
2188 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2190 priv = window->priv;
2192 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2193 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2194 return gtk_widget_activate (priv->default_widget);
2195 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2196 return gtk_widget_activate (priv->focus_widget);
2202 * gtk_window_set_modal:
2203 * @window: a #GtkWindow
2204 * @modal: whether the window is modal
2206 * Sets a window modal or non-modal. Modal windows prevent interaction
2207 * with other windows in the same application. To keep modal dialogs
2208 * on top of main application windows, use
2209 * gtk_window_set_transient_for() to make the dialog transient for the
2210 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2211 * will then disallow lowering the dialog below the parent.
2216 gtk_window_set_modal (GtkWindow *window,
2219 GtkWindowPrivate *priv;
2222 g_return_if_fail (GTK_IS_WINDOW (window));
2224 priv = window->priv;
2226 modal = modal != FALSE;
2227 if (priv->modal == modal)
2230 priv->modal = modal;
2231 widget = GTK_WIDGET (window);
2233 /* adjust desired modality state */
2234 if (gtk_widget_get_realized (widget))
2237 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2239 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2242 if (gtk_widget_get_visible (widget))
2245 gtk_grab_add (widget);
2247 gtk_grab_remove (widget);
2250 g_object_notify (G_OBJECT (window), "modal");
2254 * gtk_window_get_modal:
2255 * @window: a #GtkWindow
2257 * Returns whether the window is modal. See gtk_window_set_modal().
2259 * Return value: %TRUE if the window is set to be modal and
2260 * establishes a grab when shown
2263 gtk_window_get_modal (GtkWindow *window)
2265 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2267 return window->priv->modal;
2271 * gtk_window_list_toplevels:
2273 * Returns a list of all existing toplevel windows. The widgets
2274 * in the list are not individually referenced. If you want
2275 * to iterate through the list and perform actions involving
2276 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2277 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2278 * then unref all the widgets afterwards.
2280 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2283 gtk_window_list_toplevels (void)
2288 for (slist = toplevel_list; slist; slist = slist->next)
2289 list = g_list_prepend (list, slist->data);
2295 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2297 GList *embedded_windows;
2299 g_return_if_fail (GTK_IS_WINDOW (window));
2301 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2302 if (embedded_windows)
2303 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2304 embedded_windows = g_list_prepend (embedded_windows,
2305 GUINT_TO_POINTER (xid));
2307 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2310 (GDestroyNotify) g_list_free : NULL);
2314 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2316 GList *embedded_windows;
2319 g_return_if_fail (GTK_IS_WINDOW (window));
2321 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2322 if (embedded_windows)
2323 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2325 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2328 embedded_windows = g_list_remove_link (embedded_windows, node);
2329 g_list_free_1 (node);
2332 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2335 (GDestroyNotify) g_list_free : NULL);
2339 gtk_window_dispose (GObject *object)
2341 GtkWindow *window = GTK_WINDOW (object);
2343 gtk_window_set_focus (window, NULL);
2344 gtk_window_set_default (window, NULL);
2346 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2350 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2352 gtk_widget_destroy (GTK_WIDGET (child));
2356 connect_parent_destroyed (GtkWindow *window)
2358 GtkWindowPrivate *priv = window->priv;
2360 if (priv->transient_parent)
2362 g_signal_connect (priv->transient_parent,
2364 G_CALLBACK (parent_destroyed_callback),
2370 disconnect_parent_destroyed (GtkWindow *window)
2372 GtkWindowPrivate *priv = window->priv;
2374 if (priv->transient_parent)
2376 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2377 parent_destroyed_callback,
2383 gtk_window_transient_parent_realized (GtkWidget *parent,
2386 if (gtk_widget_get_realized (window))
2387 gdk_window_set_transient_for (gtk_widget_get_window (window),
2388 gtk_widget_get_window (parent));
2392 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2395 if (gtk_widget_get_realized (window))
2396 gdk_property_delete (gtk_widget_get_window (window),
2397 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2401 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2405 gtk_window_set_screen (window, parent->priv->screen);
2409 gtk_window_unset_transient_for (GtkWindow *window)
2411 GtkWindowPrivate *priv = window->priv;
2413 if (priv->transient_parent)
2415 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2416 gtk_window_transient_parent_realized,
2418 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2419 gtk_window_transient_parent_unrealized,
2421 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2422 gtk_window_transient_parent_screen_changed,
2424 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2425 gtk_widget_destroyed,
2426 &priv->transient_parent);
2428 if (priv->destroy_with_parent)
2429 disconnect_parent_destroyed (window);
2431 priv->transient_parent = NULL;
2433 if (priv->transient_parent_group)
2435 priv->transient_parent_group = FALSE;
2436 gtk_window_group_remove_window (priv->group,
2443 * gtk_window_set_transient_for:
2444 * @window: a #GtkWindow
2445 * @parent: (allow-none): parent window, or %NULL
2447 * Dialog windows should be set transient for the main application
2448 * window they were spawned from. This allows <link
2449 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2450 * dialog on top of the main window, or center the dialog over the
2451 * main window. gtk_dialog_new_with_buttons() and other convenience
2452 * functions in GTK+ will sometimes call
2453 * gtk_window_set_transient_for() on your behalf.
2455 * Passing %NULL for @parent unsets the current transient window.
2457 * On Windows, this function puts the child window on top of the parent,
2458 * much as the window manager would have done on X.
2461 gtk_window_set_transient_for (GtkWindow *window,
2464 GtkWindowPrivate *priv;
2466 g_return_if_fail (GTK_IS_WINDOW (window));
2467 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2468 g_return_if_fail (window != parent);
2470 priv = window->priv;
2472 if (priv->transient_parent)
2474 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2475 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2476 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2477 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2478 GTK_WIDGET (window));
2480 gtk_window_unset_transient_for (window);
2483 priv->transient_parent = parent;
2487 g_signal_connect (parent, "destroy",
2488 G_CALLBACK (gtk_widget_destroyed),
2489 &priv->transient_parent);
2490 g_signal_connect (parent, "realize",
2491 G_CALLBACK (gtk_window_transient_parent_realized),
2493 g_signal_connect (parent, "unrealize",
2494 G_CALLBACK (gtk_window_transient_parent_unrealized),
2496 g_signal_connect (parent, "notify::screen",
2497 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2500 gtk_window_set_screen (window, parent->priv->screen);
2502 if (priv->destroy_with_parent)
2503 connect_parent_destroyed (window);
2505 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2506 gtk_widget_get_realized (GTK_WIDGET (parent)))
2507 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2508 GTK_WIDGET (window));
2510 if (parent->priv->group)
2512 gtk_window_group_add_window (parent->priv->group, window);
2513 priv->transient_parent_group = TRUE;
2519 * gtk_window_get_transient_for:
2520 * @window: a #GtkWindow
2522 * Fetches the transient parent for this window. See
2523 * gtk_window_set_transient_for().
2525 * Return value: (transfer none): the transient parent for this window, or %NULL
2526 * if no transient parent has been set.
2529 gtk_window_get_transient_for (GtkWindow *window)
2531 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2533 return window->priv->transient_parent;
2537 * gtk_window_set_opacity:
2538 * @window: a #GtkWindow
2539 * @opacity: desired opacity, between 0 and 1
2541 * Request the windowing system to make @window partially transparent,
2542 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2543 * of the opacity parameter are clamped to the [0,1] range.) On X11
2544 * this has any effect only on X screens with a compositing manager
2545 * running. See gtk_widget_is_composited(). On Windows it should work
2548 * Note that setting a window's opacity after the window has been
2549 * shown causes it to flicker once on Windows.
2554 gtk_window_set_opacity (GtkWindow *window,
2557 GtkWindowPrivate *priv;
2559 g_return_if_fail (GTK_IS_WINDOW (window));
2561 priv = window->priv;
2565 else if (opacity > 1.0)
2568 priv->opacity_set = TRUE;
2569 priv->opacity = opacity;
2571 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2572 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2577 * gtk_window_get_opacity:
2578 * @window: a #GtkWindow
2580 * Fetches the requested opacity for this window. See
2581 * gtk_window_set_opacity().
2583 * Return value: the requested opacity for this window.
2588 gtk_window_get_opacity (GtkWindow *window)
2590 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2592 return window->priv->opacity;
2596 * gtk_window_get_application:
2597 * @window: a #GtkWindow
2599 * Gets the #GtkApplication associated with the window (if any).
2601 * Return value: (transfer none): a #GtkApplication, or %NULL
2606 gtk_window_get_application (GtkWindow *window)
2608 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2610 return window->priv->application;
2614 gtk_window_release_application (GtkWindow *window)
2616 if (window->priv->application)
2618 GtkApplication *application;
2620 /* steal reference into temp variable */
2621 application = window->priv->application;
2622 window->priv->application = NULL;
2624 gtk_application_remove_window (application, window);
2625 g_object_unref (application);
2630 * gtk_window_set_application:
2631 * @window: a #GtkWindow
2632 * @application: (allow-none): a #GtkApplication, or %NULL
2634 * Sets or unsets the #GtkApplication associated with the window.
2636 * The application will be kept alive for at least as long as the window
2642 gtk_window_set_application (GtkWindow *window,
2643 GtkApplication *application)
2645 GtkWindowPrivate *priv;
2647 g_return_if_fail (GTK_IS_WINDOW (window));
2649 priv = window->priv;
2650 if (priv->application != application)
2652 gtk_window_release_application (window);
2654 priv->application = application;
2656 if (priv->application != NULL)
2658 g_object_ref (priv->application);
2660 gtk_application_add_window (priv->application, window);
2663 g_object_notify (G_OBJECT (window), "application");
2668 * gtk_window_set_type_hint:
2669 * @window: a #GtkWindow
2670 * @hint: the window type
2672 * By setting the type hint for the window, you allow the window
2673 * manager to decorate and handle the window in a way which is
2674 * suitable to the function of the window in your application.
2676 * This function should be called before the window becomes visible.
2678 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2679 * will sometimes call gtk_window_set_type_hint() on your behalf.
2683 gtk_window_set_type_hint (GtkWindow *window,
2684 GdkWindowTypeHint hint)
2686 GtkWindowPrivate *priv;
2688 g_return_if_fail (GTK_IS_WINDOW (window));
2689 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2691 priv = window->priv;
2693 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2694 priv->gdk_type_hint = hint;
2696 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2698 priv->reset_type_hint = TRUE;
2699 priv->type_hint = hint;
2703 * gtk_window_get_type_hint:
2704 * @window: a #GtkWindow
2706 * Gets the type hint for this window. See gtk_window_set_type_hint().
2708 * Return value: the type hint for @window.
2711 gtk_window_get_type_hint (GtkWindow *window)
2713 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2715 return window->priv->type_hint;
2719 * gtk_window_set_skip_taskbar_hint:
2720 * @window: a #GtkWindow
2721 * @setting: %TRUE to keep this window from appearing in the task bar
2723 * Windows may set a hint asking the desktop environment not to display
2724 * the window in the task bar. This function sets this hint.
2729 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2732 GtkWindowPrivate *priv;
2734 g_return_if_fail (GTK_IS_WINDOW (window));
2736 priv = window->priv;
2738 setting = setting != FALSE;
2740 if (priv->skips_taskbar != setting)
2742 priv->skips_taskbar = setting;
2743 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2744 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2745 priv->skips_taskbar);
2746 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2751 * gtk_window_get_skip_taskbar_hint:
2752 * @window: a #GtkWindow
2754 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2756 * Return value: %TRUE if window shouldn't be in taskbar
2761 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2763 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2765 return window->priv->skips_taskbar;
2769 * gtk_window_set_skip_pager_hint:
2770 * @window: a #GtkWindow
2771 * @setting: %TRUE to keep this window from appearing in the pager
2773 * Windows may set a hint asking the desktop environment not to display
2774 * the window in the pager. This function sets this hint.
2775 * (A "pager" is any desktop navigation tool such as a workspace
2776 * switcher that displays a thumbnail representation of the windows
2782 gtk_window_set_skip_pager_hint (GtkWindow *window,
2785 GtkWindowPrivate *priv;
2787 g_return_if_fail (GTK_IS_WINDOW (window));
2789 priv = window->priv;
2791 setting = setting != FALSE;
2793 if (priv->skips_pager != setting)
2795 priv->skips_pager = setting;
2796 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2797 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2799 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2804 * gtk_window_get_skip_pager_hint:
2805 * @window: a #GtkWindow
2807 * Gets the value set by gtk_window_set_skip_pager_hint().
2809 * Return value: %TRUE if window shouldn't be in pager
2814 gtk_window_get_skip_pager_hint (GtkWindow *window)
2816 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2818 return window->priv->skips_pager;
2822 * gtk_window_set_urgency_hint:
2823 * @window: a #GtkWindow
2824 * @setting: %TRUE to mark this window as urgent
2826 * Windows may set a hint asking the desktop environment to draw
2827 * the users attention to the window. This function sets this hint.
2832 gtk_window_set_urgency_hint (GtkWindow *window,
2835 GtkWindowPrivate *priv;
2837 g_return_if_fail (GTK_IS_WINDOW (window));
2839 priv = window->priv;
2841 setting = setting != FALSE;
2843 if (priv->urgent != setting)
2845 priv->urgent = setting;
2846 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2847 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2849 g_object_notify (G_OBJECT (window), "urgency-hint");
2854 * gtk_window_get_urgency_hint:
2855 * @window: a #GtkWindow
2857 * Gets the value set by gtk_window_set_urgency_hint()
2859 * Return value: %TRUE if window is urgent
2864 gtk_window_get_urgency_hint (GtkWindow *window)
2866 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2868 return window->priv->urgent;
2872 * gtk_window_set_accept_focus:
2873 * @window: a #GtkWindow
2874 * @setting: %TRUE to let this window receive input focus
2876 * Windows may set a hint asking the desktop environment not to receive
2877 * the input focus. This function sets this hint.
2882 gtk_window_set_accept_focus (GtkWindow *window,
2885 GtkWindowPrivate *priv;
2887 g_return_if_fail (GTK_IS_WINDOW (window));
2889 priv = window->priv;
2891 setting = setting != FALSE;
2893 if (priv->accept_focus != setting)
2895 priv->accept_focus = setting;
2896 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2897 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2898 priv->accept_focus);
2899 g_object_notify (G_OBJECT (window), "accept-focus");
2904 * gtk_window_get_accept_focus:
2905 * @window: a #GtkWindow
2907 * Gets the value set by gtk_window_set_accept_focus().
2909 * Return value: %TRUE if window should receive the input focus
2914 gtk_window_get_accept_focus (GtkWindow *window)
2916 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2918 return window->priv->accept_focus;
2922 * gtk_window_set_focus_on_map:
2923 * @window: a #GtkWindow
2924 * @setting: %TRUE to let this window receive input focus on map
2926 * Windows may set a hint asking the desktop environment not to receive
2927 * the input focus when the window is mapped. This function sets this
2933 gtk_window_set_focus_on_map (GtkWindow *window,
2936 GtkWindowPrivate *priv;
2938 g_return_if_fail (GTK_IS_WINDOW (window));
2940 priv = window->priv;
2942 setting = setting != FALSE;
2944 if (priv->focus_on_map != setting)
2946 priv->focus_on_map = setting;
2947 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2948 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2949 priv->focus_on_map);
2950 g_object_notify (G_OBJECT (window), "focus-on-map");
2955 * gtk_window_get_focus_on_map:
2956 * @window: a #GtkWindow
2958 * Gets the value set by gtk_window_set_focus_on_map().
2960 * Return value: %TRUE if window should receive the input focus when
2966 gtk_window_get_focus_on_map (GtkWindow *window)
2968 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2970 return window->priv->focus_on_map;
2974 * gtk_window_set_destroy_with_parent:
2975 * @window: a #GtkWindow
2976 * @setting: whether to destroy @window with its transient parent
2978 * If @setting is %TRUE, then destroying the transient parent of @window
2979 * will also destroy @window itself. This is useful for dialogs that
2980 * shouldn't persist beyond the lifetime of the main window they're
2981 * associated with, for example.
2984 gtk_window_set_destroy_with_parent (GtkWindow *window,
2987 GtkWindowPrivate *priv;
2989 g_return_if_fail (GTK_IS_WINDOW (window));
2991 priv = window->priv;
2993 if (priv->destroy_with_parent == (setting != FALSE))
2996 if (priv->destroy_with_parent)
2998 disconnect_parent_destroyed (window);
3002 connect_parent_destroyed (window);
3005 priv->destroy_with_parent = setting;
3007 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3011 * gtk_window_get_destroy_with_parent:
3012 * @window: a #GtkWindow
3014 * Returns whether the window will be destroyed with its transient parent. See
3015 * gtk_window_set_destroy_with_parent ().
3017 * Return value: %TRUE if the window will be destroyed with its transient parent.
3020 gtk_window_get_destroy_with_parent (GtkWindow *window)
3022 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3024 return window->priv->destroy_with_parent;
3027 static GtkWindowGeometryInfo*
3028 gtk_window_get_geometry_info (GtkWindow *window,
3031 GtkWindowPrivate *priv = window->priv;
3032 GtkWindowGeometryInfo *info;
3034 info = priv->geometry_info;
3035 if (!info && create)
3037 info = g_new0 (GtkWindowGeometryInfo, 1);
3039 info->default_width = -1;
3040 info->default_height = -1;
3041 info->resize_width = -1;
3042 info->resize_height = -1;
3043 info->initial_x = 0;
3044 info->initial_y = 0;
3045 info->initial_pos_set = FALSE;
3046 info->default_is_geometry = FALSE;
3047 info->position_constraints_changed = FALSE;
3048 info->last.configure_request.x = 0;
3049 info->last.configure_request.y = 0;
3050 info->last.configure_request.width = -1;
3051 info->last.configure_request.height = -1;
3052 info->widget = NULL;
3054 priv->geometry_info = info;
3061 * gtk_window_set_geometry_hints:
3062 * @window: a #GtkWindow
3063 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3064 * @geometry: (allow-none): struct containing geometry information or %NULL
3065 * @geom_mask: mask indicating which struct fields should be paid attention to
3067 * This function sets up hints about how a window can be resized by
3068 * the user. You can set a minimum and maximum size; allowed resize
3069 * increments (e.g. for xterm, you can only resize by the size of a
3070 * character); aspect ratios; and more. See the #GdkGeometry struct.
3074 gtk_window_set_geometry_hints (GtkWindow *window,
3075 GtkWidget *geometry_widget,
3076 GdkGeometry *geometry,
3077 GdkWindowHints geom_mask)
3079 GtkWindowGeometryInfo *info;
3081 g_return_if_fail (GTK_IS_WINDOW (window));
3082 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3084 info = gtk_window_get_geometry_info (window, TRUE);
3087 g_signal_handlers_disconnect_by_func (info->widget,
3088 gtk_widget_destroyed,
3091 info->widget = geometry_widget;
3093 g_signal_connect (geometry_widget, "destroy",
3094 G_CALLBACK (gtk_widget_destroyed),
3098 info->geometry = *geometry;
3100 /* We store gravity in priv->gravity not in the hints. */
3101 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3103 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3105 gtk_window_set_gravity (window, geometry->win_gravity);
3108 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3112 * gtk_window_set_decorated:
3113 * @window: a #GtkWindow
3114 * @setting: %TRUE to decorate the window
3116 * By default, windows are decorated with a title bar, resize
3117 * controls, etc. Some <link linkend="gtk-X11-arch">window
3118 * managers</link> allow GTK+ to disable these decorations, creating a
3119 * borderless window. If you set the decorated property to %FALSE
3120 * using this function, GTK+ will do its best to convince the window
3121 * manager not to decorate the window. Depending on the system, this
3122 * function may not have any effect when called on a window that is
3123 * already visible, so you should call it before calling gtk_widget_show().
3125 * On Windows, this function always works, since there's no window manager
3130 gtk_window_set_decorated (GtkWindow *window,
3133 GtkWindowPrivate *priv;
3134 GdkWindow *gdk_window;
3136 g_return_if_fail (GTK_IS_WINDOW (window));
3138 priv = window->priv;
3140 setting = setting != FALSE;
3142 if (setting == priv->decorated)
3145 priv->decorated = setting;
3147 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3150 if (priv->decorated)
3151 gdk_window_set_decorations (gdk_window,
3154 gdk_window_set_decorations (gdk_window,
3158 g_object_notify (G_OBJECT (window), "decorated");
3162 * gtk_window_get_decorated:
3163 * @window: a #GtkWindow
3165 * Returns whether the window has been set to have decorations
3166 * such as a title bar via gtk_window_set_decorated().
3168 * Return value: %TRUE if the window has been set to have decorations
3171 gtk_window_get_decorated (GtkWindow *window)
3173 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3175 return window->priv->decorated;
3179 * gtk_window_set_deletable:
3180 * @window: a #GtkWindow
3181 * @setting: %TRUE to decorate the window as deletable
3183 * By default, windows have a close button in the window frame. Some
3184 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3185 * disable this button. If you set the deletable property to %FALSE
3186 * using this function, GTK+ will do its best to convince the window
3187 * manager not to show a close button. Depending on the system, this
3188 * function may not have any effect when called on a window that is
3189 * already visible, so you should call it before calling gtk_window_show().
3191 * On Windows, this function always works, since there's no window manager
3197 gtk_window_set_deletable (GtkWindow *window,
3200 GtkWindowPrivate *priv;
3201 GdkWindow *gdk_window;
3203 g_return_if_fail (GTK_IS_WINDOW (window));
3205 priv = window->priv;
3207 setting = setting != FALSE;
3209 if (setting == priv->deletable)
3212 priv->deletable = setting;
3214 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3217 if (priv->deletable)
3218 gdk_window_set_functions (gdk_window,
3221 gdk_window_set_functions (gdk_window,
3222 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3225 g_object_notify (G_OBJECT (window), "deletable");
3229 * gtk_window_get_deletable:
3230 * @window: a #GtkWindow
3232 * Returns whether the window has been set to have a close button
3233 * via gtk_window_set_deletable().
3235 * Return value: %TRUE if the window has been set to have a close button
3240 gtk_window_get_deletable (GtkWindow *window)
3242 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3244 return window->priv->deletable;
3247 static GtkWindowIconInfo*
3248 get_icon_info (GtkWindow *window)
3250 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3254 free_icon_info (GtkWindowIconInfo *info)
3256 g_free (info->icon_name);
3257 g_slice_free (GtkWindowIconInfo, info);
3261 static GtkWindowIconInfo*
3262 ensure_icon_info (GtkWindow *window)
3264 GtkWindowIconInfo *info;
3266 info = get_icon_info (window);
3270 info = g_slice_new0 (GtkWindowIconInfo);
3271 g_object_set_qdata_full (G_OBJECT (window),
3272 quark_gtk_window_icon_info,
3274 (GDestroyNotify)free_icon_info);
3281 icon_list_from_theme (GtkWidget *widget,
3286 GtkIconTheme *icon_theme;
3291 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3293 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3296 for (i = 0; sizes[i]; i++)
3299 * We need an EWMH extension to handle scalable icons
3300 * by passing their name to the WM. For now just use a
3304 icon = gtk_icon_theme_load_icon (icon_theme, name,
3307 icon = gtk_icon_theme_load_icon (icon_theme, name,
3310 list = g_list_append (list, icon);
3320 gtk_window_realize_icon (GtkWindow *window)
3322 GtkWindowPrivate *priv = window->priv;
3324 GtkWindowIconInfo *info;
3325 GdkWindow *gdk_window;
3328 widget = GTK_WIDGET (window);
3329 gdk_window = gtk_widget_get_window (widget);
3331 g_return_if_fail (gdk_window != NULL);
3333 /* no point setting an icon on override-redirect */
3334 if (priv->type == GTK_WINDOW_POPUP)
3339 info = ensure_icon_info (window);
3344 info->using_default_icon = FALSE;
3345 info->using_parent_icon = FALSE;
3346 info->using_themed_icon = FALSE;
3348 icon_list = info->icon_list;
3350 /* Look up themed icon */
3351 if (icon_list == NULL && info->icon_name)
3353 icon_list = icon_list_from_theme (widget, info->icon_name);
3355 info->using_themed_icon = TRUE;
3358 /* Inherit from transient parent */
3359 if (icon_list == NULL && priv->transient_parent)
3361 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3363 info->using_parent_icon = TRUE;
3366 /* Inherit from default */
3367 if (icon_list == NULL)
3369 icon_list = default_icon_list;
3371 info->using_default_icon = TRUE;
3374 /* Look up themed icon */
3375 if (icon_list == NULL && default_icon_name)
3377 icon_list = icon_list_from_theme (widget, default_icon_name);
3378 info->using_default_icon = TRUE;
3379 info->using_themed_icon = TRUE;
3382 info->realized = TRUE;
3384 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3386 if (info->using_themed_icon)
3388 GtkIconTheme *icon_theme;
3390 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3391 g_list_free (icon_list);
3393 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3394 g_signal_connect (icon_theme, "changed",
3395 G_CALLBACK (update_themed_icon), window);
3400 gtk_window_unrealize_icon (GtkWindow *window)
3402 GtkWindowIconInfo *info;
3404 info = get_icon_info (window);
3409 if (info->using_themed_icon)
3411 GtkIconTheme *icon_theme;
3413 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3415 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3418 /* We don't clear the properties on the window, just figure the
3419 * window is going away.
3422 info->realized = FALSE;
3427 * gtk_window_set_icon_list:
3428 * @window: a #GtkWindow
3429 * @list: (element-type GdkPixbuf): list of #GdkPixbuf
3431 * Sets up the icon representing a #GtkWindow. The icon is used when
3432 * the window is minimized (also known as iconified). Some window
3433 * managers or desktop environments may also place it in the window
3434 * frame, or display it in other contexts.
3436 * gtk_window_set_icon_list() allows you to pass in the same icon in
3437 * several hand-drawn sizes. The list should contain the natural sizes
3438 * your icon is available in; that is, don't scale the image before
3439 * passing it to GTK+. Scaling is postponed until the last minute,
3440 * when the desired final size is known, to allow best quality.
3442 * By passing several sizes, you may improve the final image quality
3443 * of the icon, by reducing or eliminating automatic image scaling.
3445 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3446 * larger images (64x64, 128x128) if you have them.
3448 * See also gtk_window_set_default_icon_list() to set the icon
3449 * for all windows in your application in one go.
3451 * Note that transient windows (those who have been set transient for another
3452 * window using gtk_window_set_transient_for()) will inherit their
3453 * icon from their transient parent. So there's no need to explicitly
3454 * set the icon on transient windows.
3457 gtk_window_set_icon_list (GtkWindow *window,
3460 GtkWindowIconInfo *info;
3462 g_return_if_fail (GTK_IS_WINDOW (window));
3464 info = ensure_icon_info (window);
3466 if (info->icon_list == list) /* check for NULL mostly */
3469 g_list_foreach (list,
3470 (GFunc) g_object_ref, NULL);
3472 g_list_foreach (info->icon_list,
3473 (GFunc) g_object_unref, NULL);
3475 g_list_free (info->icon_list);
3477 info->icon_list = g_list_copy (list);
3479 g_object_notify (G_OBJECT (window), "icon");
3481 gtk_window_unrealize_icon (window);
3483 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3484 gtk_window_realize_icon (window);
3486 /* We could try to update our transient children, but I don't think
3487 * it's really worth it. If we did it, the best way would probably
3488 * be to have children connect to notify::icon-list
3493 * gtk_window_get_icon_list:
3494 * @window: a #GtkWindow
3496 * Retrieves the list of icons set by gtk_window_set_icon_list().
3497 * The list is copied, but the reference count on each
3498 * member won't be incremented.
3500 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3503 gtk_window_get_icon_list (GtkWindow *window)
3505 GtkWindowIconInfo *info;
3507 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3509 info = get_icon_info (window);
3512 return g_list_copy (info->icon_list);
3518 * gtk_window_set_icon:
3519 * @window: a #GtkWindow
3520 * @icon: (allow-none): icon image, or %NULL
3522 * Sets up the icon representing a #GtkWindow. This icon is used when
3523 * the window is minimized (also known as iconified). Some window
3524 * managers or desktop environments may also place it in the window
3525 * frame, or display it in other contexts.
3527 * The icon should be provided in whatever size it was naturally
3528 * drawn; that is, don't scale the image before passing it to
3529 * GTK+. Scaling is postponed until the last minute, when the desired
3530 * final size is known, to allow best quality.
3532 * If you have your icon hand-drawn in multiple sizes, use
3533 * gtk_window_set_icon_list(). Then the best size will be used.
3535 * This function is equivalent to calling gtk_window_set_icon_list()
3536 * with a 1-element list.
3538 * See also gtk_window_set_default_icon_list() to set the icon
3539 * for all windows in your application in one go.
3542 gtk_window_set_icon (GtkWindow *window,
3547 g_return_if_fail (GTK_IS_WINDOW (window));
3548 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3553 list = g_list_append (list, icon);
3555 gtk_window_set_icon_list (window, list);
3561 update_themed_icon (GtkIconTheme *icon_theme,
3564 g_object_notify (G_OBJECT (window), "icon");
3566 gtk_window_unrealize_icon (window);
3568 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3569 gtk_window_realize_icon (window);
3573 * gtk_window_set_icon_name:
3574 * @window: a #GtkWindow
3575 * @name: (allow-none): the name of the themed icon
3577 * Sets the icon for the window from a named themed icon. See
3578 * the docs for #GtkIconTheme for more details.
3580 * Note that this has nothing to do with the WM_ICON_NAME
3581 * property which is mentioned in the ICCCM.
3586 gtk_window_set_icon_name (GtkWindow *window,
3589 GtkWindowIconInfo *info;
3592 g_return_if_fail (GTK_IS_WINDOW (window));
3594 info = ensure_icon_info (window);
3596 if (g_strcmp0 (info->icon_name, name) == 0)
3599 tmp = info->icon_name;
3600 info->icon_name = g_strdup (name);
3603 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3604 g_list_free (info->icon_list);
3605 info->icon_list = NULL;
3607 update_themed_icon (NULL, window);
3609 g_object_notify (G_OBJECT (window), "icon-name");
3613 * gtk_window_get_icon_name:
3614 * @window: a #GtkWindow
3616 * Returns the name of the themed icon for the window,
3617 * see gtk_window_set_icon_name().
3619 * Returns: the icon name or %NULL if the window has
3625 gtk_window_get_icon_name (GtkWindow *window)
3627 GtkWindowIconInfo *info;
3629 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3631 info = ensure_icon_info (window);
3633 return info->icon_name;
3637 * gtk_window_get_icon:
3638 * @window: a #GtkWindow
3640 * Gets the value set by gtk_window_set_icon() (or if you've
3641 * called gtk_window_set_icon_list(), gets the first icon in
3644 * Return value: (transfer none): icon for window
3647 gtk_window_get_icon (GtkWindow *window)
3649 GtkWindowIconInfo *info;
3651 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3653 info = get_icon_info (window);
3654 if (info && info->icon_list)
3655 return GDK_PIXBUF (info->icon_list->data);
3660 /* Load pixbuf, printing warning on failure if error == NULL
3663 load_pixbuf_verbosely (const char *filename,
3666 GError *local_err = NULL;
3669 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3677 g_warning ("Error loading icon from file '%s':\n\t%s",
3678 filename, local_err->message);
3679 g_error_free (local_err);
3687 * gtk_window_set_icon_from_file:
3688 * @window: a #GtkWindow
3689 * @filename: (type filename): location of icon file
3690 * @err: (allow-none): location to store error, or %NULL.
3692 * Sets the icon for @window.
3693 * Warns on failure if @err is %NULL.
3695 * This function is equivalent to calling gtk_window_set_icon()
3696 * with a pixbuf created by loading the image from @filename.
3698 * Returns: %TRUE if setting the icon succeeded.
3703 gtk_window_set_icon_from_file (GtkWindow *window,
3704 const gchar *filename,
3707 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3711 gtk_window_set_icon (window, pixbuf);
3712 g_object_unref (pixbuf);
3721 * gtk_window_set_default_icon_list:
3722 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3724 * Sets an icon list to be used as fallback for windows that haven't
3725 * had gtk_window_set_icon_list() called on them to set up a
3726 * window-specific icon list. This function allows you to set up the
3727 * icon for all windows in your app at once.
3729 * See gtk_window_set_icon_list() for more details.
3733 gtk_window_set_default_icon_list (GList *list)
3737 if (list == default_icon_list)
3740 /* Update serial so we don't used cached pixmaps/masks
3742 default_icon_serial++;
3744 g_list_foreach (list,
3745 (GFunc) g_object_ref, NULL);
3747 g_list_foreach (default_icon_list,
3748 (GFunc) g_object_unref, NULL);
3750 g_list_free (default_icon_list);
3752 default_icon_list = g_list_copy (list);
3754 /* Update all toplevels */
3755 toplevels = gtk_window_list_toplevels ();
3756 tmp_list = toplevels;
3757 while (tmp_list != NULL)
3759 GtkWindowIconInfo *info;
3760 GtkWindow *w = tmp_list->data;
3762 info = get_icon_info (w);
3763 if (info && info->using_default_icon)
3765 gtk_window_unrealize_icon (w);
3766 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3767 gtk_window_realize_icon (w);
3770 tmp_list = tmp_list->next;
3772 g_list_free (toplevels);
3776 * gtk_window_set_default_icon:
3779 * Sets an icon to be used as fallback for windows that haven't
3780 * had gtk_window_set_icon() called on them from a pixbuf.
3785 gtk_window_set_default_icon (GdkPixbuf *icon)
3789 g_return_if_fail (GDK_IS_PIXBUF (icon));
3791 list = g_list_prepend (NULL, icon);
3792 gtk_window_set_default_icon_list (list);
3797 * gtk_window_set_default_icon_name:
3798 * @name: the name of the themed icon
3800 * Sets an icon to be used as fallback for windows that haven't
3801 * had gtk_window_set_icon_list() called on them from a named
3802 * themed icon, see gtk_window_set_icon_name().
3807 gtk_window_set_default_icon_name (const gchar *name)
3812 /* Update serial so we don't used cached pixmaps/masks
3814 default_icon_serial++;
3816 g_free (default_icon_name);
3817 default_icon_name = g_strdup (name);
3819 g_list_foreach (default_icon_list,
3820 (GFunc) g_object_unref, NULL);
3822 g_list_free (default_icon_list);
3823 default_icon_list = NULL;
3825 /* Update all toplevels */
3826 toplevels = gtk_window_list_toplevels ();
3827 tmp_list = toplevels;
3828 while (tmp_list != NULL)
3830 GtkWindowIconInfo *info;
3831 GtkWindow *w = tmp_list->data;
3833 info = get_icon_info (w);
3834 if (info && info->using_default_icon && info->using_themed_icon)
3836 gtk_window_unrealize_icon (w);
3837 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3838 gtk_window_realize_icon (w);
3841 tmp_list = tmp_list->next;
3843 g_list_free (toplevels);
3847 * gtk_window_get_default_icon_name:
3849 * Returns the fallback icon name for windows that has been set
3850 * with gtk_window_set_default_icon_name(). The returned
3851 * string is owned by GTK+ and should not be modified. It
3852 * is only valid until the next call to
3853 * gtk_window_set_default_icon_name().
3855 * Returns: the fallback icon name for windows
3860 gtk_window_get_default_icon_name (void)
3862 return default_icon_name;
3866 * gtk_window_set_default_icon_from_file:
3867 * @filename: (type filename): location of icon file
3868 * @err: (allow-none): location to store error, or %NULL.
3870 * Sets an icon to be used as fallback for windows that haven't
3871 * had gtk_window_set_icon_list() called on them from a file
3872 * on disk. Warns on failure if @err is %NULL.
3874 * Returns: %TRUE if setting the icon succeeded.
3879 gtk_window_set_default_icon_from_file (const gchar *filename,
3882 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3886 gtk_window_set_default_icon (pixbuf);
3887 g_object_unref (pixbuf);
3896 * gtk_window_get_default_icon_list:
3898 * Gets the value set by gtk_window_set_default_icon_list().
3899 * The list is a copy and should be freed with g_list_free(),
3900 * but the pixbufs in the list have not had their reference count
3903 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3906 gtk_window_get_default_icon_list (void)
3908 return g_list_copy (default_icon_list);
3912 gtk_window_set_default_size_internal (GtkWindow *window,
3913 gboolean change_width,
3915 gboolean change_height,
3917 gboolean is_geometry)
3919 GtkWindowGeometryInfo *info;
3921 g_return_if_fail (change_width == FALSE || width >= -1);
3922 g_return_if_fail (change_height == FALSE || height >= -1);
3924 info = gtk_window_get_geometry_info (window, TRUE);
3926 g_object_freeze_notify (G_OBJECT (window));
3928 info->default_is_geometry = is_geometry != FALSE;
3938 info->default_width = width;
3940 g_object_notify (G_OBJECT (window), "default-width");
3951 info->default_height = height;
3953 g_object_notify (G_OBJECT (window), "default-height");
3956 g_object_thaw_notify (G_OBJECT (window));
3958 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3962 * gtk_window_set_default_size:
3963 * @window: a #GtkWindow
3964 * @width: width in pixels, or -1 to unset the default width
3965 * @height: height in pixels, or -1 to unset the default height
3967 * Sets the default size of a window. If the window's "natural" size
3968 * (its size request) is larger than the default, the default will be
3969 * ignored. More generally, if the default size does not obey the
3970 * geometry hints for the window (gtk_window_set_geometry_hints() can
3971 * be used to set these explicitly), the default size will be clamped
3972 * to the nearest permitted size.
3974 * Unlike gtk_widget_set_size_request(), which sets a size request for
3975 * a widget and thus would keep users from shrinking the window, this
3976 * function only sets the initial size, just as if the user had
3977 * resized the window themselves. Users can still shrink the window
3978 * again as they normally would. Setting a default size of -1 means to
3979 * use the "natural" default size (the size request of the window).
3981 * For more control over a window's initial size and how resizing works,
3982 * investigate gtk_window_set_geometry_hints().
3984 * For some uses, gtk_window_resize() is a more appropriate function.
3985 * gtk_window_resize() changes the current size of the window, rather
3986 * than the size to be used on initial display. gtk_window_resize() always
3987 * affects the window itself, not the geometry widget.
3989 * The default size of a window only affects the first time a window is
3990 * shown; if a window is hidden and re-shown, it will remember the size
3991 * it had prior to hiding, rather than using the default size.
3993 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3994 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3997 gtk_window_set_default_size (GtkWindow *window,
4001 g_return_if_fail (GTK_IS_WINDOW (window));
4002 g_return_if_fail (width >= -1);
4003 g_return_if_fail (height >= -1);
4005 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4009 * gtk_window_set_default_geometry:
4010 * @window: a #GtkWindow
4011 * @width: width in resize increments, or -1 to unset the default width
4012 * @height: height in resize increments, or -1 to unset the default height
4014 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4015 * in terms of the base size and increment set with
4016 * gtk_window_set_geometry_hints.
4021 gtk_window_set_default_geometry (GtkWindow *window,
4025 g_return_if_fail (GTK_IS_WINDOW (window));
4026 g_return_if_fail (width >= -1);
4027 g_return_if_fail (height >= -1);
4029 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4033 * gtk_window_get_default_size:
4034 * @window: a #GtkWindow
4035 * @width: (out) (allow-none): location to store the default width, or %NULL
4036 * @height: (out) (allow-none): location to store the default height, or %NULL
4038 * Gets the default size of the window. A value of -1 for the width or
4039 * height indicates that a default size has not been explicitly set
4040 * for that dimension, so the "natural" size of the window will be
4045 gtk_window_get_default_size (GtkWindow *window,
4049 GtkWindowGeometryInfo *info;
4051 g_return_if_fail (GTK_IS_WINDOW (window));
4053 info = gtk_window_get_geometry_info (window, FALSE);
4056 *width = info ? info->default_width : -1;
4059 *height = info ? info->default_height : -1;
4063 * gtk_window_resize:
4064 * @window: a #GtkWindow
4065 * @width: width in pixels to resize the window to
4066 * @height: height in pixels to resize the window to
4068 * Resizes the window as if the user had done so, obeying geometry
4069 * constraints. The default geometry constraint is that windows may
4070 * not be smaller than their size request; to override this
4071 * constraint, call gtk_widget_set_size_request() to set the window's
4072 * request to a smaller value.
4074 * If gtk_window_resize() is called before showing a window for the
4075 * first time, it overrides any default size set with
4076 * gtk_window_set_default_size().
4078 * Windows may not be resized smaller than 1 by 1 pixels.
4082 gtk_window_resize (GtkWindow *window,
4086 GtkWindowGeometryInfo *info;
4088 g_return_if_fail (GTK_IS_WINDOW (window));
4089 g_return_if_fail (width > 0);
4090 g_return_if_fail (height > 0);
4092 info = gtk_window_get_geometry_info (window, TRUE);
4094 info->resize_width = width;
4095 info->resize_height = height;
4096 info->resize_is_geometry = FALSE;
4098 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4102 * gtk_window_resize_to_geometry:
4103 * @window: a #GtkWindow
4104 * @width: width in resize increments to resize the window to
4105 * @height: height in resize increments to resize the window to
4107 * Like gtk_window_resize(), but @width and @height are interpreted
4108 * in terms of the base size and increment set with
4109 * gtk_window_set_geometry_hints.
4114 gtk_window_resize_to_geometry (GtkWindow *window,
4118 GtkWindowGeometryInfo *info;
4120 g_return_if_fail (GTK_IS_WINDOW (window));
4121 g_return_if_fail (width > 0);
4122 g_return_if_fail (height > 0);
4124 info = gtk_window_get_geometry_info (window, TRUE);
4126 info->resize_width = width;
4127 info->resize_height = height;
4128 info->resize_is_geometry = TRUE;
4130 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4134 * gtk_window_get_size:
4135 * @window: a #GtkWindow
4136 * @width: (out) (allow-none): return location for width, or %NULL
4137 * @height: (out) (allow-none): return location for height, or %NULL
4139 * Obtains the current size of @window. If @window is not onscreen,
4140 * it returns the size GTK+ will suggest to the <link
4141 * linkend="gtk-X11-arch">window manager</link> for the initial window
4142 * size (but this is not reliably the same as the size the window
4143 * manager will actually select). The size obtained by
4144 * gtk_window_get_size() is the last size received in a
4145 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4146 * rather than querying the X server for the size. As a result, if you
4147 * call gtk_window_resize() then immediately call
4148 * gtk_window_get_size(), the size won't have taken effect yet. After
4149 * the window manager processes the resize request, GTK+ receives
4150 * notification that the size has changed via a configure event, and
4151 * the size of the window gets updated.
4153 * Note 1: Nearly any use of this function creates a race condition,
4154 * because the size of the window may change between the time that you
4155 * get the size and the time that you perform some action assuming
4156 * that size is the current size. To avoid race conditions, connect to
4157 * "configure-event" on the window and adjust your size-dependent
4158 * state to match the size delivered in the #GdkEventConfigure.
4160 * Note 2: The returned size does <emphasis>not</emphasis> include the
4161 * size of the window manager decorations (aka the window frame or
4162 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4163 * method of determining their size.
4165 * Note 3: If you are getting a window size in order to position
4166 * the window onscreen, there may be a better way. The preferred
4167 * way is to simply set the window's semantic type with
4168 * gtk_window_set_type_hint(), which allows the window manager to
4169 * e.g. center dialogs. Also, if you set the transient parent of
4170 * dialogs with gtk_window_set_transient_for() window managers
4171 * will often center the dialog over its parent window. It's
4172 * much preferred to let the window manager handle these
4173 * things rather than doing it yourself, because all apps will
4174 * behave consistently and according to user prefs if the window
4175 * manager handles it. Also, the window manager can take the size
4176 * of the window decorations/border into account, while your
4177 * application cannot.
4179 * In any case, if you insist on application-specified window
4180 * positioning, there's <emphasis>still</emphasis> a better way than
4181 * doing it yourself - gtk_window_set_position() will frequently
4182 * handle the details for you.
4186 gtk_window_get_size (GtkWindow *window,
4192 g_return_if_fail (GTK_IS_WINDOW (window));
4194 if (width == NULL && height == NULL)
4197 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4199 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4200 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4204 GdkRectangle configure_request;
4206 gtk_window_compute_configure_request (window,
4210 w = configure_request.width;
4211 h = configure_request.height;
4222 * @window: a #GtkWindow
4223 * @x: X coordinate to move window to
4224 * @y: Y coordinate to move window to
4226 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4227 * @window to the given position. Window managers are free to ignore
4228 * this; most window managers ignore requests for initial window
4229 * positions (instead using a user-defined placement algorithm) and
4230 * honor requests after the window has already been shown.
4232 * Note: the position is the position of the gravity-determined
4233 * reference point for the window. The gravity determines two things:
4234 * first, the location of the reference point in root window
4235 * coordinates; and second, which point on the window is positioned at
4236 * the reference point.
4238 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4239 * point is simply the @x, @y supplied to gtk_window_move(). The
4240 * top-left corner of the window decorations (aka window frame or
4241 * border) will be placed at @x, @y. Therefore, to position a window
4242 * at the top left of the screen, you want to use the default gravity
4243 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4245 * To position a window at the bottom right corner of the screen, you
4246 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4247 * point is at @x + the window width and @y + the window height, and
4248 * the bottom-right corner of the window border will be placed at that
4249 * reference point. So, to place a window in the bottom right corner
4250 * you would first set gravity to south east, then write:
4251 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4252 * gdk_screen_height () - window_height)</literal> (note that this
4253 * example does not take multi-head scenarios into account).
4255 * The Extended Window Manager Hints specification at <ulink
4256 * url="http://www.freedesktop.org/Standards/wm-spec">
4257 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4258 * nice table of gravities in the "implementation notes" section.
4260 * The gtk_window_get_position() documentation may also be relevant.
4263 gtk_window_move (GtkWindow *window,
4267 GtkWindowPrivate *priv;
4268 GtkWindowGeometryInfo *info;
4271 g_return_if_fail (GTK_IS_WINDOW (window));
4273 priv = window->priv;
4274 widget = GTK_WIDGET (window);
4276 info = gtk_window_get_geometry_info (window, TRUE);
4278 if (gtk_widget_get_mapped (widget))
4280 GtkAllocation allocation;
4282 gtk_widget_get_allocation (widget, &allocation);
4284 /* we have now sent a request with this position
4285 * with currently-active constraints, so toggle flag.
4287 info->position_constraints_changed = FALSE;
4289 /* we only constrain if mapped - if not mapped,
4290 * then gtk_window_compute_configure_request()
4291 * will apply the constraints later, and we
4292 * don't want to lose information about
4293 * what position the user set before then.
4294 * i.e. if you do a move() then turn off POS_CENTER
4295 * then show the window, your move() will work.
4297 gtk_window_constrain_position (window,
4298 allocation.width, allocation.height,
4301 /* Note that this request doesn't go through our standard request
4302 * framework, e.g. doesn't increment configure_request_count,
4303 * doesn't set info->last, etc.; that's because
4304 * we don't save the info needed to arrive at this same request
4307 * To gtk_window_move_resize(), this will end up looking exactly
4308 * the same as the position being changed by the window
4311 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
4315 /* Save this position to apply on mapping */
4316 info->initial_x = x;
4317 info->initial_y = y;
4318 info->initial_pos_set = TRUE;
4323 * gtk_window_get_position:
4324 * @window: a #GtkWindow
4325 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4326 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4328 * This function returns the position you need to pass to
4329 * gtk_window_move() to keep @window in its current position. This
4330 * means that the meaning of the returned value varies with window
4331 * gravity. See gtk_window_move() for more details.
4333 * If you haven't changed the window gravity, its gravity will be
4334 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4335 * gets the position of the top-left corner of the window manager
4336 * frame for the window. gtk_window_move() sets the position of this
4337 * same top-left corner.
4339 * gtk_window_get_position() is not 100% reliable because the X Window System
4340 * does not specify a way to obtain the geometry of the
4341 * decorations placed on a window by the window manager.
4342 * Thus GTK+ is using a "best guess" that works with most
4345 * Moreover, nearly all window managers are historically broken with
4346 * respect to their handling of window gravity. So moving a window to
4347 * its current position as returned by gtk_window_get_position() tends
4348 * to result in moving the window slightly. Window managers are
4349 * slowly getting better over time.
4351 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4352 * frame is not relevant, and thus gtk_window_get_position() will
4353 * always produce accurate results. However you can't use static
4354 * gravity to do things like place a window in a corner of the screen,
4355 * because static gravity ignores the window manager decorations.
4357 * If you are saving and restoring your application's window
4358 * positions, you should know that it's impossible for applications to
4359 * do this without getting it somewhat wrong because applications do
4360 * not have sufficient knowledge of window manager state. The Correct
4361 * Mechanism is to support the session management protocol (see the
4362 * "GnomeClient" object in the GNOME libraries for example) and allow
4363 * the window manager to save your window sizes and positions.
4368 gtk_window_get_position (GtkWindow *window,
4372 GtkWindowPrivate *priv;
4374 GdkWindow *gdk_window;
4376 g_return_if_fail (GTK_IS_WINDOW (window));
4378 priv = window->priv;
4379 widget = GTK_WIDGET (window);
4380 gdk_window = gtk_widget_get_window (widget);
4382 if (priv->gravity == GDK_GRAVITY_STATIC)
4384 if (gtk_widget_get_mapped (widget))
4386 /* This does a server round-trip, which is sort of wrong;
4387 * but a server round-trip is inevitable for
4388 * gdk_window_get_frame_extents() in the usual
4389 * NorthWestGravity case below, so not sure what else to
4390 * do. We should likely be consistent about whether we get
4391 * the client-side info or the server-side info.
4393 gdk_window_get_origin (gdk_window, root_x, root_y);
4397 GdkRectangle configure_request;
4399 gtk_window_compute_configure_request (window,
4403 *root_x = configure_request.x;
4404 *root_y = configure_request.y;
4409 GdkRectangle frame_extents;
4414 if (gtk_widget_get_mapped (widget))
4416 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4417 x = frame_extents.x;
4418 y = frame_extents.y;
4419 gtk_window_get_size (window, &w, &h);
4423 /* We just say the frame has 0 size on all sides.
4424 * Not sure what else to do.
4426 gtk_window_compute_configure_request (window,
4429 x = frame_extents.x;
4430 y = frame_extents.y;
4431 w = frame_extents.width;
4432 h = frame_extents.height;
4435 switch (priv->gravity)
4437 case GDK_GRAVITY_NORTH:
4438 case GDK_GRAVITY_CENTER:
4439 case GDK_GRAVITY_SOUTH:
4440 /* Find center of frame. */
4441 x += frame_extents.width / 2;
4442 /* Center client window on that point. */
4446 case GDK_GRAVITY_SOUTH_EAST:
4447 case GDK_GRAVITY_EAST:
4448 case GDK_GRAVITY_NORTH_EAST:
4449 /* Find right edge of frame */
4450 x += frame_extents.width;
4451 /* Align left edge of client at that point. */
4458 switch (priv->gravity)
4460 case GDK_GRAVITY_WEST:
4461 case GDK_GRAVITY_CENTER:
4462 case GDK_GRAVITY_EAST:
4463 /* Find center of frame. */
4464 y += frame_extents.height / 2;
4465 /* Center client window there. */
4468 case GDK_GRAVITY_SOUTH_WEST:
4469 case GDK_GRAVITY_SOUTH:
4470 case GDK_GRAVITY_SOUTH_EAST:
4471 /* Find south edge of frame */
4472 y += frame_extents.height;
4473 /* Place bottom edge of client there */
4488 * gtk_window_reshow_with_initial_size:
4489 * @window: a #GtkWindow
4491 * Hides @window, then reshows it, resetting the
4492 * default size and position of the window. Used
4493 * by GUI builders only.
4496 gtk_window_reshow_with_initial_size (GtkWindow *window)
4500 g_return_if_fail (GTK_IS_WINDOW (window));
4502 widget = GTK_WIDGET (window);
4504 gtk_widget_hide (widget);
4505 gtk_widget_unrealize (widget);
4506 gtk_widget_show (widget);
4510 gtk_window_destroy (GtkWidget *widget)
4512 GtkWindow *window = GTK_WINDOW (widget);
4513 GtkWindowPrivate *priv = window->priv;
4515 gtk_window_release_application (window);
4517 toplevel_list = g_slist_remove (toplevel_list, window);
4519 if (priv->transient_parent)
4520 gtk_window_set_transient_for (window, NULL);
4522 /* frees the icons */
4523 gtk_window_set_icon_list (window, NULL);
4525 if (priv->has_user_ref_count)
4527 priv->has_user_ref_count = FALSE;
4528 g_object_unref (window);
4532 gtk_window_group_remove_window (priv->group, window);
4534 gtk_window_free_key_hash (window);
4536 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4540 gtk_window_finalize (GObject *object)
4542 GtkWindow *window = GTK_WINDOW (object);
4543 GtkWindowPrivate *priv = window->priv;
4544 GtkMnemonicHash *mnemonic_hash;
4546 g_free (priv->title);
4547 g_free (priv->wmclass_name);
4548 g_free (priv->wmclass_class);
4549 g_free (priv->wm_role);
4550 gtk_window_release_application (window);
4552 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4554 _gtk_mnemonic_hash_free (mnemonic_hash);
4556 if (priv->geometry_info)
4558 if (priv->geometry_info->widget)
4559 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4560 gtk_widget_destroyed,
4561 &priv->geometry_info->widget);
4562 g_free (priv->geometry_info);
4565 if (priv->keys_changed_handler)
4567 g_source_remove (priv->keys_changed_handler);
4568 priv->keys_changed_handler = 0;
4572 g_signal_handlers_disconnect_by_func (priv->screen,
4573 gtk_window_on_composited_changed, window);
4575 g_free (priv->startup_id);
4577 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4581 gtk_window_show (GtkWidget *widget)
4583 GtkWindow *window = GTK_WINDOW (widget);
4584 GtkWindowPrivate *priv = window->priv;
4585 GtkContainer *container = GTK_CONTAINER (window);
4586 gboolean need_resize;
4588 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4590 GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget);
4594 _gtk_widget_set_visible_flag (widget, TRUE);
4596 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4597 _gtk_container_set_need_resize (container, FALSE);
4601 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4602 GtkAllocation allocation = { 0, 0 };
4603 GdkRectangle configure_request;
4604 GdkGeometry new_geometry;
4606 gboolean was_realized;
4608 /* We are going to go ahead and perform this configure request
4609 * and then emulate a configure notify by going ahead and
4610 * doing a size allocate. Sort of a synchronous
4611 * mini-copy of gtk_window_move_resize() here.
4613 gtk_window_compute_configure_request (window,
4618 /* We update this because we are going to go ahead
4619 * and gdk_window_resize() below, rather than
4622 info->last.configure_request.width = configure_request.width;
4623 info->last.configure_request.height = configure_request.height;
4625 /* and allocate the window - this is normally done
4626 * in move_resize in response to configure notify
4628 allocation.width = configure_request.width;
4629 allocation.height = configure_request.height;
4630 gtk_widget_size_allocate (widget, &allocation);
4632 /* Then we guarantee we have a realize */
4633 was_realized = FALSE;
4634 if (!gtk_widget_get_realized (widget))
4636 gtk_widget_realize (widget);
4637 was_realized = TRUE;
4640 /* We only send configure request if we didn't just finish
4641 * creating the window; if we just created the window
4642 * then we created it with widget->allocation anyhow.
4645 gdk_window_move_resize (gtk_widget_get_window (widget),
4646 configure_request.x,
4647 configure_request.y,
4648 configure_request.width,
4649 configure_request.height);
4652 gtk_container_check_resize (container);
4654 gtk_widget_map (widget);
4656 /* Try to make sure that we have some focused widget
4658 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4659 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4662 gtk_grab_add (widget);
4666 gtk_window_hide (GtkWidget *widget)
4668 GtkWindow *window = GTK_WINDOW (widget);
4669 GtkWindowPrivate *priv = window->priv;
4671 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4673 GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget);
4677 _gtk_widget_set_visible_flag (widget, FALSE);
4678 gtk_widget_unmap (widget);
4681 gtk_grab_remove (widget);
4685 gtk_window_map (GtkWidget *widget)
4688 GtkWindow *window = GTK_WINDOW (widget);
4689 GtkWindowPrivate *priv = window->priv;
4690 GdkWindow *toplevel;
4691 GdkWindow *gdk_window;
4692 gboolean auto_mnemonics;
4694 gdk_window = gtk_widget_get_window (widget);
4696 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4698 GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
4702 gtk_widget_set_mapped (widget, TRUE);
4704 child = gtk_bin_get_child (&(window->bin));
4706 gtk_widget_get_visible (child) &&
4707 !gtk_widget_get_mapped (child))
4708 gtk_widget_map (child);
4710 toplevel = gdk_window;
4712 if (priv->maximize_initially)
4713 gdk_window_maximize (toplevel);
4715 gdk_window_unmaximize (toplevel);
4717 if (priv->stick_initially)
4718 gdk_window_stick (toplevel);
4720 gdk_window_unstick (toplevel);
4722 if (priv->iconify_initially)
4723 gdk_window_iconify (toplevel);
4725 gdk_window_deiconify (toplevel);
4727 if (priv->fullscreen_initially)
4728 gdk_window_fullscreen (toplevel);
4730 gdk_window_unfullscreen (toplevel);
4732 gdk_window_set_keep_above (toplevel, priv->above_initially);
4734 gdk_window_set_keep_below (toplevel, priv->below_initially);
4736 /* No longer use the default settings */
4737 priv->need_default_size = FALSE;
4738 priv->need_default_position = FALSE;
4740 if (priv->reset_type_hint)
4742 /* We should only reset the type hint when the application
4743 * used gtk_window_set_type_hint() to change the hint.
4744 * Some applications use X directly to change the properties;
4745 * in that case, we shouldn't overwrite what they did.
4747 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4748 priv->reset_type_hint = FALSE;
4751 gdk_window_show (gdk_window);
4753 if (priv->grip_window)
4754 gdk_window_show (priv->grip_window);
4756 if (!disable_startup_notification)
4758 /* Do we have a custom startup-notification id? */
4759 if (priv->startup_id != NULL)
4761 /* Make sure we have a "real" id */
4762 if (!startup_id_is_fake (priv->startup_id))
4763 gdk_notify_startup_complete_with_id (priv->startup_id);
4765 g_free (priv->startup_id);
4766 priv->startup_id = NULL;
4768 else if (!sent_startup_notification)
4770 sent_startup_notification = TRUE;
4771 gdk_notify_startup_complete ();
4775 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4776 * (as in the case of popup menus), then hide mnemonics initially
4778 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4779 &auto_mnemonics, NULL);
4780 if (auto_mnemonics && !priv->mnemonics_visible_set)
4781 gtk_window_set_mnemonics_visible (window, FALSE);
4785 gtk_window_map_event (GtkWidget *widget,
4788 if (!gtk_widget_get_mapped (widget))
4790 /* we should be be unmapped, but are getting a MapEvent, this may happen
4791 * to toplevel XWindows if mapping was intercepted by a window manager
4792 * and an unmap request occoured while the MapRequestEvent was still
4793 * being handled. we work around this situaiton here by re-requesting
4794 * the window being unmapped. more details can be found in:
4795 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4797 gdk_window_hide (gtk_widget_get_window (widget));
4803 gtk_window_unmap (GtkWidget *widget)
4805 GtkWindow *window = GTK_WINDOW (widget);
4806 GtkWindowPrivate *priv = window->priv;
4808 GtkWindowGeometryInfo *info;
4809 GdkWindow *gdk_window;
4810 GdkWindowState state;
4812 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
4814 GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
4818 gdk_window = gtk_widget_get_window (widget);
4820 gtk_widget_set_mapped (widget, FALSE);
4821 gdk_window_withdraw (gdk_window);
4823 priv->configure_request_count = 0;
4824 priv->configure_notify_received = FALSE;
4826 /* on unmap, we reset the default positioning of the window,
4827 * so it's placed again, but we don't reset the default
4828 * size of the window, so it's remembered.
4830 priv->need_default_position = TRUE;
4832 info = gtk_window_get_geometry_info (window, FALSE);
4835 info->initial_pos_set = FALSE;
4836 info->position_constraints_changed = FALSE;
4839 state = gdk_window_get_state (gdk_window);
4840 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4841 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4842 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4843 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4844 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4846 child = gtk_bin_get_child (&(window->bin));
4848 gtk_widget_unmap (child);
4852 gtk_window_realize (GtkWidget *widget)
4854 GtkAllocation allocation;
4856 GdkWindow *parent_window;
4857 GdkWindow *gdk_window;
4858 GdkWindowAttr attributes;
4859 gint attributes_mask;
4860 GtkWindowPrivate *priv;
4861 GtkStyleContext *context;
4863 window = GTK_WINDOW (widget);
4864 priv = window->priv;
4866 gtk_widget_get_allocation (widget, &allocation);
4868 if (gtk_widget_get_parent_window (widget))
4870 gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
4872 gtk_widget_set_realized (widget, TRUE);
4874 attributes.x = allocation.x;
4875 attributes.y = allocation.y;
4876 attributes.width = allocation.width;
4877 attributes.height = allocation.height;
4878 attributes.window_type = GDK_WINDOW_CHILD;
4880 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
4882 attributes.visual = gtk_widget_get_visual (widget);
4883 attributes.wclass = GDK_INPUT_OUTPUT;
4885 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
4887 gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget),
4888 &attributes, attributes_mask);
4889 gtk_widget_set_window (widget, gdk_window);
4890 gdk_window_set_user_data (gdk_window, widget);
4892 gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
4894 gdk_window_enable_synchronized_configure (gdk_window);
4898 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
4900 /* ensure widget tree is properly size allocated */
4901 if (allocation.x == -1 &&
4902 allocation.y == -1 &&
4903 allocation.width == 1 &&
4904 allocation.height == 1)
4906 GtkRequisition requisition;
4910 allocation.width = 200;
4911 allocation.height = 200;
4913 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4914 if (requisition.width || requisition.height)
4916 /* non-empty window */
4917 allocation.width = requisition.width;
4918 allocation.height = requisition.height;
4920 gtk_widget_size_allocate (widget, &allocation);
4922 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4924 g_return_if_fail (!gtk_widget_get_realized (widget));
4927 gtk_widget_set_realized (widget, TRUE);
4931 case GTK_WINDOW_TOPLEVEL:
4932 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4934 case GTK_WINDOW_POPUP:
4935 attributes.window_type = GDK_WINDOW_TEMP;
4938 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4942 attributes.title = priv->title;
4943 attributes.wmclass_name = priv->wmclass_name;
4944 attributes.wmclass_class = priv->wmclass_class;
4945 attributes.wclass = GDK_INPUT_OUTPUT;
4946 attributes.visual = gtk_widget_get_visual (widget);
4948 attributes_mask = 0;
4949 parent_window = gtk_widget_get_root_window (widget);
4951 gtk_widget_get_allocation (widget, &allocation);
4952 attributes.width = allocation.width;
4953 attributes.height = allocation.height;
4954 attributes.event_mask = gtk_widget_get_events (widget);
4955 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4956 GDK_KEY_PRESS_MASK |
4957 GDK_KEY_RELEASE_MASK |
4958 GDK_ENTER_NOTIFY_MASK |
4959 GDK_LEAVE_NOTIFY_MASK |
4960 GDK_FOCUS_CHANGE_MASK |
4961 GDK_STRUCTURE_MASK);
4962 attributes.type_hint = priv->type_hint;
4964 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4965 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4966 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4968 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4969 gtk_widget_set_window (widget, gdk_window);
4971 if (priv->opacity_set)
4972 gdk_window_set_opacity (gdk_window, priv->opacity);
4974 gdk_window_enable_synchronized_configure (gdk_window);
4976 gdk_window_set_user_data (gdk_window, window);
4978 context = gtk_widget_get_style_context (widget);
4979 gtk_style_context_set_background (context, gdk_window);
4982 if (priv->transient_parent &&
4983 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
4984 gdk_window_set_transient_for (gdk_window,
4985 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
4988 gdk_window_set_role (gdk_window, priv->wm_role);
4990 if (!priv->decorated)
4991 gdk_window_set_decorations (gdk_window, 0);
4993 if (!priv->deletable)
4994 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4996 if (gtk_window_get_skip_pager_hint (window))
4997 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
4999 if (gtk_window_get_skip_taskbar_hint (window))
5000 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5002 if (gtk_window_get_accept_focus (window))
5003 gdk_window_set_accept_focus (gdk_window, TRUE);
5005 gdk_window_set_accept_focus (gdk_window, FALSE);
5007 if (gtk_window_get_focus_on_map (window))
5008 gdk_window_set_focus_on_map (gdk_window, TRUE);
5010 gdk_window_set_focus_on_map (gdk_window, FALSE);
5013 gdk_window_set_modal_hint (gdk_window, TRUE);
5015 gdk_window_set_modal_hint (gdk_window, FALSE);
5017 if (priv->startup_id)
5019 #ifdef GDK_WINDOWING_X11
5020 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5021 if (timestamp != GDK_CURRENT_TIME)
5022 gdk_x11_window_set_user_time (gdk_window, timestamp);
5024 if (!startup_id_is_fake (priv->startup_id))
5025 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5029 gtk_window_realize_icon (window);
5031 if (priv->has_resize_grip)
5032 resize_grip_create_window (window);
5036 gtk_window_unrealize (GtkWidget *widget)
5038 GtkWindow *window = GTK_WINDOW (widget);
5039 GtkWindowPrivate *priv = window->priv;
5040 GtkWindowGeometryInfo *info;
5042 /* On unrealize, we reset the size of the window such
5043 * that we will re-apply the default sizing stuff
5044 * next time we show the window.
5046 * Default positioning is reset on unmap, instead of unrealize.
5048 priv->need_default_size = TRUE;
5049 info = gtk_window_get_geometry_info (window, FALSE);
5052 info->resize_width = -1;
5053 info->resize_height = -1;
5054 info->last.configure_request.x = 0;
5055 info->last.configure_request.y = 0;
5056 info->last.configure_request.width = -1;
5057 info->last.configure_request.height = -1;
5058 /* be sure we reset geom hints on re-realize */
5059 info->last.flags = 0;
5063 gtk_window_unrealize_icon (window);
5065 if (priv->grip_window != NULL)
5066 resize_grip_destroy_window (window);
5068 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5071 static GtkJunctionSides
5072 get_grip_junction (GtkWidget *widget)
5074 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5075 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5077 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5081 get_drag_edge (GtkWidget *widget,
5082 GdkWindowEdge *edge)
5084 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5085 gboolean hresizable;
5086 gboolean vresizable;
5087 GtkTextDirection dir;
5088 GtkWindowGeometryInfo *info;
5093 info = priv->geometry_info;
5096 GdkWindowHints flags = info->last.flags;
5097 GdkGeometry *geometry = &info->last.geometry;
5099 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5101 hresizable = geometry->min_width < geometry->max_width;
5102 vresizable = geometry->min_height < geometry->max_height;
5106 dir = gtk_widget_get_direction (widget);
5108 if (hresizable && vresizable)
5109 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5110 else if (hresizable)
5111 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5112 else if (vresizable)
5113 *edge = GDK_WINDOW_EDGE_SOUTH;
5121 set_grip_cursor (GtkWindow *window)
5123 GtkWidget *widget = GTK_WIDGET (window);
5124 GtkWindowPrivate *priv = window->priv;
5126 if (priv->grip_window == NULL)
5129 if (gtk_widget_is_sensitive (widget))
5132 GdkDisplay *display;
5133 GdkCursorType cursor_type;
5136 cursor_type = GDK_LEFT_PTR;
5138 if (get_drag_edge (widget, &edge))
5142 case GDK_WINDOW_EDGE_EAST:
5143 cursor_type = GDK_RIGHT_SIDE;
5145 case GDK_WINDOW_EDGE_SOUTH_EAST:
5146 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5148 case GDK_WINDOW_EDGE_SOUTH:
5149 cursor_type = GDK_BOTTOM_SIDE;
5151 case GDK_WINDOW_EDGE_SOUTH_WEST:
5152 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5154 case GDK_WINDOW_EDGE_WEST:
5155 cursor_type = GDK_LEFT_SIDE;
5161 display = gtk_widget_get_display (widget);
5162 cursor = gdk_cursor_new_for_display (display, cursor_type);
5163 gdk_window_set_cursor (priv->grip_window, cursor);
5164 g_object_unref (cursor);
5167 gdk_window_set_cursor (priv->grip_window, NULL);
5171 set_grip_shape (GtkWindow *window)
5173 GtkWindowPrivate *priv = window->priv;
5174 cairo_region_t *region;
5175 cairo_surface_t *surface;
5177 double width, height;
5179 if (priv->grip_window == NULL)
5182 width = gdk_window_get_width (priv->grip_window);
5183 height = gdk_window_get_height (priv->grip_window);
5184 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5186 cr = cairo_create (surface);
5187 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5189 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5190 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5192 cairo_move_to (cr, width, 0.0);
5193 cairo_line_to (cr, width, height);
5194 cairo_line_to (cr, 0.0, height);
5198 cairo_move_to (cr, 0.0, 0.0);
5199 cairo_line_to (cr, width, height);
5200 cairo_line_to (cr, 0.0, height);
5202 cairo_close_path (cr);
5205 region = gdk_cairo_region_create_from_surface (surface);
5206 cairo_surface_destroy (surface);
5208 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5209 cairo_region_destroy (region);
5213 set_grip_position (GtkWindow *window)
5215 GtkWindowPrivate *priv = window->priv;
5218 if (priv->grip_window == NULL)
5221 gtk_window_get_resize_grip_area (window, &rect);
5222 gdk_window_raise (priv->grip_window);
5223 gdk_window_move_resize (priv->grip_window,
5225 rect.width, rect.height);
5229 gtk_window_size_allocate (GtkWidget *widget,
5230 GtkAllocation *allocation)
5232 GtkWindow *window = GTK_WINDOW (widget);
5233 GtkAllocation child_allocation;
5237 gtk_widget_set_allocation (widget, allocation);
5239 if (gtk_widget_get_realized (widget))
5241 /* If it's not a toplevel we're embedded, we need to resize the window's
5242 * window and skip the grip.
5244 if (!gtk_widget_is_toplevel (widget))
5246 gdk_window_move_resize (gtk_widget_get_window (widget),
5247 allocation->x, allocation->y,
5248 allocation->width, allocation->height);
5252 update_grip_visibility (window);
5253 set_grip_position (window);
5257 child = gtk_bin_get_child (&(window->bin));
5258 if (child && gtk_widget_get_visible (child))
5260 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5261 child_allocation.x = border_width;
5262 child_allocation.y = border_width;
5263 child_allocation.width =
5264 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5265 child_allocation.height =
5266 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5268 gtk_widget_size_allocate (child, &child_allocation);
5273 gtk_window_configure_event (GtkWidget *widget,
5274 GdkEventConfigure *event)
5276 GtkAllocation allocation;
5277 GtkWindow *window = GTK_WINDOW (widget);
5278 GtkWindowPrivate *priv = window->priv;
5279 gboolean expected_reply = priv->configure_request_count > 0;
5281 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5283 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event)
5284 return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event);
5286 gdk_window_configure_finished (gtk_widget_get_window (widget));
5290 /* priv->configure_request_count incremented for each
5291 * configure request, and decremented to a min of 0 for
5292 * each configure notify.
5294 * All it means is that we know we will get at least
5295 * priv->configure_request_count more configure notifies.
5296 * We could get more configure notifies than that; some
5297 * of the configure notifies we get may be unrelated to
5298 * the configure requests. But we will get at least
5299 * priv->configure_request_count notifies.
5302 if (priv->configure_request_count > 0)
5304 priv->configure_request_count -= 1;
5305 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5308 /* As an optimization, we avoid a resize when possible.
5310 * The only times we can avoid a resize are:
5311 * - we know only the position changed, not the size
5312 * - we know we have made more requests and so will get more
5313 * notifies and can wait to resize when we get them
5315 gtk_widget_get_allocation (widget, &allocation);
5316 if (!expected_reply &&
5317 (allocation.width == event->width &&
5318 allocation.height == event->height))
5320 gdk_window_configure_finished (gtk_widget_get_window (widget));
5325 * If we do need to resize, we do that by:
5326 * - filling in widget->allocation with the new size
5327 * - setting configure_notify_received to TRUE
5328 * for use in gtk_window_move_resize()
5329 * - queueing a resize, leading to invocation of
5330 * gtk_window_move_resize() in an idle handler
5334 priv->configure_notify_received = TRUE;
5336 allocation.width = event->width;
5337 allocation.height = event->height;
5338 gtk_widget_set_allocation (widget, &allocation);
5340 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5342 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5348 gtk_window_state_event (GtkWidget *widget,
5349 GdkEventWindowState *event)
5351 update_grip_visibility (GTK_WINDOW (widget));
5357 gtk_window_direction_changed (GtkWidget *widget,
5358 GtkTextDirection prev_dir)
5360 GtkWindow *window = GTK_WINDOW (widget);
5362 set_grip_cursor (window);
5363 set_grip_position (window);
5364 set_grip_shape (window);
5368 gtk_window_state_changed (GtkWidget *widget,
5369 GtkStateType previous_state)
5371 GtkWindow *window = GTK_WINDOW (widget);
5373 update_grip_visibility (window);
5377 gtk_window_style_updated (GtkWidget *widget)
5379 GtkWindow *window = GTK_WINDOW (widget);
5380 GtkWindowPrivate *priv = window->priv;
5383 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5385 gdk_window_move_resize (priv->grip_window,
5387 rect.width, rect.height);
5389 set_grip_shape (window);
5390 gtk_widget_queue_resize (widget);
5395 resize_grip_create_window (GtkWindow *window)
5398 GtkWindowPrivate *priv;
5399 GdkWindowAttr attributes;
5400 gint attributes_mask;
5403 priv = window->priv;
5404 widget = GTK_WIDGET (window);
5406 g_return_if_fail (gtk_widget_get_realized (widget));
5407 g_return_if_fail (priv->grip_window == NULL);
5409 gtk_window_get_resize_grip_area (window, &rect);
5411 attributes.x = rect.x;
5412 attributes.y = rect.y;
5413 attributes.width = rect.width;
5414 attributes.height = rect.height;
5415 attributes.window_type = GDK_WINDOW_CHILD;
5416 attributes.wclass = GDK_INPUT_OUTPUT;
5417 attributes.event_mask = gtk_widget_get_events (widget) |
5419 GDK_BUTTON_PRESS_MASK;
5421 attributes_mask = GDK_WA_X | GDK_WA_Y;
5423 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5427 gdk_window_set_user_data (priv->grip_window, widget);
5429 gdk_window_raise (priv->grip_window);
5431 set_grip_shape (window);
5432 update_grip_visibility (window);
5436 resize_grip_destroy_window (GtkWindow *window)
5438 GtkWindowPrivate *priv = window->priv;
5440 gdk_window_set_user_data (priv->grip_window, NULL);
5441 gdk_window_destroy (priv->grip_window);
5442 priv->grip_window = NULL;
5443 update_grip_visibility (window);
5447 * gtk_window_set_has_resize_grip:
5448 * @window: a #GtkWindow
5449 * @value: %TRUE to allow a resize grip
5451 * Sets whether @window has a corner resize grip.
5453 * Note that the resize grip is only shown if the window
5454 * is actually resizable and not maximized. Use
5455 * gtk_window_resize_grip_is_visible() to find out if the
5456 * resize grip is currently shown.
5461 gtk_window_set_has_resize_grip (GtkWindow *window,
5464 GtkWidget *widget = GTK_WIDGET (window);
5465 GtkWindowPrivate *priv = window->priv;
5467 value = value != FALSE;
5469 if (value != priv->has_resize_grip)
5471 priv->has_resize_grip = value;
5472 gtk_widget_queue_draw (widget);
5474 if (gtk_widget_get_realized (widget) &&
5475 gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5477 if (priv->has_resize_grip && priv->grip_window == NULL)
5478 resize_grip_create_window (window);
5479 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5480 resize_grip_destroy_window (window);
5483 g_object_notify (G_OBJECT (window), "has-resize-grip");
5488 update_grip_visibility (GtkWindow *window)
5490 GtkWindowPrivate *priv = window->priv;
5493 val = gtk_window_resize_grip_is_visible (window);
5495 if (priv->grip_window != NULL)
5499 gdk_window_show (priv->grip_window);
5500 set_grip_cursor (window);
5504 gdk_window_hide (priv->grip_window);
5508 if (priv->resize_grip_visible != val)
5510 priv->resize_grip_visible = val;
5512 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5517 * gtk_window_resize_grip_is_visible:
5518 * @window: a #GtkWindow
5520 * Determines whether a resize grip is visible for the specified window.
5522 * Returns: %TRUE if a resize grip exists and is visible
5527 gtk_window_resize_grip_is_visible (GtkWindow *window)
5530 GtkWindowPrivate *priv;
5533 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5535 priv = window->priv;
5536 widget = GTK_WIDGET (window);
5538 if (priv->type == GTK_WINDOW_POPUP)
5541 if (!priv->resizable)
5544 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5547 if (gtk_widget_get_realized (widget))
5549 GdkWindowState state;
5551 state = gdk_window_get_state (gtk_widget_get_window (widget));
5553 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5557 if (!get_drag_edge (widget, &edge))
5560 return window->priv->has_resize_grip;
5564 * gtk_window_get_has_resize_grip:
5565 * @window: a #GtkWindow
5567 * Determines whether the window may have a resize grip.
5569 * Returns: %TRUE if the window has a resize grip
5574 gtk_window_get_has_resize_grip (GtkWindow *window)
5576 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5578 return window->priv->has_resize_grip;
5582 * gtk_window_get_resize_grip_area:
5583 * @window: a #GtkWindow
5584 * @rect: (out): a pointer to a #GdkRectangle which we should store
5585 * the resize grip area
5587 * If a window has a resize grip, this will retrieve the grip
5588 * position, width and height into the specified #GdkRectangle.
5590 * Returns: %TRUE if the resize grip's area was retrieved
5595 gtk_window_get_resize_grip_area (GtkWindow *window,
5598 GtkWidget *widget = GTK_WIDGET (window);
5599 GtkAllocation allocation;
5603 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5605 if (!window->priv->has_resize_grip)
5608 gtk_widget_get_allocation (widget, &allocation);
5610 gtk_widget_style_get (widget,
5611 "resize-grip-width", &grip_width,
5612 "resize-grip-height", &grip_height,
5615 if (grip_width > allocation.width)
5616 grip_width = allocation.width;
5618 if (grip_height > allocation.height)
5619 grip_height = allocation.height;
5621 rect->width = grip_width;
5622 rect->height = grip_height;
5623 rect->y = allocation.y + allocation.height - grip_height;
5625 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5626 rect->x = allocation.x + allocation.width - grip_width;
5628 rect->x = allocation.x;
5633 /* the accel_key and accel_mods fields of the key have to be setup
5634 * upon calling this function. it'll then return whether that key
5635 * is at all used as accelerator, and if so will OR in the
5636 * accel_flags member of the key.
5639 _gtk_window_query_nonaccels (GtkWindow *window,
5641 GdkModifierType accel_mods)
5643 GtkWindowPrivate *priv;
5645 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5647 priv = window->priv;
5649 /* movement keys are considered locked accels */
5652 static const guint bindings[] = {
5653 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,
5654 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,
5658 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5659 if (bindings[i] == accel_key)
5663 /* mnemonics are considered locked accels */
5664 if (accel_mods == priv->mnemonic_modifier)
5666 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5667 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5675 * gtk_window_propagate_key_event:
5676 * @window: a #GtkWindow
5677 * @event: a #GdkEventKey
5679 * Propagate a key press or release event to the focus widget and
5680 * up the focus container chain until a widget handles @event.
5681 * This is normally called by the default ::key_press_event and
5682 * ::key_release_event handlers for toplevel windows,
5683 * however in some cases it may be useful to call this directly when
5684 * overriding the standard key handling for a toplevel window.
5686 * Return value: %TRUE if a widget in the focus chain handled the event.
5691 gtk_window_propagate_key_event (GtkWindow *window,
5694 GtkWindowPrivate *priv;
5695 gboolean handled = FALSE;
5696 GtkWidget *widget, *focus;
5698 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5700 priv = window->priv;
5701 widget = GTK_WIDGET (window);
5703 focus = priv->focus_widget;
5705 g_object_ref (focus);
5708 focus && focus != widget &&
5709 gtk_widget_get_toplevel (focus) == widget)
5713 if (gtk_widget_is_sensitive (focus))
5714 handled = gtk_widget_event (focus, (GdkEvent*) event);
5716 parent = gtk_widget_get_parent (focus);
5718 g_object_ref (parent);
5720 g_object_unref (focus);
5726 g_object_unref (focus);
5732 gtk_window_key_press_event (GtkWidget *widget,
5735 GtkWindow *window = GTK_WINDOW (widget);
5736 gboolean handled = FALSE;
5738 /* handle mnemonics and accelerators */
5740 handled = gtk_window_activate_key (window, event);
5742 /* handle focus widget key events */
5744 handled = gtk_window_propagate_key_event (window, event);
5746 /* Chain up, invokes binding set */
5748 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5754 gtk_window_key_release_event (GtkWidget *widget,
5757 GtkWindow *window = GTK_WINDOW (widget);
5758 gboolean handled = FALSE;
5760 /* handle focus widget key events */
5762 handled = gtk_window_propagate_key_event (window, event);
5764 /* Chain up, invokes binding set */
5766 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5772 gtk_window_button_press_event (GtkWidget *widget,
5773 GdkEventButton *event)
5775 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5778 if (event->window == priv->grip_window)
5780 if (get_drag_edge (widget, &edge))
5781 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5795 gtk_window_real_activate_default (GtkWindow *window)
5797 gtk_window_activate_default (window);
5801 gtk_window_real_activate_focus (GtkWindow *window)
5803 gtk_window_activate_focus (window);
5807 gtk_window_enter_notify_event (GtkWidget *widget,
5808 GdkEventCrossing *event)
5814 gtk_window_leave_notify_event (GtkWidget *widget,
5815 GdkEventCrossing *event)
5821 do_focus_change (GtkWidget *widget,
5825 GdkDeviceManager *device_manager;
5828 g_object_ref (widget);
5830 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5831 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5832 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5833 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5835 for (d = devices; d; d = d->next)
5837 GdkDevice *dev = d->data;
5840 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5843 /* Skip non-master keyboards that haven't
5844 * selected for events from this window
5846 window = gtk_widget_get_window (widget);
5847 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5848 window && !gdk_window_get_device_events (window, dev))
5851 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5853 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5854 fevent->focus_change.window = window;
5856 g_object_ref (window);
5857 fevent->focus_change.in = in;
5858 gdk_event_set_device (fevent, dev);
5860 gtk_widget_send_focus_change (widget, fevent);
5862 gdk_event_free (fevent);
5865 g_list_free (devices);
5866 g_object_unref (widget);
5870 gtk_window_focus_in_event (GtkWidget *widget,
5871 GdkEventFocus *event)
5873 GtkWindow *window = GTK_WINDOW (widget);
5875 /* It appears spurious focus in events can occur when
5876 * the window is hidden. So we'll just check to see if
5877 * the window is visible before actually handling the
5880 if (gtk_widget_get_visible (widget))
5882 _gtk_window_set_has_toplevel_focus (window, TRUE);
5883 _gtk_window_set_is_active (window, TRUE);
5890 gtk_window_focus_out_event (GtkWidget *widget,
5891 GdkEventFocus *event)
5893 GtkWindow *window = GTK_WINDOW (widget);
5894 gboolean auto_mnemonics;
5896 _gtk_window_set_has_toplevel_focus (window, FALSE);
5897 _gtk_window_set_is_active (window, FALSE);
5899 /* set the mnemonic-visible property to false */
5900 g_object_get (gtk_widget_get_settings (widget),
5901 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5903 gtk_window_set_mnemonics_visible (window, FALSE);
5908 static GdkAtom atom_rcfiles = GDK_NONE;
5909 static GdkAtom atom_iconthemes = GDK_NONE;
5912 send_client_message_to_embedded_windows (GtkWidget *widget,
5913 GdkAtom message_type)
5915 GList *embedded_windows;
5917 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5918 if (embedded_windows)
5920 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5923 for (i = 0; i < 5; i++)
5924 send_event->client.data.l[i] = 0;
5925 send_event->client.data_format = 32;
5926 send_event->client.message_type = message_type;
5928 while (embedded_windows)
5930 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
5931 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5932 embedded_windows = embedded_windows->next;
5935 gdk_event_free (send_event);
5940 gtk_window_client_event (GtkWidget *widget,
5941 GdkEventClient *event)
5945 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5946 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5949 if (event->message_type == atom_rcfiles)
5951 send_client_message_to_embedded_windows (widget, atom_rcfiles);
5952 gtk_style_context_reset_widgets (gtk_widget_get_screen (widget));
5955 if (event->message_type == atom_iconthemes)
5957 send_client_message_to_embedded_windows (widget, atom_iconthemes);
5958 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
5965 gtk_window_check_resize (GtkContainer *container)
5967 /* If the window is not toplevel anymore than it's embedded somewhere,
5968 * so handle it like a normal window */
5969 if (!gtk_widget_is_toplevel (GTK_WIDGET (container)))
5970 GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
5971 else if (gtk_widget_get_visible (GTK_WIDGET (container)))
5972 gtk_window_move_resize (GTK_WINDOW (container));
5976 gtk_window_focus (GtkWidget *widget,
5977 GtkDirectionType direction)
5979 GtkWindowPrivate *priv;
5982 GtkContainer *container;
5984 GtkWidget *old_focus_child;
5987 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
5988 return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction);
5990 container = GTK_CONTAINER (widget);
5991 window = GTK_WINDOW (widget);
5992 priv = window->priv;
5993 bin = GTK_BIN (widget);
5995 old_focus_child = gtk_container_get_focus_child (container);
5997 /* We need a special implementation here to deal properly with wrapping
5998 * around in the tab chain without the danger of going into an
6001 if (old_focus_child)
6003 if (gtk_widget_child_focus (old_focus_child, direction))
6007 if (priv->focus_widget)
6009 if (direction == GTK_DIR_LEFT ||
6010 direction == GTK_DIR_RIGHT ||
6011 direction == GTK_DIR_UP ||
6012 direction == GTK_DIR_DOWN)
6017 /* Wrapped off the end, clear the focus setting for the toplpevel */
6018 parent = gtk_widget_get_parent (priv->focus_widget);
6021 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6022 parent = gtk_widget_get_parent (parent);
6025 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6028 /* Now try to focus the first widget in the window */
6029 child = gtk_bin_get_child (bin);
6032 if (gtk_widget_child_focus (child, direction))
6040 gtk_window_move_focus (GtkWidget *widget,
6041 GtkDirectionType dir)
6043 if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
6045 GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir);
6049 gtk_widget_child_focus (widget, dir);
6051 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6052 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6056 gtk_window_real_set_focus (GtkWindow *window,
6059 GtkWindowPrivate *priv = window->priv;
6060 GtkWidget *old_focus = priv->focus_widget;
6061 gboolean had_default = FALSE;
6062 gboolean focus_had_default = FALSE;
6063 gboolean old_focus_had_default = FALSE;
6067 g_object_ref (old_focus);
6068 g_object_freeze_notify (G_OBJECT (old_focus));
6069 old_focus_had_default = gtk_widget_has_default (old_focus);
6073 g_object_ref (focus);
6074 g_object_freeze_notify (G_OBJECT (focus));
6075 focus_had_default = gtk_widget_has_default (focus);
6078 if (priv->default_widget)
6079 had_default = gtk_widget_has_default (priv->default_widget);
6081 if (priv->focus_widget)
6083 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6084 (priv->focus_widget != priv->default_widget))
6086 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6087 gtk_widget_queue_draw (priv->focus_widget);
6089 if (priv->default_widget)
6090 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6093 priv->focus_widget = NULL;
6095 if (priv->has_focus)
6096 do_focus_change (old_focus, FALSE);
6098 g_object_notify (G_OBJECT (old_focus), "is-focus");
6101 /* The above notifications may have set a new focus widget,
6102 * if so, we don't want to override it.
6104 if (focus && !priv->focus_widget)
6106 priv->focus_widget = focus;
6108 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6109 (priv->focus_widget != priv->default_widget))
6111 if (gtk_widget_get_can_default (priv->focus_widget))
6112 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6114 if (priv->default_widget)
6115 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6118 if (priv->has_focus)
6119 do_focus_change (priv->focus_widget, TRUE);
6121 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6124 /* If the default widget changed, a redraw will have been queued
6125 * on the old and new default widgets by gtk_window_set_default(), so
6126 * we only have to worry about the case where it didn't change.
6127 * We'll sometimes queue a draw twice on the new widget but that
6130 if (priv->default_widget &&
6131 (had_default != gtk_widget_has_default (priv->default_widget)))
6132 gtk_widget_queue_draw (priv->default_widget);
6136 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6137 gtk_widget_queue_draw (old_focus);
6139 g_object_thaw_notify (G_OBJECT (old_focus));
6140 g_object_unref (old_focus);
6144 if (focus_had_default != gtk_widget_has_default (focus))
6145 gtk_widget_queue_draw (focus);
6147 g_object_thaw_notify (G_OBJECT (focus));
6148 g_object_unref (focus);
6154 gtk_window_get_preferred_width (GtkWidget *widget,
6162 window = GTK_WINDOW (widget);
6163 child = gtk_bin_get_child (GTK_BIN (window));
6165 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6166 *minimum_size = border_width * 2;
6167 *natural_size = border_width * 2;
6169 if (child && gtk_widget_get_visible (child))
6171 gint child_min, child_nat;
6172 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6174 *minimum_size += child_min;
6175 *natural_size += child_nat;
6180 gtk_window_get_preferred_height (GtkWidget *widget,
6188 window = GTK_WINDOW (widget);
6189 child = gtk_bin_get_child (GTK_BIN (window));
6191 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6192 *minimum_size = border_width * 2;
6193 *natural_size = border_width * 2;
6195 if (child && gtk_widget_get_visible (child))
6197 gint child_min, child_nat;
6198 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6200 *minimum_size += child_min;
6201 *natural_size += child_nat;
6207 * _gtk_window_unset_focus_and_default:
6208 * @window: a #GtkWindow
6209 * @widget: a widget inside of @window
6211 * Checks whether the focus and default widgets of @window are
6212 * @widget or a descendent of @widget, and if so, unset them.
6215 _gtk_window_unset_focus_and_default (GtkWindow *window,
6219 GtkWindowPrivate *priv = window->priv;
6223 g_object_ref (window);
6224 g_object_ref (widget);
6226 parent = gtk_widget_get_parent (widget);
6227 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6229 child = priv->focus_widget;
6231 while (child && child != widget)
6232 child = gtk_widget_get_parent (child);
6234 if (child == widget)
6235 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6238 child = priv->default_widget;
6240 while (child && child != widget)
6241 child = gtk_widget_get_parent (child);
6243 if (child == widget)
6244 gtk_window_set_default (window, NULL);
6246 g_object_unref (widget);
6247 g_object_unref (window);
6250 /*********************************
6251 * Functions related to resizing *
6252 *********************************/
6255 geometry_size_to_pixels (GdkGeometry *geometry,
6260 gint base_width = 0;
6261 gint base_height = 0;
6263 gint min_height = 0;
6265 gint height_inc = 1;
6267 if (flags & GDK_HINT_BASE_SIZE)
6269 base_width = geometry->base_width;
6270 base_height = geometry->base_height;
6272 if (flags & GDK_HINT_MIN_SIZE)
6274 min_width = geometry->min_width;
6275 min_height = geometry->min_height;
6277 if (flags & GDK_HINT_RESIZE_INC)
6279 width_inc = geometry->width_inc;
6280 height_inc = geometry->height_inc;
6284 *width = MAX (*width * width_inc + base_width, min_width);
6286 *height = MAX (*height * height_inc + base_height, min_height);
6289 /* This function doesn't constrain to geometry hints */
6291 gtk_window_compute_configure_request_size (GtkWindow *window,
6292 GdkGeometry *geometry,
6297 GtkWindowPrivate *priv = window->priv;
6298 GtkRequisition requisition;
6299 GtkWindowGeometryInfo *info;
6303 * - we've done a size request
6306 widget = GTK_WIDGET (window);
6308 info = gtk_window_get_geometry_info (window, FALSE);
6310 if (priv->need_default_size)
6312 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6314 /* Default to requisition */
6315 *width = requisition.width;
6316 *height = requisition.height;
6318 /* If window is empty so requests 0, default to random nonzero size */
6319 if (*width == 0 && *height == 0)
6325 /* Override requisition with default size */
6329 if (info->default_width > 0)
6330 *width = info->default_width;
6331 if (info->default_height > 0)
6332 *height = info->default_height;
6334 if (info->default_is_geometry)
6335 geometry_size_to_pixels (geometry, flags,
6336 info->default_width > 0 ? width : NULL,
6337 info->default_height > 0 ? height : NULL);
6342 GtkAllocation allocation;
6344 gtk_widget_get_allocation (widget, &allocation);
6346 /* Default to keeping current size */
6347 *width = allocation.width;
6348 *height = allocation.height;
6351 /* Override any size with gtk_window_resize() values */
6354 if (info->resize_width > 0)
6355 *width = info->resize_width;
6356 if (info->resize_height > 0)
6357 *height = info->resize_height;
6359 if (info->resize_is_geometry)
6360 geometry_size_to_pixels (geometry, flags,
6361 info->resize_width > 0 ? width : NULL,
6362 info->resize_height > 0 ? height : NULL);
6365 /* Don't ever request zero width or height, its not supported by
6366 gdk. The size allocation code will round it to 1 anyway but if
6367 we do it then the value returned from this function will is
6368 not comparable to the size allocation read from the GtkWindow. */
6369 *width = MAX (*width, 1);
6370 *height = MAX (*height, 1);
6373 static GtkWindowPosition
6374 get_effective_position (GtkWindow *window)
6376 GtkWindowPrivate *priv = window->priv;
6377 GtkWindowPosition pos = priv->position;
6379 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6380 (priv->transient_parent == NULL ||
6381 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6382 pos = GTK_WIN_POS_NONE;
6388 get_center_monitor_of_window (GtkWindow *window)
6390 /* We could try to sort out the relative positions of the monitors and
6391 * stuff, or we could just be losers and assume you have a row
6392 * or column of monitors.
6394 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6398 get_monitor_containing_pointer (GtkWindow *window)
6402 GdkScreen *window_screen;
6403 GdkScreen *pointer_screen;
6404 GdkDisplay *display;
6405 GdkDeviceManager *device_manager;
6408 window_screen = gtk_window_check_screen (window);
6409 display = gdk_screen_get_display (window_screen);
6410 device_manager = gdk_display_get_device_manager (display);
6411 pointer = gdk_device_manager_get_client_pointer (device_manager);
6413 gdk_device_get_position (pointer,
6417 if (pointer_screen == window_screen)
6418 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6426 center_window_on_monitor (GtkWindow *window,
6432 GdkRectangle monitor;
6435 monitor_num = get_monitor_containing_pointer (window);
6437 if (monitor_num == -1)
6438 monitor_num = get_center_monitor_of_window (window);
6440 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6441 monitor_num, &monitor);
6443 *x = (monitor.width - w) / 2 + monitor.x;
6444 *y = (monitor.height - h) / 2 + monitor.y;
6446 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6447 * and WM decorations.
6461 if (extent > clamp_extent)
6463 *base = clamp_base + clamp_extent/2 - extent/2;
6464 else if (*base < clamp_base)
6466 else if (*base + extent > clamp_base + clamp_extent)
6467 *base = clamp_base + clamp_extent - extent;
6471 clamp_window_to_rectangle (gint *x,
6475 const GdkRectangle *rect)
6477 #ifdef DEBUGGING_OUTPUT
6478 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);
6481 /* If it is too large, center it. If it fits on the monitor but is
6482 * partially outside, move it to the closest edge. Do this
6483 * separately in x and y directions.
6485 clamp (x, w, rect->x, rect->width);
6486 clamp (y, h, rect->y, rect->height);
6487 #ifdef DEBUGGING_OUTPUT
6488 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6494 gtk_window_compute_configure_request (GtkWindow *window,
6495 GdkRectangle *request,
6496 GdkGeometry *geometry,
6499 GtkWindowPrivate *priv = window->priv;
6500 GdkGeometry new_geometry;
6504 GtkWindowPosition pos;
6505 GtkWidget *parent_widget;
6506 GtkWindowGeometryInfo *info;
6510 widget = GTK_WIDGET (window);
6512 screen = gtk_window_check_screen (window);
6514 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6515 gtk_window_compute_configure_request_size (window,
6516 &new_geometry, new_flags,
6517 (guint *)&w, (guint *)&h);
6519 gtk_window_constrain_size (window,
6520 &new_geometry, new_flags,
6524 parent_widget = (GtkWidget*) priv->transient_parent;
6526 pos = get_effective_position (window);
6527 info = gtk_window_get_geometry_info (window, FALSE);
6529 /* by default, don't change position requested */
6532 x = info->last.configure_request.x;
6533 y = info->last.configure_request.y;
6542 if (priv->need_default_position)
6545 /* FIXME this all interrelates with window gravity.
6546 * For most of them I think we want to set GRAVITY_CENTER.
6548 * Not sure how to go about that.
6553 /* here we are only handling CENTER_ALWAYS
6554 * as it relates to default positioning,
6555 * where it's equivalent to simply CENTER
6557 case GTK_WIN_POS_CENTER_ALWAYS:
6558 case GTK_WIN_POS_CENTER:
6559 center_window_on_monitor (window, w, h, &x, &y);
6562 case GTK_WIN_POS_CENTER_ON_PARENT:
6564 GtkAllocation allocation;
6565 GdkWindow *gdk_window;
6567 GdkRectangle monitor;
6570 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6572 gdk_window = gtk_widget_get_window (parent_widget);
6574 if (gdk_window != NULL)
6575 monitor_num = gdk_screen_get_monitor_at_window (screen,
6580 gdk_window_get_origin (gdk_window,
6583 gtk_widget_get_allocation (parent_widget, &allocation);
6584 x = ox + (allocation.width - w) / 2;
6585 y = oy + (allocation.height - h) / 2;
6587 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6588 * WM decorations. If parent wasn't on a monitor, just
6591 if (monitor_num >= 0)
6593 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6594 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6599 case GTK_WIN_POS_MOUSE:
6601 gint screen_width = gdk_screen_get_width (screen);
6602 gint screen_height = gdk_screen_get_height (screen);
6604 GdkRectangle monitor;
6605 GdkDisplay *display;
6606 GdkDeviceManager *device_manager;
6608 GdkScreen *pointer_screen;
6611 display = gdk_screen_get_display (screen);
6612 device_manager = gdk_display_get_device_manager (display);
6613 pointer = gdk_device_manager_get_client_pointer (device_manager);
6615 gdk_device_get_position (pointer,
6619 if (pointer_screen == screen)
6620 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6626 x = CLAMP (x, 0, screen_width - w);
6627 y = CLAMP (y, 0, screen_height - h);
6629 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6630 * WM decorations. Don't try to figure out what's going
6631 * on if the mouse wasn't inside a monitor.
6633 if (monitor_num >= 0)
6635 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6636 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6644 } /* if (priv->need_default_position) */
6646 if (priv->need_default_position && info &&
6647 info->initial_pos_set)
6649 x = info->initial_x;
6650 y = info->initial_y;
6651 gtk_window_constrain_position (window, w, h, &x, &y);
6657 request->height = h;
6660 *geometry = new_geometry;
6666 gtk_window_constrain_position (GtkWindow *window,
6672 GtkWindowPrivate *priv = window->priv;
6674 /* See long comments in gtk_window_move_resize()
6675 * on when it's safe to call this function.
6677 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6679 gint center_x, center_y;
6681 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6689 gtk_window_move_resize (GtkWindow *window)
6693 * First we determine whether any information has changed that would
6694 * cause us to revise our last configure request. If we would send
6695 * a different configure request from last time, then
6696 * configure_request_size_changed = TRUE or
6697 * configure_request_pos_changed = TRUE. configure_request_size_changed
6698 * may be true due to new hints, a gtk_window_resize(), or whatever.
6699 * configure_request_pos_changed may be true due to gtk_window_set_position()
6700 * or gtk_window_move().
6702 * If the configure request has changed, we send off a new one. To
6703 * ensure GTK+ invariants are maintained (resize queue does what it
6704 * should), we go ahead and size_allocate the requested size in this
6707 * If the configure request has not changed, we don't ever resend
6708 * it, because it could mean fighting the user or window manager.
6711 * To prepare the configure request, we come up with a base size/pos:
6712 * - the one from gtk_window_move()/gtk_window_resize()
6713 * - else default_width, default_height if we haven't ever
6715 * - else the size request if we haven't ever been mapped,
6716 * as a substitute default size
6717 * - else the current size of the window, as received from
6718 * configure notifies (i.e. the current allocation)
6720 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6721 * the position request to be centered.
6723 GtkWindowPrivate *priv = window->priv;
6724 GtkAllocation allocation;
6726 GtkContainer *container;
6727 GtkWindowGeometryInfo *info;
6728 GdkGeometry new_geometry;
6729 GdkWindow *gdk_window;
6731 GdkRectangle new_request;
6732 gboolean configure_request_size_changed;
6733 gboolean configure_request_pos_changed;
6734 gboolean hints_changed; /* do we need to send these again */
6735 GtkWindowLastGeometryInfo saved_last_info;
6737 widget = GTK_WIDGET (window);
6739 gdk_window = gtk_widget_get_window (widget);
6740 container = GTK_CONTAINER (widget);
6741 info = gtk_window_get_geometry_info (window, TRUE);
6743 configure_request_size_changed = FALSE;
6744 configure_request_pos_changed = FALSE;
6746 gtk_window_compute_configure_request (window, &new_request,
6747 &new_geometry, &new_flags);
6749 /* This check implies the invariant that we never set info->last
6750 * without setting the hints and sending off a configure request.
6752 * If we change info->last without sending the request, we may
6755 if (info->last.configure_request.x != new_request.x ||
6756 info->last.configure_request.y != new_request.y)
6757 configure_request_pos_changed = TRUE;
6759 if ((info->last.configure_request.width != new_request.width ||
6760 info->last.configure_request.height != new_request.height))
6761 configure_request_size_changed = TRUE;
6763 hints_changed = FALSE;
6765 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6766 &new_geometry, new_flags))
6768 hints_changed = TRUE;
6771 /* Position Constraints
6772 * ====================
6774 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6775 * a default. The other POS_ values are used only when the
6776 * window is shown, not after that.
6778 * However, we can't implement a position constraint as
6779 * "anytime the window size changes, center the window"
6780 * because this may well end up fighting the WM or user. In
6781 * fact it gets in an infinite loop with at least one WM.
6783 * Basically, applications are in no way in a position to
6784 * constrain the position of a window, with one exception:
6785 * override redirect windows. (Really the intended purpose
6786 * of CENTER_ALWAYS anyhow, I would think.)
6788 * So the way we implement this "constraint" is to say that when WE
6789 * cause a move or resize, i.e. we make a configure request changing
6790 * window size, we recompute the CENTER_ALWAYS position to reflect
6791 * the new window size, and include it in our request. Also, if we
6792 * just turned on CENTER_ALWAYS we snap to center with a new
6793 * request. Otherwise, if we are just NOTIFIED of a move or resize
6794 * done by someone else e.g. the window manager, we do NOT send a
6795 * new configure request.
6797 * For override redirect windows, this works fine; all window
6798 * sizes are from our configure requests. For managed windows,
6799 * it is at least semi-sane, though who knows what the
6800 * app author is thinking.
6803 /* This condition should be kept in sync with the condition later on
6804 * that determines whether we send a configure request. i.e. we
6805 * should do this position constraining anytime we were going to
6806 * send a configure request anyhow, plus when constraints have
6809 if (configure_request_pos_changed ||
6810 configure_request_size_changed ||
6812 info->position_constraints_changed)
6814 /* We request the constrained position if:
6815 * - we were changing position, and need to clamp
6816 * the change to the constraint
6817 * - we're changing the size anyway
6818 * - set_position() was called to toggle CENTER_ALWAYS on
6821 gtk_window_constrain_position (window,
6827 /* Update whether we need to request a move */
6828 if (info->last.configure_request.x != new_request.x ||
6829 info->last.configure_request.y != new_request.y)
6830 configure_request_pos_changed = TRUE;
6832 configure_request_pos_changed = FALSE;
6836 if (priv->type == GTK_WINDOW_TOPLEVEL)
6838 int notify_x, notify_y;
6840 /* this is the position from the last configure notify */
6841 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6843 g_message ("--- %s ---\n"
6844 "last : %d,%d\t%d x %d\n"
6845 "this : %d,%d\t%d x %d\n"
6846 "alloc : %d,%d\t%d x %d\n"
6848 "resize: \t%d x %d\n"
6849 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6850 "configure_notify_received: %d\n"
6851 "configure_request_count: %d\n"
6852 "position_constraints_changed: %d\n",
6853 priv->title ? priv->title : "(no title)",
6854 info->last.configure_request.x,
6855 info->last.configure_request.y,
6856 info->last.configure_request.width,
6857 info->last.configure_request.height,
6863 widget->allocation.width,
6864 widget->allocation.height,
6865 widget->requisition.width,
6866 widget->requisition.height,
6868 info->resize_height,
6869 configure_request_pos_changed,
6870 configure_request_size_changed,
6872 priv->configure_notify_received,
6873 priv->configure_request_count,
6874 info->position_constraints_changed);
6878 saved_last_info = info->last;
6879 info->last.geometry = new_geometry;
6880 info->last.flags = new_flags;
6881 info->last.configure_request = new_request;
6883 /* need to set PPosition so the WM will look at our position,
6884 * but we don't want to count PPosition coming and going as a hints
6885 * change for future iterations. So we saved info->last prior to
6889 /* Also, if the initial position was explicitly set, then we always
6890 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6894 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6895 * this is an initial map
6898 if ((configure_request_pos_changed ||
6899 info->initial_pos_set ||
6900 (priv->need_default_position &&
6901 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6902 (new_flags & GDK_HINT_POS) == 0)
6904 new_flags |= GDK_HINT_POS;
6905 hints_changed = TRUE;
6908 /* Set hints if necessary
6911 gdk_window_set_geometry_hints (gdk_window,
6915 gtk_widget_get_allocation (widget, &allocation);
6917 /* handle resizing/moving and widget tree allocation
6919 if (priv->configure_notify_received)
6921 /* If we have received a configure event since
6922 * the last time in this function, we need to
6923 * accept our new size and size_allocate child widgets.
6924 * (see gtk_window_configure_event() for more details).
6926 * 1 or more configure notifies may have been received.
6927 * Also, configure_notify_received will only be TRUE
6928 * if all expected configure notifies have been received
6929 * (one per configure request), as an optimization.
6932 priv->configure_notify_received = FALSE;
6934 /* gtk_window_configure_event() filled in widget->allocation */
6935 gtk_widget_size_allocate (widget, &allocation);
6937 set_grip_position (window);
6938 update_grip_visibility (window);
6940 gdk_window_process_updates (gdk_window, TRUE);
6942 gdk_window_configure_finished (gdk_window);
6944 /* If the configure request changed, it means that
6946 * 1) coincidentally changed hints or widget properties
6947 * impacting the configure request before getting
6948 * a configure notify, or
6949 * 2) some broken widget is changing its size request
6950 * during size allocation, resulting in
6951 * a false appearance of changed configure request.
6953 * For 1), we could just go ahead and ask for the
6954 * new size right now, but doing that for 2)
6955 * might well be fighting the user (and can even
6956 * trigger a loop). Since we really don't want to
6957 * do that, we requeue a resize in hopes that
6958 * by the time it gets handled, the child has seen
6959 * the light and is willing to go along with the
6960 * new size. (this happens for the zvt widget, since
6961 * the size_allocate() above will have stored the
6962 * requisition corresponding to the new size in the
6965 * This doesn't buy us anything for 1), but it shouldn't
6966 * hurt us too badly, since it is what would have
6967 * happened if we had gotten the configure event before
6968 * the new size had been set.
6971 if (configure_request_size_changed ||
6972 configure_request_pos_changed)
6974 /* Don't change the recorded last info after all, because we
6975 * haven't actually updated to the new info yet - we decided
6976 * to postpone our configure request until later.
6978 info->last = saved_last_info;
6980 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6983 return; /* Bail out, we didn't really process the move/resize */
6985 else if ((configure_request_size_changed || hints_changed) &&
6986 (allocation.width != new_request.width || allocation.height != new_request.height))
6989 /* We are in one of the following situations:
6990 * A. configure_request_size_changed
6991 * our requisition has changed and we need a different window size,
6992 * so we request it from the window manager.
6993 * B. !configure_request_size_changed && hints_changed
6994 * the window manager rejects our size, but we have just changed the
6995 * window manager hints, so there's a chance our request will
6996 * be honoured this time, so we try again.
6998 * However, if the new requisition is the same as the current allocation,
6999 * we don't request it again, since we won't get a ConfigureNotify back from
7000 * the window manager unless it decides to change our requisition. If
7001 * we don't get the ConfigureNotify back, the resize queue will never be run.
7004 /* Now send the configure request */
7005 if (configure_request_pos_changed)
7007 gdk_window_move_resize (gdk_window,
7008 new_request.x, new_request.y,
7009 new_request.width, new_request.height);
7011 else /* only size changed */
7013 gdk_window_resize (gdk_window,
7014 new_request.width, new_request.height);
7017 if (priv->type == GTK_WINDOW_POPUP)
7019 GtkAllocation allocation;
7021 /* Directly size allocate for override redirect (popup) windows. */
7024 allocation.width = new_request.width;
7025 allocation.height = new_request.height;
7027 gtk_widget_size_allocate (widget, &allocation);
7029 gdk_window_process_updates (gdk_window, TRUE);
7031 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7032 gtk_widget_queue_draw (widget);
7036 /* Increment the number of have-not-yet-received-notify requests */
7037 priv->configure_request_count += 1;
7038 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7040 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7041 * configure event in response to our resizing request.
7042 * the configure event will cause a new resize with
7043 * ->configure_notify_received=TRUE.
7044 * until then, we want to
7045 * - discard expose events
7046 * - coalesce resizes for our children
7047 * - defer any window resizes until the configure event arrived
7048 * to achieve this, we queue a resize for the window, but remove its
7049 * resizing handler, so resizing will not be handled from the next
7050 * idle handler but when the configure event arrives.
7052 * FIXME: we should also dequeue the pending redraws here, since
7053 * we handle those ourselves upon ->configure_notify_received==TRUE.
7055 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7057 gtk_widget_queue_resize_no_redraw (widget);
7058 _gtk_container_dequeue_resize_handler (container);
7064 /* Handle any position changes.
7066 if (configure_request_pos_changed)
7068 gdk_window_move (gdk_window,
7069 new_request.x, new_request.y);
7072 /* And run the resize queue.
7074 gtk_container_resize_children (container);
7077 /* We have now processed a move/resize since the last position
7078 * constraint change, setting of the initial position, or resize.
7079 * (Not resetting these flags here can lead to infinite loops for
7080 * GTK_RESIZE_IMMEDIATE containers)
7082 info->position_constraints_changed = FALSE;
7083 info->initial_pos_set = FALSE;
7084 info->resize_width = -1;
7085 info->resize_height = -1;
7088 /* Compare two sets of Geometry hints for equality.
7091 gtk_window_compare_hints (GdkGeometry *geometry_a,
7093 GdkGeometry *geometry_b,
7096 if (flags_a != flags_b)
7099 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7100 (geometry_a->min_width != geometry_b->min_width ||
7101 geometry_a->min_height != geometry_b->min_height))
7104 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7105 (geometry_a->max_width != geometry_b->max_width ||
7106 geometry_a->max_height != geometry_b->max_height))
7109 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7110 (geometry_a->base_width != geometry_b->base_width ||
7111 geometry_a->base_height != geometry_b->base_height))
7114 if ((flags_a & GDK_HINT_ASPECT) &&
7115 (geometry_a->min_aspect != geometry_b->min_aspect ||
7116 geometry_a->max_aspect != geometry_b->max_aspect))
7119 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7120 (geometry_a->width_inc != geometry_b->width_inc ||
7121 geometry_a->height_inc != geometry_b->height_inc))
7124 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7125 geometry_a->win_gravity != geometry_b->win_gravity)
7132 _gtk_window_constrain_size (GtkWindow *window,
7138 GtkWindowPrivate *priv;
7139 GtkWindowGeometryInfo *info;
7141 g_return_if_fail (GTK_IS_WINDOW (window));
7143 priv = window->priv;
7145 info = priv->geometry_info;
7148 GdkWindowHints flags = info->last.flags;
7149 GdkGeometry *geometry = &info->last.geometry;
7151 gtk_window_constrain_size (window,
7162 gtk_window_constrain_size (GtkWindow *window,
7163 GdkGeometry *geometry,
7170 gdk_window_constrain_size (geometry, flags, width, height,
7171 new_width, new_height);
7174 /* Compute the set of geometry hints and flags for a window
7175 * based on the application set geometry, and requisition
7176 * of the window. gtk_widget_get_preferred_size() must have been
7180 gtk_window_compute_hints (GtkWindow *window,
7181 GdkGeometry *new_geometry,
7184 GtkWindowPrivate *priv = window->priv;
7186 gint extra_width = 0;
7187 gint extra_height = 0;
7188 GtkWindowGeometryInfo *geometry_info;
7189 GtkRequisition requisition;
7191 widget = GTK_WIDGET (window);
7193 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7194 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7198 *new_flags = geometry_info->mask;
7199 *new_geometry = geometry_info->geometry;
7206 if (geometry_info && geometry_info->widget)
7208 /* If the geometry widget is set, then the hints really apply to that
7209 * widget. This is pretty much meaningless unless the window layout
7210 * is such that the rest of the window adds fixed size borders to
7211 * the geometry widget. Our job is to figure the size of the borders;
7212 * We do that by asking how big the toplevel would be if the
7213 * geometry widget was *really big*.
7216 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7217 * |GGGGG B| in the border can confuse things
7223 * |AAAAAAAAA | When the geometry widget is large, things are
7224 * |GGGGGGGGGGB| clearer.
7229 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7230 GtkRequisition requisition;
7231 int current_width, current_height;
7233 _gtk_widget_override_size_request (geometry_info->widget,
7234 TEMPORARY_SIZE, TEMPORARY_SIZE,
7235 ¤t_width, ¤t_height);
7236 gtk_widget_get_preferred_size (widget,
7237 &requisition, NULL);
7238 _gtk_widget_restore_size_request (geometry_info->widget,
7239 current_width, current_height);
7241 extra_width = requisition.width - TEMPORARY_SIZE;
7242 extra_height = requisition.height - TEMPORARY_SIZE;
7244 if (extra_width < 0 || extra_width < 0)
7246 g_warning("Toplevel size doesn't seem to directly depend on the "
7247 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7248 "The geometry widget might not be in the window, or it might not "
7249 "be packed into the window appropriately");
7250 extra_width = MAX(extra_width, 0);
7251 extra_height = MAX(extra_height, 0);
7253 #undef TEMPORARY_SIZE
7256 /* We don't want to set GDK_HINT_POS in here, we just set it
7257 * in gtk_window_move_resize() when we want the position
7261 if (*new_flags & GDK_HINT_BASE_SIZE)
7263 new_geometry->base_width += extra_width;
7264 new_geometry->base_height += extra_height;
7268 /* For simplicity, we always set the base hint, even when we
7269 * don't expect it to have any visible effect.
7270 * (Note: geometry_size_to_pixels() depends on this.)
7272 *new_flags |= GDK_HINT_BASE_SIZE;
7274 new_geometry->base_width = extra_width;
7275 new_geometry->base_height = extra_height;
7277 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7278 * base size is the minimum size */
7279 if (*new_flags & GDK_HINT_MIN_SIZE)
7281 if (new_geometry->min_width > 0)
7282 new_geometry->base_width += new_geometry->min_width;
7283 if (new_geometry->min_height > 0)
7284 new_geometry->base_height += new_geometry->min_height;
7288 if (*new_flags & GDK_HINT_MIN_SIZE)
7290 if (new_geometry->min_width < 0)
7291 new_geometry->min_width = requisition.width;
7293 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7295 if (new_geometry->min_height < 0)
7296 new_geometry->min_height = requisition.height;
7298 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7302 *new_flags |= GDK_HINT_MIN_SIZE;
7304 new_geometry->min_width = requisition.width;
7305 new_geometry->min_height = requisition.height;
7308 if (*new_flags & GDK_HINT_MAX_SIZE)
7310 if (new_geometry->max_width < 0)
7311 new_geometry->max_width = requisition.width;
7313 new_geometry->max_width += extra_width;
7315 if (new_geometry->max_height < 0)
7316 new_geometry->max_height = requisition.height;
7318 new_geometry->max_height += extra_height;
7320 else if (!priv->resizable)
7322 *new_flags |= GDK_HINT_MAX_SIZE;
7324 new_geometry->max_width = requisition.width;
7325 new_geometry->max_height = requisition.height;
7328 *new_flags |= GDK_HINT_WIN_GRAVITY;
7329 new_geometry->win_gravity = priv->gravity;
7332 /***********************
7333 * Redrawing functions *
7334 ***********************/
7337 gtk_window_draw (GtkWidget *widget,
7340 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7341 GtkStyleContext *context;
7342 gboolean ret = FALSE;
7344 context = gtk_widget_get_style_context (widget);
7346 gtk_style_context_save (context);
7348 if (!gtk_widget_get_app_paintable (widget))
7350 GtkStateFlags state;
7352 state = gtk_widget_get_state_flags (widget);
7354 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7355 state |= GTK_STATE_FLAG_FOCUSED;
7357 gtk_style_context_set_state (context, state);
7358 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7359 gtk_render_background (context, cr, 0, 0,
7360 gtk_widget_get_allocated_width (widget),
7361 gtk_widget_get_allocated_height (widget));
7364 gtk_style_context_restore (context);
7366 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7367 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7369 if (priv->grip_window != NULL &&
7370 gtk_cairo_should_draw_window (cr, priv->grip_window))
7374 gtk_style_context_save (context);
7377 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7378 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7380 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7381 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7382 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7385 gtk_style_context_restore (context);
7392 * gtk_window_present:
7393 * @window: a #GtkWindow
7395 * Presents a window to the user. This may mean raising the window
7396 * in the stacking order, deiconifying it, moving it to the current
7397 * desktop, and/or giving it the keyboard focus, possibly dependent
7398 * on the user's platform, window manager, and preferences.
7400 * If @window is hidden, this function calls gtk_widget_show()
7403 * This function should be used when the user tries to open a window
7404 * that's already open. Say for example the preferences dialog is
7405 * currently open, and the user chooses Preferences from the menu
7406 * a second time; use gtk_window_present() to move the already-open dialog
7407 * where the user can see it.
7409 * If you are calling this function in response to a user interaction,
7410 * it is preferable to use gtk_window_present_with_time().
7414 gtk_window_present (GtkWindow *window)
7416 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7420 * gtk_window_present_with_time:
7421 * @window: a #GtkWindow
7422 * @timestamp: the timestamp of the user interaction (typically a
7423 * button or key press event) which triggered this call
7425 * Presents a window to the user in response to a user interaction.
7426 * If you need to present a window without a timestamp, use
7427 * gtk_window_present(). See gtk_window_present() for details.
7432 gtk_window_present_with_time (GtkWindow *window,
7436 GdkWindow *gdk_window;
7438 g_return_if_fail (GTK_IS_WINDOW (window));
7440 widget = GTK_WIDGET (window);
7442 if (gtk_widget_get_visible (widget))
7444 gdk_window = gtk_widget_get_window (widget);
7446 g_assert (gdk_window != NULL);
7448 gdk_window_show (gdk_window);
7450 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7451 if (timestamp == GDK_CURRENT_TIME)
7453 #ifdef GDK_WINDOWING_X11
7454 GdkDisplay *display;
7456 display = gtk_widget_get_display (GTK_WIDGET (window));
7457 timestamp = gdk_x11_display_get_user_time (display);
7459 timestamp = gtk_get_current_event_time ();
7463 gdk_window_focus (gdk_window, timestamp);
7467 gtk_widget_show (widget);
7472 * gtk_window_iconify:
7473 * @window: a #GtkWindow
7475 * Asks to iconify (i.e. minimize) the specified @window. Note that
7476 * you shouldn't assume the window is definitely iconified afterward,
7477 * because other entities (e.g. the user or <link
7478 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7479 * again, or there may not be a window manager in which case
7480 * iconification isn't possible, etc. But normally the window will end
7481 * up iconified. Just don't write code that crashes if not.
7483 * It's permitted to call this function before showing a window,
7484 * in which case the window will be iconified before it ever appears
7487 * You can track iconification via the "window-state-event" signal
7492 gtk_window_iconify (GtkWindow *window)
7494 GtkWindowPrivate *priv;
7496 GdkWindow *toplevel;
7498 g_return_if_fail (GTK_IS_WINDOW (window));
7500 priv = window->priv;
7501 widget = GTK_WIDGET (window);
7503 priv->iconify_initially = TRUE;
7505 toplevel = gtk_widget_get_window (widget);
7507 if (toplevel != NULL)
7508 gdk_window_iconify (toplevel);
7512 * gtk_window_deiconify:
7513 * @window: a #GtkWindow
7515 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7516 * that you shouldn't assume the window is definitely deiconified
7517 * afterward, because other entities (e.g. the user or <link
7518 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7519 * again before your code which assumes deiconification gets to run.
7521 * You can track iconification via the "window-state-event" signal
7525 gtk_window_deiconify (GtkWindow *window)
7527 GtkWindowPrivate *priv;
7529 GdkWindow *toplevel;
7531 g_return_if_fail (GTK_IS_WINDOW (window));
7533 priv = window->priv;
7534 widget = GTK_WIDGET (window);
7536 priv->iconify_initially = FALSE;
7538 toplevel = gtk_widget_get_window (widget);
7540 if (toplevel != NULL)
7541 gdk_window_deiconify (toplevel);
7546 * @window: a #GtkWindow
7548 * Asks to stick @window, which means that it will appear on all user
7549 * desktops. Note that you shouldn't assume the window is definitely
7550 * stuck afterward, because other entities (e.g. the user or <link
7551 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7552 * again, and some window managers do not support sticking
7553 * windows. But normally the window will end up stuck. Just don't
7554 * write code that crashes if not.
7556 * It's permitted to call this function before showing a window.
7558 * You can track stickiness via the "window-state-event" signal
7563 gtk_window_stick (GtkWindow *window)
7565 GtkWindowPrivate *priv;
7567 GdkWindow *toplevel;
7569 g_return_if_fail (GTK_IS_WINDOW (window));
7571 priv = window->priv;
7572 widget = GTK_WIDGET (window);
7574 priv->stick_initially = TRUE;
7576 toplevel = gtk_widget_get_window (widget);
7578 if (toplevel != NULL)
7579 gdk_window_stick (toplevel);
7583 * gtk_window_unstick:
7584 * @window: a #GtkWindow
7586 * Asks to unstick @window, which means that it will appear on only
7587 * one of the user's desktops. Note that you shouldn't assume the
7588 * window is definitely unstuck afterward, because other entities
7589 * (e.g. the user or <link linkend="gtk-X11-arch">window
7590 * manager</link>) could stick it again. But normally the window will
7591 * end up stuck. Just don't write code that crashes if not.
7593 * You can track stickiness via the "window-state-event" signal
7598 gtk_window_unstick (GtkWindow *window)
7600 GtkWindowPrivate *priv;
7602 GdkWindow *toplevel;
7604 g_return_if_fail (GTK_IS_WINDOW (window));
7606 priv = window->priv;
7607 widget = GTK_WIDGET (window);
7609 priv->stick_initially = FALSE;
7611 toplevel = gtk_widget_get_window (widget);
7613 if (toplevel != NULL)
7614 gdk_window_unstick (toplevel);
7618 * gtk_window_maximize:
7619 * @window: a #GtkWindow
7621 * Asks to maximize @window, so that it becomes full-screen. Note that
7622 * you shouldn't assume the window is definitely maximized afterward,
7623 * because other entities (e.g. the user or <link
7624 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7625 * again, and not all window managers support maximization. But
7626 * normally the window will end up maximized. Just don't write code
7627 * that crashes if not.
7629 * It's permitted to call this function before showing a window,
7630 * in which case the window will be maximized when it appears onscreen
7633 * You can track maximization via the "window-state-event" signal
7638 gtk_window_maximize (GtkWindow *window)
7640 GtkWindowPrivate *priv;
7642 GdkWindow *toplevel;
7644 g_return_if_fail (GTK_IS_WINDOW (window));
7646 priv = window->priv;
7647 widget = GTK_WIDGET (window);
7649 priv->maximize_initially = TRUE;
7651 toplevel = gtk_widget_get_window (widget);
7653 if (toplevel != NULL)
7654 gdk_window_maximize (toplevel);
7658 * gtk_window_unmaximize:
7659 * @window: a #GtkWindow
7661 * Asks to unmaximize @window. Note that you shouldn't assume the
7662 * window is definitely unmaximized afterward, because other entities
7663 * (e.g. the user or <link linkend="gtk-X11-arch">window
7664 * manager</link>) could maximize it again, and not all window
7665 * managers honor requests to unmaximize. But normally the window will
7666 * end up unmaximized. Just don't write code that crashes if not.
7668 * You can track maximization via the "window-state-event" signal
7673 gtk_window_unmaximize (GtkWindow *window)
7675 GtkWindowPrivate *priv;
7677 GdkWindow *toplevel;
7679 g_return_if_fail (GTK_IS_WINDOW (window));
7681 priv = window->priv;
7682 widget = GTK_WIDGET (window);
7684 priv->maximize_initially = FALSE;
7686 toplevel = gtk_widget_get_window (widget);
7688 if (toplevel != NULL)
7689 gdk_window_unmaximize (toplevel);
7693 * gtk_window_fullscreen:
7694 * @window: a #GtkWindow
7696 * Asks to place @window in the fullscreen state. Note that you
7697 * shouldn't assume the window is definitely full screen afterward,
7698 * because other entities (e.g. the user or <link
7699 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7700 * again, and not all window managers honor requests to fullscreen
7701 * windows. But normally the window will end up fullscreen. Just
7702 * don't write code that crashes if not.
7704 * You can track the fullscreen state via the "window-state-event" signal
7710 gtk_window_fullscreen (GtkWindow *window)
7712 GtkWindowPrivate *priv;
7714 GdkWindow *toplevel;
7716 g_return_if_fail (GTK_IS_WINDOW (window));
7718 priv = window->priv;
7719 widget = GTK_WIDGET (window);
7721 priv->fullscreen_initially = TRUE;
7723 toplevel = gtk_widget_get_window (widget);
7725 if (toplevel != NULL)
7726 gdk_window_fullscreen (toplevel);
7730 * gtk_window_unfullscreen:
7731 * @window: a #GtkWindow
7733 * Asks to toggle off the fullscreen state for @window. Note that you
7734 * shouldn't assume the window is definitely not full screen
7735 * afterward, because other entities (e.g. the user or <link
7736 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7737 * again, and not all window managers honor requests to unfullscreen
7738 * windows. But normally the window will end up restored to its normal
7739 * state. Just don't write code that crashes if not.
7741 * You can track the fullscreen state via the "window-state-event" signal
7747 gtk_window_unfullscreen (GtkWindow *window)
7750 GdkWindow *toplevel;
7751 GtkWindowPrivate *priv;
7753 g_return_if_fail (GTK_IS_WINDOW (window));
7755 priv = window->priv;
7756 widget = GTK_WIDGET (window);
7758 priv->fullscreen_initially = FALSE;
7760 toplevel = gtk_widget_get_window (widget);
7762 if (toplevel != NULL)
7763 gdk_window_unfullscreen (toplevel);
7767 * gtk_window_set_keep_above:
7768 * @window: a #GtkWindow
7769 * @setting: whether to keep @window above other windows
7771 * Asks to keep @window above, so that it stays on top. Note that
7772 * you shouldn't assume the window is definitely above afterward,
7773 * because other entities (e.g. the user or <link
7774 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7775 * and not all window managers support keeping windows above. But
7776 * normally the window will end kept above. Just don't write code
7777 * that crashes if not.
7779 * It's permitted to call this function before showing a window,
7780 * in which case the window will be kept above when it appears onscreen
7783 * You can track the above state via the "window-state-event" signal
7786 * Note that, according to the <ulink
7787 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7788 * Manager Hints</ulink> specification, the above state is mainly meant
7789 * for user preferences and should not be used by applications e.g. for
7790 * drawing attention to their dialogs.
7795 gtk_window_set_keep_above (GtkWindow *window,
7799 GtkWindowPrivate *priv;
7800 GdkWindow *toplevel;
7802 g_return_if_fail (GTK_IS_WINDOW (window));
7804 priv = window->priv;
7805 widget = GTK_WIDGET (window);
7807 priv->above_initially = setting != FALSE;
7809 priv->below_initially = FALSE;
7811 toplevel = gtk_widget_get_window (widget);
7813 if (toplevel != NULL)
7814 gdk_window_set_keep_above (toplevel, setting);
7818 * gtk_window_set_keep_below:
7819 * @window: a #GtkWindow
7820 * @setting: whether to keep @window below other windows
7822 * Asks to keep @window below, so that it stays in bottom. Note that
7823 * you shouldn't assume the window is definitely below afterward,
7824 * because other entities (e.g. the user or <link
7825 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7826 * and not all window managers support putting windows below. But
7827 * normally the window will be kept below. Just don't write code
7828 * that crashes if not.
7830 * It's permitted to call this function before showing a window,
7831 * in which case the window will be kept below when it appears onscreen
7834 * You can track the below state via the "window-state-event" signal
7837 * Note that, according to the <ulink
7838 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7839 * Manager Hints</ulink> specification, the above state is mainly meant
7840 * for user preferences and should not be used by applications e.g. for
7841 * drawing attention to their dialogs.
7846 gtk_window_set_keep_below (GtkWindow *window,
7850 GtkWindowPrivate *priv;
7851 GdkWindow *toplevel;
7853 g_return_if_fail (GTK_IS_WINDOW (window));
7855 priv = window->priv;
7856 widget = GTK_WIDGET (window);
7858 priv->below_initially = setting != FALSE;
7860 priv->above_initially = FALSE;
7862 toplevel = gtk_widget_get_window (widget);
7864 if (toplevel != NULL)
7865 gdk_window_set_keep_below (toplevel, setting);
7869 * gtk_window_set_resizable:
7870 * @window: a #GtkWindow
7871 * @resizable: %TRUE if the user can resize this window
7873 * Sets whether the user can resize a window. Windows are user resizable
7877 gtk_window_set_resizable (GtkWindow *window,
7880 GtkWindowPrivate *priv;
7882 g_return_if_fail (GTK_IS_WINDOW (window));
7884 priv = window->priv;
7886 resizable = (resizable != FALSE);
7888 if (priv->resizable != resizable)
7890 priv->resizable = (resizable != FALSE);
7892 update_grip_visibility (window);
7894 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7896 g_object_notify (G_OBJECT (window), "resizable");
7901 * gtk_window_get_resizable:
7902 * @window: a #GtkWindow
7904 * Gets the value set by gtk_window_set_resizable().
7906 * Return value: %TRUE if the user can resize the window
7909 gtk_window_get_resizable (GtkWindow *window)
7911 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7913 return window->priv->resizable;
7917 * gtk_window_set_gravity:
7918 * @window: a #GtkWindow
7919 * @gravity: window gravity
7921 * Window gravity defines the meaning of coordinates passed to
7922 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7925 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7926 * typically "do what you mean."
7930 gtk_window_set_gravity (GtkWindow *window,
7933 GtkWindowPrivate *priv;
7935 g_return_if_fail (GTK_IS_WINDOW (window));
7937 priv = window->priv;
7939 if (gravity != priv->gravity)
7941 priv->gravity = gravity;
7943 /* gtk_window_move_resize() will adapt gravity
7945 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7947 g_object_notify (G_OBJECT (window), "gravity");
7952 * gtk_window_get_gravity:
7953 * @window: a #GtkWindow
7955 * Gets the value set by gtk_window_set_gravity().
7957 * Return value: (transfer none): window gravity
7960 gtk_window_get_gravity (GtkWindow *window)
7962 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7964 return window->priv->gravity;
7968 * gtk_window_begin_resize_drag:
7969 * @window: a #GtkWindow
7970 * @button: mouse button that initiated the drag
7971 * @edge: position of the resize control
7972 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7973 * @root_y: Y position where the user clicked to initiate the drag
7974 * @timestamp: timestamp from the click event that initiated the drag
7976 * Starts resizing a window. This function is used if an application
7977 * has window resizing controls. When GDK can support it, the resize
7978 * will be done using the standard mechanism for the <link
7979 * linkend="gtk-X11-arch">window manager</link> or windowing
7980 * system. Otherwise, GDK will try to emulate window resizing,
7981 * potentially not all that well, depending on the windowing system.
7985 gtk_window_begin_resize_drag (GtkWindow *window,
7992 GtkWindowPrivate *priv;
7994 GdkWindow *toplevel;
7996 g_return_if_fail (GTK_IS_WINDOW (window));
7997 widget = GTK_WIDGET (window);
7998 g_return_if_fail (gtk_widget_get_visible (widget));
8000 priv = window->priv;
8002 toplevel = gtk_widget_get_window (widget);
8004 gdk_window_begin_resize_drag (toplevel,
8011 * gtk_window_begin_move_drag:
8012 * @window: a #GtkWindow
8013 * @button: mouse button that initiated the drag
8014 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8015 * @root_y: Y position where the user clicked to initiate the drag
8016 * @timestamp: timestamp from the click event that initiated the drag
8018 * Starts moving a window. This function is used if an application has
8019 * window movement grips. When GDK can support it, the window movement
8020 * will be done using the standard mechanism for the <link
8021 * linkend="gtk-X11-arch">window manager</link> or windowing
8022 * system. Otherwise, GDK will try to emulate window movement,
8023 * potentially not all that well, depending on the windowing system.
8027 gtk_window_begin_move_drag (GtkWindow *window,
8033 GtkWindowPrivate *priv;
8035 GdkWindow *toplevel;
8037 g_return_if_fail (GTK_IS_WINDOW (window));
8038 widget = GTK_WIDGET (window);
8039 g_return_if_fail (gtk_widget_get_visible (widget));
8041 priv = window->priv;
8043 toplevel = gtk_widget_get_window (widget);
8045 gdk_window_begin_move_drag (toplevel,
8052 * gtk_window_set_screen:
8053 * @window: a #GtkWindow.
8054 * @screen: a #GdkScreen.
8056 * Sets the #GdkScreen where the @window is displayed; if
8057 * the window is already mapped, it will be unmapped, and
8058 * then remapped on the new screen.
8063 gtk_window_set_screen (GtkWindow *window,
8066 GtkWindowPrivate *priv;
8068 GdkScreen *previous_screen;
8069 gboolean was_mapped;
8071 g_return_if_fail (GTK_IS_WINDOW (window));
8072 g_return_if_fail (GDK_IS_SCREEN (screen));
8074 priv = window->priv;
8076 if (screen == priv->screen)
8079 widget = GTK_WIDGET (window);
8081 previous_screen = priv->screen;
8082 was_mapped = gtk_widget_get_mapped (widget);
8085 gtk_widget_unmap (widget);
8086 if (gtk_widget_get_realized (widget))
8087 gtk_widget_unrealize (widget);
8089 gtk_window_free_key_hash (window);
8090 priv->screen = screen;
8091 gtk_widget_reset_rc_styles (widget);
8092 if (screen != previous_screen)
8094 g_signal_handlers_disconnect_by_func (previous_screen,
8095 gtk_window_on_composited_changed, window);
8096 g_signal_connect (screen, "composited-changed",
8097 G_CALLBACK (gtk_window_on_composited_changed), window);
8099 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8100 _gtk_widget_propagate_composited_changed (widget);
8102 g_object_notify (G_OBJECT (window), "screen");
8105 gtk_widget_map (widget);
8109 gtk_window_on_composited_changed (GdkScreen *screen,
8112 gtk_widget_queue_draw (GTK_WIDGET (window));
8114 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8118 gtk_window_check_screen (GtkWindow *window)
8120 GtkWindowPrivate *priv = window->priv;
8123 return priv->screen;
8126 g_warning ("Screen for GtkWindow not set; you must always set\n"
8127 "a screen for a GtkWindow before using the window");
8133 * gtk_window_get_screen:
8134 * @window: a #GtkWindow.
8136 * Returns the #GdkScreen associated with @window.
8138 * Return value: (transfer none): a #GdkScreen.
8143 gtk_window_get_screen (GtkWindow *window)
8145 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8147 return window->priv->screen;
8151 * gtk_window_is_active:
8152 * @window: a #GtkWindow
8154 * Returns whether the window is part of the current active toplevel.
8155 * (That is, the toplevel window receiving keystrokes.)
8156 * The return value is %TRUE if the window is active toplevel
8157 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8158 * You might use this function if you wanted to draw a widget
8159 * differently in an active window from a widget in an inactive window.
8160 * See gtk_window_has_toplevel_focus()
8162 * Return value: %TRUE if the window part of the current active window.
8167 gtk_window_is_active (GtkWindow *window)
8169 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8171 return window->priv->is_active;
8175 * gtk_window_has_toplevel_focus:
8176 * @window: a #GtkWindow
8178 * Returns whether the input focus is within this GtkWindow.
8179 * For real toplevel windows, this is identical to gtk_window_is_active(),
8180 * but for embedded windows, like #GtkPlug, the results will differ.
8182 * Return value: %TRUE if the input focus is within this GtkWindow
8187 gtk_window_has_toplevel_focus (GtkWindow *window)
8189 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8191 return window->priv->has_toplevel_focus;
8194 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8197 gtk_window_group_init (GtkWindowGroup *group)
8199 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8200 GTK_TYPE_WINDOW_GROUP,
8201 GtkWindowGroupPrivate);
8205 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8207 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8211 * gtk_window_group_new:
8213 * Creates a new #GtkWindowGroup object. Grabs added with
8214 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8216 * Return value: a new #GtkWindowGroup.
8219 gtk_window_group_new (void)
8221 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8225 window_group_cleanup_grabs (GtkWindowGroup *group,
8228 GtkWindowGroupPrivate *priv;
8229 GtkDeviceGrabInfo *info;
8231 GSList *to_remove = NULL;
8235 tmp_list = priv->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 tmp_list = priv->device_grabs;
8254 info = tmp_list->data;
8256 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8257 to_remove = g_slist_prepend (to_remove, info);
8259 tmp_list = tmp_list->next;
8264 info = to_remove->data;
8266 gtk_device_grab_remove (info->widget, info->device);
8267 to_remove = g_slist_delete_link (to_remove, to_remove);
8272 * gtk_window_group_add_window:
8273 * @window_group: a #GtkWindowGroup
8274 * @window: the #GtkWindow to add
8276 * Adds a window to a #GtkWindowGroup.
8279 gtk_window_group_add_window (GtkWindowGroup *window_group,
8282 GtkWindowPrivate *priv;
8284 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8285 g_return_if_fail (GTK_IS_WINDOW (window));
8287 priv = window->priv;
8289 if (priv->group != window_group)
8291 g_object_ref (window);
8292 g_object_ref (window_group);
8295 gtk_window_group_remove_window (priv->group, window);
8297 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8299 priv->group = window_group;
8301 g_object_unref (window);
8306 * gtk_window_group_remove_window:
8307 * @window_group: a #GtkWindowGroup
8308 * @window: the #GtkWindow to remove
8310 * Removes a window from a #GtkWindowGroup.
8313 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8316 GtkWindowPrivate *priv;
8318 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8319 g_return_if_fail (GTK_IS_WINDOW (window));
8320 priv = window->priv;
8321 g_return_if_fail (priv->group == window_group);
8323 g_object_ref (window);
8325 window_group_cleanup_grabs (window_group, window);
8328 g_object_unref (window_group);
8329 g_object_unref (window);
8333 * gtk_window_group_list_windows:
8334 * @window_group: a #GtkWindowGroup
8336 * Returns a list of the #GtkWindows that belong to @window_group.
8338 * Returns: (element-type GtkWindow) (transfer container): A
8339 * newly-allocated list of windows inside the group.
8344 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8346 GList *toplevels, *toplevel, *group_windows;
8348 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8350 group_windows = NULL;
8351 toplevels = gtk_window_list_toplevels ();
8353 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8355 GtkWindow *window = toplevel->data;
8357 if (window_group == window->priv->group)
8358 group_windows = g_list_prepend (group_windows, window);
8361 g_list_free (toplevels);
8363 return g_list_reverse (group_windows);
8367 * gtk_window_get_group:
8368 * @window: (allow-none): a #GtkWindow, or %NULL
8370 * Returns the group for @window or the default group, if
8371 * @window is %NULL or if @window does not have an explicit
8374 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8379 gtk_window_get_group (GtkWindow *window)
8381 if (window && window->priv->group)
8382 return window->priv->group;
8385 static GtkWindowGroup *default_group = NULL;
8388 default_group = gtk_window_group_new ();
8390 return default_group;
8395 * gtk_window_has_group:
8396 * @window: a #GtkWindow
8398 * Returns whether @window has an explicit window group.
8400 * Return value: %TRUE if @window has an explicit window group.
8405 gtk_window_has_group (GtkWindow *window)
8407 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8409 return window->priv->group != NULL;
8413 * gtk_window_group_get_current_grab:
8414 * @window_group: a #GtkWindowGroup
8416 * Gets the current grab widget of the given group,
8417 * see gtk_grab_add().
8419 * Returns: (transfer none): the current grab widget of the group
8424 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8426 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8428 if (window_group->priv->grabs)
8429 return GTK_WIDGET (window_group->priv->grabs->data);
8434 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8437 GtkWindowGroupPrivate *priv;
8439 priv = window_group->priv;
8440 priv->grabs = g_slist_prepend (priv->grabs, widget);
8444 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8447 GtkWindowGroupPrivate *priv;
8449 priv = window_group->priv;
8450 priv->grabs = g_slist_remove (priv->grabs, widget);
8455 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8458 gboolean block_others)
8460 GtkWindowGroupPrivate *priv;
8461 GtkDeviceGrabInfo *info;
8463 priv = window_group->priv;
8465 info = g_slice_new0 (GtkDeviceGrabInfo);
8466 info->widget = widget;
8467 info->device = device;
8468 info->block_others = block_others;
8470 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8474 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8478 GtkWindowGroupPrivate *priv;
8479 GtkDeviceGrabInfo *info;
8480 GSList *list, *node = NULL;
8481 GdkDevice *other_device;
8483 priv = window_group->priv;
8484 other_device = gdk_device_get_associated_device (device);
8485 list = priv->device_grabs;
8491 if (info->widget == widget &&
8492 (info->device == device ||
8493 info->device == other_device))
8506 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8507 g_slice_free (GtkDeviceGrabInfo, info);
8512 * gtk_window_group_get_current_device_grab:
8513 * @window_group: a #GtkWindowGroup
8514 * @device: a #GdkDevice
8516 * Returns the current grab widget for @device, or %NULL if none.
8518 * Returns: (transfer none): The grab widget, or %NULL
8523 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8526 GtkWindowGroupPrivate *priv;
8527 GtkDeviceGrabInfo *info;
8528 GdkDevice *other_device;
8531 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8532 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8534 priv = window_group->priv;
8535 list = priv->device_grabs;
8536 other_device = gdk_device_get_associated_device (device);
8543 if (info->device == device ||
8544 info->device == other_device)
8545 return info->widget;
8552 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8556 GtkWindowGroupPrivate *priv;
8557 GtkDeviceGrabInfo *info;
8558 GdkDevice *other_device;
8561 priv = window_group->priv;
8562 other_device = gdk_device_get_associated_device (device);
8563 list = priv->device_grabs;
8570 /* Look for blocking grabs on other device pairs
8571 * that have the passed widget within the GTK+ grab.
8573 if (info->block_others &&
8574 info->device != device &&
8575 info->device != other_device &&
8576 (info->widget == widget ||
8577 gtk_widget_is_ancestor (widget, info->widget)))
8585 Derived from XParseGeometry() in XFree86
8587 Copyright 1985, 1986, 1987,1998 The Open Group
8589 All Rights Reserved.
8591 The above copyright notice and this permission notice shall be included
8592 in all copies or substantial portions of the Software.
8594 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8595 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8596 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8597 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8598 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8599 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8600 OTHER DEALINGS IN THE SOFTWARE.
8602 Except as contained in this notice, the name of The Open Group shall
8603 not be used in advertising or otherwise to promote the sale, use or
8604 other dealings in this Software without prior written authorization
8605 from The Open Group.
8610 * XParseGeometry parses strings of the form
8611 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8612 * width, height, xoffset, and yoffset are unsigned integers.
8613 * Example: "=80x24+300-49"
8614 * The equal sign is optional.
8615 * It returns a bitmask that indicates which of the four values
8616 * were actually found in the string. For each value found,
8617 * the corresponding argument is updated; for each value
8618 * not found, the corresponding argument is left unchanged.
8621 /* The following code is from Xlib, and is minimally modified, so we
8622 * can track any upstream changes if required. Don't change this
8623 * code. Or if you do, put in a huge comment marking which thing
8628 read_int (gchar *string,
8636 else if (*string == '-')
8642 for (; (*string >= '0') && (*string <= '9'); string++)
8644 result = (result * 10) + (*string - '0');
8656 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8657 * value (x, y, width, height) was found in the parsed string.
8659 #define NoValue 0x0000
8660 #define XValue 0x0001
8661 #define YValue 0x0002
8662 #define WidthValue 0x0004
8663 #define HeightValue 0x0008
8664 #define AllValues 0x000F
8665 #define XNegative 0x0010
8666 #define YNegative 0x0020
8668 /* Try not to reformat/modify, so we can compare/sync with X sources */
8670 gtk_XParseGeometry (const char *string,
8673 unsigned int *width,
8674 unsigned int *height)
8678 unsigned int tempWidth, tempHeight;
8680 char *nextCharacter;
8682 /* These initializations are just to silence gcc */
8688 if ( (string == NULL) || (*string == '\0')) return(mask);
8690 string++; /* ignore possible '=' at beg of geometry spec */
8692 strind = (char *)string;
8693 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8694 tempWidth = read_int(strind, &nextCharacter);
8695 if (strind == nextCharacter)
8697 strind = nextCharacter;
8701 if (*strind == 'x' || *strind == 'X') {
8703 tempHeight = read_int(strind, &nextCharacter);
8704 if (strind == nextCharacter)
8706 strind = nextCharacter;
8707 mask |= HeightValue;
8710 if ((*strind == '+') || (*strind == '-')) {
8711 if (*strind == '-') {
8713 tempX = -read_int(strind, &nextCharacter);
8714 if (strind == nextCharacter)
8716 strind = nextCharacter;
8722 tempX = read_int(strind, &nextCharacter);
8723 if (strind == nextCharacter)
8725 strind = nextCharacter;
8728 if ((*strind == '+') || (*strind == '-')) {
8729 if (*strind == '-') {
8731 tempY = -read_int(strind, &nextCharacter);
8732 if (strind == nextCharacter)
8734 strind = nextCharacter;
8741 tempY = read_int(strind, &nextCharacter);
8742 if (strind == nextCharacter)
8744 strind = nextCharacter;
8750 /* If strind isn't at the end of the string the it's an invalid
8751 geometry specification. */
8753 if (*strind != '\0') return (0);
8759 if (mask & WidthValue)
8761 if (mask & HeightValue)
8762 *height = tempHeight;
8767 * gtk_window_parse_geometry:
8768 * @window: a #GtkWindow
8769 * @geometry: geometry string
8771 * Parses a standard X Window System geometry string - see the
8772 * manual page for X (type 'man X') for details on this.
8773 * gtk_window_parse_geometry() does work on all GTK+ ports
8774 * including Win32 but is primarily intended for an X environment.
8776 * If either a size or a position can be extracted from the
8777 * geometry string, gtk_window_parse_geometry() returns %TRUE
8778 * and calls gtk_window_set_default_size() and/or gtk_window_move()
8779 * to resize/move the window.
8781 * If gtk_window_parse_geometry() returns %TRUE, it will also
8782 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8783 * indicating to the window manager that the size/position of
8784 * the window was user-specified. This causes most window
8785 * managers to honor the geometry.
8787 * Note that for gtk_window_parse_geometry() to work as expected, it has
8788 * to be called when the window has its "final" size, i.e. after calling
8789 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8792 * #include <gtk/gtk.h>
8795 * fill_with_content (GtkWidget *vbox)
8797 * /* fill with content... */
8801 * main (int argc, char *argv[])
8803 * GtkWidget *window, *vbox;
8804 * GdkGeometry size_hints = {
8805 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
8808 * gtk_init (&argc, &argv);
8810 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8811 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
8813 * gtk_container_add (GTK_CONTAINER (window), vbox);
8814 * fill_with_content (vbox);
8815 * gtk_widget_show_all (vbox);
8817 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
8820 * GDK_HINT_MIN_SIZE |
8821 * GDK_HINT_BASE_SIZE |
8822 * GDK_HINT_RESIZE_INC);
8826 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8827 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8830 * gtk_widget_show_all (window);
8837 * Return value: %TRUE if string was parsed successfully
8840 gtk_window_parse_geometry (GtkWindow *window,
8841 const gchar *geometry)
8843 gint result, x = 0, y = 0;
8847 gboolean size_set, pos_set;
8850 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8851 g_return_val_if_fail (geometry != NULL, FALSE);
8853 child = gtk_bin_get_child (GTK_BIN (window));
8854 if (!child || !gtk_widget_get_visible (child))
8855 g_warning ("gtk_window_parse_geometry() called on a window with no "
8856 "visible children; the window should be set up before "
8857 "gtk_window_parse_geometry() is called.");
8859 screen = gtk_window_check_screen (window);
8861 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8864 if ((result & WidthValue) || (result & HeightValue))
8866 gtk_window_set_default_size_internal (window,
8867 TRUE, result & WidthValue ? w : -1,
8868 TRUE, result & HeightValue ? h : -1,
8873 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8875 grav = GDK_GRAVITY_NORTH_WEST;
8877 if ((result & XNegative) && (result & YNegative))
8878 grav = GDK_GRAVITY_SOUTH_EAST;
8879 else if (result & XNegative)
8880 grav = GDK_GRAVITY_NORTH_EAST;
8881 else if (result & YNegative)
8882 grav = GDK_GRAVITY_SOUTH_WEST;
8884 if ((result & XValue) == 0)
8887 if ((result & YValue) == 0)
8890 if (grav == GDK_GRAVITY_SOUTH_WEST ||
8891 grav == GDK_GRAVITY_SOUTH_EAST)
8892 y = gdk_screen_get_height (screen) - h + y;
8894 if (grav == GDK_GRAVITY_SOUTH_EAST ||
8895 grav == GDK_GRAVITY_NORTH_EAST)
8896 x = gdk_screen_get_width (screen) - w + x;
8898 /* we don't let you put a window offscreen; maybe some people would
8899 * prefer to be able to, but it's kind of a bogus thing to do.
8908 if ((result & XValue) || (result & YValue))
8910 gtk_window_set_gravity (window, grav);
8911 gtk_window_move (window, x, y);
8915 if (size_set || pos_set)
8917 /* Set USSize, USPosition hints */
8918 GtkWindowGeometryInfo *info;
8920 info = gtk_window_get_geometry_info (window, TRUE);
8923 info->mask |= GDK_HINT_USER_POS;
8925 info->mask |= GDK_HINT_USER_SIZE;
8932 gtk_window_mnemonic_hash_foreach (guint keyval,
8938 GtkWindowKeysForeachFunc func;
8942 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
8946 _gtk_window_keys_foreach (GtkWindow *window,
8947 GtkWindowKeysForeachFunc func,
8951 GtkMnemonicHash *mnemonic_hash;
8955 GtkWindowKeysForeachFunc func;
8959 info.window = window;
8961 info.func_data = func_data;
8963 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8965 _gtk_mnemonic_hash_foreach (mnemonic_hash,
8966 gtk_window_mnemonic_hash_foreach, &info);
8968 groups = gtk_accel_groups_from_object (G_OBJECT (window));
8971 GtkAccelGroup *group = groups->data;
8974 for (i = 0; i < group->priv->n_accels; i++)
8976 GtkAccelKey *key = &group->priv->priv_accels[i].key;
8979 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8982 groups = groups->next;
8987 gtk_window_keys_changed (GtkWindow *window)
8989 gtk_window_free_key_hash (window);
8990 gtk_window_get_key_hash (window);
8993 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8995 struct _GtkWindowKeyEntry
8999 guint is_mnemonic : 1;
9003 window_key_entry_destroy (gpointer data)
9005 g_slice_free (GtkWindowKeyEntry, data);
9009 add_to_key_hash (GtkWindow *window,
9011 GdkModifierType modifiers,
9012 gboolean is_mnemonic,
9015 GtkKeyHash *key_hash = data;
9017 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9019 entry->keyval = keyval;
9020 entry->modifiers = modifiers;
9021 entry->is_mnemonic = is_mnemonic;
9023 /* GtkAccelGroup stores lowercased accelerators. To deal
9024 * with this, if <Shift> was specified, uppercase.
9026 if (modifiers & GDK_SHIFT_MASK)
9028 if (keyval == GDK_KEY_Tab)
9029 keyval = GDK_KEY_ISO_Left_Tab;
9031 keyval = gdk_keyval_to_upper (keyval);
9034 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9038 gtk_window_get_key_hash (GtkWindow *window)
9040 GdkScreen *screen = gtk_window_check_screen (window);
9041 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9046 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9047 (GDestroyNotify)window_key_entry_destroy);
9048 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9049 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9055 gtk_window_free_key_hash (GtkWindow *window)
9057 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9060 _gtk_key_hash_free (key_hash);
9061 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9066 * gtk_window_activate_key:
9067 * @window: a #GtkWindow
9068 * @event: a #GdkEventKey
9070 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9071 * called by the default ::key_press_event handler for toplevel windows,
9072 * however in some cases it may be useful to call this directly when
9073 * overriding the standard key handling for a toplevel window.
9075 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9080 gtk_window_activate_key (GtkWindow *window,
9083 GtkKeyHash *key_hash;
9084 GtkWindowKeyEntry *found_entry = NULL;
9085 gboolean enable_mnemonics;
9086 gboolean enable_accels;
9088 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9089 g_return_val_if_fail (event != NULL, FALSE);
9091 key_hash = gtk_window_get_key_hash (window);
9096 GSList *entries = _gtk_key_hash_lookup (key_hash,
9097 event->hardware_keycode,
9099 gtk_accelerator_get_default_mod_mask (),
9102 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9103 "gtk-enable-mnemonics", &enable_mnemonics,
9104 "gtk-enable-accels", &enable_accels,
9107 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9109 GtkWindowKeyEntry *entry = tmp_list->data;
9110 if (entry->is_mnemonic)
9112 if (enable_mnemonics)
9114 found_entry = entry;
9120 if (enable_accels && !found_entry)
9122 found_entry = entry;
9127 g_slist_free (entries);
9132 if (found_entry->is_mnemonic)
9134 if (enable_mnemonics)
9135 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9136 found_entry->modifiers);
9141 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9142 found_entry->modifiers);
9150 window_update_has_focus (GtkWindow *window)
9152 GtkWindowPrivate *priv = window->priv;
9153 GtkWidget *widget = GTK_WIDGET (window);
9154 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9156 if (has_focus != priv->has_focus)
9158 priv->has_focus = has_focus;
9162 if (priv->focus_widget &&
9163 priv->focus_widget != widget &&
9164 !gtk_widget_has_focus (priv->focus_widget))
9165 do_focus_change (priv->focus_widget, TRUE);
9169 if (priv->focus_widget &&
9170 priv->focus_widget != widget &&
9171 gtk_widget_has_focus (priv->focus_widget))
9172 do_focus_change (priv->focus_widget, FALSE);
9178 * _gtk_window_set_is_active:
9179 * @window: a #GtkWindow
9180 * @is_active: %TRUE if the window is in the currently active toplevel
9182 * Internal function that sets whether the #GtkWindow is part
9183 * of the currently active toplevel window (taking into account inter-process
9187 _gtk_window_set_is_active (GtkWindow *window,
9190 GtkWindowPrivate *priv;
9192 g_return_if_fail (GTK_IS_WINDOW (window));
9194 priv = window->priv;
9196 is_active = is_active != FALSE;
9198 if (is_active != priv->is_active)
9200 priv->is_active = is_active;
9201 window_update_has_focus (window);
9203 g_object_notify (G_OBJECT (window), "is-active");
9208 * _gtk_window_set_is_toplevel:
9209 * @window: a #GtkWindow
9210 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9211 * child of the root window); %FALSE if it is not (for example, for an
9212 * in-process, parented GtkPlug)
9214 * Internal function used by #GtkPlug when it gets parented/unparented by a
9215 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9216 * global list of toplevel windows.
9219 _gtk_window_set_is_toplevel (GtkWindow *window,
9220 gboolean is_toplevel)
9223 GtkWidget *toplevel;
9224 gboolean was_anchored;
9226 widget = GTK_WIDGET (window);
9228 if (gtk_widget_is_toplevel (widget))
9229 g_assert (g_slist_find (toplevel_list, window) != NULL);
9231 g_assert (g_slist_find (toplevel_list, window) == NULL);
9233 if (is_toplevel == gtk_widget_is_toplevel (widget))
9236 was_anchored = _gtk_widget_get_anchored (widget);
9240 /* Pass through regular pathways of an embedded toplevel
9241 * to go through unmapping and hiding the widget before
9242 * becomming a toplevel again.
9244 * We remain hidden after becomming toplevel in order to
9245 * avoid problems during an embedded toplevel's dispose cycle
9246 * (When a toplevel window is shown it tries to grab focus again,
9247 * this causes problems while disposing).
9249 gtk_widget_hide (widget);
9251 /* Save the toplevel this widget was previously anchored into before
9252 * propagating a hierarchy-changed.
9254 * Usually this happens by way of gtk_widget_unparent() and we are
9255 * already unanchored at this point, just adding this clause incase
9256 * things happen differently.
9258 toplevel = gtk_widget_get_toplevel (widget);
9259 if (!gtk_widget_is_toplevel (toplevel))
9262 _gtk_widget_set_is_toplevel (widget, TRUE);
9264 /* When a window becomes toplevel after being embedded and anchored
9265 * into another window we need to unset it's anchored flag so that
9266 * the hierarchy changed signal kicks in properly.
9268 _gtk_widget_set_anchored (widget, FALSE);
9269 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
9271 toplevel_list = g_slist_prepend (toplevel_list, window);
9275 _gtk_widget_set_is_toplevel (widget, FALSE);
9276 toplevel_list = g_slist_remove (toplevel_list, window);
9278 _gtk_widget_propagate_hierarchy_changed (widget, widget);
9283 * _gtk_window_set_has_toplevel_focus:
9284 * @window: a #GtkWindow
9285 * @has_toplevel_focus: %TRUE if the in
9287 * Internal function that sets whether the keyboard focus for the
9288 * toplevel window (taking into account inter-process embedding.)
9291 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9292 gboolean has_toplevel_focus)
9294 GtkWindowPrivate *priv;
9296 g_return_if_fail (GTK_IS_WINDOW (window));
9298 priv = window->priv;
9300 has_toplevel_focus = has_toplevel_focus != FALSE;
9302 if (has_toplevel_focus != priv->has_toplevel_focus)
9304 priv->has_toplevel_focus = has_toplevel_focus;
9305 window_update_has_focus (window);
9307 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9312 * gtk_window_set_auto_startup_notification:
9313 * @setting: %TRUE to automatically do startup notification
9315 * By default, after showing the first #GtkWindow, GTK+ calls
9316 * gdk_notify_startup_complete(). Call this function to disable
9317 * the automatic startup notification. You might do this if your
9318 * first window is a splash screen, and you want to delay notification
9319 * until after your real main window has been shown, for example.
9321 * In that example, you would disable startup notification
9322 * temporarily, show your splash screen, then re-enable it so that
9323 * showing the main window would automatically result in notification.
9328 gtk_window_set_auto_startup_notification (gboolean setting)
9330 disable_startup_notification = !setting;
9334 * gtk_window_get_window_type:
9335 * @window: a #GtkWindow
9337 * Gets the type of the window. See #GtkWindowType.
9339 * Return value: the type of the window
9344 gtk_window_get_window_type (GtkWindow *window)
9346 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9348 return window->priv->type;
9352 * gtk_window_get_mnemonics_visible:
9353 * @window: a #GtkWindow
9355 * Gets the value of the #GtkWindow:mnemonics-visible property.
9357 * Returns: %TRUE if mnemonics are supposed to be visible
9363 gtk_window_get_mnemonics_visible (GtkWindow *window)
9365 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9367 return window->priv->mnemonics_visible;
9371 * gtk_window_set_mnemonics_visible:
9372 * @window: a #GtkWindow
9373 * @setting: the new value
9375 * Sets the #GtkWindow:mnemonics-visible property.
9380 gtk_window_set_mnemonics_visible (GtkWindow *window,
9383 GtkWindowPrivate *priv;
9385 g_return_if_fail (GTK_IS_WINDOW (window));
9387 priv = window->priv;
9389 setting = setting != FALSE;
9391 if (priv->mnemonics_visible != setting)
9393 priv->mnemonics_visible = setting;
9394 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9397 priv->mnemonics_visible_set = TRUE;
9401 _gtk_window_get_wmclass (GtkWindow *window,
9402 gchar **wmclass_name,
9403 gchar **wmclass_class)
9405 GtkWindowPrivate *priv = window->priv;
9407 *wmclass_name = priv->wmclass_name;
9408 *wmclass_class = priv->wmclass_class;
9412 * gtk_window_set_has_user_ref_count:
9413 * @window: a #GtkWindow
9414 * @setting: the new value
9416 * Tells GTK+ whether to drop its extra reference to the window
9417 * when gtk_window_destroy() is called.
9419 * This function is only exported for the benefit of language
9420 * bindings which may need to keep the window alive until their
9421 * wrapper object is garbage collected. There is no justification
9422 * for ever calling this function in an application.
9427 gtk_window_set_has_user_ref_count (GtkWindow *window,
9430 g_return_if_fail (GTK_IS_WINDOW (window));
9432 window->priv->has_user_ref_count = setting;