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/.
36 #include "gdk/gdkkeysyms.h"
38 #include "gtkprivate.h"
40 #include "gtkwindow.h"
41 #include "gtkwindowprivate.h"
42 #include "gtkbindings.h"
43 #include "gtkkeyhash.h"
45 #include "gtkmnemonichash.h"
46 #include "gtkmenubar.h"
47 #include "gtkiconfactory.h"
48 #include "gtkicontheme.h"
49 #include "gtkmarshalers.h"
51 #include "gtkbuildable.h"
52 #include "gtkwidgetprivate.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;
114 GdkWindowTypeHint gdk_type_hint;
116 GtkApplication *application;
120 GdkWindow *grip_window;
124 gchar *wmclass_class;
132 guint keys_changed_handler;
134 guint16 configure_request_count;
136 /* The following flags are initially TRUE (before a window is mapped).
137 * They cause us to compute a configure request that involves
138 * default-only parameters. Once mapped, we set them to FALSE.
139 * Then we set them to TRUE again on unmap (for position)
140 * and on unrealize (for size).
142 guint need_default_position : 1;
143 guint need_default_size : 1;
145 guint above_initially : 1;
146 guint accept_focus : 1;
147 guint below_initially : 1;
148 guint builder_visible : 1;
149 guint configure_notify_received : 1;
152 guint destroy_with_parent : 1;
153 guint focus_on_map : 1;
154 guint fullscreen_initially : 1;
155 guint gravity : 5; /* GdkGravity */
157 guint has_user_ref_count : 1;
159 guint has_toplevel_focus : 1;
160 guint iconify_initially : 1; /* gtk_window_iconify() called before realization */
162 guint maximize_initially : 1;
163 guint mnemonics_visible : 1;
164 guint mnemonics_visible_set : 1;
166 guint opacity_set : 1;
168 guint reset_type_hint : 1;
170 guint skips_pager : 1;
171 guint skips_taskbar : 1;
172 guint stick_initially : 1;
173 guint transient_parent_group : 1;
174 guint type : 4; /* GtkWindowType */
175 guint type_hint : 3; /* GdkWindowTypeHint if the hint is
176 * one of the original eight. If not,
178 * GDK_WINDOW_TYPE_HINT_NORMAL
181 guint has_resize_grip : 1;
182 guint resize_grip_visible : 1; /* don't use, just for "resize-
183 * grip-visible" notification
211 PROP_DESTROY_WITH_PARENT,
216 PROP_SKIP_TASKBAR_HINT,
217 PROP_SKIP_PAGER_HINT,
226 PROP_HAS_RESIZE_GRIP,
227 PROP_RESIZE_GRIP_VISIBLE,
229 /* Readonly properties */
231 PROP_HAS_TOPLEVEL_FOCUS,
233 /* Writeonly properties */
236 PROP_MNEMONICS_VISIBLE,
246 guint using_default_icon : 1;
247 guint using_parent_icon : 1;
248 guint using_themed_icon : 1;
252 GdkGeometry geometry; /* Last set of geometry hints we set */
253 GdkWindowHints flags;
254 GdkRectangle configure_request;
255 } GtkWindowLastGeometryInfo;
257 struct _GtkWindowGeometryInfo
259 /* Properties that the app has set on the window
261 GdkGeometry geometry; /* Geometry hints */
263 GtkWidget *widget; /* subwidget to which hints apply */
264 /* from last gtk_window_resize () - if > 0, indicates that
265 * we should resize to this size.
270 /* From last gtk_window_move () prior to mapping -
271 * only used if initial_pos_set
276 /* Default size - used only the FIRST time we map a window,
281 /* whether to use initial_x, initial_y */
282 guint initial_pos_set : 1;
283 /* CENTER_ALWAYS or other position constraint changed since
284 * we sent the last configure request.
286 guint position_constraints_changed : 1;
288 /* if true, default_width, height should be multiplied by the
289 * increments and affect the geometry widget only
291 guint default_is_geometry : 1;
293 /* if true, resize_width, height should be multiplied by the
294 * increments and affect the geometry widget only
296 guint resize_is_geometry : 1;
298 GtkWindowLastGeometryInfo last;
302 struct _GtkDeviceGrabInfo
306 guint block_others : 1;
309 struct _GtkWindowGroupPrivate
312 GSList *device_grabs;
315 static void gtk_window_dispose (GObject *object);
316 static void gtk_window_finalize (GObject *object);
317 static void gtk_window_destroy (GtkWidget *widget);
318 static void gtk_window_show (GtkWidget *widget);
319 static void gtk_window_hide (GtkWidget *widget);
320 static void gtk_window_map (GtkWidget *widget);
321 static void gtk_window_unmap (GtkWidget *widget);
322 static void gtk_window_realize (GtkWidget *widget);
323 static void gtk_window_unrealize (GtkWidget *widget);
324 static void gtk_window_size_allocate (GtkWidget *widget,
325 GtkAllocation *allocation);
326 static gint gtk_window_event (GtkWidget *widget,
328 static gboolean gtk_window_map_event (GtkWidget *widget,
330 static gboolean gtk_window_frame_event (GtkWindow *window,
332 static gint gtk_window_configure_event (GtkWidget *widget,
333 GdkEventConfigure *event);
334 static gint gtk_window_key_press_event (GtkWidget *widget,
336 static gint gtk_window_key_release_event (GtkWidget *widget,
338 static gint gtk_window_button_press_event (GtkWidget *widget,
339 GdkEventButton *event);
340 static gint gtk_window_enter_notify_event (GtkWidget *widget,
341 GdkEventCrossing *event);
342 static gint gtk_window_leave_notify_event (GtkWidget *widget,
343 GdkEventCrossing *event);
344 static gint gtk_window_focus_in_event (GtkWidget *widget,
345 GdkEventFocus *event);
346 static gint gtk_window_focus_out_event (GtkWidget *widget,
347 GdkEventFocus *event);
348 static void gtk_window_style_updated (GtkWidget *widget);
349 static gint gtk_window_client_event (GtkWidget *widget,
350 GdkEventClient *event);
351 static gboolean gtk_window_state_event (GtkWidget *widget,
352 GdkEventWindowState *event);
353 static void gtk_window_check_resize (GtkContainer *container);
354 static gint gtk_window_focus (GtkWidget *widget,
355 GtkDirectionType direction);
356 static void gtk_window_move_focus (GtkWidget *widget,
357 GtkDirectionType dir);
358 static void gtk_window_real_set_focus (GtkWindow *window,
360 static void gtk_window_direction_changed (GtkWidget *widget,
361 GtkTextDirection prev_dir);
362 static void gtk_window_state_changed (GtkWidget *widget,
363 GtkStateType previous_state);
365 static void gtk_window_real_activate_default (GtkWindow *window);
366 static void gtk_window_real_activate_focus (GtkWindow *window);
367 static void gtk_window_keys_changed (GtkWindow *window);
368 static gint gtk_window_draw (GtkWidget *widget,
370 static void gtk_window_unset_transient_for (GtkWindow *window);
371 static void gtk_window_transient_parent_realized (GtkWidget *parent,
373 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
376 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
378 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
381 static void gtk_window_move_resize (GtkWindow *window);
382 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
384 GdkGeometry *geometry_b,
386 static void gtk_window_constrain_size (GtkWindow *window,
387 GdkGeometry *geometry,
393 static void gtk_window_constrain_position (GtkWindow *window,
398 static void gtk_window_compute_hints (GtkWindow *window,
399 GdkGeometry *new_geometry,
401 static void gtk_window_compute_configure_request (GtkWindow *window,
402 GdkRectangle *request,
403 GdkGeometry *geometry,
406 static void gtk_window_set_default_size_internal (GtkWindow *window,
407 gboolean change_width,
409 gboolean change_height,
411 gboolean is_geometry);
413 static void update_themed_icon (GtkIconTheme *theme,
415 static GList *icon_list_from_theme (GtkWidget *widget,
417 static void gtk_window_realize_icon (GtkWindow *window);
418 static void gtk_window_unrealize_icon (GtkWindow *window);
419 static void resize_grip_create_window (GtkWindow *window);
420 static void resize_grip_destroy_window (GtkWindow *window);
421 static void update_grip_visibility (GtkWindow *window);
423 static void gtk_window_notify_keys_changed (GtkWindow *window);
424 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
425 static void gtk_window_free_key_hash (GtkWindow *window);
426 static void gtk_window_on_composited_changed (GdkScreen *screen,
429 static GSList *toplevel_list = NULL;
430 static guint window_signals[LAST_SIGNAL] = { 0 };
431 static GList *default_icon_list = NULL;
432 static gchar *default_icon_name = NULL;
433 static guint default_icon_serial = 0;
434 static gboolean disable_startup_notification = FALSE;
435 static gboolean sent_startup_notification = FALSE;
437 static GQuark quark_gtk_embedded = 0;
438 static GQuark quark_gtk_window_key_hash = 0;
439 static GQuark quark_gtk_window_icon_info = 0;
440 static GQuark quark_gtk_buildable_accels = 0;
442 static GtkBuildableIface *parent_buildable_iface;
444 static void gtk_window_set_property (GObject *object,
448 static void gtk_window_get_property (GObject *object,
454 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
455 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
458 const GValue *value);
459 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
460 GtkBuilder *builder);
461 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
464 const gchar *tagname,
465 GMarkupParser *parser,
467 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
470 const gchar *tagname,
474 static void gtk_window_get_preferred_width (GtkWidget *widget,
477 static void gtk_window_get_preferred_height (GtkWidget *widget,
481 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
482 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
483 gtk_window_buildable_interface_init))
486 add_tab_bindings (GtkBindingSet *binding_set,
487 GdkModifierType modifiers,
488 GtkDirectionType direction)
490 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
492 GTK_TYPE_DIRECTION_TYPE, direction);
493 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
495 GTK_TYPE_DIRECTION_TYPE, direction);
499 add_arrow_bindings (GtkBindingSet *binding_set,
501 GtkDirectionType direction)
503 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
505 gtk_binding_entry_add_signal (binding_set, keysym, 0,
507 GTK_TYPE_DIRECTION_TYPE, direction);
508 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
510 GTK_TYPE_DIRECTION_TYPE, direction);
511 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
513 GTK_TYPE_DIRECTION_TYPE, direction);
514 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
516 GTK_TYPE_DIRECTION_TYPE, direction);
520 extract_time_from_startup_id (const gchar* startup_id)
522 gchar *timestr = g_strrstr (startup_id, "_TIME");
523 guint32 retval = GDK_CURRENT_TIME;
530 /* Skip past the "_TIME" part */
535 timestamp = g_ascii_strtoull (timestr, &end, 0);
536 if (errno == 0 && end != timestr)
544 startup_id_is_fake (const gchar* startup_id)
546 return strncmp (startup_id, "_TIME", 5) == 0;
550 gtk_window_class_init (GtkWindowClass *klass)
552 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
553 GtkWidgetClass *widget_class;
554 GtkContainerClass *container_class;
555 GtkBindingSet *binding_set;
557 widget_class = (GtkWidgetClass*) klass;
558 container_class = (GtkContainerClass*) klass;
560 quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
561 quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
562 quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
563 quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
565 gobject_class->dispose = gtk_window_dispose;
566 gobject_class->finalize = gtk_window_finalize;
568 gobject_class->set_property = gtk_window_set_property;
569 gobject_class->get_property = gtk_window_get_property;
571 widget_class->destroy = gtk_window_destroy;
572 widget_class->show = gtk_window_show;
573 widget_class->hide = gtk_window_hide;
574 widget_class->map = gtk_window_map;
575 widget_class->map_event = gtk_window_map_event;
576 widget_class->unmap = gtk_window_unmap;
577 widget_class->realize = gtk_window_realize;
578 widget_class->unrealize = gtk_window_unrealize;
579 widget_class->size_allocate = gtk_window_size_allocate;
580 widget_class->configure_event = gtk_window_configure_event;
581 widget_class->key_press_event = gtk_window_key_press_event;
582 widget_class->key_release_event = gtk_window_key_release_event;
583 widget_class->enter_notify_event = gtk_window_enter_notify_event;
584 widget_class->leave_notify_event = gtk_window_leave_notify_event;
585 widget_class->focus_in_event = gtk_window_focus_in_event;
586 widget_class->button_press_event = gtk_window_button_press_event;
587 widget_class->focus_out_event = gtk_window_focus_out_event;
588 widget_class->client_event = gtk_window_client_event;
589 widget_class->focus = gtk_window_focus;
590 widget_class->move_focus = gtk_window_move_focus;
591 widget_class->draw = gtk_window_draw;
592 widget_class->get_preferred_width = gtk_window_get_preferred_width;
593 widget_class->get_preferred_height = gtk_window_get_preferred_height;
594 widget_class->window_state_event = gtk_window_state_event;
595 widget_class->direction_changed = gtk_window_direction_changed;
596 widget_class->state_changed = gtk_window_state_changed;
597 widget_class->style_updated = gtk_window_style_updated;
599 container_class->check_resize = gtk_window_check_resize;
601 klass->set_focus = gtk_window_real_set_focus;
602 klass->frame_event = gtk_window_frame_event;
604 klass->activate_default = gtk_window_real_activate_default;
605 klass->activate_focus = gtk_window_real_activate_focus;
606 klass->keys_changed = gtk_window_keys_changed;
608 g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
611 g_object_class_install_property (gobject_class,
613 g_param_spec_enum ("type",
615 P_("The type of the window"),
616 GTK_TYPE_WINDOW_TYPE,
618 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
620 g_object_class_install_property (gobject_class,
622 g_param_spec_string ("title",
624 P_("The title of the window"),
626 GTK_PARAM_READWRITE));
628 g_object_class_install_property (gobject_class,
630 g_param_spec_string ("role",
632 P_("Unique identifier for the window to be used when restoring a session"),
634 GTK_PARAM_READWRITE));
637 * GtkWindow:startup-id:
639 * The :startup-id is a write-only property for setting window's
640 * startup notification identifier. See gtk_window_set_startup_id()
645 g_object_class_install_property (gobject_class,
647 g_param_spec_string ("startup-id",
649 P_("Unique startup identifier for the window used by startup-notification"),
651 GTK_PARAM_WRITABLE));
653 g_object_class_install_property (gobject_class,
655 g_param_spec_boolean ("resizable",
657 P_("If TRUE, users can resize the window"),
659 GTK_PARAM_READWRITE));
661 g_object_class_install_property (gobject_class,
663 g_param_spec_boolean ("modal",
665 P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
667 GTK_PARAM_READWRITE));
669 g_object_class_install_property (gobject_class,
671 g_param_spec_enum ("window-position",
672 P_("Window Position"),
673 P_("The initial position of the window"),
674 GTK_TYPE_WINDOW_POSITION,
676 GTK_PARAM_READWRITE));
678 g_object_class_install_property (gobject_class,
680 g_param_spec_int ("default-width",
682 P_("The default width of the window, used when initially showing the window"),
686 GTK_PARAM_READWRITE));
688 g_object_class_install_property (gobject_class,
690 g_param_spec_int ("default-height",
691 P_("Default Height"),
692 P_("The default height of the window, used when initially showing the window"),
696 GTK_PARAM_READWRITE));
698 g_object_class_install_property (gobject_class,
699 PROP_DESTROY_WITH_PARENT,
700 g_param_spec_boolean ("destroy-with-parent",
701 P_("Destroy with Parent"),
702 P_("If this window should be destroyed when the parent is destroyed"),
704 GTK_PARAM_READWRITE));
706 g_object_class_install_property (gobject_class,
708 g_param_spec_object ("icon",
710 P_("Icon for this window"),
712 GTK_PARAM_READWRITE));
713 g_object_class_install_property (gobject_class,
714 PROP_MNEMONICS_VISIBLE,
715 g_param_spec_boolean ("mnemonics-visible",
716 P_("Mnemonics Visible"),
717 P_("Whether mnemonics are currently visible in this window"),
719 GTK_PARAM_READWRITE));
722 * GtkWindow:icon-name:
724 * The :icon-name property specifies the name of the themed icon to
725 * use as the window icon. See #GtkIconTheme for more details.
729 g_object_class_install_property (gobject_class,
731 g_param_spec_string ("icon-name",
733 P_("Name of the themed icon for this window"),
735 GTK_PARAM_READWRITE));
737 g_object_class_install_property (gobject_class,
739 g_param_spec_object ("screen",
741 P_("The screen where this window will be displayed"),
743 GTK_PARAM_READWRITE));
745 g_object_class_install_property (gobject_class,
747 g_param_spec_boolean ("is-active",
749 P_("Whether the toplevel is the current active window"),
751 GTK_PARAM_READABLE));
753 g_object_class_install_property (gobject_class,
754 PROP_HAS_TOPLEVEL_FOCUS,
755 g_param_spec_boolean ("has-toplevel-focus",
756 P_("Focus in Toplevel"),
757 P_("Whether the input focus is within this GtkWindow"),
759 GTK_PARAM_READABLE));
761 g_object_class_install_property (gobject_class,
763 g_param_spec_enum ("type-hint",
765 P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
766 GDK_TYPE_WINDOW_TYPE_HINT,
767 GDK_WINDOW_TYPE_HINT_NORMAL,
768 GTK_PARAM_READWRITE));
770 g_object_class_install_property (gobject_class,
771 PROP_SKIP_TASKBAR_HINT,
772 g_param_spec_boolean ("skip-taskbar-hint",
774 P_("TRUE if the window should not be in the task bar."),
776 GTK_PARAM_READWRITE));
778 g_object_class_install_property (gobject_class,
779 PROP_SKIP_PAGER_HINT,
780 g_param_spec_boolean ("skip-pager-hint",
782 P_("TRUE if the window should not be in the pager."),
784 GTK_PARAM_READWRITE));
786 g_object_class_install_property (gobject_class,
788 g_param_spec_boolean ("urgency-hint",
790 P_("TRUE if the window should be brought to the user's attention."),
792 GTK_PARAM_READWRITE));
795 * GtkWindow:accept-focus:
797 * Whether the window should receive the input focus.
801 g_object_class_install_property (gobject_class,
803 g_param_spec_boolean ("accept-focus",
805 P_("TRUE if the window should receive the input focus."),
807 GTK_PARAM_READWRITE));
810 * GtkWindow:focus-on-map:
812 * Whether the window should receive the input focus when mapped.
816 g_object_class_install_property (gobject_class,
818 g_param_spec_boolean ("focus-on-map",
820 P_("TRUE if the window should receive the input focus when mapped."),
822 GTK_PARAM_READWRITE));
825 * GtkWindow:decorated:
827 * Whether the window should be decorated by the window manager.
831 g_object_class_install_property (gobject_class,
833 g_param_spec_boolean ("decorated",
835 P_("Whether the window should be decorated by the window manager"),
837 GTK_PARAM_READWRITE));
840 * GtkWindow:deletable:
842 * Whether the window frame should have a close button.
846 g_object_class_install_property (gobject_class,
848 g_param_spec_boolean ("deletable",
850 P_("Whether the window frame should have a close button"),
852 GTK_PARAM_READWRITE));
855 * GtkWindow:has-resize-grip
857 * Whether the window has a corner resize grip.
859 * Note that the resize grip is only shown if the window is
860 * actually resizable and not maximized. Use
861 * #GtkWindow:resize-grip-visible to find out if the resize
862 * grip is currently shown.
866 g_object_class_install_property (gobject_class,
867 PROP_HAS_RESIZE_GRIP,
868 g_param_spec_boolean ("has-resize-grip",
870 P_("Specifies whether the window should have a resize grip"),
872 GTK_PARAM_READWRITE));
875 * GtkWindow: resize-grip-visible:
877 * Whether a corner resize grip is currently shown.
881 g_object_class_install_property (gobject_class,
882 PROP_RESIZE_GRIP_VISIBLE,
883 g_param_spec_boolean ("resize-grip-visible",
884 P_("Resize grip is visible"),
885 P_("Specifies whether the window's resize grip is visible."),
887 GTK_PARAM_READABLE));
893 * The window gravity of the window. See gtk_window_move() and #GdkGravity for
894 * more details about window gravity.
898 g_object_class_install_property (gobject_class,
900 g_param_spec_enum ("gravity",
902 P_("The window gravity of the window"),
904 GDK_GRAVITY_NORTH_WEST,
905 GTK_PARAM_READWRITE));
909 * GtkWindow:transient-for:
911 * The transient parent of the window. See gtk_window_set_transient_for() for
912 * more details about transient windows.
916 g_object_class_install_property (gobject_class,
918 g_param_spec_object ("transient-for",
919 P_("Transient for Window"),
920 P_("The transient parent of the dialog"),
922 GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
927 * The requested opacity of the window. See gtk_window_set_opacity() for
928 * more details about window opacity.
932 g_object_class_install_property (gobject_class,
934 g_param_spec_double ("opacity",
935 P_("Opacity for Window"),
936 P_("The opacity of the window, from 0 to 1"),
940 GTK_PARAM_READWRITE));
944 gtk_widget_class_install_style_property (widget_class,
945 g_param_spec_int ("resize-grip-width",
946 P_("Width of resize grip"),
947 P_("Width of resize grip"),
948 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
950 gtk_widget_class_install_style_property (widget_class,
951 g_param_spec_int ("resize-grip-height",
952 P_("Height of resize grip"),
953 P_("Height of resize grip"),
954 0, G_MAXINT, 16, GTK_PARAM_READWRITE));
960 * GtkWindow:application:
962 * The #GtkApplication associated with the window.
964 * The application will be kept alive for at least as long as the
969 g_object_class_install_property (gobject_class,
971 g_param_spec_object ("application",
972 P_("GtkApplication"),
973 P_("The GtkApplication for the window"),
974 GTK_TYPE_APPLICATION,
975 GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
977 window_signals[SET_FOCUS] =
978 g_signal_new (I_("set-focus"),
979 G_TYPE_FROM_CLASS (gobject_class),
981 G_STRUCT_OFFSET (GtkWindowClass, set_focus),
983 _gtk_marshal_VOID__OBJECT,
987 window_signals[FRAME_EVENT] =
988 g_signal_new (I_("frame-event"),
989 G_TYPE_FROM_CLASS (gobject_class),
991 G_STRUCT_OFFSET(GtkWindowClass, frame_event),
992 _gtk_boolean_handled_accumulator, NULL,
993 _gtk_marshal_BOOLEAN__BOXED,
998 * GtkWindow::activate-focus:
999 * @window: the window which received the signal
1001 * The ::activate-focus signal is a
1002 * <link linkend="keybinding-signals">keybinding signal</link>
1003 * which gets emitted when the user activates the currently
1004 * focused widget of @window.
1006 window_signals[ACTIVATE_FOCUS] =
1007 g_signal_new (I_("activate-focus"),
1008 G_TYPE_FROM_CLASS (gobject_class),
1009 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1010 G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
1012 _gtk_marshal_VOID__VOID,
1017 * GtkWindow::activate-default:
1018 * @window: the window which received the signal
1020 * The ::activate-default signal is a
1021 * <link linkend="keybinding-signals">keybinding signal</link>
1022 * which gets emitted when the user activates the default widget
1025 window_signals[ACTIVATE_DEFAULT] =
1026 g_signal_new (I_("activate-default"),
1027 G_TYPE_FROM_CLASS (gobject_class),
1028 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1029 G_STRUCT_OFFSET (GtkWindowClass, activate_default),
1031 _gtk_marshal_VOID__VOID,
1036 * GtkWindow::keys-changed:
1037 * @window: the window which received the signal
1039 * The ::keys-changed signal gets emitted when the set of accelerators
1040 * or mnemonics that are associated with @window changes.
1042 window_signals[KEYS_CHANGED] =
1043 g_signal_new (I_("keys-changed"),
1044 G_TYPE_FROM_CLASS (gobject_class),
1046 G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
1048 _gtk_marshal_VOID__VOID,
1056 binding_set = gtk_binding_set_by_class (klass);
1058 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1059 "activate-focus", 0);
1060 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1061 "activate-focus", 0);
1063 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1064 "activate-default", 0);
1065 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1066 "activate-default", 0);
1067 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1068 "activate-default", 0);
1070 add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
1071 add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
1072 add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
1073 add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
1075 add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
1076 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
1077 add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1078 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1082 gtk_window_init (GtkWindow *window)
1084 GtkWindowPrivate *priv;
1086 window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
1089 priv = window->priv;
1091 gtk_widget_set_has_window (GTK_WIDGET (window), TRUE);
1092 _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE);
1094 _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE);
1096 gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
1099 priv->wmclass_name = g_strdup (g_get_prgname ());
1100 priv->wmclass_class = g_strdup (gdk_get_program_class ());
1101 priv->wm_role = NULL;
1102 priv->geometry_info = NULL;
1103 priv->type = GTK_WINDOW_TOPLEVEL;
1104 priv->focus_widget = NULL;
1105 priv->default_widget = NULL;
1106 priv->configure_request_count = 0;
1107 priv->resizable = TRUE;
1108 priv->configure_notify_received = FALSE;
1109 priv->position = GTK_WIN_POS_NONE;
1110 priv->need_default_size = TRUE;
1111 priv->need_default_position = TRUE;
1112 priv->modal = FALSE;
1114 priv->has_frame = FALSE;
1115 priv->frame_left = 0;
1116 priv->frame_right = 0;
1117 priv->frame_top = 0;
1118 priv->frame_bottom = 0;
1119 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1120 priv->gravity = GDK_GRAVITY_NORTH_WEST;
1121 priv->decorated = TRUE;
1122 priv->mnemonic_modifier = GDK_MOD1_MASK;
1123 priv->screen = gdk_screen_get_default ();
1125 priv->accept_focus = TRUE;
1126 priv->focus_on_map = TRUE;
1127 priv->deletable = TRUE;
1128 priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
1129 priv->opacity = 1.0;
1130 priv->startup_id = NULL;
1131 priv->has_resize_grip = TRUE;
1132 priv->mnemonics_visible = TRUE;
1134 g_object_ref_sink (window);
1135 priv->has_user_ref_count = TRUE;
1136 toplevel_list = g_slist_prepend (toplevel_list, window);
1138 g_signal_connect (priv->screen, "composited-changed",
1139 G_CALLBACK (gtk_window_on_composited_changed), window);
1143 gtk_window_set_property (GObject *object,
1145 const GValue *value,
1148 GtkWindow *window = GTK_WINDOW (object);
1149 GtkWindowPrivate *priv = window->priv;
1154 priv->type = g_value_get_enum (value);
1157 gtk_window_set_title (window, g_value_get_string (value));
1160 gtk_window_set_role (window, g_value_get_string (value));
1162 case PROP_STARTUP_ID:
1163 gtk_window_set_startup_id (window, g_value_get_string (value));
1165 case PROP_RESIZABLE:
1166 gtk_window_set_resizable (window, g_value_get_boolean (value));
1169 gtk_window_set_modal (window, g_value_get_boolean (value));
1172 gtk_window_set_position (window, g_value_get_enum (value));
1174 case PROP_DEFAULT_WIDTH:
1175 gtk_window_set_default_size_internal (window,
1176 TRUE, g_value_get_int (value),
1179 case PROP_DEFAULT_HEIGHT:
1180 gtk_window_set_default_size_internal (window,
1182 TRUE, g_value_get_int (value), FALSE);
1184 case PROP_DESTROY_WITH_PARENT:
1185 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1188 gtk_window_set_icon (window,
1189 g_value_get_object (value));
1191 case PROP_ICON_NAME:
1192 gtk_window_set_icon_name (window, g_value_get_string (value));
1195 gtk_window_set_screen (window, g_value_get_object (value));
1197 case PROP_TYPE_HINT:
1198 gtk_window_set_type_hint (window,
1199 g_value_get_enum (value));
1201 case PROP_SKIP_TASKBAR_HINT:
1202 gtk_window_set_skip_taskbar_hint (window,
1203 g_value_get_boolean (value));
1205 case PROP_SKIP_PAGER_HINT:
1206 gtk_window_set_skip_pager_hint (window,
1207 g_value_get_boolean (value));
1209 case PROP_URGENCY_HINT:
1210 gtk_window_set_urgency_hint (window,
1211 g_value_get_boolean (value));
1213 case PROP_ACCEPT_FOCUS:
1214 gtk_window_set_accept_focus (window,
1215 g_value_get_boolean (value));
1217 case PROP_FOCUS_ON_MAP:
1218 gtk_window_set_focus_on_map (window,
1219 g_value_get_boolean (value));
1221 case PROP_DECORATED:
1222 gtk_window_set_decorated (window, g_value_get_boolean (value));
1224 case PROP_DELETABLE:
1225 gtk_window_set_deletable (window, g_value_get_boolean (value));
1228 gtk_window_set_gravity (window, g_value_get_enum (value));
1230 case PROP_TRANSIENT_FOR:
1231 gtk_window_set_transient_for (window, g_value_get_object (value));
1234 gtk_window_set_opacity (window, g_value_get_double (value));
1236 case PROP_HAS_RESIZE_GRIP:
1237 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1239 case PROP_APPLICATION:
1240 gtk_window_set_application (window, g_value_get_object (value));
1242 case PROP_MNEMONICS_VISIBLE:
1243 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1246 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1252 gtk_window_get_property (GObject *object,
1257 GtkWindow *window = GTK_WINDOW (object);
1258 GtkWindowPrivate *priv = window->priv;
1262 GtkWindowGeometryInfo *info;
1264 g_value_set_enum (value, priv->type);
1267 g_value_set_string (value, priv->wm_role);
1270 g_value_set_string (value, priv->title);
1272 case PROP_RESIZABLE:
1273 g_value_set_boolean (value, priv->resizable);
1276 g_value_set_boolean (value, priv->modal);
1279 g_value_set_enum (value, priv->position);
1281 case PROP_DEFAULT_WIDTH:
1282 info = gtk_window_get_geometry_info (window, FALSE);
1284 g_value_set_int (value, -1);
1286 g_value_set_int (value, info->default_width);
1288 case PROP_DEFAULT_HEIGHT:
1289 info = gtk_window_get_geometry_info (window, FALSE);
1291 g_value_set_int (value, -1);
1293 g_value_set_int (value, info->default_height);
1295 case PROP_DESTROY_WITH_PARENT:
1296 g_value_set_boolean (value, priv->destroy_with_parent);
1299 g_value_set_object (value, gtk_window_get_icon (window));
1301 case PROP_ICON_NAME:
1302 g_value_set_string (value, gtk_window_get_icon_name (window));
1305 g_value_set_object (value, priv->screen);
1307 case PROP_IS_ACTIVE:
1308 g_value_set_boolean (value, priv->is_active);
1310 case PROP_HAS_TOPLEVEL_FOCUS:
1311 g_value_set_boolean (value, priv->has_toplevel_focus);
1313 case PROP_TYPE_HINT:
1314 g_value_set_enum (value, priv->type_hint);
1316 case PROP_SKIP_TASKBAR_HINT:
1317 g_value_set_boolean (value,
1318 gtk_window_get_skip_taskbar_hint (window));
1320 case PROP_SKIP_PAGER_HINT:
1321 g_value_set_boolean (value,
1322 gtk_window_get_skip_pager_hint (window));
1324 case PROP_URGENCY_HINT:
1325 g_value_set_boolean (value,
1326 gtk_window_get_urgency_hint (window));
1328 case PROP_ACCEPT_FOCUS:
1329 g_value_set_boolean (value,
1330 gtk_window_get_accept_focus (window));
1332 case PROP_FOCUS_ON_MAP:
1333 g_value_set_boolean (value,
1334 gtk_window_get_focus_on_map (window));
1336 case PROP_DECORATED:
1337 g_value_set_boolean (value, gtk_window_get_decorated (window));
1339 case PROP_DELETABLE:
1340 g_value_set_boolean (value, gtk_window_get_deletable (window));
1343 g_value_set_enum (value, gtk_window_get_gravity (window));
1345 case PROP_TRANSIENT_FOR:
1346 g_value_set_object (value, gtk_window_get_transient_for (window));
1349 g_value_set_double (value, gtk_window_get_opacity (window));
1351 case PROP_HAS_RESIZE_GRIP:
1352 g_value_set_boolean (value, priv->has_resize_grip);
1354 case PROP_RESIZE_GRIP_VISIBLE:
1355 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1357 case PROP_APPLICATION:
1358 g_value_set_object (value, gtk_window_get_application (window));
1360 case PROP_MNEMONICS_VISIBLE:
1361 g_value_set_boolean (value, priv->mnemonics_visible);
1364 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1370 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1372 parent_buildable_iface = g_type_interface_peek_parent (iface);
1373 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1374 iface->parser_finished = gtk_window_buildable_parser_finished;
1375 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1376 iface->custom_finished = gtk_window_buildable_custom_finished;
1380 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1381 GtkBuilder *builder,
1383 const GValue *value)
1385 GtkWindow *window = GTK_WINDOW (buildable);
1386 GtkWindowPrivate *priv = window->priv;
1388 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1389 priv->builder_visible = TRUE;
1391 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1395 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1396 GtkBuilder *builder)
1398 GtkWindow *window = GTK_WINDOW (buildable);
1399 GtkWindowPrivate *priv = window->priv;
1403 if (priv->builder_visible)
1404 gtk_widget_show (GTK_WIDGET (buildable));
1406 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1407 for (l = accels; l; l = l->next)
1409 object = gtk_builder_get_object (builder, l->data);
1412 g_warning ("Unknown accel group %s specified in window %s",
1413 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1416 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1417 GTK_ACCEL_GROUP (object));
1421 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1423 parent_buildable_iface->parser_finished (buildable, builder);
1429 } GSListSubParserData;
1432 window_start_element (GMarkupParseContext *context,
1433 const gchar *element_name,
1434 const gchar **names,
1435 const gchar **values,
1440 GSListSubParserData *data = (GSListSubParserData*)user_data;
1442 if (strcmp (element_name, "group") == 0)
1444 for (i = 0; names[i]; i++)
1446 if (strcmp (names[i], "name") == 0)
1447 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1450 else if (strcmp (element_name, "accel-groups") == 0)
1453 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1458 static const GMarkupParser window_parser =
1460 window_start_element
1464 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1465 GtkBuilder *builder,
1467 const gchar *tagname,
1468 GMarkupParser *parser,
1471 GSListSubParserData *parser_data;
1473 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1474 tagname, parser, data))
1477 if (strcmp (tagname, "accel-groups") == 0)
1479 parser_data = g_slice_new0 (GSListSubParserData);
1480 parser_data->items = NULL;
1481 parser_data->object = G_OBJECT (buildable);
1483 *parser = window_parser;
1484 *data = parser_data;
1492 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1493 GtkBuilder *builder,
1495 const gchar *tagname,
1498 GSListSubParserData *data;
1500 parent_buildable_iface->custom_finished (buildable, builder, child,
1501 tagname, user_data);
1503 if (strcmp (tagname, "accel-groups") != 0)
1506 data = (GSListSubParserData*)user_data;
1508 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1509 data->items, (GDestroyNotify) g_slist_free);
1511 g_slice_free (GSListSubParserData, data);
1516 * @type: type of window
1518 * Creates a new #GtkWindow, which is a toplevel window that can
1519 * contain other widgets. Nearly always, the type of the window should
1520 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1521 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1522 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1523 * dialogs, though in some other toolkits dialogs are called "popups".
1524 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1525 * On X11, popup windows are not controlled by the <link
1526 * linkend="gtk-X11-arch">window manager</link>.
1528 * If you simply want an undecorated window (no window borders), use
1529 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1531 * Return value: a new #GtkWindow.
1534 gtk_window_new (GtkWindowType type)
1536 GtkWindowPrivate *priv;
1539 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1541 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1542 priv = window->priv;
1546 return GTK_WIDGET (window);
1550 * gtk_window_set_title:
1551 * @window: a #GtkWindow
1552 * @title: title of the window
1554 * Sets the title of the #GtkWindow. The title of a window will be
1555 * displayed in its title bar; on the X Window System, the title bar
1556 * is rendered by the <link linkend="gtk-X11-arch">window
1557 * manager</link>, so exactly how the title appears to users may vary
1558 * according to a user's exact configuration. The title should help a
1559 * user distinguish this window from other windows they may have
1560 * open. A good title might include the application name and current
1561 * document filename, for example.
1565 gtk_window_set_title (GtkWindow *window,
1568 GtkWindowPrivate *priv;
1572 g_return_if_fail (GTK_IS_WINDOW (window));
1574 priv = window->priv;
1575 widget = GTK_WIDGET (window);
1577 new_title = g_strdup (title);
1578 g_free (priv->title);
1579 priv->title = new_title;
1581 if (gtk_widget_get_realized (widget))
1583 gdk_window_set_title (gtk_widget_get_window (widget),
1587 g_object_notify (G_OBJECT (window), "title");
1591 * gtk_window_get_title:
1592 * @window: a #GtkWindow
1594 * Retrieves the title of the window. See gtk_window_set_title().
1596 * Return value: the title of the window, or %NULL if none has
1597 * been set explicitely. The returned string is owned by the widget
1598 * and must not be modified or freed.
1600 G_CONST_RETURN gchar *
1601 gtk_window_get_title (GtkWindow *window)
1603 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1605 return window->priv->title;
1609 * gtk_window_set_wmclass:
1610 * @window: a #GtkWindow
1611 * @wmclass_name: window name hint
1612 * @wmclass_class: window class hint
1614 * Don't use this function. It sets the X Window System "class" and
1615 * "name" hints for a window. According to the ICCCM, you should
1616 * always set these to the same value for all windows in an
1617 * application, and GTK+ sets them to that value by default, so calling
1618 * this function is sort of pointless. However, you may want to call
1619 * gtk_window_set_role() on each window in your application, for the
1620 * benefit of the session manager. Setting the role allows the window
1621 * manager to restore window positions when loading a saved session.
1625 gtk_window_set_wmclass (GtkWindow *window,
1626 const gchar *wmclass_name,
1627 const gchar *wmclass_class)
1629 GtkWindowPrivate *priv;
1631 g_return_if_fail (GTK_IS_WINDOW (window));
1633 priv = window->priv;
1635 g_free (priv->wmclass_name);
1636 priv->wmclass_name = g_strdup (wmclass_name);
1638 g_free (priv->wmclass_class);
1639 priv->wmclass_class = g_strdup (wmclass_class);
1641 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1642 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1646 * gtk_window_set_role:
1647 * @window: a #GtkWindow
1648 * @role: unique identifier for the window to be used when restoring a session
1650 * This function is only useful on X11, not with other GTK+ targets.
1652 * In combination with the window title, the window role allows a
1653 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1654 * same" window when an application is restarted. So for example you
1655 * might set the "toolbox" role on your app's toolbox window, so that
1656 * when the user restarts their session, the window manager can put
1657 * the toolbox back in the same place.
1659 * If a window already has a unique title, you don't need to set the
1660 * role, since the WM can use the title to identify the window when
1661 * restoring the session.
1665 gtk_window_set_role (GtkWindow *window,
1668 GtkWindowPrivate *priv;
1671 g_return_if_fail (GTK_IS_WINDOW (window));
1673 priv = window->priv;
1675 new_role = g_strdup (role);
1676 g_free (priv->wm_role);
1677 priv->wm_role = new_role;
1679 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1680 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1683 g_object_notify (G_OBJECT (window), "role");
1687 * gtk_window_set_startup_id:
1688 * @window: a #GtkWindow
1689 * @startup_id: a string with startup-notification identifier
1691 * Startup notification identifiers are used by desktop environment to
1692 * track application startup, to provide user feedback and other
1693 * features. This function changes the corresponding property on the
1694 * underlying GdkWindow. Normally, startup identifier is managed
1695 * automatically and you should only use this function in special cases
1696 * like transferring focus from other processes. You should use this
1697 * function before calling gtk_window_present() or any equivalent
1698 * function generating a window map event.
1700 * This function is only useful on X11, not with other GTK+ targets.
1705 gtk_window_set_startup_id (GtkWindow *window,
1706 const gchar *startup_id)
1708 GtkWindowPrivate *priv;
1711 g_return_if_fail (GTK_IS_WINDOW (window));
1713 priv = window->priv;
1714 widget = GTK_WIDGET (window);
1716 g_free (priv->startup_id);
1717 priv->startup_id = g_strdup (startup_id);
1719 if (gtk_widget_get_realized (widget))
1721 GdkWindow *gdk_window;
1722 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1724 gdk_window = gtk_widget_get_window (widget);
1726 #ifdef GDK_WINDOWING_X11
1727 if (timestamp != GDK_CURRENT_TIME)
1728 gdk_x11_window_set_user_time (gdk_window, timestamp);
1731 /* Here we differentiate real and "fake" startup notification IDs,
1732 * constructed on purpose just to pass interaction timestamp
1734 if (startup_id_is_fake (priv->startup_id))
1735 gtk_window_present_with_time (window, timestamp);
1738 gdk_window_set_startup_id (gdk_window,
1741 /* If window is mapped, terminate the startup-notification too */
1742 if (gtk_widget_get_mapped (widget) &&
1743 !disable_startup_notification)
1744 gdk_notify_startup_complete_with_id (priv->startup_id);
1748 g_object_notify (G_OBJECT (window), "startup-id");
1752 * gtk_window_get_role:
1753 * @window: a #GtkWindow
1755 * Returns the role of the window. See gtk_window_set_role() for
1756 * further explanation.
1758 * Return value: the role of the window if set, or %NULL. The
1759 * returned is owned by the widget and must not be modified
1762 G_CONST_RETURN gchar *
1763 gtk_window_get_role (GtkWindow *window)
1765 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1767 return window->priv->wm_role;
1771 * gtk_window_set_focus:
1772 * @window: a #GtkWindow
1773 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1774 * any focus widget for the toplevel window.
1776 * If @focus is not the current focus widget, and is focusable, sets
1777 * it as the focus widget for the window. If @focus is %NULL, unsets
1778 * the focus widget for this window. To set the focus to a particular
1779 * widget in the toplevel, it is usually more convenient to use
1780 * gtk_widget_grab_focus() instead of this function.
1783 gtk_window_set_focus (GtkWindow *window,
1786 GtkWindowPrivate *priv;
1789 g_return_if_fail (GTK_IS_WINDOW (window));
1791 priv = window->priv;
1795 g_return_if_fail (GTK_IS_WIDGET (focus));
1796 g_return_if_fail (gtk_widget_get_can_focus (focus));
1800 gtk_widget_grab_focus (focus);
1803 /* Clear the existing focus chain, so that when we focus into
1804 * the window again, we start at the beginnning.
1806 GtkWidget *widget = priv->focus_widget;
1809 while ((parent = gtk_widget_get_parent (widget)))
1812 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1816 _gtk_window_internal_set_focus (window, NULL);
1821 _gtk_window_internal_set_focus (GtkWindow *window,
1824 GtkWindowPrivate *priv;
1826 g_return_if_fail (GTK_IS_WINDOW (window));
1828 priv = window->priv;
1830 if ((priv->focus_widget != focus) ||
1831 (focus && !gtk_widget_has_focus (focus)))
1832 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1836 * gtk_window_set_default:
1837 * @window: a #GtkWindow
1838 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1839 * default widget for the toplevel.
1841 * The default widget is the widget that's activated when the user
1842 * presses Enter in a dialog (for example). This function sets or
1843 * unsets the default widget for a #GtkWindow about. When setting
1844 * (rather than unsetting) the default widget it's generally easier to
1845 * call gtk_widget_grab_focus() on the widget. Before making a widget
1846 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1847 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1850 gtk_window_set_default (GtkWindow *window,
1851 GtkWidget *default_widget)
1853 GtkWindowPrivate *priv;
1855 g_return_if_fail (GTK_IS_WINDOW (window));
1857 priv = window->priv;
1860 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1862 if (priv->default_widget != default_widget)
1864 GtkWidget *old_default_widget = NULL;
1867 g_object_ref (default_widget);
1869 if (priv->default_widget)
1871 old_default_widget = priv->default_widget;
1873 if (priv->focus_widget != priv->default_widget ||
1874 !gtk_widget_get_receives_default (priv->default_widget))
1875 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1877 gtk_widget_queue_draw (priv->default_widget);
1880 priv->default_widget = default_widget;
1882 if (priv->default_widget)
1884 if (priv->focus_widget == NULL ||
1885 !gtk_widget_get_receives_default (priv->focus_widget))
1886 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1888 gtk_widget_queue_draw (priv->default_widget);
1891 if (old_default_widget)
1892 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1896 g_object_notify (G_OBJECT (default_widget), "has-default");
1897 g_object_unref (default_widget);
1903 * gtk_window_get_default_widget:
1904 * @window: a #GtkWindow
1906 * Returns the default widget for @window. See gtk_window_set_default()
1909 * Returns: (transfer none): the default widget, or %NULL if there is none.
1914 gtk_window_get_default_widget (GtkWindow *window)
1916 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1918 return window->priv->default_widget;
1922 handle_keys_changed (gpointer data)
1924 GtkWindow *window = GTK_WINDOW (data);
1925 GtkWindowPrivate *priv = window->priv;
1927 if (priv->keys_changed_handler)
1929 g_source_remove (priv->keys_changed_handler);
1930 priv->keys_changed_handler = 0;
1933 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1939 gtk_window_notify_keys_changed (GtkWindow *window)
1941 GtkWindowPrivate *priv = window->priv;
1943 if (!priv->keys_changed_handler)
1944 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1948 * gtk_window_add_accel_group:
1949 * @window: window to attach accelerator group to
1950 * @accel_group: a #GtkAccelGroup
1952 * Associate @accel_group with @window, such that calling
1953 * gtk_accel_groups_activate() on @window will activate accelerators
1957 gtk_window_add_accel_group (GtkWindow *window,
1958 GtkAccelGroup *accel_group)
1960 g_return_if_fail (GTK_IS_WINDOW (window));
1961 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1963 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1964 g_signal_connect_object (accel_group, "accel-changed",
1965 G_CALLBACK (gtk_window_notify_keys_changed),
1966 window, G_CONNECT_SWAPPED);
1967 gtk_window_notify_keys_changed (window);
1971 * gtk_window_remove_accel_group:
1972 * @window: a #GtkWindow
1973 * @accel_group: a #GtkAccelGroup
1975 * Reverses the effects of gtk_window_add_accel_group().
1978 gtk_window_remove_accel_group (GtkWindow *window,
1979 GtkAccelGroup *accel_group)
1981 g_return_if_fail (GTK_IS_WINDOW (window));
1982 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1984 g_signal_handlers_disconnect_by_func (accel_group,
1985 gtk_window_notify_keys_changed,
1987 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1988 gtk_window_notify_keys_changed (window);
1991 static GtkMnemonicHash *
1992 gtk_window_get_mnemonic_hash (GtkWindow *window,
1995 GtkWindowPrivate *private = window->priv;
1997 if (!private->mnemonic_hash && create)
1998 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2000 return private->mnemonic_hash;
2004 * gtk_window_add_mnemonic:
2005 * @window: a #GtkWindow
2006 * @keyval: the mnemonic
2007 * @target: the widget that gets activated by the mnemonic
2009 * Adds a mnemonic to this window.
2012 gtk_window_add_mnemonic (GtkWindow *window,
2016 g_return_if_fail (GTK_IS_WINDOW (window));
2017 g_return_if_fail (GTK_IS_WIDGET (target));
2019 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2021 gtk_window_notify_keys_changed (window);
2025 * gtk_window_remove_mnemonic:
2026 * @window: a #GtkWindow
2027 * @keyval: the mnemonic
2028 * @target: the widget that gets activated by the mnemonic
2030 * Removes a mnemonic from this window.
2033 gtk_window_remove_mnemonic (GtkWindow *window,
2037 g_return_if_fail (GTK_IS_WINDOW (window));
2038 g_return_if_fail (GTK_IS_WIDGET (target));
2040 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2042 gtk_window_notify_keys_changed (window);
2046 * gtk_window_mnemonic_activate:
2047 * @window: a #GtkWindow
2048 * @keyval: the mnemonic
2049 * @modifier: the modifiers
2050 * @returns: %TRUE if the activation is done.
2052 * Activates the targets associated with the mnemonic.
2055 gtk_window_mnemonic_activate (GtkWindow *window,
2057 GdkModifierType modifier)
2059 GtkWindowPrivate *priv;
2061 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2063 priv = window->priv;
2065 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2067 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2069 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2076 * gtk_window_set_mnemonic_modifier:
2077 * @window: a #GtkWindow
2078 * @modifier: the modifier mask used to activate
2079 * mnemonics on this window.
2081 * Sets the mnemonic modifier for this window.
2084 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2085 GdkModifierType modifier)
2087 GtkWindowPrivate *priv;
2089 g_return_if_fail (GTK_IS_WINDOW (window));
2090 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2092 priv = window->priv;
2094 priv->mnemonic_modifier = modifier;
2095 gtk_window_notify_keys_changed (window);
2099 * gtk_window_get_mnemonic_modifier:
2100 * @window: a #GtkWindow
2102 * Returns the mnemonic modifier for this window. See
2103 * gtk_window_set_mnemonic_modifier().
2105 * Return value: the modifier mask used to activate
2106 * mnemonics on this window.
2109 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2111 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2113 return window->priv->mnemonic_modifier;
2117 * gtk_window_set_position:
2118 * @window: a #GtkWindow.
2119 * @position: a position constraint.
2121 * Sets a position constraint for this window. If the old or new
2122 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2123 * the window to be repositioned to satisfy the new constraint.
2126 gtk_window_set_position (GtkWindow *window,
2127 GtkWindowPosition position)
2129 GtkWindowPrivate *priv;
2131 g_return_if_fail (GTK_IS_WINDOW (window));
2133 priv = window->priv;
2135 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2136 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2138 GtkWindowGeometryInfo *info;
2140 info = gtk_window_get_geometry_info (window, TRUE);
2142 /* this flag causes us to re-request the CENTER_ALWAYS
2143 * constraint in gtk_window_move_resize(), see
2144 * comment in that function.
2146 info->position_constraints_changed = TRUE;
2148 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2151 priv->position = position;
2153 g_object_notify (G_OBJECT (window), "window-position");
2157 * gtk_window_activate_focus:
2158 * @window: a #GtkWindow
2160 * Activates the current focused widget within the window.
2162 * Return value: %TRUE if a widget got activated.
2165 gtk_window_activate_focus (GtkWindow *window)
2167 GtkWindowPrivate *priv;
2169 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2171 priv = window->priv;
2173 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2174 return gtk_widget_activate (priv->focus_widget);
2180 * gtk_window_get_focus:
2181 * @window: a #GtkWindow
2183 * Retrieves the current focused widget within the window.
2184 * Note that this is the widget that would have the focus
2185 * if the toplevel window focused; if the toplevel window
2186 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2187 * not be %TRUE for the widget.
2189 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2192 gtk_window_get_focus (GtkWindow *window)
2194 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2196 return window->priv->focus_widget;
2200 * gtk_window_activate_default:
2201 * @window: a #GtkWindow
2203 * Activates the default widget for the window, unless the current
2204 * focused widget has been configured to receive the default action
2205 * (see gtk_widget_set_receives_default()), in which case the
2206 * focused widget is activated.
2208 * Return value: %TRUE if a widget got activated.
2211 gtk_window_activate_default (GtkWindow *window)
2213 GtkWindowPrivate *priv;
2215 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2217 priv = window->priv;
2219 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2220 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2221 return gtk_widget_activate (priv->default_widget);
2222 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2223 return gtk_widget_activate (priv->focus_widget);
2229 * gtk_window_set_modal:
2230 * @window: a #GtkWindow
2231 * @modal: whether the window is modal
2233 * Sets a window modal or non-modal. Modal windows prevent interaction
2234 * with other windows in the same application. To keep modal dialogs
2235 * on top of main application windows, use
2236 * gtk_window_set_transient_for() to make the dialog transient for the
2237 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2238 * will then disallow lowering the dialog below the parent.
2243 gtk_window_set_modal (GtkWindow *window,
2246 GtkWindowPrivate *priv;
2249 g_return_if_fail (GTK_IS_WINDOW (window));
2251 priv = window->priv;
2253 modal = modal != FALSE;
2254 if (priv->modal == modal)
2257 priv->modal = modal;
2258 widget = GTK_WIDGET (window);
2260 /* adjust desired modality state */
2261 if (gtk_widget_get_realized (widget))
2264 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2266 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2269 if (gtk_widget_get_visible (widget))
2272 gtk_grab_add (widget);
2274 gtk_grab_remove (widget);
2277 g_object_notify (G_OBJECT (window), "modal");
2281 * gtk_window_get_modal:
2282 * @window: a #GtkWindow
2284 * Returns whether the window is modal. See gtk_window_set_modal().
2286 * Return value: %TRUE if the window is set to be modal and
2287 * establishes a grab when shown
2290 gtk_window_get_modal (GtkWindow *window)
2292 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2294 return window->priv->modal;
2298 * gtk_window_list_toplevels:
2300 * Returns a list of all existing toplevel windows. The widgets
2301 * in the list are not individually referenced. If you want
2302 * to iterate through the list and perform actions involving
2303 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2304 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2305 * then unref all the widgets afterwards.
2307 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2310 gtk_window_list_toplevels (void)
2315 for (slist = toplevel_list; slist; slist = slist->next)
2316 list = g_list_prepend (list, slist->data);
2322 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2324 GList *embedded_windows;
2326 g_return_if_fail (GTK_IS_WINDOW (window));
2328 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2329 if (embedded_windows)
2330 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2331 embedded_windows = g_list_prepend (embedded_windows,
2332 GUINT_TO_POINTER (xid));
2334 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2337 (GDestroyNotify) g_list_free : NULL);
2341 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2343 GList *embedded_windows;
2346 g_return_if_fail (GTK_IS_WINDOW (window));
2348 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2349 if (embedded_windows)
2350 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2352 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2355 embedded_windows = g_list_remove_link (embedded_windows, node);
2356 g_list_free_1 (node);
2359 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2362 (GDestroyNotify) g_list_free : NULL);
2366 gtk_window_dispose (GObject *object)
2368 GtkWindow *window = GTK_WINDOW (object);
2370 gtk_window_set_focus (window, NULL);
2371 gtk_window_set_default (window, NULL);
2373 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2377 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2379 gtk_widget_destroy (GTK_WIDGET (child));
2383 connect_parent_destroyed (GtkWindow *window)
2385 GtkWindowPrivate *priv = window->priv;
2387 if (priv->transient_parent)
2389 g_signal_connect (priv->transient_parent,
2391 G_CALLBACK (parent_destroyed_callback),
2397 disconnect_parent_destroyed (GtkWindow *window)
2399 GtkWindowPrivate *priv = window->priv;
2401 if (priv->transient_parent)
2403 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2404 parent_destroyed_callback,
2410 gtk_window_transient_parent_realized (GtkWidget *parent,
2413 if (gtk_widget_get_realized (window))
2414 gdk_window_set_transient_for (gtk_widget_get_window (window),
2415 gtk_widget_get_window (parent));
2419 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2422 if (gtk_widget_get_realized (window))
2423 gdk_property_delete (gtk_widget_get_window (window),
2424 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2428 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2432 gtk_window_set_screen (window, parent->priv->screen);
2436 gtk_window_unset_transient_for (GtkWindow *window)
2438 GtkWindowPrivate *priv = window->priv;
2440 if (priv->transient_parent)
2442 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2443 gtk_window_transient_parent_realized,
2445 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2446 gtk_window_transient_parent_unrealized,
2448 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2449 gtk_window_transient_parent_screen_changed,
2451 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2452 gtk_widget_destroyed,
2453 &priv->transient_parent);
2455 if (priv->destroy_with_parent)
2456 disconnect_parent_destroyed (window);
2458 priv->transient_parent = NULL;
2460 if (priv->transient_parent_group)
2462 priv->transient_parent_group = FALSE;
2463 gtk_window_group_remove_window (priv->group,
2470 * gtk_window_set_transient_for:
2471 * @window: a #GtkWindow
2472 * @parent: (allow-none): parent window, or %NULL
2474 * Dialog windows should be set transient for the main application
2475 * window they were spawned from. This allows <link
2476 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2477 * dialog on top of the main window, or center the dialog over the
2478 * main window. gtk_dialog_new_with_buttons() and other convenience
2479 * functions in GTK+ will sometimes call
2480 * gtk_window_set_transient_for() on your behalf.
2482 * Passing %NULL for @parent unsets the current transient window.
2484 * On Windows, this function puts the child window on top of the parent,
2485 * much as the window manager would have done on X.
2488 gtk_window_set_transient_for (GtkWindow *window,
2491 GtkWindowPrivate *priv;
2493 g_return_if_fail (GTK_IS_WINDOW (window));
2494 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2495 g_return_if_fail (window != parent);
2497 priv = window->priv;
2499 if (priv->transient_parent)
2501 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2502 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2503 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2504 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2505 GTK_WIDGET (window));
2507 gtk_window_unset_transient_for (window);
2510 priv->transient_parent = parent;
2514 g_signal_connect (parent, "destroy",
2515 G_CALLBACK (gtk_widget_destroyed),
2516 &priv->transient_parent);
2517 g_signal_connect (parent, "realize",
2518 G_CALLBACK (gtk_window_transient_parent_realized),
2520 g_signal_connect (parent, "unrealize",
2521 G_CALLBACK (gtk_window_transient_parent_unrealized),
2523 g_signal_connect (parent, "notify::screen",
2524 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2527 gtk_window_set_screen (window, parent->priv->screen);
2529 if (priv->destroy_with_parent)
2530 connect_parent_destroyed (window);
2532 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2533 gtk_widget_get_realized (GTK_WIDGET (parent)))
2534 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2535 GTK_WIDGET (window));
2537 if (parent->priv->group)
2539 gtk_window_group_add_window (parent->priv->group, window);
2540 priv->transient_parent_group = TRUE;
2546 * gtk_window_get_transient_for:
2547 * @window: a #GtkWindow
2549 * Fetches the transient parent for this window. See
2550 * gtk_window_set_transient_for().
2552 * Return value: (transfer none): the transient parent for this window, or %NULL
2553 * if no transient parent has been set.
2556 gtk_window_get_transient_for (GtkWindow *window)
2558 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2560 return window->priv->transient_parent;
2564 * gtk_window_set_opacity:
2565 * @window: a #GtkWindow
2566 * @opacity: desired opacity, between 0 and 1
2568 * Request the windowing system to make @window partially transparent,
2569 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2570 * of the opacity parameter are clamped to the [0,1] range.) On X11
2571 * this has any effect only on X screens with a compositing manager
2572 * running. See gtk_widget_is_composited(). On Windows it should work
2575 * Note that setting a window's opacity after the window has been
2576 * shown causes it to flicker once on Windows.
2581 gtk_window_set_opacity (GtkWindow *window,
2584 GtkWindowPrivate *priv;
2586 g_return_if_fail (GTK_IS_WINDOW (window));
2588 priv = window->priv;
2592 else if (opacity > 1.0)
2595 priv->opacity_set = TRUE;
2596 priv->opacity = opacity;
2598 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2599 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2604 * gtk_window_get_opacity:
2605 * @window: a #GtkWindow
2607 * Fetches the requested opacity for this window. See
2608 * gtk_window_set_opacity().
2610 * Return value: the requested opacity for this window.
2615 gtk_window_get_opacity (GtkWindow *window)
2617 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2619 return window->priv->opacity;
2623 * gtk_window_get_application:
2624 * @window: a #GtkWindow
2626 * Gets the #GtkApplication associated with the window (if any).
2628 * Return value: a #GtkApplication, or %NULL
2633 gtk_window_get_application (GtkWindow *window)
2635 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2637 return window->priv->application;
2641 gtk_window_release_application (GtkWindow *window)
2643 if (window->priv->application)
2645 GtkApplication *application;
2647 /* steal reference into temp variable */
2648 application = window->priv->application;
2649 window->priv->application = NULL;
2651 gtk_application_remove_window (application, window);
2652 g_object_unref (application);
2657 * gtk_window_set_application:
2658 * @window: a #GtkWindow
2659 * @application: a #GtkApplication, or %NULL
2661 * Sets or unsets the #GtkApplication associated with the window.
2663 * The application will be kept alive for at least as long as the window
2669 gtk_window_set_application (GtkWindow *window,
2670 GtkApplication *application)
2672 GtkWindowPrivate *priv;
2674 g_return_if_fail (GTK_IS_WINDOW (window));
2676 priv = window->priv;
2677 if (priv->application != application)
2679 gtk_window_release_application (window);
2681 priv->application = application;
2683 if (priv->application != NULL)
2685 g_object_ref (priv->application);
2687 gtk_application_add_window (priv->application, window);
2690 g_object_notify (G_OBJECT (window), "application");
2695 * gtk_window_set_type_hint:
2696 * @window: a #GtkWindow
2697 * @hint: the window type
2699 * By setting the type hint for the window, you allow the window
2700 * manager to decorate and handle the window in a way which is
2701 * suitable to the function of the window in your application.
2703 * This function should be called before the window becomes visible.
2705 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2706 * will sometimes call gtk_window_set_type_hint() on your behalf.
2710 gtk_window_set_type_hint (GtkWindow *window,
2711 GdkWindowTypeHint hint)
2713 GtkWindowPrivate *priv;
2715 g_return_if_fail (GTK_IS_WINDOW (window));
2716 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2718 priv = window->priv;
2720 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2721 priv->gdk_type_hint = hint;
2723 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2725 priv->reset_type_hint = TRUE;
2726 priv->type_hint = hint;
2730 * gtk_window_get_type_hint:
2731 * @window: a #GtkWindow
2733 * Gets the type hint for this window. See gtk_window_set_type_hint().
2735 * Return value: the type hint for @window.
2738 gtk_window_get_type_hint (GtkWindow *window)
2740 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2742 return window->priv->type_hint;
2746 * gtk_window_set_skip_taskbar_hint:
2747 * @window: a #GtkWindow
2748 * @setting: %TRUE to keep this window from appearing in the task bar
2750 * Windows may set a hint asking the desktop environment not to display
2751 * the window in the task bar. This function sets this hint.
2756 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2759 GtkWindowPrivate *priv;
2761 g_return_if_fail (GTK_IS_WINDOW (window));
2763 priv = window->priv;
2765 setting = setting != FALSE;
2767 if (priv->skips_taskbar != setting)
2769 priv->skips_taskbar = setting;
2770 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2771 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2772 priv->skips_taskbar);
2773 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2778 * gtk_window_get_skip_taskbar_hint:
2779 * @window: a #GtkWindow
2781 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2783 * Return value: %TRUE if window shouldn't be in taskbar
2788 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2790 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2792 return window->priv->skips_taskbar;
2796 * gtk_window_set_skip_pager_hint:
2797 * @window: a #GtkWindow
2798 * @setting: %TRUE to keep this window from appearing in the pager
2800 * Windows may set a hint asking the desktop environment not to display
2801 * the window in the pager. This function sets this hint.
2802 * (A "pager" is any desktop navigation tool such as a workspace
2803 * switcher that displays a thumbnail representation of the windows
2809 gtk_window_set_skip_pager_hint (GtkWindow *window,
2812 GtkWindowPrivate *priv;
2814 g_return_if_fail (GTK_IS_WINDOW (window));
2816 priv = window->priv;
2818 setting = setting != FALSE;
2820 if (priv->skips_pager != setting)
2822 priv->skips_pager = setting;
2823 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2824 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2826 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2831 * gtk_window_get_skip_pager_hint:
2832 * @window: a #GtkWindow
2834 * Gets the value set by gtk_window_set_skip_pager_hint().
2836 * Return value: %TRUE if window shouldn't be in pager
2841 gtk_window_get_skip_pager_hint (GtkWindow *window)
2843 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2845 return window->priv->skips_pager;
2849 * gtk_window_set_urgency_hint:
2850 * @window: a #GtkWindow
2851 * @setting: %TRUE to mark this window as urgent
2853 * Windows may set a hint asking the desktop environment to draw
2854 * the users attention to the window. This function sets this hint.
2859 gtk_window_set_urgency_hint (GtkWindow *window,
2862 GtkWindowPrivate *priv;
2864 g_return_if_fail (GTK_IS_WINDOW (window));
2866 priv = window->priv;
2868 setting = setting != FALSE;
2870 if (priv->urgent != setting)
2872 priv->urgent = setting;
2873 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2874 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2876 g_object_notify (G_OBJECT (window), "urgency-hint");
2881 * gtk_window_get_urgency_hint:
2882 * @window: a #GtkWindow
2884 * Gets the value set by gtk_window_set_urgency_hint()
2886 * Return value: %TRUE if window is urgent
2891 gtk_window_get_urgency_hint (GtkWindow *window)
2893 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2895 return window->priv->urgent;
2899 * gtk_window_set_accept_focus:
2900 * @window: a #GtkWindow
2901 * @setting: %TRUE to let this window receive input focus
2903 * Windows may set a hint asking the desktop environment not to receive
2904 * the input focus. This function sets this hint.
2909 gtk_window_set_accept_focus (GtkWindow *window,
2912 GtkWindowPrivate *priv;
2914 g_return_if_fail (GTK_IS_WINDOW (window));
2916 priv = window->priv;
2918 setting = setting != FALSE;
2920 if (priv->accept_focus != setting)
2922 priv->accept_focus = setting;
2923 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2924 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2925 priv->accept_focus);
2926 g_object_notify (G_OBJECT (window), "accept-focus");
2931 * gtk_window_get_accept_focus:
2932 * @window: a #GtkWindow
2934 * Gets the value set by gtk_window_set_accept_focus().
2936 * Return value: %TRUE if window should receive the input focus
2941 gtk_window_get_accept_focus (GtkWindow *window)
2943 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2945 return window->priv->accept_focus;
2949 * gtk_window_set_focus_on_map:
2950 * @window: a #GtkWindow
2951 * @setting: %TRUE to let this window receive input focus on map
2953 * Windows may set a hint asking the desktop environment not to receive
2954 * the input focus when the window is mapped. This function sets this
2960 gtk_window_set_focus_on_map (GtkWindow *window,
2963 GtkWindowPrivate *priv;
2965 g_return_if_fail (GTK_IS_WINDOW (window));
2967 priv = window->priv;
2969 setting = setting != FALSE;
2971 if (priv->focus_on_map != setting)
2973 priv->focus_on_map = setting;
2974 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2975 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2976 priv->focus_on_map);
2977 g_object_notify (G_OBJECT (window), "focus-on-map");
2982 * gtk_window_get_focus_on_map:
2983 * @window: a #GtkWindow
2985 * Gets the value set by gtk_window_set_focus_on_map().
2987 * Return value: %TRUE if window should receive the input focus when
2993 gtk_window_get_focus_on_map (GtkWindow *window)
2995 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2997 return window->priv->focus_on_map;
3001 * gtk_window_set_destroy_with_parent:
3002 * @window: a #GtkWindow
3003 * @setting: whether to destroy @window with its transient parent
3005 * If @setting is %TRUE, then destroying the transient parent of @window
3006 * will also destroy @window itself. This is useful for dialogs that
3007 * shouldn't persist beyond the lifetime of the main window they're
3008 * associated with, for example.
3011 gtk_window_set_destroy_with_parent (GtkWindow *window,
3014 GtkWindowPrivate *priv;
3016 g_return_if_fail (GTK_IS_WINDOW (window));
3018 priv = window->priv;
3020 if (priv->destroy_with_parent == (setting != FALSE))
3023 if (priv->destroy_with_parent)
3025 disconnect_parent_destroyed (window);
3029 connect_parent_destroyed (window);
3032 priv->destroy_with_parent = setting;
3034 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3038 * gtk_window_get_destroy_with_parent:
3039 * @window: a #GtkWindow
3041 * Returns whether the window will be destroyed with its transient parent. See
3042 * gtk_window_set_destroy_with_parent ().
3044 * Return value: %TRUE if the window will be destroyed with its transient parent.
3047 gtk_window_get_destroy_with_parent (GtkWindow *window)
3049 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3051 return window->priv->destroy_with_parent;
3054 static GtkWindowGeometryInfo*
3055 gtk_window_get_geometry_info (GtkWindow *window,
3058 GtkWindowPrivate *priv = window->priv;
3059 GtkWindowGeometryInfo *info;
3061 info = priv->geometry_info;
3062 if (!info && create)
3064 info = g_new0 (GtkWindowGeometryInfo, 1);
3066 info->default_width = -1;
3067 info->default_height = -1;
3068 info->resize_width = -1;
3069 info->resize_height = -1;
3070 info->initial_x = 0;
3071 info->initial_y = 0;
3072 info->initial_pos_set = FALSE;
3073 info->default_is_geometry = FALSE;
3074 info->position_constraints_changed = FALSE;
3075 info->last.configure_request.x = 0;
3076 info->last.configure_request.y = 0;
3077 info->last.configure_request.width = -1;
3078 info->last.configure_request.height = -1;
3079 info->widget = NULL;
3081 priv->geometry_info = info;
3088 * gtk_window_set_geometry_hints:
3089 * @window: a #GtkWindow
3090 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3091 * @geometry: (allow-none): struct containing geometry information or %NULL
3092 * @geom_mask: mask indicating which struct fields should be paid attention to
3094 * This function sets up hints about how a window can be resized by
3095 * the user. You can set a minimum and maximum size; allowed resize
3096 * increments (e.g. for xterm, you can only resize by the size of a
3097 * character); aspect ratios; and more. See the #GdkGeometry struct.
3101 gtk_window_set_geometry_hints (GtkWindow *window,
3102 GtkWidget *geometry_widget,
3103 GdkGeometry *geometry,
3104 GdkWindowHints geom_mask)
3106 GtkWindowGeometryInfo *info;
3108 g_return_if_fail (GTK_IS_WINDOW (window));
3109 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3111 info = gtk_window_get_geometry_info (window, TRUE);
3114 g_signal_handlers_disconnect_by_func (info->widget,
3115 gtk_widget_destroyed,
3118 info->widget = geometry_widget;
3120 g_signal_connect (geometry_widget, "destroy",
3121 G_CALLBACK (gtk_widget_destroyed),
3125 info->geometry = *geometry;
3127 /* We store gravity in priv->gravity not in the hints. */
3128 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3130 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3132 gtk_window_set_gravity (window, geometry->win_gravity);
3135 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3139 * gtk_window_set_decorated:
3140 * @window: a #GtkWindow
3141 * @setting: %TRUE to decorate the window
3143 * By default, windows are decorated with a title bar, resize
3144 * controls, etc. Some <link linkend="gtk-X11-arch">window
3145 * managers</link> allow GTK+ to disable these decorations, creating a
3146 * borderless window. If you set the decorated property to %FALSE
3147 * using this function, GTK+ will do its best to convince the window
3148 * manager not to decorate the window. Depending on the system, this
3149 * function may not have any effect when called on a window that is
3150 * already visible, so you should call it before calling gtk_widget_show().
3152 * On Windows, this function always works, since there's no window manager
3157 gtk_window_set_decorated (GtkWindow *window,
3160 GtkWindowPrivate *priv;
3161 GdkWindow *gdk_window;
3163 g_return_if_fail (GTK_IS_WINDOW (window));
3165 priv = window->priv;
3167 setting = setting != FALSE;
3169 if (setting == priv->decorated)
3172 priv->decorated = setting;
3174 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3177 if (priv->decorated)
3178 gdk_window_set_decorations (gdk_window,
3181 gdk_window_set_decorations (gdk_window,
3185 g_object_notify (G_OBJECT (window), "decorated");
3189 * gtk_window_get_decorated:
3190 * @window: a #GtkWindow
3192 * Returns whether the window has been set to have decorations
3193 * such as a title bar via gtk_window_set_decorated().
3195 * Return value: %TRUE if the window has been set to have decorations
3198 gtk_window_get_decorated (GtkWindow *window)
3200 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3202 return window->priv->decorated;
3206 * gtk_window_set_deletable:
3207 * @window: a #GtkWindow
3208 * @setting: %TRUE to decorate the window as deletable
3210 * By default, windows have a close button in the window frame. Some
3211 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3212 * disable this button. If you set the deletable property to %FALSE
3213 * using this function, GTK+ will do its best to convince the window
3214 * manager not to show a close button. Depending on the system, this
3215 * function may not have any effect when called on a window that is
3216 * already visible, so you should call it before calling gtk_window_show().
3218 * On Windows, this function always works, since there's no window manager
3224 gtk_window_set_deletable (GtkWindow *window,
3227 GtkWindowPrivate *priv;
3228 GdkWindow *gdk_window;
3230 g_return_if_fail (GTK_IS_WINDOW (window));
3232 priv = window->priv;
3234 setting = setting != FALSE;
3236 if (setting == priv->deletable)
3239 priv->deletable = setting;
3241 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3244 if (priv->deletable)
3245 gdk_window_set_functions (gdk_window,
3248 gdk_window_set_functions (gdk_window,
3249 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3252 g_object_notify (G_OBJECT (window), "deletable");
3256 * gtk_window_get_deletable:
3257 * @window: a #GtkWindow
3259 * Returns whether the window has been set to have a close button
3260 * via gtk_window_set_deletable().
3262 * Return value: %TRUE if the window has been set to have a close button
3267 gtk_window_get_deletable (GtkWindow *window)
3269 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3271 return window->priv->deletable;
3274 static GtkWindowIconInfo*
3275 get_icon_info (GtkWindow *window)
3277 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3281 free_icon_info (GtkWindowIconInfo *info)
3283 g_free (info->icon_name);
3284 g_slice_free (GtkWindowIconInfo, info);
3288 static GtkWindowIconInfo*
3289 ensure_icon_info (GtkWindow *window)
3291 GtkWindowIconInfo *info;
3293 info = get_icon_info (window);
3297 info = g_slice_new0 (GtkWindowIconInfo);
3298 g_object_set_qdata_full (G_OBJECT (window),
3299 quark_gtk_window_icon_info,
3301 (GDestroyNotify)free_icon_info);
3308 icon_list_from_theme (GtkWidget *widget,
3313 GtkIconTheme *icon_theme;
3318 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3320 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3323 for (i = 0; sizes[i]; i++)
3326 * We need an EWMH extension to handle scalable icons
3327 * by passing their name to the WM. For now just use a
3331 icon = gtk_icon_theme_load_icon (icon_theme, name,
3334 icon = gtk_icon_theme_load_icon (icon_theme, name,
3337 list = g_list_append (list, icon);
3347 gtk_window_realize_icon (GtkWindow *window)
3349 GtkWindowPrivate *priv = window->priv;
3351 GtkWindowIconInfo *info;
3352 GdkWindow *gdk_window;
3355 widget = GTK_WIDGET (window);
3356 gdk_window = gtk_widget_get_window (widget);
3358 g_return_if_fail (gdk_window != NULL);
3360 /* no point setting an icon on override-redirect */
3361 if (priv->type == GTK_WINDOW_POPUP)
3366 info = ensure_icon_info (window);
3371 info->using_default_icon = FALSE;
3372 info->using_parent_icon = FALSE;
3373 info->using_themed_icon = FALSE;
3375 icon_list = info->icon_list;
3377 /* Look up themed icon */
3378 if (icon_list == NULL && info->icon_name)
3380 icon_list = icon_list_from_theme (widget, info->icon_name);
3382 info->using_themed_icon = TRUE;
3385 /* Inherit from transient parent */
3386 if (icon_list == NULL && priv->transient_parent)
3388 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3390 info->using_parent_icon = TRUE;
3393 /* Inherit from default */
3394 if (icon_list == NULL)
3396 icon_list = default_icon_list;
3398 info->using_default_icon = TRUE;
3401 /* Look up themed icon */
3402 if (icon_list == NULL && default_icon_name)
3404 icon_list = icon_list_from_theme (widget, default_icon_name);
3405 info->using_default_icon = TRUE;
3406 info->using_themed_icon = TRUE;
3409 info->realized = TRUE;
3411 gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
3413 if (info->using_themed_icon)
3415 GtkIconTheme *icon_theme;
3417 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3418 g_list_free (icon_list);
3420 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3421 g_signal_connect (icon_theme, "changed",
3422 G_CALLBACK (update_themed_icon), window);
3427 gtk_window_unrealize_icon (GtkWindow *window)
3429 GtkWindowIconInfo *info;
3431 info = get_icon_info (window);
3436 if (info->using_themed_icon)
3438 GtkIconTheme *icon_theme;
3440 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3442 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3445 /* We don't clear the properties on the window, just figure the
3446 * window is going away.
3449 info->realized = FALSE;
3454 * gtk_window_set_icon_list:
3455 * @window: a #GtkWindow
3456 * @list: (element-type GdkPixbuf) (transfer container): list of #GdkPixbuf
3458 * Sets up the icon representing a #GtkWindow. The icon is used when
3459 * the window is minimized (also known as iconified). Some window
3460 * managers or desktop environments may also place it in the window
3461 * frame, or display it in other contexts.
3463 * gtk_window_set_icon_list() allows you to pass in the same icon in
3464 * several hand-drawn sizes. The list should contain the natural sizes
3465 * your icon is available in; that is, don't scale the image before
3466 * passing it to GTK+. Scaling is postponed until the last minute,
3467 * when the desired final size is known, to allow best quality.
3469 * By passing several sizes, you may improve the final image quality
3470 * of the icon, by reducing or eliminating automatic image scaling.
3472 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3473 * larger images (64x64, 128x128) if you have them.
3475 * See also gtk_window_set_default_icon_list() to set the icon
3476 * for all windows in your application in one go.
3478 * Note that transient windows (those who have been set transient for another
3479 * window using gtk_window_set_transient_for()) will inherit their
3480 * icon from their transient parent. So there's no need to explicitly
3481 * set the icon on transient windows.
3484 gtk_window_set_icon_list (GtkWindow *window,
3487 GtkWindowIconInfo *info;
3489 g_return_if_fail (GTK_IS_WINDOW (window));
3491 info = ensure_icon_info (window);
3493 if (info->icon_list == list) /* check for NULL mostly */
3496 g_list_foreach (list,
3497 (GFunc) g_object_ref, NULL);
3499 g_list_foreach (info->icon_list,
3500 (GFunc) g_object_unref, NULL);
3502 g_list_free (info->icon_list);
3504 info->icon_list = g_list_copy (list);
3506 g_object_notify (G_OBJECT (window), "icon");
3508 gtk_window_unrealize_icon (window);
3510 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3511 gtk_window_realize_icon (window);
3513 /* We could try to update our transient children, but I don't think
3514 * it's really worth it. If we did it, the best way would probably
3515 * be to have children connect to notify::icon-list
3520 * gtk_window_get_icon_list:
3521 * @window: a #GtkWindow
3523 * Retrieves the list of icons set by gtk_window_set_icon_list().
3524 * The list is copied, but the reference count on each
3525 * member won't be incremented.
3527 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3530 gtk_window_get_icon_list (GtkWindow *window)
3532 GtkWindowIconInfo *info;
3534 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3536 info = get_icon_info (window);
3539 return g_list_copy (info->icon_list);
3545 * gtk_window_set_icon:
3546 * @window: a #GtkWindow
3547 * @icon: (allow-none): icon image, or %NULL
3549 * Sets up the icon representing a #GtkWindow. This icon is used when
3550 * the window is minimized (also known as iconified). Some window
3551 * managers or desktop environments may also place it in the window
3552 * frame, or display it in other contexts.
3554 * The icon should be provided in whatever size it was naturally
3555 * drawn; that is, don't scale the image before passing it to
3556 * GTK+. Scaling is postponed until the last minute, when the desired
3557 * final size is known, to allow best quality.
3559 * If you have your icon hand-drawn in multiple sizes, use
3560 * gtk_window_set_icon_list(). Then the best size will be used.
3562 * This function is equivalent to calling gtk_window_set_icon_list()
3563 * with a 1-element list.
3565 * See also gtk_window_set_default_icon_list() to set the icon
3566 * for all windows in your application in one go.
3569 gtk_window_set_icon (GtkWindow *window,
3574 g_return_if_fail (GTK_IS_WINDOW (window));
3575 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3580 list = g_list_append (list, icon);
3582 gtk_window_set_icon_list (window, list);
3588 update_themed_icon (GtkIconTheme *icon_theme,
3591 g_object_notify (G_OBJECT (window), "icon");
3593 gtk_window_unrealize_icon (window);
3595 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3596 gtk_window_realize_icon (window);
3600 * gtk_window_set_icon_name:
3601 * @window: a #GtkWindow
3602 * @name: (allow-none): the name of the themed icon
3604 * Sets the icon for the window from a named themed icon. See
3605 * the docs for #GtkIconTheme for more details.
3607 * Note that this has nothing to do with the WM_ICON_NAME
3608 * property which is mentioned in the ICCCM.
3613 gtk_window_set_icon_name (GtkWindow *window,
3616 GtkWindowIconInfo *info;
3619 g_return_if_fail (GTK_IS_WINDOW (window));
3621 info = ensure_icon_info (window);
3623 if (g_strcmp0 (info->icon_name, name) == 0)
3626 tmp = info->icon_name;
3627 info->icon_name = g_strdup (name);
3630 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3631 g_list_free (info->icon_list);
3632 info->icon_list = NULL;
3634 update_themed_icon (NULL, window);
3636 g_object_notify (G_OBJECT (window), "icon-name");
3640 * gtk_window_get_icon_name:
3641 * @window: a #GtkWindow
3643 * Returns the name of the themed icon for the window,
3644 * see gtk_window_set_icon_name().
3646 * Returns: the icon name or %NULL if the window has
3652 gtk_window_get_icon_name (GtkWindow *window)
3654 GtkWindowIconInfo *info;
3656 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3658 info = ensure_icon_info (window);
3660 return info->icon_name;
3664 * gtk_window_get_icon:
3665 * @window: a #GtkWindow
3667 * Gets the value set by gtk_window_set_icon() (or if you've
3668 * called gtk_window_set_icon_list(), gets the first icon in
3671 * Return value: (transfer none): icon for window
3674 gtk_window_get_icon (GtkWindow *window)
3676 GtkWindowIconInfo *info;
3678 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3680 info = get_icon_info (window);
3681 if (info && info->icon_list)
3682 return GDK_PIXBUF (info->icon_list->data);
3687 /* Load pixbuf, printing warning on failure if error == NULL
3690 load_pixbuf_verbosely (const char *filename,
3693 GError *local_err = NULL;
3696 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3704 g_warning ("Error loading icon from file '%s':\n\t%s",
3705 filename, local_err->message);
3706 g_error_free (local_err);
3714 * gtk_window_set_icon_from_file:
3715 * @window: a #GtkWindow
3716 * @filename: location of icon file
3717 * @err: (allow-none): location to store error, or %NULL.
3719 * Sets the icon for @window.
3720 * Warns on failure if @err is %NULL.
3722 * This function is equivalent to calling gtk_window_set_icon()
3723 * with a pixbuf created by loading the image from @filename.
3725 * Returns: %TRUE if setting the icon succeeded.
3730 gtk_window_set_icon_from_file (GtkWindow *window,
3731 const gchar *filename,
3734 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3738 gtk_window_set_icon (window, pixbuf);
3739 g_object_unref (pixbuf);
3748 * gtk_window_set_default_icon_list:
3749 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3751 * Sets an icon list to be used as fallback for windows that haven't
3752 * had gtk_window_set_icon_list() called on them to set up a
3753 * window-specific icon list. This function allows you to set up the
3754 * icon for all windows in your app at once.
3756 * See gtk_window_set_icon_list() for more details.
3760 gtk_window_set_default_icon_list (GList *list)
3764 if (list == default_icon_list)
3767 /* Update serial so we don't used cached pixmaps/masks
3769 default_icon_serial++;
3771 g_list_foreach (list,
3772 (GFunc) g_object_ref, NULL);
3774 g_list_foreach (default_icon_list,
3775 (GFunc) g_object_unref, NULL);
3777 g_list_free (default_icon_list);
3779 default_icon_list = g_list_copy (list);
3781 /* Update all toplevels */
3782 toplevels = gtk_window_list_toplevels ();
3783 tmp_list = toplevels;
3784 while (tmp_list != NULL)
3786 GtkWindowIconInfo *info;
3787 GtkWindow *w = tmp_list->data;
3789 info = get_icon_info (w);
3790 if (info && info->using_default_icon)
3792 gtk_window_unrealize_icon (w);
3793 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3794 gtk_window_realize_icon (w);
3797 tmp_list = tmp_list->next;
3799 g_list_free (toplevels);
3803 * gtk_window_set_default_icon:
3806 * Sets an icon to be used as fallback for windows that haven't
3807 * had gtk_window_set_icon() called on them from a pixbuf.
3812 gtk_window_set_default_icon (GdkPixbuf *icon)
3816 g_return_if_fail (GDK_IS_PIXBUF (icon));
3818 list = g_list_prepend (NULL, icon);
3819 gtk_window_set_default_icon_list (list);
3824 * gtk_window_set_default_icon_name:
3825 * @name: the name of the themed icon
3827 * Sets an icon to be used as fallback for windows that haven't
3828 * had gtk_window_set_icon_list() called on them from a named
3829 * themed icon, see gtk_window_set_icon_name().
3834 gtk_window_set_default_icon_name (const gchar *name)
3839 /* Update serial so we don't used cached pixmaps/masks
3841 default_icon_serial++;
3843 g_free (default_icon_name);
3844 default_icon_name = g_strdup (name);
3846 g_list_foreach (default_icon_list,
3847 (GFunc) g_object_unref, NULL);
3849 g_list_free (default_icon_list);
3850 default_icon_list = NULL;
3852 /* Update all toplevels */
3853 toplevels = gtk_window_list_toplevels ();
3854 tmp_list = toplevels;
3855 while (tmp_list != NULL)
3857 GtkWindowIconInfo *info;
3858 GtkWindow *w = tmp_list->data;
3860 info = get_icon_info (w);
3861 if (info && info->using_default_icon && info->using_themed_icon)
3863 gtk_window_unrealize_icon (w);
3864 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3865 gtk_window_realize_icon (w);
3868 tmp_list = tmp_list->next;
3870 g_list_free (toplevels);
3874 * gtk_window_get_default_icon_name:
3876 * Returns the fallback icon name for windows that has been set
3877 * with gtk_window_set_default_icon_name(). The returned
3878 * string is owned by GTK+ and should not be modified. It
3879 * is only valid until the next call to
3880 * gtk_window_set_default_icon_name().
3882 * Returns: the fallback icon name for windows
3887 gtk_window_get_default_icon_name (void)
3889 return default_icon_name;
3893 * gtk_window_set_default_icon_from_file:
3894 * @filename: location of icon file
3895 * @err: (allow-none): location to store error, or %NULL.
3897 * Sets an icon to be used as fallback for windows that haven't
3898 * had gtk_window_set_icon_list() called on them from a file
3899 * on disk. Warns on failure if @err is %NULL.
3901 * Returns: %TRUE if setting the icon succeeded.
3906 gtk_window_set_default_icon_from_file (const gchar *filename,
3909 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3913 gtk_window_set_default_icon (pixbuf);
3914 g_object_unref (pixbuf);
3923 * gtk_window_get_default_icon_list:
3925 * Gets the value set by gtk_window_set_default_icon_list().
3926 * The list is a copy and should be freed with g_list_free(),
3927 * but the pixbufs in the list have not had their reference count
3930 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3933 gtk_window_get_default_icon_list (void)
3935 return g_list_copy (default_icon_list);
3939 gtk_window_set_default_size_internal (GtkWindow *window,
3940 gboolean change_width,
3942 gboolean change_height,
3944 gboolean is_geometry)
3946 GtkWindowGeometryInfo *info;
3948 g_return_if_fail (change_width == FALSE || width >= -1);
3949 g_return_if_fail (change_height == FALSE || height >= -1);
3951 info = gtk_window_get_geometry_info (window, TRUE);
3953 g_object_freeze_notify (G_OBJECT (window));
3955 info->default_is_geometry = is_geometry != FALSE;
3965 info->default_width = width;
3967 g_object_notify (G_OBJECT (window), "default-width");
3978 info->default_height = height;
3980 g_object_notify (G_OBJECT (window), "default-height");
3983 g_object_thaw_notify (G_OBJECT (window));
3985 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3989 * gtk_window_set_default_size:
3990 * @window: a #GtkWindow
3991 * @width: width in pixels, or -1 to unset the default width
3992 * @height: height in pixels, or -1 to unset the default height
3994 * Sets the default size of a window. If the window's "natural" size
3995 * (its size request) is larger than the default, the default will be
3996 * ignored. More generally, if the default size does not obey the
3997 * geometry hints for the window (gtk_window_set_geometry_hints() can
3998 * be used to set these explicitly), the default size will be clamped
3999 * to the nearest permitted size.
4001 * Unlike gtk_widget_set_size_request(), which sets a size request for
4002 * a widget and thus would keep users from shrinking the window, this
4003 * function only sets the initial size, just as if the user had
4004 * resized the window themselves. Users can still shrink the window
4005 * again as they normally would. Setting a default size of -1 means to
4006 * use the "natural" default size (the size request of the window).
4008 * For more control over a window's initial size and how resizing works,
4009 * investigate gtk_window_set_geometry_hints().
4011 * For some uses, gtk_window_resize() is a more appropriate function.
4012 * gtk_window_resize() changes the current size of the window, rather
4013 * than the size to be used on initial display. gtk_window_resize() always
4014 * affects the window itself, not the geometry widget.
4016 * The default size of a window only affects the first time a window is
4017 * shown; if a window is hidden and re-shown, it will remember the size
4018 * it had prior to hiding, rather than using the default size.
4020 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4021 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4024 gtk_window_set_default_size (GtkWindow *window,
4028 g_return_if_fail (GTK_IS_WINDOW (window));
4029 g_return_if_fail (width >= -1);
4030 g_return_if_fail (height >= -1);
4032 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4036 * gtk_window_set_default_geometry:
4037 * @window: a #GtkWindow
4038 * @width: width in resize increments, or -1 to unset the default width
4039 * @height: height in resize increments, or -1 to unset the default height
4041 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4042 * in terms of the base size and increment set with
4043 * gtk_window_set_geometry_hints.
4048 gtk_window_set_default_geometry (GtkWindow *window,
4052 g_return_if_fail (GTK_IS_WINDOW (window));
4053 g_return_if_fail (width >= -1);
4054 g_return_if_fail (height >= -1);
4056 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4060 * gtk_window_get_default_size:
4061 * @window: a #GtkWindow
4062 * @width: (out) (allow-none): location to store the default width, or %NULL
4063 * @height: (out) (allow-none): location to store the default height, or %NULL
4065 * Gets the default size of the window. A value of -1 for the width or
4066 * height indicates that a default size has not been explicitly set
4067 * for that dimension, so the "natural" size of the window will be
4072 gtk_window_get_default_size (GtkWindow *window,
4076 GtkWindowGeometryInfo *info;
4078 g_return_if_fail (GTK_IS_WINDOW (window));
4080 info = gtk_window_get_geometry_info (window, FALSE);
4083 *width = info ? info->default_width : -1;
4086 *height = info ? info->default_height : -1;
4090 * gtk_window_resize:
4091 * @window: a #GtkWindow
4092 * @width: width in pixels to resize the window to
4093 * @height: height in pixels to resize the window to
4095 * Resizes the window as if the user had done so, obeying geometry
4096 * constraints. The default geometry constraint is that windows may
4097 * not be smaller than their size request; to override this
4098 * constraint, call gtk_widget_set_size_request() to set the window's
4099 * request to a smaller value.
4101 * If gtk_window_resize() is called before showing a window for the
4102 * first time, it overrides any default size set with
4103 * gtk_window_set_default_size().
4105 * Windows may not be resized smaller than 1 by 1 pixels.
4109 gtk_window_resize (GtkWindow *window,
4113 GtkWindowGeometryInfo *info;
4115 g_return_if_fail (GTK_IS_WINDOW (window));
4116 g_return_if_fail (width > 0);
4117 g_return_if_fail (height > 0);
4119 info = gtk_window_get_geometry_info (window, TRUE);
4121 info->resize_width = width;
4122 info->resize_height = height;
4123 info->resize_is_geometry = FALSE;
4125 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4129 * gtk_window_resize_to_geometry:
4130 * @window: a #GtkWindow
4131 * @width: width in resize increments to resize the window to
4132 * @height: height in resize increments to resize the window to
4134 * Like gtk_window_resize(), but @width and @height are interpreted
4135 * in terms of the base size and increment set with
4136 * gtk_window_set_geometry_hints.
4141 gtk_window_resize_to_geometry (GtkWindow *window,
4145 GtkWindowGeometryInfo *info;
4147 g_return_if_fail (GTK_IS_WINDOW (window));
4148 g_return_if_fail (width > 0);
4149 g_return_if_fail (height > 0);
4151 info = gtk_window_get_geometry_info (window, TRUE);
4153 info->resize_width = width;
4154 info->resize_height = height;
4155 info->resize_is_geometry = TRUE;
4157 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4161 * gtk_window_get_size:
4162 * @window: a #GtkWindow
4163 * @width: (out) (allow-none): return location for width, or %NULL
4164 * @height: (out) (allow-none): return location for height, or %NULL
4166 * Obtains the current size of @window. If @window is not onscreen,
4167 * it returns the size GTK+ will suggest to the <link
4168 * linkend="gtk-X11-arch">window manager</link> for the initial window
4169 * size (but this is not reliably the same as the size the window
4170 * manager will actually select). The size obtained by
4171 * gtk_window_get_size() is the last size received in a
4172 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4173 * rather than querying the X server for the size. As a result, if you
4174 * call gtk_window_resize() then immediately call
4175 * gtk_window_get_size(), the size won't have taken effect yet. After
4176 * the window manager processes the resize request, GTK+ receives
4177 * notification that the size has changed via a configure event, and
4178 * the size of the window gets updated.
4180 * Note 1: Nearly any use of this function creates a race condition,
4181 * because the size of the window may change between the time that you
4182 * get the size and the time that you perform some action assuming
4183 * that size is the current size. To avoid race conditions, connect to
4184 * "configure-event" on the window and adjust your size-dependent
4185 * state to match the size delivered in the #GdkEventConfigure.
4187 * Note 2: The returned size does <emphasis>not</emphasis> include the
4188 * size of the window manager decorations (aka the window frame or
4189 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4190 * method of determining their size.
4192 * Note 3: If you are getting a window size in order to position
4193 * the window onscreen, there may be a better way. The preferred
4194 * way is to simply set the window's semantic type with
4195 * gtk_window_set_type_hint(), which allows the window manager to
4196 * e.g. center dialogs. Also, if you set the transient parent of
4197 * dialogs with gtk_window_set_transient_for() window managers
4198 * will often center the dialog over its parent window. It's
4199 * much preferred to let the window manager handle these
4200 * things rather than doing it yourself, because all apps will
4201 * behave consistently and according to user prefs if the window
4202 * manager handles it. Also, the window manager can take the size
4203 * of the window decorations/border into account, while your
4204 * application cannot.
4206 * In any case, if you insist on application-specified window
4207 * positioning, there's <emphasis>still</emphasis> a better way than
4208 * doing it yourself - gtk_window_set_position() will frequently
4209 * handle the details for you.
4213 gtk_window_get_size (GtkWindow *window,
4219 g_return_if_fail (GTK_IS_WINDOW (window));
4221 if (width == NULL && height == NULL)
4224 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4226 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4227 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4231 GdkRectangle configure_request;
4233 gtk_window_compute_configure_request (window,
4237 w = configure_request.width;
4238 h = configure_request.height;
4249 * @window: a #GtkWindow
4250 * @x: X coordinate to move window to
4251 * @y: Y coordinate to move window to
4253 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4254 * @window to the given position. Window managers are free to ignore
4255 * this; most window managers ignore requests for initial window
4256 * positions (instead using a user-defined placement algorithm) and
4257 * honor requests after the window has already been shown.
4259 * Note: the position is the position of the gravity-determined
4260 * reference point for the window. The gravity determines two things:
4261 * first, the location of the reference point in root window
4262 * coordinates; and second, which point on the window is positioned at
4263 * the reference point.
4265 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4266 * point is simply the @x, @y supplied to gtk_window_move(). The
4267 * top-left corner of the window decorations (aka window frame or
4268 * border) will be placed at @x, @y. Therefore, to position a window
4269 * at the top left of the screen, you want to use the default gravity
4270 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4272 * To position a window at the bottom right corner of the screen, you
4273 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4274 * point is at @x + the window width and @y + the window height, and
4275 * the bottom-right corner of the window border will be placed at that
4276 * reference point. So, to place a window in the bottom right corner
4277 * you would first set gravity to south east, then write:
4278 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4279 * gdk_screen_height () - window_height)</literal> (note that this
4280 * example does not take multi-head scenarios into account).
4282 * The Extended Window Manager Hints specification at <ulink
4283 * url="http://www.freedesktop.org/Standards/wm-spec">
4284 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4285 * nice table of gravities in the "implementation notes" section.
4287 * The gtk_window_get_position() documentation may also be relevant.
4290 gtk_window_move (GtkWindow *window,
4294 GtkWindowPrivate *priv;
4295 GtkWindowGeometryInfo *info;
4298 g_return_if_fail (GTK_IS_WINDOW (window));
4300 priv = window->priv;
4301 widget = GTK_WIDGET (window);
4303 info = gtk_window_get_geometry_info (window, TRUE);
4305 if (gtk_widget_get_mapped (widget))
4307 GtkAllocation allocation;
4309 gtk_widget_get_allocation (widget, &allocation);
4311 /* we have now sent a request with this position
4312 * with currently-active constraints, so toggle flag.
4314 info->position_constraints_changed = FALSE;
4316 /* we only constrain if mapped - if not mapped,
4317 * then gtk_window_compute_configure_request()
4318 * will apply the constraints later, and we
4319 * don't want to lose information about
4320 * what position the user set before then.
4321 * i.e. if you do a move() then turn off POS_CENTER
4322 * then show the window, your move() will work.
4324 gtk_window_constrain_position (window,
4325 allocation.width, allocation.height,
4328 /* Note that this request doesn't go through our standard request
4329 * framework, e.g. doesn't increment configure_request_count,
4330 * doesn't set info->last, etc.; that's because
4331 * we don't save the info needed to arrive at this same request
4334 * To gtk_window_move_resize(), this will end up looking exactly
4335 * the same as the position being changed by the window
4339 /* FIXME are we handling gravity properly for framed windows? */
4341 gdk_window_move (priv->frame,
4342 x - priv->frame_left,
4343 y - priv->frame_top);
4345 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)),
4350 /* Save this position to apply on mapping */
4351 info->initial_x = x;
4352 info->initial_y = y;
4353 info->initial_pos_set = TRUE;
4358 * gtk_window_get_position:
4359 * @window: a #GtkWindow
4360 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4361 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4363 * This function returns the position you need to pass to
4364 * gtk_window_move() to keep @window in its current position. This
4365 * means that the meaning of the returned value varies with window
4366 * gravity. See gtk_window_move() for more details.
4368 * If you haven't changed the window gravity, its gravity will be
4369 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4370 * gets the position of the top-left corner of the window manager
4371 * frame for the window. gtk_window_move() sets the position of this
4372 * same top-left corner.
4374 * gtk_window_get_position() is not 100% reliable because the X Window System
4375 * does not specify a way to obtain the geometry of the
4376 * decorations placed on a window by the window manager.
4377 * Thus GTK+ is using a "best guess" that works with most
4380 * Moreover, nearly all window managers are historically broken with
4381 * respect to their handling of window gravity. So moving a window to
4382 * its current position as returned by gtk_window_get_position() tends
4383 * to result in moving the window slightly. Window managers are
4384 * slowly getting better over time.
4386 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4387 * frame is not relevant, and thus gtk_window_get_position() will
4388 * always produce accurate results. However you can't use static
4389 * gravity to do things like place a window in a corner of the screen,
4390 * because static gravity ignores the window manager decorations.
4392 * If you are saving and restoring your application's window
4393 * positions, you should know that it's impossible for applications to
4394 * do this without getting it somewhat wrong because applications do
4395 * not have sufficient knowledge of window manager state. The Correct
4396 * Mechanism is to support the session management protocol (see the
4397 * "GnomeClient" object in the GNOME libraries for example) and allow
4398 * the window manager to save your window sizes and positions.
4403 gtk_window_get_position (GtkWindow *window,
4407 GtkWindowPrivate *priv;
4409 GdkWindow *gdk_window;
4411 g_return_if_fail (GTK_IS_WINDOW (window));
4413 priv = window->priv;
4414 widget = GTK_WIDGET (window);
4415 gdk_window = gtk_widget_get_window (widget);
4417 if (priv->gravity == GDK_GRAVITY_STATIC)
4419 if (gtk_widget_get_mapped (widget))
4421 /* This does a server round-trip, which is sort of wrong;
4422 * but a server round-trip is inevitable for
4423 * gdk_window_get_frame_extents() in the usual
4424 * NorthWestGravity case below, so not sure what else to
4425 * do. We should likely be consistent about whether we get
4426 * the client-side info or the server-side info.
4428 gdk_window_get_origin (gdk_window, root_x, root_y);
4432 GdkRectangle configure_request;
4434 gtk_window_compute_configure_request (window,
4438 *root_x = configure_request.x;
4439 *root_y = configure_request.y;
4444 GdkRectangle frame_extents;
4449 if (gtk_widget_get_mapped (widget))
4452 gdk_window_get_frame_extents (priv->frame, &frame_extents);
4454 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4455 x = frame_extents.x;
4456 y = frame_extents.y;
4457 gtk_window_get_size (window, &w, &h);
4461 /* We just say the frame has 0 size on all sides.
4462 * Not sure what else to do.
4464 gtk_window_compute_configure_request (window,
4467 x = frame_extents.x;
4468 y = frame_extents.y;
4469 w = frame_extents.width;
4470 h = frame_extents.height;
4473 switch (priv->gravity)
4475 case GDK_GRAVITY_NORTH:
4476 case GDK_GRAVITY_CENTER:
4477 case GDK_GRAVITY_SOUTH:
4478 /* Find center of frame. */
4479 x += frame_extents.width / 2;
4480 /* Center client window on that point. */
4484 case GDK_GRAVITY_SOUTH_EAST:
4485 case GDK_GRAVITY_EAST:
4486 case GDK_GRAVITY_NORTH_EAST:
4487 /* Find right edge of frame */
4488 x += frame_extents.width;
4489 /* Align left edge of client at that point. */
4496 switch (priv->gravity)
4498 case GDK_GRAVITY_WEST:
4499 case GDK_GRAVITY_CENTER:
4500 case GDK_GRAVITY_EAST:
4501 /* Find center of frame. */
4502 y += frame_extents.height / 2;
4503 /* Center client window there. */
4506 case GDK_GRAVITY_SOUTH_WEST:
4507 case GDK_GRAVITY_SOUTH:
4508 case GDK_GRAVITY_SOUTH_EAST:
4509 /* Find south edge of frame */
4510 y += frame_extents.height;
4511 /* Place bottom edge of client there */
4526 * gtk_window_reshow_with_initial_size:
4527 * @window: a #GtkWindow
4529 * Hides @window, then reshows it, resetting the
4530 * default size and position of the window. Used
4531 * by GUI builders only.
4534 gtk_window_reshow_with_initial_size (GtkWindow *window)
4538 g_return_if_fail (GTK_IS_WINDOW (window));
4540 widget = GTK_WIDGET (window);
4542 gtk_widget_hide (widget);
4543 gtk_widget_unrealize (widget);
4544 gtk_widget_show (widget);
4548 gtk_window_destroy (GtkWidget *widget)
4550 GtkWindow *window = GTK_WINDOW (widget);
4551 GtkWindowPrivate *priv = window->priv;
4553 toplevel_list = g_slist_remove (toplevel_list, window);
4555 if (priv->transient_parent)
4556 gtk_window_set_transient_for (window, NULL);
4558 /* frees the icons */
4559 gtk_window_set_icon_list (window, NULL);
4561 if (priv->has_user_ref_count)
4563 priv->has_user_ref_count = FALSE;
4564 g_object_unref (window);
4568 gtk_window_group_remove_window (priv->group, window);
4570 gtk_window_free_key_hash (window);
4572 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4576 gtk_window_finalize (GObject *object)
4578 GtkWindow *window = GTK_WINDOW (object);
4579 GtkWindowPrivate *priv = window->priv;
4580 GtkMnemonicHash *mnemonic_hash;
4582 g_free (priv->title);
4583 g_free (priv->wmclass_name);
4584 g_free (priv->wmclass_class);
4585 g_free (priv->wm_role);
4586 gtk_window_release_application (window);
4588 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4590 _gtk_mnemonic_hash_free (mnemonic_hash);
4592 if (priv->geometry_info)
4594 if (priv->geometry_info->widget)
4595 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4596 gtk_widget_destroyed,
4597 &priv->geometry_info->widget);
4598 g_free (priv->geometry_info);
4601 if (priv->keys_changed_handler)
4603 g_source_remove (priv->keys_changed_handler);
4604 priv->keys_changed_handler = 0;
4608 g_signal_handlers_disconnect_by_func (priv->screen,
4609 gtk_window_on_composited_changed, window);
4611 g_free (priv->startup_id);
4613 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4617 gtk_window_show (GtkWidget *widget)
4619 GtkWindow *window = GTK_WINDOW (widget);
4620 GtkWindowPrivate *priv = window->priv;
4621 GtkContainer *container = GTK_CONTAINER (window);
4622 gboolean need_resize;
4624 _gtk_widget_set_visible_flag (widget, TRUE);
4626 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4627 _gtk_container_set_need_resize (container, FALSE);
4631 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4632 GtkAllocation allocation = { 0, 0 };
4633 GdkRectangle configure_request;
4634 GdkGeometry new_geometry;
4636 gboolean was_realized;
4638 /* We are going to go ahead and perform this configure request
4639 * and then emulate a configure notify by going ahead and
4640 * doing a size allocate. Sort of a synchronous
4641 * mini-copy of gtk_window_move_resize() here.
4643 gtk_window_compute_configure_request (window,
4648 /* We update this because we are going to go ahead
4649 * and gdk_window_resize() below, rather than
4652 info->last.configure_request.width = configure_request.width;
4653 info->last.configure_request.height = configure_request.height;
4655 /* and allocate the window - this is normally done
4656 * in move_resize in response to configure notify
4658 allocation.width = configure_request.width;
4659 allocation.height = configure_request.height;
4660 gtk_widget_size_allocate (widget, &allocation);
4662 /* Then we guarantee we have a realize */
4663 was_realized = FALSE;
4664 if (!gtk_widget_get_realized (widget))
4666 gtk_widget_realize (widget);
4667 was_realized = TRUE;
4670 /* We only send configure request if we didn't just finish
4671 * creating the window; if we just created the window
4672 * then we created it with widget->allocation anyhow.
4675 gdk_window_move_resize (gtk_widget_get_window (widget),
4676 configure_request.x,
4677 configure_request.y,
4678 configure_request.width,
4679 configure_request.height);
4682 gtk_container_check_resize (container);
4684 gtk_widget_map (widget);
4686 /* Try to make sure that we have some focused widget
4688 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4689 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4692 gtk_grab_add (widget);
4696 gtk_window_hide (GtkWidget *widget)
4698 GtkWindow *window = GTK_WINDOW (widget);
4699 GtkWindowPrivate *priv = window->priv;
4701 _gtk_widget_set_visible_flag (widget, FALSE);
4702 gtk_widget_unmap (widget);
4705 gtk_grab_remove (widget);
4709 gtk_window_map (GtkWidget *widget)
4712 GtkWindow *window = GTK_WINDOW (widget);
4713 GtkWindowPrivate *priv = window->priv;
4714 GdkWindow *toplevel;
4715 GdkWindow *gdk_window;
4716 gboolean auto_mnemonics;
4718 gdk_window = gtk_widget_get_window (widget);
4720 gtk_widget_set_mapped (widget, TRUE);
4722 child = gtk_bin_get_child (&(window->bin));
4724 gtk_widget_get_visible (child) &&
4725 !gtk_widget_get_mapped (child))
4726 gtk_widget_map (child);
4729 toplevel = priv->frame;
4731 toplevel = gdk_window;
4733 if (priv->maximize_initially)
4734 gdk_window_maximize (toplevel);
4736 gdk_window_unmaximize (toplevel);
4738 if (priv->stick_initially)
4739 gdk_window_stick (toplevel);
4741 gdk_window_unstick (toplevel);
4743 if (priv->iconify_initially)
4744 gdk_window_iconify (toplevel);
4746 gdk_window_deiconify (toplevel);
4748 if (priv->fullscreen_initially)
4749 gdk_window_fullscreen (toplevel);
4751 gdk_window_unfullscreen (toplevel);
4753 gdk_window_set_keep_above (toplevel, priv->above_initially);
4755 gdk_window_set_keep_below (toplevel, priv->below_initially);
4757 /* No longer use the default settings */
4758 priv->need_default_size = FALSE;
4759 priv->need_default_position = FALSE;
4761 if (priv->reset_type_hint)
4763 /* We should only reset the type hint when the application
4764 * used gtk_window_set_type_hint() to change the hint.
4765 * Some applications use X directly to change the properties;
4766 * in that case, we shouldn't overwrite what they did.
4768 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4769 priv->reset_type_hint = FALSE;
4772 gdk_window_show (gdk_window);
4775 gdk_window_show (priv->frame);
4777 if (priv->grip_window)
4778 gdk_window_show (priv->grip_window);
4780 if (!disable_startup_notification)
4782 /* Do we have a custom startup-notification id? */
4783 if (priv->startup_id != NULL)
4785 /* Make sure we have a "real" id */
4786 if (!startup_id_is_fake (priv->startup_id))
4787 gdk_notify_startup_complete_with_id (priv->startup_id);
4789 g_free (priv->startup_id);
4790 priv->startup_id = NULL;
4792 else if (!sent_startup_notification)
4794 sent_startup_notification = TRUE;
4795 gdk_notify_startup_complete ();
4799 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4800 * (as in the case of popup menus), then hide mnemonics initially
4802 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4803 &auto_mnemonics, NULL);
4804 if (auto_mnemonics && !priv->mnemonics_visible_set)
4805 gtk_window_set_mnemonics_visible (window, FALSE);
4809 gtk_window_map_event (GtkWidget *widget,
4812 if (!gtk_widget_get_mapped (widget))
4814 /* we should be be unmapped, but are getting a MapEvent, this may happen
4815 * to toplevel XWindows if mapping was intercepted by a window manager
4816 * and an unmap request occoured while the MapRequestEvent was still
4817 * being handled. we work around this situaiton here by re-requesting
4818 * the window being unmapped. more details can be found in:
4819 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4821 gdk_window_hide (gtk_widget_get_window (widget));
4827 gtk_window_unmap (GtkWidget *widget)
4829 GtkWindow *window = GTK_WINDOW (widget);
4830 GtkWindowPrivate *priv = window->priv;
4832 GtkWindowGeometryInfo *info;
4833 GdkWindow *gdk_window;
4834 GdkWindowState state;
4836 gdk_window = gtk_widget_get_window (widget);
4838 gtk_widget_set_mapped (widget, FALSE);
4840 gdk_window_withdraw (priv->frame);
4842 gdk_window_withdraw (gdk_window);
4844 priv->configure_request_count = 0;
4845 priv->configure_notify_received = FALSE;
4847 /* on unmap, we reset the default positioning of the window,
4848 * so it's placed again, but we don't reset the default
4849 * size of the window, so it's remembered.
4851 priv->need_default_position = TRUE;
4853 info = gtk_window_get_geometry_info (window, FALSE);
4856 info->initial_pos_set = FALSE;
4857 info->position_constraints_changed = FALSE;
4860 state = gdk_window_get_state (gdk_window);
4861 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4862 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4863 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4864 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4865 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4867 child = gtk_bin_get_child (&(window->bin));
4869 gtk_widget_unmap (child);
4873 gtk_window_realize (GtkWidget *widget)
4875 GtkAllocation allocation;
4877 GdkWindow *parent_window;
4878 GdkWindow *gdk_window;
4879 GdkWindowAttr attributes;
4880 gint attributes_mask;
4881 GtkWindowPrivate *priv;
4882 GtkStyleContext *context;
4884 window = GTK_WINDOW (widget);
4885 priv = window->priv;
4887 gtk_widget_get_allocation (widget, &allocation);
4889 /* ensure widget tree is properly size allocated */
4890 if (allocation.x == -1 &&
4891 allocation.y == -1 &&
4892 allocation.width == 1 &&
4893 allocation.height == 1)
4895 GtkRequisition requisition;
4899 allocation.width = 200;
4900 allocation.height = 200;
4902 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4903 if (requisition.width || requisition.height)
4905 /* non-empty window */
4906 allocation.width = requisition.width;
4907 allocation.height = requisition.height;
4909 gtk_widget_size_allocate (widget, &allocation);
4911 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4913 g_return_if_fail (!gtk_widget_get_realized (widget));
4916 gtk_widget_set_realized (widget, TRUE);
4920 case GTK_WINDOW_TOPLEVEL:
4921 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4923 case GTK_WINDOW_POPUP:
4924 attributes.window_type = GDK_WINDOW_TEMP;
4927 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4931 attributes.title = priv->title;
4932 attributes.wmclass_name = priv->wmclass_name;
4933 attributes.wmclass_class = priv->wmclass_class;
4934 attributes.wclass = GDK_INPUT_OUTPUT;
4935 attributes.visual = gtk_widget_get_visual (widget);
4937 if (priv->has_frame)
4939 gtk_widget_get_allocation (widget, &allocation);
4940 attributes.width = allocation.width + priv->frame_left + priv->frame_right;
4941 attributes.height = allocation.height + priv->frame_top + priv->frame_bottom;
4942 attributes.event_mask = (GDK_EXPOSURE_MASK |
4943 GDK_KEY_PRESS_MASK |
4944 GDK_ENTER_NOTIFY_MASK |
4945 GDK_LEAVE_NOTIFY_MASK |
4946 GDK_FOCUS_CHANGE_MASK |
4947 GDK_STRUCTURE_MASK |
4948 GDK_BUTTON_MOTION_MASK |
4949 GDK_POINTER_MOTION_HINT_MASK |
4950 GDK_BUTTON_PRESS_MASK |
4951 GDK_BUTTON_RELEASE_MASK);
4953 attributes_mask = GDK_WA_VISUAL;
4955 priv->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4956 &attributes, attributes_mask);
4958 if (priv->opacity_set)
4959 gdk_window_set_opacity (priv->frame, priv->opacity);
4961 gdk_window_set_user_data (priv->frame, widget);
4963 attributes.window_type = GDK_WINDOW_CHILD;
4964 attributes.x = priv->frame_left;
4965 attributes.y = priv->frame_top;
4967 attributes_mask = GDK_WA_X | GDK_WA_Y;
4969 parent_window = priv->frame;
4971 g_signal_connect (window,
4973 G_CALLBACK (gtk_window_event),
4978 attributes_mask = 0;
4979 parent_window = gtk_widget_get_root_window (widget);
4982 gtk_widget_get_allocation (widget, &allocation);
4983 attributes.width = allocation.width;
4984 attributes.height = allocation.height;
4985 attributes.event_mask = gtk_widget_get_events (widget);
4986 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4987 GDK_KEY_PRESS_MASK |
4988 GDK_KEY_RELEASE_MASK |
4989 GDK_ENTER_NOTIFY_MASK |
4990 GDK_LEAVE_NOTIFY_MASK |
4991 GDK_FOCUS_CHANGE_MASK |
4992 GDK_STRUCTURE_MASK);
4993 attributes.type_hint = priv->type_hint;
4995 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4996 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4997 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4999 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5000 gtk_widget_set_window (widget, gdk_window);
5002 if (!priv->has_frame && priv->opacity_set)
5003 gdk_window_set_opacity (gdk_window, priv->opacity);
5005 gdk_window_enable_synchronized_configure (gdk_window);
5007 gdk_window_set_user_data (gdk_window, window);
5009 gtk_widget_style_attach (widget);
5010 context = gtk_widget_get_style_context (widget);
5012 gtk_style_context_set_background (context, gdk_window);
5014 gtk_style_context_set_background (context, priv->frame);
5016 if (priv->transient_parent &&
5017 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5018 gdk_window_set_transient_for (gdk_window,
5019 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5022 gdk_window_set_role (gdk_window, priv->wm_role);
5024 if (!priv->decorated)
5025 gdk_window_set_decorations (gdk_window, 0);
5027 if (!priv->deletable)
5028 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5030 if (gtk_window_get_skip_pager_hint (window))
5031 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5033 if (gtk_window_get_skip_taskbar_hint (window))
5034 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5036 if (gtk_window_get_accept_focus (window))
5037 gdk_window_set_accept_focus (gdk_window, TRUE);
5039 gdk_window_set_accept_focus (gdk_window, FALSE);
5041 if (gtk_window_get_focus_on_map (window))
5042 gdk_window_set_focus_on_map (gdk_window, TRUE);
5044 gdk_window_set_focus_on_map (gdk_window, FALSE);
5047 gdk_window_set_modal_hint (gdk_window, TRUE);
5049 gdk_window_set_modal_hint (gdk_window, FALSE);
5051 if (priv->startup_id)
5053 #ifdef GDK_WINDOWING_X11
5054 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5055 if (timestamp != GDK_CURRENT_TIME)
5056 gdk_x11_window_set_user_time (gdk_window, timestamp);
5058 if (!startup_id_is_fake (priv->startup_id))
5059 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5063 gtk_window_realize_icon (window);
5065 if (priv->has_resize_grip)
5066 resize_grip_create_window (window);
5070 gtk_window_unrealize (GtkWidget *widget)
5072 GtkWindow *window = GTK_WINDOW (widget);
5073 GtkWindowPrivate *priv = window->priv;
5074 GtkWindowGeometryInfo *info;
5076 /* On unrealize, we reset the size of the window such
5077 * that we will re-apply the default sizing stuff
5078 * next time we show the window.
5080 * Default positioning is reset on unmap, instead of unrealize.
5082 priv->need_default_size = TRUE;
5083 info = gtk_window_get_geometry_info (window, FALSE);
5086 info->resize_width = -1;
5087 info->resize_height = -1;
5088 info->last.configure_request.x = 0;
5089 info->last.configure_request.y = 0;
5090 info->last.configure_request.width = -1;
5091 info->last.configure_request.height = -1;
5092 /* be sure we reset geom hints on re-realize */
5093 info->last.flags = 0;
5098 gdk_window_set_user_data (priv->frame, NULL);
5099 gdk_window_destroy (priv->frame);
5104 gtk_window_unrealize_icon (window);
5106 if (priv->grip_window != NULL)
5107 resize_grip_destroy_window (window);
5109 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5112 static GtkJunctionSides
5113 get_grip_junction (GtkWidget *widget)
5115 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5116 return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5118 return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5122 get_drag_edge (GtkWidget *widget,
5123 GdkWindowEdge *edge)
5125 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5126 gboolean hresizable;
5127 gboolean vresizable;
5128 GtkTextDirection dir;
5129 GtkWindowGeometryInfo *info;
5134 info = priv->geometry_info;
5137 GdkWindowHints flags = info->last.flags;
5138 GdkGeometry *geometry = &info->last.geometry;
5140 if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5142 hresizable = geometry->min_width < geometry->max_width;
5143 vresizable = geometry->min_height < geometry->max_height;
5147 dir = gtk_widget_get_direction (widget);
5149 if (hresizable && vresizable)
5150 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5151 else if (hresizable)
5152 *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5153 else if (vresizable)
5154 *edge = GDK_WINDOW_EDGE_SOUTH;
5162 set_grip_cursor (GtkWindow *window)
5164 GtkWidget *widget = GTK_WIDGET (window);
5165 GtkWindowPrivate *priv = window->priv;
5167 if (priv->grip_window == NULL)
5170 if (gtk_widget_is_sensitive (widget))
5173 GdkDisplay *display;
5174 GdkCursorType cursor_type;
5177 cursor_type = GDK_LEFT_PTR;
5179 if (get_drag_edge (widget, &edge))
5183 case GDK_WINDOW_EDGE_EAST:
5184 cursor_type = GDK_RIGHT_SIDE;
5186 case GDK_WINDOW_EDGE_SOUTH_EAST:
5187 cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5189 case GDK_WINDOW_EDGE_SOUTH:
5190 cursor_type = GDK_BOTTOM_SIDE;
5192 case GDK_WINDOW_EDGE_SOUTH_WEST:
5193 cursor_type = GDK_BOTTOM_LEFT_CORNER;
5195 case GDK_WINDOW_EDGE_WEST:
5196 cursor_type = GDK_LEFT_SIDE;
5202 display = gtk_widget_get_display (widget);
5203 cursor = gdk_cursor_new_for_display (display, cursor_type);
5204 gdk_window_set_cursor (priv->grip_window, cursor);
5205 g_object_unref (cursor);
5208 gdk_window_set_cursor (priv->grip_window, NULL);
5212 set_grip_shape (GtkWindow *window)
5214 GtkWindowPrivate *priv = window->priv;
5215 cairo_region_t *region;
5216 cairo_surface_t *surface;
5218 double width, height;
5220 if (priv->grip_window == NULL)
5223 width = gdk_window_get_width (priv->grip_window);
5224 height = gdk_window_get_height (priv->grip_window);
5225 surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5227 cr = cairo_create (surface);
5228 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5230 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5231 if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5233 cairo_move_to (cr, width, 0.0);
5234 cairo_line_to (cr, width, height);
5235 cairo_line_to (cr, 0.0, height);
5239 cairo_move_to (cr, 0.0, 0.0);
5240 cairo_line_to (cr, width, height);
5241 cairo_line_to (cr, 0.0, height);
5243 cairo_close_path (cr);
5246 region = gdk_cairo_region_create_from_surface (surface);
5247 cairo_surface_destroy (surface);
5249 gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5250 cairo_region_destroy (region);
5254 set_grip_position (GtkWindow *window)
5256 GtkWindowPrivate *priv = window->priv;
5259 if (priv->grip_window == NULL)
5262 gtk_window_get_resize_grip_area (window, &rect);
5263 gdk_window_raise (priv->grip_window);
5264 gdk_window_move_resize (priv->grip_window,
5266 rect.width, rect.height);
5270 gtk_window_size_allocate (GtkWidget *widget,
5271 GtkAllocation *allocation)
5273 GtkWindow *window = GTK_WINDOW (widget);
5274 GtkWindowPrivate *priv = window->priv;
5275 GtkAllocation child_allocation;
5279 gtk_widget_set_allocation (widget, allocation);
5281 child = gtk_bin_get_child (&(window->bin));
5282 if (child && gtk_widget_get_visible (child))
5284 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5285 child_allocation.x = border_width;
5286 child_allocation.y = border_width;
5287 child_allocation.width =
5288 MAX (1, (gint)allocation->width - child_allocation.x * 2);
5289 child_allocation.height =
5290 MAX (1, (gint)allocation->height - child_allocation.y * 2);
5292 gtk_widget_size_allocate (child, &child_allocation);
5295 if (gtk_widget_get_realized (widget))
5298 gdk_window_resize (priv->frame,
5299 allocation->width + priv->frame_left + priv->frame_right,
5300 allocation->height + priv->frame_top + priv->frame_bottom);
5301 update_grip_visibility (window);
5302 set_grip_position (window);
5307 gtk_window_event (GtkWidget *widget, GdkEvent *event)
5309 GtkWindow *window = GTK_WINDOW (widget);
5310 GtkWindowPrivate *priv = window->priv;
5311 gboolean return_val;
5313 if (priv->frame && (event->any.window == priv->frame))
5315 if ((event->type != GDK_KEY_PRESS) &&
5316 (event->type != GDK_KEY_RELEASE) &&
5317 (event->type != GDK_FOCUS_CHANGE))
5319 g_signal_stop_emission_by_name (widget, "event");
5321 g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
5326 g_object_unref (event->any.window);
5327 event->any.window = g_object_ref (gtk_widget_get_window (widget));
5335 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
5337 GtkWindowPrivate *priv = window->priv;
5338 GdkEventConfigure *configure_event;
5341 switch (event->type)
5344 configure_event = (GdkEventConfigure *)event;
5346 /* Invalidate the decorations */
5349 rect.width = configure_event->width;
5350 rect.height = configure_event->height;
5352 gdk_window_invalidate_rect (priv->frame, &rect, FALSE);
5354 /* Pass on the (modified) configure event */
5355 configure_event->width -= priv->frame_left + priv->frame_right;
5356 configure_event->height -= priv->frame_top + priv->frame_bottom;
5357 return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
5366 gtk_window_configure_event (GtkWidget *widget,
5367 GdkEventConfigure *event)
5369 GtkAllocation allocation;
5370 GtkWindow *window = GTK_WINDOW (widget);
5371 GtkWindowPrivate *priv = window->priv;
5372 gboolean expected_reply = priv->configure_request_count > 0;
5374 /* priv->configure_request_count incremented for each
5375 * configure request, and decremented to a min of 0 for
5376 * each configure notify.
5378 * All it means is that we know we will get at least
5379 * priv->configure_request_count more configure notifies.
5380 * We could get more configure notifies than that; some
5381 * of the configure notifies we get may be unrelated to
5382 * the configure requests. But we will get at least
5383 * priv->configure_request_count notifies.
5386 if (priv->configure_request_count > 0)
5388 priv->configure_request_count -= 1;
5389 gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5392 /* As an optimization, we avoid a resize when possible.
5394 * The only times we can avoid a resize are:
5395 * - we know only the position changed, not the size
5396 * - we know we have made more requests and so will get more
5397 * notifies and can wait to resize when we get them
5399 gtk_widget_get_allocation (widget, &allocation);
5400 if (!expected_reply &&
5401 (allocation.width == event->width &&
5402 allocation.height == event->height))
5404 gdk_window_configure_finished (gtk_widget_get_window (widget));
5409 * If we do need to resize, we do that by:
5410 * - filling in widget->allocation with the new size
5411 * - setting configure_notify_received to TRUE
5412 * for use in gtk_window_move_resize()
5413 * - queueing a resize, leading to invocation of
5414 * gtk_window_move_resize() in an idle handler
5418 priv->configure_notify_received = TRUE;
5420 allocation.width = event->width;
5421 allocation.height = event->height;
5422 gtk_widget_set_allocation (widget, &allocation);
5424 gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5426 _gtk_container_queue_resize (GTK_CONTAINER (widget));
5432 gtk_window_state_event (GtkWidget *widget,
5433 GdkEventWindowState *event)
5435 update_grip_visibility (GTK_WINDOW (widget));
5441 gtk_window_direction_changed (GtkWidget *widget,
5442 GtkTextDirection prev_dir)
5444 GtkWindow *window = GTK_WINDOW (widget);
5446 set_grip_cursor (window);
5447 set_grip_position (window);
5448 set_grip_shape (window);
5452 gtk_window_state_changed (GtkWidget *widget,
5453 GtkStateType previous_state)
5455 GtkWindow *window = GTK_WINDOW (widget);
5457 update_grip_visibility (window);
5461 gtk_window_style_updated (GtkWidget *widget)
5463 GtkWindow *window = GTK_WINDOW (widget);
5464 GtkWindowPrivate *priv = window->priv;
5467 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5469 gdk_window_move_resize (priv->grip_window,
5471 rect.width, rect.height);
5473 set_grip_shape (window);
5474 gtk_widget_queue_resize (widget);
5479 resize_grip_create_window (GtkWindow *window)
5482 GtkWindowPrivate *priv;
5483 GdkWindowAttr attributes;
5484 gint attributes_mask;
5487 priv = window->priv;
5488 widget = GTK_WIDGET (window);
5490 g_return_if_fail (gtk_widget_get_realized (widget));
5491 g_return_if_fail (priv->grip_window == NULL);
5493 gtk_window_get_resize_grip_area (window, &rect);
5495 attributes.x = rect.x;
5496 attributes.y = rect.y;
5497 attributes.width = rect.width;
5498 attributes.height = rect.height;
5499 attributes.window_type = GDK_WINDOW_CHILD;
5500 attributes.wclass = GDK_INPUT_OUTPUT;
5501 attributes.event_mask = gtk_widget_get_events (widget) |
5503 GDK_BUTTON_PRESS_MASK;
5505 attributes_mask = GDK_WA_X | GDK_WA_Y;
5507 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5511 gdk_window_set_user_data (priv->grip_window, widget);
5513 gdk_window_raise (priv->grip_window);
5515 set_grip_shape (window);
5516 update_grip_visibility (window);
5520 resize_grip_destroy_window (GtkWindow *window)
5522 GtkWindowPrivate *priv = window->priv;
5524 gdk_window_set_user_data (priv->grip_window, NULL);
5525 gdk_window_destroy (priv->grip_window);
5526 priv->grip_window = NULL;
5527 update_grip_visibility (window);
5531 * gtk_window_set_has_resize_grip:
5532 * @window: a #GtkWindow
5533 * @value: %TRUE to allow a resize grip
5535 * Sets whether @window has a corner resize grip.
5537 * Note that the resize grip is only shown if the window
5538 * is actually resizable and not maximized. Use
5539 * gtk_window_resize_grip_is_visible() to find out if the
5540 * resize grip is currently shown.
5545 gtk_window_set_has_resize_grip (GtkWindow *window,
5548 GtkWidget *widget = GTK_WIDGET (window);
5549 GtkWindowPrivate *priv = window->priv;
5551 value = value != FALSE;
5553 if (value != priv->has_resize_grip)
5555 priv->has_resize_grip = value;
5556 gtk_widget_queue_draw (widget);
5558 if (gtk_widget_get_realized (widget))
5560 if (priv->has_resize_grip && priv->grip_window == NULL)
5561 resize_grip_create_window (window);
5562 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5563 resize_grip_destroy_window (window);
5566 g_object_notify (G_OBJECT (window), "has-resize-grip");
5571 update_grip_visibility (GtkWindow *window)
5573 GtkWindowPrivate *priv = window->priv;
5576 val = gtk_window_resize_grip_is_visible (window);
5578 if (priv->grip_window != NULL)
5582 gdk_window_show (priv->grip_window);
5583 set_grip_cursor (window);
5587 gdk_window_hide (priv->grip_window);
5591 if (priv->resize_grip_visible != val)
5593 priv->resize_grip_visible = val;
5595 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5600 * gtk_window_resize_grip_is_visible:
5601 * @window: a #GtkWindow
5603 * Determines whether a resize grip is visible for the specified window.
5605 * Returns %TRUE if a resize grip exists and is visible.
5610 gtk_window_resize_grip_is_visible (GtkWindow *window)
5613 GtkWindowPrivate *priv;
5616 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5618 priv = window->priv;
5619 widget = GTK_WIDGET (window);
5621 if (priv->type == GTK_WINDOW_POPUP)
5624 if (!priv->resizable)
5627 if (gtk_widget_get_realized (widget))
5629 GdkWindowState state;
5631 state = gdk_window_get_state (gtk_widget_get_window (widget));
5633 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5637 if (!get_drag_edge (widget, &edge))
5640 return window->priv->has_resize_grip;
5644 * gtk_window_get_has_resize_grip:
5645 * @window: a #GtkWindow
5647 * Determines whether the window may have a resize grip.
5649 * Returns: %TRUE if the window has a resize grip.
5654 gtk_window_get_has_resize_grip (GtkWindow *window)
5656 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5658 return window->priv->has_resize_grip;
5662 * gtk_window_get_resize_grip_area:
5663 * @window: a #GtkWindow
5664 * @rect: a pointer to a #GdkRectangle which we should store the
5667 * If a window has a resize grip, this will retrieve the grip
5668 * position, width and height into the specified #GdkRectangle.
5670 * Returns: %TRUE if the resize grip's area was retrieved.
5675 gtk_window_get_resize_grip_area (GtkWindow *window,
5678 GtkWidget *widget = GTK_WIDGET (window);
5679 GtkAllocation allocation;
5683 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5685 if (!window->priv->has_resize_grip)
5688 gtk_widget_get_allocation (widget, &allocation);
5690 gtk_widget_style_get (widget,
5691 "resize-grip-width", &grip_width,
5692 "resize-grip-height", &grip_height,
5695 if (grip_width > allocation.width)
5696 grip_width = allocation.width;
5698 if (grip_height > allocation.height)
5699 grip_height = allocation.height;
5701 rect->width = grip_width;
5702 rect->height = grip_height;
5703 rect->y = allocation.y + allocation.height - grip_height;
5705 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5706 rect->x = allocation.x + allocation.width - grip_width;
5708 rect->x = allocation.x;
5713 /* the accel_key and accel_mods fields of the key have to be setup
5714 * upon calling this function. it'll then return whether that key
5715 * is at all used as accelerator, and if so will OR in the
5716 * accel_flags member of the key.
5719 _gtk_window_query_nonaccels (GtkWindow *window,
5721 GdkModifierType accel_mods)
5723 GtkWindowPrivate *priv;
5725 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5727 priv = window->priv;
5729 /* movement keys are considered locked accels */
5732 static const guint bindings[] = {
5733 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,
5734 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,
5738 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5739 if (bindings[i] == accel_key)
5743 /* mnemonics are considered locked accels */
5744 if (accel_mods == priv->mnemonic_modifier)
5746 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5747 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5755 * gtk_window_propagate_key_event:
5756 * @window: a #GtkWindow
5757 * @event: a #GdkEventKey
5759 * Propagate a key press or release event to the focus widget and
5760 * up the focus container chain until a widget handles @event.
5761 * This is normally called by the default ::key_press_event and
5762 * ::key_release_event handlers for toplevel windows,
5763 * however in some cases it may be useful to call this directly when
5764 * overriding the standard key handling for a toplevel window.
5766 * Return value: %TRUE if a widget in the focus chain handled the event.
5771 gtk_window_propagate_key_event (GtkWindow *window,
5774 GtkWindowPrivate *priv;
5775 gboolean handled = FALSE;
5776 GtkWidget *widget, *focus;
5778 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5780 priv = window->priv;
5781 widget = GTK_WIDGET (window);
5783 focus = priv->focus_widget;
5785 g_object_ref (focus);
5788 focus && focus != widget &&
5789 gtk_widget_get_toplevel (focus) == widget)
5793 if (gtk_widget_is_sensitive (focus))
5794 handled = gtk_widget_event (focus, (GdkEvent*) event);
5796 parent = gtk_widget_get_parent (focus);
5798 g_object_ref (parent);
5800 g_object_unref (focus);
5806 g_object_unref (focus);
5812 gtk_window_key_press_event (GtkWidget *widget,
5815 GtkWindow *window = GTK_WINDOW (widget);
5816 gboolean handled = FALSE;
5818 /* handle mnemonics and accelerators */
5820 handled = gtk_window_activate_key (window, event);
5822 /* handle focus widget key events */
5824 handled = gtk_window_propagate_key_event (window, event);
5826 /* Chain up, invokes binding set */
5828 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5834 gtk_window_key_release_event (GtkWidget *widget,
5837 GtkWindow *window = GTK_WINDOW (widget);
5838 gboolean handled = FALSE;
5840 /* handle focus widget key events */
5842 handled = gtk_window_propagate_key_event (window, event);
5844 /* Chain up, invokes binding set */
5846 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5852 gtk_window_button_press_event (GtkWidget *widget,
5853 GdkEventButton *event)
5855 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5858 if (event->window == priv->grip_window)
5860 if (get_drag_edge (widget, &edge))
5861 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5875 gtk_window_real_activate_default (GtkWindow *window)
5877 gtk_window_activate_default (window);
5881 gtk_window_real_activate_focus (GtkWindow *window)
5883 gtk_window_activate_focus (window);
5887 gtk_window_enter_notify_event (GtkWidget *widget,
5888 GdkEventCrossing *event)
5894 gtk_window_leave_notify_event (GtkWidget *widget,
5895 GdkEventCrossing *event)
5901 do_focus_change (GtkWidget *widget,
5905 GdkDeviceManager *device_manager;
5908 g_object_ref (widget);
5910 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5911 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5912 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5913 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5915 for (d = devices; d; d = d->next)
5917 GdkDevice *dev = d->data;
5920 if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5923 /* Skip non-master keyboards that haven't
5924 * selected for events from this window
5926 window = gtk_widget_get_window (widget);
5927 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5928 window && !gdk_window_get_device_events (window, dev))
5931 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5933 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5934 fevent->focus_change.window = window;
5936 g_object_ref (window);
5937 fevent->focus_change.in = in;
5938 gdk_event_set_device (fevent, dev);
5940 gtk_widget_send_focus_change (widget, fevent);
5942 gdk_event_free (fevent);
5945 g_list_free (devices);
5946 g_object_unref (widget);
5950 gtk_window_focus_in_event (GtkWidget *widget,
5951 GdkEventFocus *event)
5953 GtkWindow *window = GTK_WINDOW (widget);
5955 /* It appears spurious focus in events can occur when
5956 * the window is hidden. So we'll just check to see if
5957 * the window is visible before actually handling the
5960 if (gtk_widget_get_visible (widget))
5962 _gtk_window_set_has_toplevel_focus (window, TRUE);
5963 _gtk_window_set_is_active (window, TRUE);
5970 gtk_window_focus_out_event (GtkWidget *widget,
5971 GdkEventFocus *event)
5973 GtkWindow *window = GTK_WINDOW (widget);
5974 gboolean auto_mnemonics;
5976 _gtk_window_set_has_toplevel_focus (window, FALSE);
5977 _gtk_window_set_is_active (window, FALSE);
5979 /* set the mnemonic-visible property to false */
5980 g_object_get (gtk_widget_get_settings (widget),
5981 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5983 gtk_window_set_mnemonics_visible (window, FALSE);
5988 static GdkAtom atom_rcfiles = GDK_NONE;
5989 static GdkAtom atom_iconthemes = GDK_NONE;
5992 send_client_message_to_embedded_windows (GtkWidget *widget,
5993 GdkAtom message_type)
5995 GList *embedded_windows;
5997 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5998 if (embedded_windows)
6000 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
6003 for (i = 0; i < 5; i++)
6004 send_event->client.data.l[i] = 0;
6005 send_event->client.data_format = 32;
6006 send_event->client.message_type = message_type;
6008 while (embedded_windows)
6010 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
6011 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
6012 embedded_windows = embedded_windows->next;
6015 gdk_event_free (send_event);
6020 gtk_window_client_event (GtkWidget *widget,
6021 GdkEventClient *event)
6025 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
6026 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
6029 if (event->message_type == atom_rcfiles)
6031 send_client_message_to_embedded_windows (widget, atom_rcfiles);
6032 gtk_style_context_reset_widgets (gtk_widget_get_screen (widget));
6035 if (event->message_type == atom_iconthemes)
6037 send_client_message_to_embedded_windows (widget, atom_iconthemes);
6038 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
6045 gtk_window_check_resize (GtkContainer *container)
6047 if (gtk_widget_get_visible (GTK_WIDGET (container)))
6048 gtk_window_move_resize (GTK_WINDOW (container));
6052 gtk_window_focus (GtkWidget *widget,
6053 GtkDirectionType direction)
6055 GtkWindowPrivate *priv;
6058 GtkContainer *container;
6060 GtkWidget *old_focus_child;
6063 container = GTK_CONTAINER (widget);
6064 window = GTK_WINDOW (widget);
6065 priv = window->priv;
6066 bin = GTK_BIN (widget);
6068 old_focus_child = gtk_container_get_focus_child (container);
6070 /* We need a special implementation here to deal properly with wrapping
6071 * around in the tab chain without the danger of going into an
6074 if (old_focus_child)
6076 if (gtk_widget_child_focus (old_focus_child, direction))
6080 if (priv->focus_widget)
6082 if (direction == GTK_DIR_LEFT ||
6083 direction == GTK_DIR_RIGHT ||
6084 direction == GTK_DIR_UP ||
6085 direction == GTK_DIR_DOWN)
6090 /* Wrapped off the end, clear the focus setting for the toplpevel */
6091 parent = gtk_widget_get_parent (priv->focus_widget);
6094 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6095 parent = gtk_widget_get_parent (parent);
6098 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6101 /* Now try to focus the first widget in the window */
6102 child = gtk_bin_get_child (bin);
6105 if (gtk_widget_child_focus (child, direction))
6113 gtk_window_move_focus (GtkWidget *widget,
6114 GtkDirectionType dir)
6116 gtk_widget_child_focus (widget, dir);
6118 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6119 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6123 gtk_window_real_set_focus (GtkWindow *window,
6126 GtkWindowPrivate *priv = window->priv;
6127 GtkWidget *old_focus = priv->focus_widget;
6128 gboolean had_default = FALSE;
6129 gboolean focus_had_default = FALSE;
6130 gboolean old_focus_had_default = FALSE;
6134 g_object_ref (old_focus);
6135 g_object_freeze_notify (G_OBJECT (old_focus));
6136 old_focus_had_default = gtk_widget_has_default (old_focus);
6140 g_object_ref (focus);
6141 g_object_freeze_notify (G_OBJECT (focus));
6142 focus_had_default = gtk_widget_has_default (focus);
6145 if (priv->default_widget)
6146 had_default = gtk_widget_has_default (priv->default_widget);
6148 if (priv->focus_widget)
6150 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6151 (priv->focus_widget != priv->default_widget))
6153 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6154 gtk_widget_queue_draw (priv->focus_widget);
6156 if (priv->default_widget)
6157 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6160 priv->focus_widget = NULL;
6162 if (priv->has_focus)
6163 do_focus_change (old_focus, FALSE);
6165 g_object_notify (G_OBJECT (old_focus), "is-focus");
6168 /* The above notifications may have set a new focus widget,
6169 * if so, we don't want to override it.
6171 if (focus && !priv->focus_widget)
6173 priv->focus_widget = focus;
6175 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6176 (priv->focus_widget != priv->default_widget))
6178 if (gtk_widget_get_can_default (priv->focus_widget))
6179 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6181 if (priv->default_widget)
6182 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6185 if (priv->has_focus)
6186 do_focus_change (priv->focus_widget, TRUE);
6188 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6191 /* If the default widget changed, a redraw will have been queued
6192 * on the old and new default widgets by gtk_window_set_default(), so
6193 * we only have to worry about the case where it didn't change.
6194 * We'll sometimes queue a draw twice on the new widget but that
6197 if (priv->default_widget &&
6198 (had_default != gtk_widget_has_default (priv->default_widget)))
6199 gtk_widget_queue_draw (priv->default_widget);
6203 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6204 gtk_widget_queue_draw (old_focus);
6206 g_object_thaw_notify (G_OBJECT (old_focus));
6207 g_object_unref (old_focus);
6211 if (focus_had_default != gtk_widget_has_default (focus))
6212 gtk_widget_queue_draw (focus);
6214 g_object_thaw_notify (G_OBJECT (focus));
6215 g_object_unref (focus);
6221 gtk_window_get_preferred_width (GtkWidget *widget,
6229 window = GTK_WINDOW (widget);
6230 child = gtk_bin_get_child (GTK_BIN (window));
6232 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6233 *minimum_size = border_width * 2;
6234 *natural_size = border_width * 2;
6236 if (child && gtk_widget_get_visible (child))
6238 gint child_min, child_nat;
6239 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6241 *minimum_size += child_min;
6242 *natural_size += child_nat;
6247 gtk_window_get_preferred_height (GtkWidget *widget,
6255 window = GTK_WINDOW (widget);
6256 child = gtk_bin_get_child (GTK_BIN (window));
6258 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6259 *minimum_size = border_width * 2;
6260 *natural_size = border_width * 2;
6262 if (child && gtk_widget_get_visible (child))
6264 gint child_min, child_nat;
6265 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6267 *minimum_size += child_min;
6268 *natural_size += child_nat;
6274 * _gtk_window_unset_focus_and_default:
6275 * @window: a #GtkWindow
6276 * @widget: a widget inside of @window
6278 * Checks whether the focus and default widgets of @window are
6279 * @widget or a descendent of @widget, and if so, unset them.
6282 _gtk_window_unset_focus_and_default (GtkWindow *window,
6286 GtkWindowPrivate *priv = window->priv;
6290 g_object_ref (window);
6291 g_object_ref (widget);
6293 parent = gtk_widget_get_parent (widget);
6294 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6296 child = priv->focus_widget;
6298 while (child && child != widget)
6299 child = gtk_widget_get_parent (child);
6301 if (child == widget)
6302 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6305 child = priv->default_widget;
6307 while (child && child != widget)
6308 child = gtk_widget_get_parent (child);
6310 if (child == widget)
6311 gtk_window_set_default (window, NULL);
6313 g_object_unref (widget);
6314 g_object_unref (window);
6317 /*********************************
6318 * Functions related to resizing *
6319 *********************************/
6322 geometry_size_to_pixels (GdkGeometry *geometry,
6327 gint base_width = 0;
6328 gint base_height = 0;
6330 gint min_height = 0;
6332 gint height_inc = 1;
6334 if (flags & GDK_HINT_BASE_SIZE)
6336 base_width = geometry->base_width;
6337 base_height = geometry->base_height;
6339 if (flags & GDK_HINT_MIN_SIZE)
6341 min_width = geometry->min_width;
6342 min_height = geometry->min_height;
6344 if (flags & GDK_HINT_RESIZE_INC)
6346 width_inc = geometry->width_inc;
6347 height_inc = geometry->height_inc;
6351 *width = MAX (*width * width_inc + base_width, min_width);
6353 *height = MAX (*height * height_inc + base_height, min_height);
6356 /* This function doesn't constrain to geometry hints */
6358 gtk_window_compute_configure_request_size (GtkWindow *window,
6359 GdkGeometry *geometry,
6364 GtkWindowPrivate *priv = window->priv;
6365 GtkRequisition requisition;
6366 GtkWindowGeometryInfo *info;
6370 * - we've done a size request
6373 widget = GTK_WIDGET (window);
6375 info = gtk_window_get_geometry_info (window, FALSE);
6377 if (priv->need_default_size)
6379 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6381 /* Default to requisition */
6382 *width = requisition.width;
6383 *height = requisition.height;
6385 /* If window is empty so requests 0, default to random nonzero size */
6386 if (*width == 0 && *height == 0)
6392 /* Override requisition with default size */
6396 if (info->default_width > 0)
6397 *width = info->default_width;
6398 if (info->default_height > 0)
6399 *height = info->default_height;
6401 if (info->default_is_geometry)
6402 geometry_size_to_pixels (geometry, flags,
6403 info->default_width > 0 ? width : NULL,
6404 info->default_height > 0 ? height : NULL);
6409 GtkAllocation allocation;
6411 gtk_widget_get_allocation (widget, &allocation);
6413 /* Default to keeping current size */
6414 *width = allocation.width;
6415 *height = allocation.height;
6418 /* Override any size with gtk_window_resize() values */
6421 if (info->resize_width > 0)
6422 *width = info->resize_width;
6423 if (info->resize_height > 0)
6424 *height = info->resize_height;
6426 if (info->resize_is_geometry)
6427 geometry_size_to_pixels (geometry, flags,
6428 info->resize_width > 0 ? width : NULL,
6429 info->resize_height > 0 ? height : NULL);
6432 /* Don't ever request zero width or height, its not supported by
6433 gdk. The size allocation code will round it to 1 anyway but if
6434 we do it then the value returned from this function will is
6435 not comparable to the size allocation read from the GtkWindow. */
6436 *width = MAX (*width, 1);
6437 *height = MAX (*height, 1);
6440 static GtkWindowPosition
6441 get_effective_position (GtkWindow *window)
6443 GtkWindowPrivate *priv = window->priv;
6444 GtkWindowPosition pos = priv->position;
6446 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6447 (priv->transient_parent == NULL ||
6448 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6449 pos = GTK_WIN_POS_NONE;
6455 get_center_monitor_of_window (GtkWindow *window)
6457 /* We could try to sort out the relative positions of the monitors and
6458 * stuff, or we could just be losers and assume you have a row
6459 * or column of monitors.
6461 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6465 get_monitor_containing_pointer (GtkWindow *window)
6469 GdkScreen *window_screen;
6470 GdkScreen *pointer_screen;
6471 GdkDisplay *display;
6472 GdkDeviceManager *device_manager;
6475 window_screen = gtk_window_check_screen (window);
6476 display = gdk_screen_get_display (window_screen);
6477 device_manager = gdk_display_get_device_manager (display);
6478 pointer = gdk_device_manager_get_client_pointer (device_manager);
6480 gdk_display_get_device_state (display, pointer,
6484 if (pointer_screen == window_screen)
6485 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6493 center_window_on_monitor (GtkWindow *window,
6499 GdkRectangle monitor;
6502 monitor_num = get_monitor_containing_pointer (window);
6504 if (monitor_num == -1)
6505 monitor_num = get_center_monitor_of_window (window);
6507 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6508 monitor_num, &monitor);
6510 *x = (monitor.width - w) / 2 + monitor.x;
6511 *y = (monitor.height - h) / 2 + monitor.y;
6513 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6514 * and WM decorations.
6528 if (extent > clamp_extent)
6530 *base = clamp_base + clamp_extent/2 - extent/2;
6531 else if (*base < clamp_base)
6533 else if (*base + extent > clamp_base + clamp_extent)
6534 *base = clamp_base + clamp_extent - extent;
6538 clamp_window_to_rectangle (gint *x,
6542 const GdkRectangle *rect)
6544 #ifdef DEBUGGING_OUTPUT
6545 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);
6548 /* If it is too large, center it. If it fits on the monitor but is
6549 * partially outside, move it to the closest edge. Do this
6550 * separately in x and y directions.
6552 clamp (x, w, rect->x, rect->width);
6553 clamp (y, h, rect->y, rect->height);
6554 #ifdef DEBUGGING_OUTPUT
6555 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6561 gtk_window_compute_configure_request (GtkWindow *window,
6562 GdkRectangle *request,
6563 GdkGeometry *geometry,
6566 GtkWindowPrivate *priv = window->priv;
6567 GdkGeometry new_geometry;
6571 GtkWindowPosition pos;
6572 GtkWidget *parent_widget;
6573 GtkWindowGeometryInfo *info;
6577 widget = GTK_WIDGET (window);
6579 screen = gtk_window_check_screen (window);
6581 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6582 gtk_window_compute_configure_request_size (window,
6583 &new_geometry, new_flags,
6584 (guint *)&w, (guint *)&h);
6586 gtk_window_constrain_size (window,
6587 &new_geometry, new_flags,
6591 parent_widget = (GtkWidget*) priv->transient_parent;
6593 pos = get_effective_position (window);
6594 info = gtk_window_get_geometry_info (window, FALSE);
6596 /* by default, don't change position requested */
6599 x = info->last.configure_request.x;
6600 y = info->last.configure_request.y;
6609 if (priv->need_default_position)
6612 /* FIXME this all interrelates with window gravity.
6613 * For most of them I think we want to set GRAVITY_CENTER.
6615 * Not sure how to go about that.
6620 /* here we are only handling CENTER_ALWAYS
6621 * as it relates to default positioning,
6622 * where it's equivalent to simply CENTER
6624 case GTK_WIN_POS_CENTER_ALWAYS:
6625 case GTK_WIN_POS_CENTER:
6626 center_window_on_monitor (window, w, h, &x, &y);
6629 case GTK_WIN_POS_CENTER_ON_PARENT:
6631 GtkAllocation allocation;
6632 GdkWindow *gdk_window;
6634 GdkRectangle monitor;
6637 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6639 gdk_window = gtk_widget_get_window (parent_widget);
6641 if (gdk_window != NULL)
6642 monitor_num = gdk_screen_get_monitor_at_window (screen,
6647 gdk_window_get_origin (gdk_window,
6650 gtk_widget_get_allocation (parent_widget, &allocation);
6651 x = ox + (allocation.width - w) / 2;
6652 y = oy + (allocation.height - h) / 2;
6654 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6655 * WM decorations. If parent wasn't on a monitor, just
6658 if (monitor_num >= 0)
6660 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6661 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6666 case GTK_WIN_POS_MOUSE:
6668 gint screen_width = gdk_screen_get_width (screen);
6669 gint screen_height = gdk_screen_get_height (screen);
6671 GdkRectangle monitor;
6672 GdkDisplay *display;
6673 GdkDeviceManager *device_manager;
6675 GdkScreen *pointer_screen;
6678 display = gdk_screen_get_display (screen);
6679 device_manager = gdk_display_get_device_manager (display);
6680 pointer = gdk_device_manager_get_client_pointer (device_manager);
6682 gdk_display_get_device_state (display, pointer,
6686 if (pointer_screen == screen)
6687 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6693 x = CLAMP (x, 0, screen_width - w);
6694 y = CLAMP (y, 0, screen_height - h);
6696 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6697 * WM decorations. Don't try to figure out what's going
6698 * on if the mouse wasn't inside a monitor.
6700 if (monitor_num >= 0)
6702 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6703 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6711 } /* if (priv->need_default_position) */
6713 if (priv->need_default_position && info &&
6714 info->initial_pos_set)
6716 x = info->initial_x;
6717 y = info->initial_y;
6718 gtk_window_constrain_position (window, w, h, &x, &y);
6724 request->height = h;
6727 *geometry = new_geometry;
6733 gtk_window_constrain_position (GtkWindow *window,
6739 GtkWindowPrivate *priv = window->priv;
6741 /* See long comments in gtk_window_move_resize()
6742 * on when it's safe to call this function.
6744 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6746 gint center_x, center_y;
6748 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6756 gtk_window_move_resize (GtkWindow *window)
6760 * First we determine whether any information has changed that would
6761 * cause us to revise our last configure request. If we would send
6762 * a different configure request from last time, then
6763 * configure_request_size_changed = TRUE or
6764 * configure_request_pos_changed = TRUE. configure_request_size_changed
6765 * may be true due to new hints, a gtk_window_resize(), or whatever.
6766 * configure_request_pos_changed may be true due to gtk_window_set_position()
6767 * or gtk_window_move().
6769 * If the configure request has changed, we send off a new one. To
6770 * ensure GTK+ invariants are maintained (resize queue does what it
6771 * should), we go ahead and size_allocate the requested size in this
6774 * If the configure request has not changed, we don't ever resend
6775 * it, because it could mean fighting the user or window manager.
6778 * To prepare the configure request, we come up with a base size/pos:
6779 * - the one from gtk_window_move()/gtk_window_resize()
6780 * - else default_width, default_height if we haven't ever
6782 * - else the size request if we haven't ever been mapped,
6783 * as a substitute default size
6784 * - else the current size of the window, as received from
6785 * configure notifies (i.e. the current allocation)
6787 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6788 * the position request to be centered.
6790 GtkWindowPrivate *priv = window->priv;
6791 GtkAllocation allocation;
6793 GtkContainer *container;
6794 GtkWindowGeometryInfo *info;
6795 GdkGeometry new_geometry;
6796 GdkWindow *gdk_window;
6798 GdkRectangle new_request;
6799 gboolean configure_request_size_changed;
6800 gboolean configure_request_pos_changed;
6801 gboolean hints_changed; /* do we need to send these again */
6802 GtkWindowLastGeometryInfo saved_last_info;
6804 widget = GTK_WIDGET (window);
6805 gdk_window = gtk_widget_get_window (widget);
6806 container = GTK_CONTAINER (widget);
6807 info = gtk_window_get_geometry_info (window, TRUE);
6809 configure_request_size_changed = FALSE;
6810 configure_request_pos_changed = FALSE;
6812 gtk_window_compute_configure_request (window, &new_request,
6813 &new_geometry, &new_flags);
6815 /* This check implies the invariant that we never set info->last
6816 * without setting the hints and sending off a configure request.
6818 * If we change info->last without sending the request, we may
6821 if (info->last.configure_request.x != new_request.x ||
6822 info->last.configure_request.y != new_request.y)
6823 configure_request_pos_changed = TRUE;
6825 if ((info->last.configure_request.width != new_request.width ||
6826 info->last.configure_request.height != new_request.height))
6827 configure_request_size_changed = TRUE;
6829 hints_changed = FALSE;
6831 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6832 &new_geometry, new_flags))
6834 hints_changed = TRUE;
6837 /* Position Constraints
6838 * ====================
6840 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6841 * a default. The other POS_ values are used only when the
6842 * window is shown, not after that.
6844 * However, we can't implement a position constraint as
6845 * "anytime the window size changes, center the window"
6846 * because this may well end up fighting the WM or user. In
6847 * fact it gets in an infinite loop with at least one WM.
6849 * Basically, applications are in no way in a position to
6850 * constrain the position of a window, with one exception:
6851 * override redirect windows. (Really the intended purpose
6852 * of CENTER_ALWAYS anyhow, I would think.)
6854 * So the way we implement this "constraint" is to say that when WE
6855 * cause a move or resize, i.e. we make a configure request changing
6856 * window size, we recompute the CENTER_ALWAYS position to reflect
6857 * the new window size, and include it in our request. Also, if we
6858 * just turned on CENTER_ALWAYS we snap to center with a new
6859 * request. Otherwise, if we are just NOTIFIED of a move or resize
6860 * done by someone else e.g. the window manager, we do NOT send a
6861 * new configure request.
6863 * For override redirect windows, this works fine; all window
6864 * sizes are from our configure requests. For managed windows,
6865 * it is at least semi-sane, though who knows what the
6866 * app author is thinking.
6869 /* This condition should be kept in sync with the condition later on
6870 * that determines whether we send a configure request. i.e. we
6871 * should do this position constraining anytime we were going to
6872 * send a configure request anyhow, plus when constraints have
6875 if (configure_request_pos_changed ||
6876 configure_request_size_changed ||
6878 info->position_constraints_changed)
6880 /* We request the constrained position if:
6881 * - we were changing position, and need to clamp
6882 * the change to the constraint
6883 * - we're changing the size anyway
6884 * - set_position() was called to toggle CENTER_ALWAYS on
6887 gtk_window_constrain_position (window,
6893 /* Update whether we need to request a move */
6894 if (info->last.configure_request.x != new_request.x ||
6895 info->last.configure_request.y != new_request.y)
6896 configure_request_pos_changed = TRUE;
6898 configure_request_pos_changed = FALSE;
6902 if (priv->type == GTK_WINDOW_TOPLEVEL)
6904 int notify_x, notify_y;
6906 /* this is the position from the last configure notify */
6907 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6909 g_message ("--- %s ---\n"
6910 "last : %d,%d\t%d x %d\n"
6911 "this : %d,%d\t%d x %d\n"
6912 "alloc : %d,%d\t%d x %d\n"
6914 "resize: \t%d x %d\n"
6915 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6916 "configure_notify_received: %d\n"
6917 "configure_request_count: %d\n"
6918 "position_constraints_changed: %d\n",
6919 priv->title ? priv->title : "(no title)",
6920 info->last.configure_request.x,
6921 info->last.configure_request.y,
6922 info->last.configure_request.width,
6923 info->last.configure_request.height,
6929 widget->allocation.width,
6930 widget->allocation.height,
6931 widget->requisition.width,
6932 widget->requisition.height,
6934 info->resize_height,
6935 configure_request_pos_changed,
6936 configure_request_size_changed,
6938 priv->configure_notify_received,
6939 priv->configure_request_count,
6940 info->position_constraints_changed);
6944 saved_last_info = info->last;
6945 info->last.geometry = new_geometry;
6946 info->last.flags = new_flags;
6947 info->last.configure_request = new_request;
6949 /* need to set PPosition so the WM will look at our position,
6950 * but we don't want to count PPosition coming and going as a hints
6951 * change for future iterations. So we saved info->last prior to
6955 /* Also, if the initial position was explicitly set, then we always
6956 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6960 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6961 * this is an initial map
6964 if ((configure_request_pos_changed ||
6965 info->initial_pos_set ||
6966 (priv->need_default_position &&
6967 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6968 (new_flags & GDK_HINT_POS) == 0)
6970 new_flags |= GDK_HINT_POS;
6971 hints_changed = TRUE;
6974 /* Set hints if necessary
6977 gdk_window_set_geometry_hints (gdk_window,
6981 gtk_widget_get_allocation (widget, &allocation);
6983 /* handle resizing/moving and widget tree allocation
6985 if (priv->configure_notify_received)
6987 /* If we have received a configure event since
6988 * the last time in this function, we need to
6989 * accept our new size and size_allocate child widgets.
6990 * (see gtk_window_configure_event() for more details).
6992 * 1 or more configure notifies may have been received.
6993 * Also, configure_notify_received will only be TRUE
6994 * if all expected configure notifies have been received
6995 * (one per configure request), as an optimization.
6998 priv->configure_notify_received = FALSE;
7000 /* gtk_window_configure_event() filled in widget->allocation */
7001 gtk_widget_size_allocate (widget, &allocation);
7003 set_grip_position (window);
7004 update_grip_visibility (window);
7006 gdk_window_process_updates (gdk_window, TRUE);
7008 gdk_window_configure_finished (gdk_window);
7010 /* If the configure request changed, it means that
7012 * 1) coincidentally changed hints or widget properties
7013 * impacting the configure request before getting
7014 * a configure notify, or
7015 * 2) some broken widget is changing its size request
7016 * during size allocation, resulting in
7017 * a false appearance of changed configure request.
7019 * For 1), we could just go ahead and ask for the
7020 * new size right now, but doing that for 2)
7021 * might well be fighting the user (and can even
7022 * trigger a loop). Since we really don't want to
7023 * do that, we requeue a resize in hopes that
7024 * by the time it gets handled, the child has seen
7025 * the light and is willing to go along with the
7026 * new size. (this happens for the zvt widget, since
7027 * the size_allocate() above will have stored the
7028 * requisition corresponding to the new size in the
7031 * This doesn't buy us anything for 1), but it shouldn't
7032 * hurt us too badly, since it is what would have
7033 * happened if we had gotten the configure event before
7034 * the new size had been set.
7037 if (configure_request_size_changed ||
7038 configure_request_pos_changed)
7040 /* Don't change the recorded last info after all, because we
7041 * haven't actually updated to the new info yet - we decided
7042 * to postpone our configure request until later.
7044 info->last = saved_last_info;
7046 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7049 return; /* Bail out, we didn't really process the move/resize */
7051 else if ((configure_request_size_changed || hints_changed) &&
7052 (allocation.width != new_request.width || allocation.height != new_request.height))
7055 /* We are in one of the following situations:
7056 * A. configure_request_size_changed
7057 * our requisition has changed and we need a different window size,
7058 * so we request it from the window manager.
7059 * B. !configure_request_size_changed && hints_changed
7060 * the window manager rejects our size, but we have just changed the
7061 * window manager hints, so there's a chance our request will
7062 * be honoured this time, so we try again.
7064 * However, if the new requisition is the same as the current allocation,
7065 * we don't request it again, since we won't get a ConfigureNotify back from
7066 * the window manager unless it decides to change our requisition. If
7067 * we don't get the ConfigureNotify back, the resize queue will never be run.
7070 /* Now send the configure request */
7071 if (configure_request_pos_changed)
7075 gdk_window_move_resize (priv->frame,
7076 new_request.x - priv->frame_left,
7077 new_request.y - priv->frame_top,
7078 new_request.width + priv->frame_left + priv->frame_right,
7079 new_request.height + priv->frame_top + priv->frame_bottom);
7080 gdk_window_resize (gdk_window,
7081 new_request.width, new_request.height);
7084 gdk_window_move_resize (gdk_window,
7085 new_request.x, new_request.y,
7086 new_request.width, new_request.height);
7088 else /* only size changed */
7091 gdk_window_resize (priv->frame,
7092 new_request.width + priv->frame_left + priv->frame_right,
7093 new_request.height + priv->frame_top + priv->frame_bottom);
7094 gdk_window_resize (gdk_window,
7095 new_request.width, new_request.height);
7098 if (priv->type == GTK_WINDOW_POPUP)
7100 GtkAllocation allocation;
7102 /* Directly size allocate for override redirect (popup) windows. */
7105 allocation.width = new_request.width;
7106 allocation.height = new_request.height;
7108 gtk_widget_size_allocate (widget, &allocation);
7110 gdk_window_process_updates (gdk_window, TRUE);
7112 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7113 gtk_widget_queue_draw (widget);
7117 /* Increment the number of have-not-yet-received-notify requests */
7118 priv->configure_request_count += 1;
7119 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7121 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7122 * configure event in response to our resizing request.
7123 * the configure event will cause a new resize with
7124 * ->configure_notify_received=TRUE.
7125 * until then, we want to
7126 * - discard expose events
7127 * - coalesce resizes for our children
7128 * - defer any window resizes until the configure event arrived
7129 * to achieve this, we queue a resize for the window, but remove its
7130 * resizing handler, so resizing will not be handled from the next
7131 * idle handler but when the configure event arrives.
7133 * FIXME: we should also dequeue the pending redraws here, since
7134 * we handle those ourselves upon ->configure_notify_received==TRUE.
7136 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7138 gtk_widget_queue_resize_no_redraw (widget);
7139 _gtk_container_dequeue_resize_handler (container);
7145 /* Handle any position changes.
7147 if (configure_request_pos_changed)
7151 gdk_window_move (priv->frame,
7152 new_request.x - priv->frame_left,
7153 new_request.y - priv->frame_top);
7156 gdk_window_move (gdk_window,
7157 new_request.x, new_request.y);
7160 /* And run the resize queue.
7162 gtk_container_resize_children (container);
7165 /* We have now processed a move/resize since the last position
7166 * constraint change, setting of the initial position, or resize.
7167 * (Not resetting these flags here can lead to infinite loops for
7168 * GTK_RESIZE_IMMEDIATE containers)
7170 info->position_constraints_changed = FALSE;
7171 info->initial_pos_set = FALSE;
7172 info->resize_width = -1;
7173 info->resize_height = -1;
7176 /* Compare two sets of Geometry hints for equality.
7179 gtk_window_compare_hints (GdkGeometry *geometry_a,
7181 GdkGeometry *geometry_b,
7184 if (flags_a != flags_b)
7187 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7188 (geometry_a->min_width != geometry_b->min_width ||
7189 geometry_a->min_height != geometry_b->min_height))
7192 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7193 (geometry_a->max_width != geometry_b->max_width ||
7194 geometry_a->max_height != geometry_b->max_height))
7197 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7198 (geometry_a->base_width != geometry_b->base_width ||
7199 geometry_a->base_height != geometry_b->base_height))
7202 if ((flags_a & GDK_HINT_ASPECT) &&
7203 (geometry_a->min_aspect != geometry_b->min_aspect ||
7204 geometry_a->max_aspect != geometry_b->max_aspect))
7207 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7208 (geometry_a->width_inc != geometry_b->width_inc ||
7209 geometry_a->height_inc != geometry_b->height_inc))
7212 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7213 geometry_a->win_gravity != geometry_b->win_gravity)
7220 _gtk_window_constrain_size (GtkWindow *window,
7226 GtkWindowPrivate *priv;
7227 GtkWindowGeometryInfo *info;
7229 g_return_if_fail (GTK_IS_WINDOW (window));
7231 priv = window->priv;
7233 info = priv->geometry_info;
7236 GdkWindowHints flags = info->last.flags;
7237 GdkGeometry *geometry = &info->last.geometry;
7239 gtk_window_constrain_size (window,
7250 gtk_window_constrain_size (GtkWindow *window,
7251 GdkGeometry *geometry,
7258 gdk_window_constrain_size (geometry, flags, width, height,
7259 new_width, new_height);
7262 /* Compute the set of geometry hints and flags for a window
7263 * based on the application set geometry, and requisition
7264 * of the window. gtk_widget_get_preferred_size() must have been
7268 gtk_window_compute_hints (GtkWindow *window,
7269 GdkGeometry *new_geometry,
7272 GtkWindowPrivate *priv = window->priv;
7274 gint extra_width = 0;
7275 gint extra_height = 0;
7276 GtkWindowGeometryInfo *geometry_info;
7277 GtkRequisition requisition;
7279 widget = GTK_WIDGET (window);
7281 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7282 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7286 *new_flags = geometry_info->mask;
7287 *new_geometry = geometry_info->geometry;
7294 if (geometry_info && geometry_info->widget)
7296 /* If the geometry widget is set, then the hints really apply to that
7297 * widget. This is pretty much meaningless unless the window layout
7298 * is such that the rest of the window adds fixed size borders to
7299 * the geometry widget. Our job is to figure the size of the borders;
7300 * We do that by asking how big the toplevel would be if the
7301 * geometry widget was *really big*.
7304 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7305 * |GGGGG B| in the border can confuse things
7311 * |AAAAAAAAA | When the geometry widget is large, things are
7312 * |GGGGGGGGGGB| clearer.
7317 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7318 GtkRequisition requisition;
7319 int current_width, current_height;
7321 _gtk_widget_override_size_request (geometry_info->widget,
7322 TEMPORARY_SIZE, TEMPORARY_SIZE,
7323 ¤t_width, ¤t_height);
7324 gtk_widget_get_preferred_size (widget,
7325 &requisition, NULL);
7326 _gtk_widget_restore_size_request (geometry_info->widget,
7327 current_width, current_height);
7329 extra_width = requisition.width - TEMPORARY_SIZE;
7330 extra_height = requisition.height - TEMPORARY_SIZE;
7332 if (extra_width < 0 || extra_width < 0)
7334 g_warning("Toplevel size doesn't seem to directly depend on the "
7335 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7336 "The geometry widget might not be in the window, or it might not "
7337 "be packed into the window appropriately");
7338 extra_width = MAX(extra_width, 0);
7339 extra_height = MAX(extra_height, 0);
7341 #undef TEMPORARY_SIZE
7344 /* We don't want to set GDK_HINT_POS in here, we just set it
7345 * in gtk_window_move_resize() when we want the position
7349 if (*new_flags & GDK_HINT_BASE_SIZE)
7351 new_geometry->base_width += extra_width;
7352 new_geometry->base_height += extra_height;
7356 /* For simplicity, we always set the base hint, even when we
7357 * don't expect it to have any visible effect.
7358 * (Note: geometry_size_to_pixels() depends on this.)
7360 *new_flags |= GDK_HINT_BASE_SIZE;
7362 new_geometry->base_width = extra_width;
7363 new_geometry->base_height = extra_height;
7365 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7366 * base size is the minimum size */
7367 if (*new_flags & GDK_HINT_MIN_SIZE)
7369 if (new_geometry->min_width > 0)
7370 new_geometry->base_width += new_geometry->min_width;
7371 if (new_geometry->min_height > 0)
7372 new_geometry->base_height += new_geometry->min_height;
7376 if (*new_flags & GDK_HINT_MIN_SIZE)
7378 if (new_geometry->min_width < 0)
7379 new_geometry->min_width = requisition.width;
7381 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7383 if (new_geometry->min_height < 0)
7384 new_geometry->min_height = requisition.height;
7386 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7390 *new_flags |= GDK_HINT_MIN_SIZE;
7392 new_geometry->min_width = requisition.width;
7393 new_geometry->min_height = requisition.height;
7396 if (*new_flags & GDK_HINT_MAX_SIZE)
7398 if (new_geometry->max_width < 0)
7399 new_geometry->max_width = requisition.width;
7401 new_geometry->max_width += extra_width;
7403 if (new_geometry->max_height < 0)
7404 new_geometry->max_height = requisition.height;
7406 new_geometry->max_height += extra_height;
7408 else if (!priv->resizable)
7410 *new_flags |= GDK_HINT_MAX_SIZE;
7412 new_geometry->max_width = requisition.width;
7413 new_geometry->max_height = requisition.height;
7416 *new_flags |= GDK_HINT_WIN_GRAVITY;
7417 new_geometry->win_gravity = priv->gravity;
7420 /***********************
7421 * Redrawing functions *
7422 ***********************/
7425 gtk_window_draw (GtkWidget *widget,
7428 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7429 GtkStyleContext *context;
7430 gboolean ret = FALSE;
7432 context = gtk_widget_get_style_context (widget);
7434 gtk_style_context_save (context);
7436 if (!gtk_widget_get_app_paintable (widget))
7438 GtkStateFlags state;
7440 state = gtk_widget_get_state_flags (widget);
7442 if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7443 state |= GTK_STATE_FLAG_FOCUSED;
7445 gtk_style_context_set_state (context, state);
7446 gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7447 gtk_render_background (context, cr, 0, 0,
7448 gtk_widget_get_allocated_width (widget),
7449 gtk_widget_get_allocated_height (widget));
7452 gtk_style_context_restore (context);
7454 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7455 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7457 if (priv->grip_window != NULL &&
7458 gtk_cairo_should_draw_window (cr, priv->grip_window))
7462 gtk_style_context_save (context);
7465 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7466 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7468 gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7469 gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7470 gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7473 gtk_style_context_restore (context);
7480 * gtk_window_set_has_frame:
7481 * @window: a #GtkWindow
7482 * @setting: a boolean
7484 * (Note: this is a special-purpose function for the framebuffer port,
7485 * that causes GTK+ to draw its own window border. For most applications,
7486 * you want gtk_window_set_decorated() instead, which tells the window
7487 * manager whether to draw the window border.)
7489 * If this function is called on a window with setting of %TRUE, before
7490 * it is realized or showed, it will have a "frame" window around
7491 * @window->window, accessible in @window->frame. Using the signal
7492 * frame_event you can receive all events targeted at the frame.
7494 * This function is used by the linux-fb port to implement managed
7495 * windows, but it could conceivably be used by X-programs that
7496 * want to do their own window decorations.
7500 gtk_window_set_has_frame (GtkWindow *window,
7503 GtkWindowPrivate *priv;
7505 g_return_if_fail (GTK_IS_WINDOW (window));
7506 g_return_if_fail (!gtk_widget_get_realized (GTK_WIDGET (window)));
7508 priv = window->priv;
7510 priv->has_frame = setting != FALSE;
7514 * gtk_window_get_has_frame:
7515 * @window: a #GtkWindow
7517 * Accessor for whether the window has a frame window exterior to
7518 * @window->window. Gets the value set by gtk_window_set_has_frame ().
7520 * Return value: %TRUE if a frame has been added to the window
7521 * via gtk_window_set_has_frame().
7524 gtk_window_get_has_frame (GtkWindow *window)
7526 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7528 return window->priv->has_frame;
7532 * gtk_window_set_frame_dimensions:
7533 * @window: a #GtkWindow that has a frame
7534 * @left: The width of the left border
7535 * @top: The height of the top border
7536 * @right: The width of the right border
7537 * @bottom: The height of the bottom border
7539 * (Note: this is a special-purpose function intended for the framebuffer
7540 * port; see gtk_window_set_has_frame(). It will have no effect on the
7541 * window border drawn by the window manager, which is the normal
7542 * case when using the X Window system.)
7544 * For windows with frames (see gtk_window_set_has_frame()) this function
7545 * can be used to change the size of the frame border.
7548 gtk_window_set_frame_dimensions (GtkWindow *window,
7554 GtkWindowPrivate *priv;
7555 GtkAllocation allocation;
7558 g_return_if_fail (GTK_IS_WINDOW (window));
7560 priv = window->priv;
7561 widget = GTK_WIDGET (window);
7563 if (priv->frame_left == left &&
7564 priv->frame_top == top &&
7565 priv->frame_right == right &&
7566 priv->frame_bottom == bottom)
7569 priv->frame_left = left;
7570 priv->frame_top = top;
7571 priv->frame_right = right;
7572 priv->frame_bottom = bottom;
7574 if (gtk_widget_get_realized (widget) && priv->frame)
7577 gtk_widget_get_allocation (widget, &allocation);
7579 width = allocation.width + left + right;
7580 height = allocation.height + top + bottom;
7581 gdk_window_resize (priv->frame, width, height);
7582 gdk_window_move_resize (gtk_widget_get_window (GTK_WIDGET (window)),
7590 * gtk_window_present:
7591 * @window: a #GtkWindow
7593 * Presents a window to the user. This may mean raising the window
7594 * in the stacking order, deiconifying it, moving it to the current
7595 * desktop, and/or giving it the keyboard focus, possibly dependent
7596 * on the user's platform, window manager, and preferences.
7598 * If @window is hidden, this function calls gtk_widget_show()
7601 * This function should be used when the user tries to open a window
7602 * that's already open. Say for example the preferences dialog is
7603 * currently open, and the user chooses Preferences from the menu
7604 * a second time; use gtk_window_present() to move the already-open dialog
7605 * where the user can see it.
7607 * If you are calling this function in response to a user interaction,
7608 * it is preferable to use gtk_window_present_with_time().
7612 gtk_window_present (GtkWindow *window)
7614 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7618 * gtk_window_present_with_time:
7619 * @window: a #GtkWindow
7620 * @timestamp: the timestamp of the user interaction (typically a
7621 * button or key press event) which triggered this call
7623 * Presents a window to the user in response to a user interaction.
7624 * If you need to present a window without a timestamp, use
7625 * gtk_window_present(). See gtk_window_present() for details.
7630 gtk_window_present_with_time (GtkWindow *window,
7634 GdkWindow *gdk_window;
7636 g_return_if_fail (GTK_IS_WINDOW (window));
7638 widget = GTK_WIDGET (window);
7640 if (gtk_widget_get_visible (widget))
7642 gdk_window = gtk_widget_get_window (widget);
7644 g_assert (gdk_window != NULL);
7646 gdk_window_show (gdk_window);
7648 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7649 if (timestamp == GDK_CURRENT_TIME)
7651 #ifdef GDK_WINDOWING_X11
7652 GdkDisplay *display;
7654 display = gtk_widget_get_display (GTK_WIDGET (window));
7655 timestamp = gdk_x11_display_get_user_time (display);
7657 timestamp = gtk_get_current_event_time ();
7661 gdk_window_focus (gdk_window, timestamp);
7665 gtk_widget_show (widget);
7670 * gtk_window_iconify:
7671 * @window: a #GtkWindow
7673 * Asks to iconify (i.e. minimize) the specified @window. Note that
7674 * you shouldn't assume the window is definitely iconified afterward,
7675 * because other entities (e.g. the user or <link
7676 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7677 * again, or there may not be a window manager in which case
7678 * iconification isn't possible, etc. But normally the window will end
7679 * up iconified. Just don't write code that crashes if not.
7681 * It's permitted to call this function before showing a window,
7682 * in which case the window will be iconified before it ever appears
7685 * You can track iconification via the "window-state-event" signal
7690 gtk_window_iconify (GtkWindow *window)
7692 GtkWindowPrivate *priv;
7694 GdkWindow *toplevel;
7696 g_return_if_fail (GTK_IS_WINDOW (window));
7698 priv = window->priv;
7699 widget = GTK_WIDGET (window);
7701 priv->iconify_initially = TRUE;
7704 toplevel = priv->frame;
7706 toplevel = gtk_widget_get_window (widget);
7708 if (toplevel != NULL)
7709 gdk_window_iconify (toplevel);
7713 * gtk_window_deiconify:
7714 * @window: a #GtkWindow
7716 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7717 * that you shouldn't assume the window is definitely deiconified
7718 * afterward, because other entities (e.g. the user or <link
7719 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7720 * again before your code which assumes deiconification gets to run.
7722 * You can track iconification via the "window-state-event" signal
7726 gtk_window_deiconify (GtkWindow *window)
7728 GtkWindowPrivate *priv;
7730 GdkWindow *toplevel;
7732 g_return_if_fail (GTK_IS_WINDOW (window));
7734 priv = window->priv;
7735 widget = GTK_WIDGET (window);
7737 priv->iconify_initially = FALSE;
7740 toplevel = priv->frame;
7742 toplevel = gtk_widget_get_window (widget);
7744 if (toplevel != NULL)
7745 gdk_window_deiconify (toplevel);
7750 * @window: a #GtkWindow
7752 * Asks to stick @window, which means that it will appear on all user
7753 * desktops. Note that you shouldn't assume the window is definitely
7754 * stuck afterward, because other entities (e.g. the user or <link
7755 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7756 * again, and some window managers do not support sticking
7757 * windows. But normally the window will end up stuck. Just don't
7758 * write code that crashes if not.
7760 * It's permitted to call this function before showing a window.
7762 * You can track stickiness via the "window-state-event" signal
7767 gtk_window_stick (GtkWindow *window)
7769 GtkWindowPrivate *priv;
7771 GdkWindow *toplevel;
7773 g_return_if_fail (GTK_IS_WINDOW (window));
7775 priv = window->priv;
7776 widget = GTK_WIDGET (window);
7778 priv->stick_initially = TRUE;
7781 toplevel = priv->frame;
7783 toplevel = gtk_widget_get_window (widget);
7785 if (toplevel != NULL)
7786 gdk_window_stick (toplevel);
7790 * gtk_window_unstick:
7791 * @window: a #GtkWindow
7793 * Asks to unstick @window, which means that it will appear on only
7794 * one of the user's desktops. Note that you shouldn't assume the
7795 * window is definitely unstuck afterward, because other entities
7796 * (e.g. the user or <link linkend="gtk-X11-arch">window
7797 * manager</link>) could stick it again. But normally the window will
7798 * end up stuck. Just don't write code that crashes if not.
7800 * You can track stickiness via the "window-state-event" signal
7805 gtk_window_unstick (GtkWindow *window)
7807 GtkWindowPrivate *priv;
7809 GdkWindow *toplevel;
7811 g_return_if_fail (GTK_IS_WINDOW (window));
7813 priv = window->priv;
7814 widget = GTK_WIDGET (window);
7816 priv->stick_initially = FALSE;
7819 toplevel = priv->frame;
7821 toplevel = gtk_widget_get_window (widget);
7823 if (toplevel != NULL)
7824 gdk_window_unstick (toplevel);
7828 * gtk_window_maximize:
7829 * @window: a #GtkWindow
7831 * Asks to maximize @window, so that it becomes full-screen. Note that
7832 * you shouldn't assume the window is definitely maximized afterward,
7833 * because other entities (e.g. the user or <link
7834 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7835 * again, and not all window managers support maximization. But
7836 * normally the window will end up maximized. Just don't write code
7837 * that crashes if not.
7839 * It's permitted to call this function before showing a window,
7840 * in which case the window will be maximized when it appears onscreen
7843 * You can track maximization via the "window-state-event" signal
7848 gtk_window_maximize (GtkWindow *window)
7850 GtkWindowPrivate *priv;
7852 GdkWindow *toplevel;
7854 g_return_if_fail (GTK_IS_WINDOW (window));
7856 priv = window->priv;
7857 widget = GTK_WIDGET (window);
7859 priv->maximize_initially = TRUE;
7862 toplevel = priv->frame;
7864 toplevel = gtk_widget_get_window (widget);
7866 if (toplevel != NULL)
7867 gdk_window_maximize (toplevel);
7871 * gtk_window_unmaximize:
7872 * @window: a #GtkWindow
7874 * Asks to unmaximize @window. Note that you shouldn't assume the
7875 * window is definitely unmaximized afterward, because other entities
7876 * (e.g. the user or <link linkend="gtk-X11-arch">window
7877 * manager</link>) could maximize it again, and not all window
7878 * managers honor requests to unmaximize. But normally the window will
7879 * end up unmaximized. Just don't write code that crashes if not.
7881 * You can track maximization via the "window-state-event" signal
7886 gtk_window_unmaximize (GtkWindow *window)
7888 GtkWindowPrivate *priv;
7890 GdkWindow *toplevel;
7892 g_return_if_fail (GTK_IS_WINDOW (window));
7894 priv = window->priv;
7895 widget = GTK_WIDGET (window);
7897 priv->maximize_initially = FALSE;
7900 toplevel = priv->frame;
7902 toplevel = gtk_widget_get_window (widget);
7904 if (toplevel != NULL)
7905 gdk_window_unmaximize (toplevel);
7909 * gtk_window_fullscreen:
7910 * @window: a #GtkWindow
7912 * Asks to place @window in the fullscreen state. Note that you
7913 * shouldn't assume the window is definitely full screen afterward,
7914 * because other entities (e.g. the user or <link
7915 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7916 * again, and not all window managers honor requests to fullscreen
7917 * windows. But normally the window will end up fullscreen. Just
7918 * don't write code that crashes if not.
7920 * You can track the fullscreen state via the "window-state-event" signal
7926 gtk_window_fullscreen (GtkWindow *window)
7928 GtkWindowPrivate *priv;
7930 GdkWindow *toplevel;
7932 g_return_if_fail (GTK_IS_WINDOW (window));
7934 priv = window->priv;
7935 widget = GTK_WIDGET (window);
7937 priv->fullscreen_initially = TRUE;
7940 toplevel = priv->frame;
7942 toplevel = gtk_widget_get_window (widget);
7944 if (toplevel != NULL)
7945 gdk_window_fullscreen (toplevel);
7949 * gtk_window_unfullscreen:
7950 * @window: a #GtkWindow
7952 * Asks to toggle off the fullscreen state for @window. Note that you
7953 * shouldn't assume the window is definitely not full screen
7954 * afterward, because other entities (e.g. the user or <link
7955 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7956 * again, and not all window managers honor requests to unfullscreen
7957 * windows. But normally the window will end up restored to its normal
7958 * state. Just don't write code that crashes if not.
7960 * You can track the fullscreen state via the "window-state-event" signal
7966 gtk_window_unfullscreen (GtkWindow *window)
7969 GdkWindow *toplevel;
7970 GtkWindowPrivate *priv;
7972 g_return_if_fail (GTK_IS_WINDOW (window));
7974 priv = window->priv;
7975 widget = GTK_WIDGET (window);
7977 priv->fullscreen_initially = FALSE;
7980 toplevel = priv->frame;
7982 toplevel = gtk_widget_get_window (widget);
7984 if (toplevel != NULL)
7985 gdk_window_unfullscreen (toplevel);
7989 * gtk_window_set_keep_above:
7990 * @window: a #GtkWindow
7991 * @setting: whether to keep @window above other windows
7993 * Asks to keep @window above, so that it stays on top. Note that
7994 * you shouldn't assume the window is definitely above afterward,
7995 * because other entities (e.g. the user or <link
7996 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7997 * and not all window managers support keeping windows above. But
7998 * normally the window will end kept above. Just don't write code
7999 * that crashes if not.
8001 * It's permitted to call this function before showing a window,
8002 * in which case the window will be kept above when it appears onscreen
8005 * You can track the above state via the "window-state-event" signal
8008 * Note that, according to the <ulink
8009 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8010 * Manager Hints</ulink> specification, the above state is mainly meant
8011 * for user preferences and should not be used by applications e.g. for
8012 * drawing attention to their dialogs.
8017 gtk_window_set_keep_above (GtkWindow *window,
8021 GtkWindowPrivate *priv;
8022 GdkWindow *toplevel;
8024 g_return_if_fail (GTK_IS_WINDOW (window));
8026 priv = window->priv;
8027 widget = GTK_WIDGET (window);
8029 priv->above_initially = setting != FALSE;
8031 priv->below_initially = FALSE;
8034 toplevel = priv->frame;
8036 toplevel = gtk_widget_get_window (widget);
8038 if (toplevel != NULL)
8039 gdk_window_set_keep_above (toplevel, setting);
8043 * gtk_window_set_keep_below:
8044 * @window: a #GtkWindow
8045 * @setting: whether to keep @window below other windows
8047 * Asks to keep @window below, so that it stays in bottom. Note that
8048 * you shouldn't assume the window is definitely below afterward,
8049 * because other entities (e.g. the user or <link
8050 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8051 * and not all window managers support putting windows below. But
8052 * normally the window will be kept below. Just don't write code
8053 * that crashes if not.
8055 * It's permitted to call this function before showing a window,
8056 * in which case the window will be kept below when it appears onscreen
8059 * You can track the below state via the "window-state-event" signal
8062 * Note that, according to the <ulink
8063 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8064 * Manager Hints</ulink> specification, the above state is mainly meant
8065 * for user preferences and should not be used by applications e.g. for
8066 * drawing attention to their dialogs.
8071 gtk_window_set_keep_below (GtkWindow *window,
8075 GtkWindowPrivate *priv;
8076 GdkWindow *toplevel;
8078 g_return_if_fail (GTK_IS_WINDOW (window));
8080 priv = window->priv;
8081 widget = GTK_WIDGET (window);
8083 priv->below_initially = setting != FALSE;
8085 priv->above_initially = FALSE;
8088 toplevel = priv->frame;
8090 toplevel = gtk_widget_get_window (widget);
8092 if (toplevel != NULL)
8093 gdk_window_set_keep_below (toplevel, setting);
8097 * gtk_window_set_resizable:
8098 * @window: a #GtkWindow
8099 * @resizable: %TRUE if the user can resize this window
8101 * Sets whether the user can resize a window. Windows are user resizable
8105 gtk_window_set_resizable (GtkWindow *window,
8108 GtkWindowPrivate *priv;
8110 g_return_if_fail (GTK_IS_WINDOW (window));
8112 priv = window->priv;
8114 resizable = (resizable != FALSE);
8116 if (priv->resizable != resizable)
8118 priv->resizable = (resizable != FALSE);
8120 update_grip_visibility (window);
8122 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8124 g_object_notify (G_OBJECT (window), "resizable");
8129 * gtk_window_get_resizable:
8130 * @window: a #GtkWindow
8132 * Gets the value set by gtk_window_set_resizable().
8134 * Return value: %TRUE if the user can resize the window
8137 gtk_window_get_resizable (GtkWindow *window)
8139 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8141 return window->priv->resizable;
8145 * gtk_window_set_gravity:
8146 * @window: a #GtkWindow
8147 * @gravity: window gravity
8149 * Window gravity defines the meaning of coordinates passed to
8150 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8153 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8154 * typically "do what you mean."
8158 gtk_window_set_gravity (GtkWindow *window,
8161 GtkWindowPrivate *priv;
8163 g_return_if_fail (GTK_IS_WINDOW (window));
8165 priv = window->priv;
8167 if (gravity != priv->gravity)
8169 priv->gravity = gravity;
8171 /* gtk_window_move_resize() will adapt gravity
8173 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8175 g_object_notify (G_OBJECT (window), "gravity");
8180 * gtk_window_get_gravity:
8181 * @window: a #GtkWindow
8183 * Gets the value set by gtk_window_set_gravity().
8185 * Return value: (transfer none): window gravity
8188 gtk_window_get_gravity (GtkWindow *window)
8190 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8192 return window->priv->gravity;
8196 * gtk_window_begin_resize_drag:
8197 * @window: a #GtkWindow
8198 * @button: mouse button that initiated the drag
8199 * @edge: position of the resize control
8200 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8201 * @root_y: Y position where the user clicked to initiate the drag
8202 * @timestamp: timestamp from the click event that initiated the drag
8204 * Starts resizing a window. This function is used if an application
8205 * has window resizing controls. When GDK can support it, the resize
8206 * will be done using the standard mechanism for the <link
8207 * linkend="gtk-X11-arch">window manager</link> or windowing
8208 * system. Otherwise, GDK will try to emulate window resizing,
8209 * potentially not all that well, depending on the windowing system.
8213 gtk_window_begin_resize_drag (GtkWindow *window,
8220 GtkWindowPrivate *priv;
8222 GdkWindow *toplevel;
8224 g_return_if_fail (GTK_IS_WINDOW (window));
8225 widget = GTK_WIDGET (window);
8226 g_return_if_fail (gtk_widget_get_visible (widget));
8228 priv = window->priv;
8231 toplevel = priv->frame;
8233 toplevel = gtk_widget_get_window (widget);
8235 gdk_window_begin_resize_drag (toplevel,
8242 * gtk_window_get_frame_dimensions:
8243 * @window: a #GtkWindow
8244 * @left: (out) (allow-none): location to store the width of the frame at the left, or %NULL
8245 * @top: (out) (allow-none): location to store the height of the frame at the top, or %NULL
8246 * @right: (out) (allow-none): location to store the width of the frame at the returns, or %NULL
8247 * @bottom: (out) (allow-none): location to store the height of the frame at the bottom, or %NULL
8249 * (Note: this is a special-purpose function intended for the
8250 * framebuffer port; see gtk_window_set_has_frame(). It will not
8251 * return the size of the window border drawn by the <link
8252 * linkend="gtk-X11-arch">window manager</link>, which is the normal
8253 * case when using a windowing system. See
8254 * gdk_window_get_frame_extents() to get the standard window border
8257 * Retrieves the dimensions of the frame window for this toplevel.
8258 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
8261 gtk_window_get_frame_dimensions (GtkWindow *window,
8267 GtkWindowPrivate *priv;
8269 g_return_if_fail (GTK_IS_WINDOW (window));
8271 priv = window->priv;
8274 *left = priv->frame_left;
8276 *top = priv->frame_top;
8278 *right = priv->frame_right;
8280 *bottom = priv->frame_bottom;
8284 * gtk_window_begin_move_drag:
8285 * @window: a #GtkWindow
8286 * @button: mouse button that initiated the drag
8287 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8288 * @root_y: Y position where the user clicked to initiate the drag
8289 * @timestamp: timestamp from the click event that initiated the drag
8291 * Starts moving a window. This function is used if an application has
8292 * window movement grips. When GDK can support it, the window movement
8293 * will be done using the standard mechanism for the <link
8294 * linkend="gtk-X11-arch">window manager</link> or windowing
8295 * system. Otherwise, GDK will try to emulate window movement,
8296 * potentially not all that well, depending on the windowing system.
8300 gtk_window_begin_move_drag (GtkWindow *window,
8306 GtkWindowPrivate *priv;
8308 GdkWindow *toplevel;
8310 g_return_if_fail (GTK_IS_WINDOW (window));
8311 widget = GTK_WIDGET (window);
8312 g_return_if_fail (gtk_widget_get_visible (widget));
8314 priv = window->priv;
8317 toplevel = priv->frame;
8319 toplevel = gtk_widget_get_window (widget);
8321 gdk_window_begin_move_drag (toplevel,
8328 * gtk_window_set_screen:
8329 * @window: a #GtkWindow.
8330 * @screen: a #GdkScreen.
8332 * Sets the #GdkScreen where the @window is displayed; if
8333 * the window is already mapped, it will be unmapped, and
8334 * then remapped on the new screen.
8339 gtk_window_set_screen (GtkWindow *window,
8342 GtkWindowPrivate *priv;
8344 GdkScreen *previous_screen;
8345 gboolean was_mapped;
8347 g_return_if_fail (GTK_IS_WINDOW (window));
8348 g_return_if_fail (GDK_IS_SCREEN (screen));
8350 priv = window->priv;
8352 if (screen == priv->screen)
8355 widget = GTK_WIDGET (window);
8357 previous_screen = priv->screen;
8358 was_mapped = gtk_widget_get_mapped (widget);
8361 gtk_widget_unmap (widget);
8362 if (gtk_widget_get_realized (widget))
8363 gtk_widget_unrealize (widget);
8365 gtk_window_free_key_hash (window);
8366 priv->screen = screen;
8367 gtk_widget_reset_rc_styles (widget);
8368 if (screen != previous_screen)
8370 g_signal_handlers_disconnect_by_func (previous_screen,
8371 gtk_window_on_composited_changed, window);
8372 g_signal_connect (screen, "composited-changed",
8373 G_CALLBACK (gtk_window_on_composited_changed), window);
8375 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8376 _gtk_widget_propagate_composited_changed (widget);
8378 g_object_notify (G_OBJECT (window), "screen");
8381 gtk_widget_map (widget);
8385 gtk_window_on_composited_changed (GdkScreen *screen,
8388 gtk_widget_queue_draw (GTK_WIDGET (window));
8390 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8394 gtk_window_check_screen (GtkWindow *window)
8396 GtkWindowPrivate *priv = window->priv;
8399 return priv->screen;
8402 g_warning ("Screen for GtkWindow not set; you must always set\n"
8403 "a screen for a GtkWindow before using the window");
8409 * gtk_window_get_screen:
8410 * @window: a #GtkWindow.
8412 * Returns the #GdkScreen associated with @window.
8414 * Return value: (transfer none): a #GdkScreen.
8419 gtk_window_get_screen (GtkWindow *window)
8421 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8423 return window->priv->screen;
8427 * gtk_window_is_active:
8428 * @window: a #GtkWindow
8430 * Returns whether the window is part of the current active toplevel.
8431 * (That is, the toplevel window receiving keystrokes.)
8432 * The return value is %TRUE if the window is active toplevel
8433 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8434 * You might use this function if you wanted to draw a widget
8435 * differently in an active window from a widget in an inactive window.
8436 * See gtk_window_has_toplevel_focus()
8438 * Return value: %TRUE if the window part of the current active window.
8443 gtk_window_is_active (GtkWindow *window)
8445 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8447 return window->priv->is_active;
8451 * gtk_window_has_toplevel_focus:
8452 * @window: a #GtkWindow
8454 * Returns whether the input focus is within this GtkWindow.
8455 * For real toplevel windows, this is identical to gtk_window_is_active(),
8456 * but for embedded windows, like #GtkPlug, the results will differ.
8458 * Return value: %TRUE if the input focus is within this GtkWindow
8463 gtk_window_has_toplevel_focus (GtkWindow *window)
8465 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8467 return window->priv->has_toplevel_focus;
8470 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8473 gtk_window_group_init (GtkWindowGroup *group)
8475 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8476 GTK_TYPE_WINDOW_GROUP,
8477 GtkWindowGroupPrivate);
8481 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8483 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8487 * gtk_window_group_new:
8489 * Creates a new #GtkWindowGroup object. Grabs added with
8490 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8492 * Return value: a new #GtkWindowGroup.
8495 gtk_window_group_new (void)
8497 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8501 window_group_cleanup_grabs (GtkWindowGroup *group,
8504 GtkWindowGroupPrivate *priv;
8505 GtkDeviceGrabInfo *info;
8507 GSList *to_remove = NULL;
8511 tmp_list = priv->grabs;
8514 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8515 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8516 tmp_list = tmp_list->next;
8521 gtk_grab_remove (to_remove->data);
8522 g_object_unref (to_remove->data);
8523 to_remove = g_slist_delete_link (to_remove, to_remove);
8526 tmp_list = priv->device_grabs;
8530 info = tmp_list->data;
8532 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8533 to_remove = g_slist_prepend (to_remove, info);
8535 tmp_list = tmp_list->next;
8540 info = to_remove->data;
8542 gtk_device_grab_remove (info->widget, info->device);
8543 to_remove = g_slist_delete_link (to_remove, to_remove);
8548 * gtk_window_group_add_window:
8549 * @window_group: a #GtkWindowGroup
8550 * @window: the #GtkWindow to add
8552 * Adds a window to a #GtkWindowGroup.
8555 gtk_window_group_add_window (GtkWindowGroup *window_group,
8558 GtkWindowPrivate *priv;
8560 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8561 g_return_if_fail (GTK_IS_WINDOW (window));
8563 priv = window->priv;
8565 if (priv->group != window_group)
8567 g_object_ref (window);
8568 g_object_ref (window_group);
8571 gtk_window_group_remove_window (priv->group, window);
8573 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8575 priv->group = window_group;
8577 g_object_unref (window);
8582 * gtk_window_group_remove_window:
8583 * @window_group: a #GtkWindowGroup
8584 * @window: the #GtkWindow to remove
8586 * Removes a window from a #GtkWindowGroup.
8589 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8592 GtkWindowPrivate *priv;
8594 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8595 g_return_if_fail (GTK_IS_WINDOW (window));
8596 priv = window->priv;
8597 g_return_if_fail (priv->group == window_group);
8599 g_object_ref (window);
8601 window_group_cleanup_grabs (window_group, window);
8604 g_object_unref (window_group);
8605 g_object_unref (window);
8609 * gtk_window_group_list_windows:
8610 * @window_group: a #GtkWindowGroup
8612 * Returns a list of the #GtkWindows that belong to @window_group.
8614 * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
8615 * windows inside the group.
8620 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8622 GList *toplevels, *toplevel, *group_windows;
8624 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8626 group_windows = NULL;
8627 toplevels = gtk_window_list_toplevels ();
8629 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8631 GtkWindow *window = toplevel->data;
8633 if (window_group == window->priv->group)
8634 group_windows = g_list_prepend (group_windows, window);
8637 return g_list_reverse (group_windows);
8641 * gtk_window_get_group:
8642 * @window: (allow-none): a #GtkWindow, or %NULL
8644 * Returns the group for @window or the default group, if
8645 * @window is %NULL or if @window does not have an explicit
8648 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8653 gtk_window_get_group (GtkWindow *window)
8655 if (window && window->priv->group)
8656 return window->priv->group;
8659 static GtkWindowGroup *default_group = NULL;
8662 default_group = gtk_window_group_new ();
8664 return default_group;
8669 * gtk_window_has_group:
8670 * @window: a #GtkWindow
8672 * Returns whether @window has an explicit window group.
8674 * Return value: %TRUE if @window has an explicit window group.
8679 gtk_window_has_group (GtkWindow *window)
8681 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8683 return window->priv->group != NULL;
8687 * gtk_window_group_get_current_grab:
8688 * @window_group: a #GtkWindowGroup
8690 * Gets the current grab widget of the given group,
8691 * see gtk_grab_add().
8693 * Returns: the current grab widget of the group
8698 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8700 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8702 if (window_group->priv->grabs)
8703 return GTK_WIDGET (window_group->priv->grabs->data);
8708 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8711 GtkWindowGroupPrivate *priv;
8713 priv = window_group->priv;
8714 priv->grabs = g_slist_prepend (priv->grabs, widget);
8718 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8721 GtkWindowGroupPrivate *priv;
8723 priv = window_group->priv;
8724 priv->grabs = g_slist_remove (priv->grabs, widget);
8729 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8732 gboolean block_others)
8734 GtkWindowGroupPrivate *priv;
8735 GtkDeviceGrabInfo *info;
8737 priv = window_group->priv;
8739 info = g_slice_new0 (GtkDeviceGrabInfo);
8740 info->widget = widget;
8741 info->device = device;
8742 info->block_others = block_others;
8744 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8748 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8752 GtkWindowGroupPrivate *priv;
8753 GtkDeviceGrabInfo *info;
8754 GSList *list, *node = NULL;
8755 GdkDevice *other_device;
8757 priv = window_group->priv;
8758 other_device = gdk_device_get_associated_device (device);
8759 list = priv->device_grabs;
8765 if (info->widget == widget &&
8766 (info->device == device ||
8767 info->device == other_device))
8780 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8781 g_slice_free (GtkDeviceGrabInfo, info);
8786 * gtk_window_group_get_current_device_grab:
8787 * @window_group: a #GtkWindowGroup
8788 * @device: a #GdkDevice
8790 * Returns the current grab widget for @device, or %NULL if none.
8792 * Returns: The grab widget, or %NULL
8797 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8800 GtkWindowGroupPrivate *priv;
8801 GtkDeviceGrabInfo *info;
8802 GdkDevice *other_device;
8805 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8806 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8808 priv = window_group->priv;
8809 list = priv->device_grabs;
8810 other_device = gdk_device_get_associated_device (device);
8817 if (info->device == device ||
8818 info->device == other_device)
8819 return info->widget;
8826 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8830 GtkWindowGroupPrivate *priv;
8831 GtkDeviceGrabInfo *info;
8832 GdkDevice *other_device;
8835 priv = window_group->priv;
8836 other_device = gdk_device_get_associated_device (device);
8837 list = priv->device_grabs;
8844 /* Look for blocking grabs on other device pairs
8845 * that have the passed widget within the GTK+ grab.
8847 if (info->block_others &&
8848 info->device != device &&
8849 info->device != other_device &&
8850 (info->widget == widget ||
8851 gtk_widget_is_ancestor (widget, info->widget)))
8859 Derived from XParseGeometry() in XFree86
8861 Copyright 1985, 1986, 1987,1998 The Open Group
8863 All Rights Reserved.
8865 The above copyright notice and this permission notice shall be included
8866 in all copies or substantial portions of the Software.
8868 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8869 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8870 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8871 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8872 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8873 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8874 OTHER DEALINGS IN THE SOFTWARE.
8876 Except as contained in this notice, the name of The Open Group shall
8877 not be used in advertising or otherwise to promote the sale, use or
8878 other dealings in this Software without prior written authorization
8879 from The Open Group.
8884 * XParseGeometry parses strings of the form
8885 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8886 * width, height, xoffset, and yoffset are unsigned integers.
8887 * Example: "=80x24+300-49"
8888 * The equal sign is optional.
8889 * It returns a bitmask that indicates which of the four values
8890 * were actually found in the string. For each value found,
8891 * the corresponding argument is updated; for each value
8892 * not found, the corresponding argument is left unchanged.
8895 /* The following code is from Xlib, and is minimally modified, so we
8896 * can track any upstream changes if required. Don't change this
8897 * code. Or if you do, put in a huge comment marking which thing
8902 read_int (gchar *string,
8910 else if (*string == '-')
8916 for (; (*string >= '0') && (*string <= '9'); string++)
8918 result = (result * 10) + (*string - '0');
8930 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8931 * value (x, y, width, height) was found in the parsed string.
8933 #define NoValue 0x0000
8934 #define XValue 0x0001
8935 #define YValue 0x0002
8936 #define WidthValue 0x0004
8937 #define HeightValue 0x0008
8938 #define AllValues 0x000F
8939 #define XNegative 0x0010
8940 #define YNegative 0x0020
8942 /* Try not to reformat/modify, so we can compare/sync with X sources */
8944 gtk_XParseGeometry (const char *string,
8947 unsigned int *width,
8948 unsigned int *height)
8952 unsigned int tempWidth, tempHeight;
8954 char *nextCharacter;
8956 /* These initializations are just to silence gcc */
8962 if ( (string == NULL) || (*string == '\0')) return(mask);
8964 string++; /* ignore possible '=' at beg of geometry spec */
8966 strind = (char *)string;
8967 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8968 tempWidth = read_int(strind, &nextCharacter);
8969 if (strind == nextCharacter)
8971 strind = nextCharacter;
8975 if (*strind == 'x' || *strind == 'X') {
8977 tempHeight = read_int(strind, &nextCharacter);
8978 if (strind == nextCharacter)
8980 strind = nextCharacter;
8981 mask |= HeightValue;
8984 if ((*strind == '+') || (*strind == '-')) {
8985 if (*strind == '-') {
8987 tempX = -read_int(strind, &nextCharacter);
8988 if (strind == nextCharacter)
8990 strind = nextCharacter;
8996 tempX = read_int(strind, &nextCharacter);
8997 if (strind == nextCharacter)
8999 strind = nextCharacter;
9002 if ((*strind == '+') || (*strind == '-')) {
9003 if (*strind == '-') {
9005 tempY = -read_int(strind, &nextCharacter);
9006 if (strind == nextCharacter)
9008 strind = nextCharacter;
9015 tempY = read_int(strind, &nextCharacter);
9016 if (strind == nextCharacter)
9018 strind = nextCharacter;
9024 /* If strind isn't at the end of the string the it's an invalid
9025 geometry specification. */
9027 if (*strind != '\0') return (0);
9033 if (mask & WidthValue)
9035 if (mask & HeightValue)
9036 *height = tempHeight;
9041 * gtk_window_parse_geometry:
9042 * @window: a #GtkWindow
9043 * @geometry: geometry string
9045 * Parses a standard X Window System geometry string - see the
9046 * manual page for X (type 'man X') for details on this.
9047 * gtk_window_parse_geometry() does work on all GTK+ ports
9048 * including Win32 but is primarily intended for an X environment.
9050 * If either a size or a position can be extracted from the
9051 * geometry string, gtk_window_parse_geometry() returns %TRUE
9052 * and calls gtk_window_set_default_size() and/or gtk_window_move()
9053 * to resize/move the window.
9055 * If gtk_window_parse_geometry() returns %TRUE, it will also
9056 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9057 * indicating to the window manager that the size/position of
9058 * the window was user-specified. This causes most window
9059 * managers to honor the geometry.
9061 * Note that for gtk_window_parse_geometry() to work as expected, it has
9062 * to be called when the window has its "final" size, i.e. after calling
9063 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9066 * #include <gtk/gtk.h>
9069 * fill_with_content (GtkWidget *vbox)
9071 * /* fill with content... */
9075 * main (int argc, char *argv[])
9077 * GtkWidget *window, *vbox;
9078 * GdkGeometry size_hints = {
9079 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
9082 * gtk_init (&argc, &argv);
9084 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9085 * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
9087 * gtk_container_add (GTK_CONTAINER (window), vbox);
9088 * fill_with_content (vbox);
9089 * gtk_widget_show_all (vbox);
9091 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
9094 * GDK_HINT_MIN_SIZE |
9095 * GDK_HINT_BASE_SIZE |
9096 * GDK_HINT_RESIZE_INC);
9100 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9101 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9104 * gtk_widget_show_all (window);
9111 * Return value: %TRUE if string was parsed successfully
9114 gtk_window_parse_geometry (GtkWindow *window,
9115 const gchar *geometry)
9117 gint result, x = 0, y = 0;
9121 gboolean size_set, pos_set;
9124 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9125 g_return_val_if_fail (geometry != NULL, FALSE);
9127 child = gtk_bin_get_child (GTK_BIN (window));
9128 if (!child || !gtk_widget_get_visible (child))
9129 g_warning ("gtk_window_parse_geometry() called on a window with no "
9130 "visible children; the window should be set up before "
9131 "gtk_window_parse_geometry() is called.");
9133 screen = gtk_window_check_screen (window);
9135 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9138 if ((result & WidthValue) || (result & HeightValue))
9140 gtk_window_set_default_size_internal (window,
9141 TRUE, result & WidthValue ? w : -1,
9142 TRUE, result & HeightValue ? h : -1,
9147 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9149 grav = GDK_GRAVITY_NORTH_WEST;
9151 if ((result & XNegative) && (result & YNegative))
9152 grav = GDK_GRAVITY_SOUTH_EAST;
9153 else if (result & XNegative)
9154 grav = GDK_GRAVITY_NORTH_EAST;
9155 else if (result & YNegative)
9156 grav = GDK_GRAVITY_SOUTH_WEST;
9158 if ((result & XValue) == 0)
9161 if ((result & YValue) == 0)
9164 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9165 grav == GDK_GRAVITY_SOUTH_EAST)
9166 y = gdk_screen_get_height (screen) - h + y;
9168 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9169 grav == GDK_GRAVITY_NORTH_EAST)
9170 x = gdk_screen_get_width (screen) - w + x;
9172 /* we don't let you put a window offscreen; maybe some people would
9173 * prefer to be able to, but it's kind of a bogus thing to do.
9182 if ((result & XValue) || (result & YValue))
9184 gtk_window_set_gravity (window, grav);
9185 gtk_window_move (window, x, y);
9189 if (size_set || pos_set)
9191 /* Set USSize, USPosition hints */
9192 GtkWindowGeometryInfo *info;
9194 info = gtk_window_get_geometry_info (window, TRUE);
9197 info->mask |= GDK_HINT_USER_POS;
9199 info->mask |= GDK_HINT_USER_SIZE;
9206 gtk_window_mnemonic_hash_foreach (guint keyval,
9212 GtkWindowKeysForeachFunc func;
9216 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9220 _gtk_window_keys_foreach (GtkWindow *window,
9221 GtkWindowKeysForeachFunc func,
9225 GtkMnemonicHash *mnemonic_hash;
9229 GtkWindowKeysForeachFunc func;
9233 info.window = window;
9235 info.func_data = func_data;
9237 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9239 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9240 gtk_window_mnemonic_hash_foreach, &info);
9242 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9245 GtkAccelGroup *group = groups->data;
9248 for (i = 0; i < group->priv->n_accels; i++)
9250 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9253 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9256 groups = groups->next;
9261 gtk_window_keys_changed (GtkWindow *window)
9263 gtk_window_free_key_hash (window);
9264 gtk_window_get_key_hash (window);
9267 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9269 struct _GtkWindowKeyEntry
9273 guint is_mnemonic : 1;
9277 window_key_entry_destroy (gpointer data)
9279 g_slice_free (GtkWindowKeyEntry, data);
9283 add_to_key_hash (GtkWindow *window,
9285 GdkModifierType modifiers,
9286 gboolean is_mnemonic,
9289 GtkKeyHash *key_hash = data;
9291 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9293 entry->keyval = keyval;
9294 entry->modifiers = modifiers;
9295 entry->is_mnemonic = is_mnemonic;
9297 /* GtkAccelGroup stores lowercased accelerators. To deal
9298 * with this, if <Shift> was specified, uppercase.
9300 if (modifiers & GDK_SHIFT_MASK)
9302 if (keyval == GDK_KEY_Tab)
9303 keyval = GDK_KEY_ISO_Left_Tab;
9305 keyval = gdk_keyval_to_upper (keyval);
9308 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9312 gtk_window_get_key_hash (GtkWindow *window)
9314 GdkScreen *screen = gtk_window_check_screen (window);
9315 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9320 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9321 (GDestroyNotify)window_key_entry_destroy);
9322 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9323 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9329 gtk_window_free_key_hash (GtkWindow *window)
9331 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9334 _gtk_key_hash_free (key_hash);
9335 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9340 * gtk_window_activate_key:
9341 * @window: a #GtkWindow
9342 * @event: a #GdkEventKey
9344 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9345 * called by the default ::key_press_event handler for toplevel windows,
9346 * however in some cases it may be useful to call this directly when
9347 * overriding the standard key handling for a toplevel window.
9349 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9354 gtk_window_activate_key (GtkWindow *window,
9357 GtkKeyHash *key_hash;
9358 GtkWindowKeyEntry *found_entry = NULL;
9359 gboolean enable_mnemonics;
9360 gboolean enable_accels;
9362 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9363 g_return_val_if_fail (event != NULL, FALSE);
9365 key_hash = gtk_window_get_key_hash (window);
9370 GSList *entries = _gtk_key_hash_lookup (key_hash,
9371 event->hardware_keycode,
9373 gtk_accelerator_get_default_mod_mask (),
9376 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9377 "gtk-enable-mnemonics", &enable_mnemonics,
9378 "gtk-enable-accels", &enable_accels,
9381 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9383 GtkWindowKeyEntry *entry = tmp_list->data;
9384 if (entry->is_mnemonic)
9386 if (enable_mnemonics)
9388 found_entry = entry;
9394 if (enable_accels && !found_entry)
9396 found_entry = entry;
9401 g_slist_free (entries);
9406 if (found_entry->is_mnemonic)
9408 if (enable_mnemonics)
9409 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9410 found_entry->modifiers);
9415 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9416 found_entry->modifiers);
9424 window_update_has_focus (GtkWindow *window)
9426 GtkWindowPrivate *priv = window->priv;
9427 GtkWidget *widget = GTK_WIDGET (window);
9428 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9430 if (has_focus != priv->has_focus)
9432 priv->has_focus = has_focus;
9436 if (priv->focus_widget &&
9437 priv->focus_widget != widget &&
9438 !gtk_widget_has_focus (priv->focus_widget))
9439 do_focus_change (priv->focus_widget, TRUE);
9443 if (priv->focus_widget &&
9444 priv->focus_widget != widget &&
9445 gtk_widget_has_focus (priv->focus_widget))
9446 do_focus_change (priv->focus_widget, FALSE);
9452 * _gtk_window_set_is_active:
9453 * @window: a #GtkWindow
9454 * @is_active: %TRUE if the window is in the currently active toplevel
9456 * Internal function that sets whether the #GtkWindow is part
9457 * of the currently active toplevel window (taking into account inter-process
9461 _gtk_window_set_is_active (GtkWindow *window,
9464 GtkWindowPrivate *priv;
9466 g_return_if_fail (GTK_IS_WINDOW (window));
9468 priv = window->priv;
9470 is_active = is_active != FALSE;
9472 if (is_active != priv->is_active)
9474 priv->is_active = is_active;
9475 window_update_has_focus (window);
9477 g_object_notify (G_OBJECT (window), "is-active");
9482 * _gtk_window_set_is_toplevel:
9483 * @window: a #GtkWindow
9484 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9485 * child of the root window); %FALSE if it is not (for example, for an
9486 * in-process, parented GtkPlug)
9488 * Internal function used by #GtkPlug when it gets parented/unparented by a
9489 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9490 * global list of toplevel windows.
9493 _gtk_window_set_is_toplevel (GtkWindow *window,
9494 gboolean is_toplevel)
9498 widget = GTK_WIDGET (window);
9500 if (gtk_widget_is_toplevel (widget))
9501 g_assert (g_slist_find (toplevel_list, window) != NULL);
9503 g_assert (g_slist_find (toplevel_list, window) == NULL);
9505 if (is_toplevel == gtk_widget_is_toplevel (widget))
9510 _gtk_widget_set_is_toplevel (widget, TRUE);
9511 toplevel_list = g_slist_prepend (toplevel_list, window);
9515 _gtk_widget_set_is_toplevel (widget, FALSE);
9516 toplevel_list = g_slist_remove (toplevel_list, window);
9521 * _gtk_window_set_has_toplevel_focus:
9522 * @window: a #GtkWindow
9523 * @has_toplevel_focus: %TRUE if the in
9525 * Internal function that sets whether the keyboard focus for the
9526 * toplevel window (taking into account inter-process embedding.)
9529 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9530 gboolean has_toplevel_focus)
9532 GtkWindowPrivate *priv;
9534 g_return_if_fail (GTK_IS_WINDOW (window));
9536 priv = window->priv;
9538 has_toplevel_focus = has_toplevel_focus != FALSE;
9540 if (has_toplevel_focus != priv->has_toplevel_focus)
9542 priv->has_toplevel_focus = has_toplevel_focus;
9543 window_update_has_focus (window);
9545 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9550 * gtk_window_set_auto_startup_notification:
9551 * @setting: %TRUE to automatically do startup notification
9553 * By default, after showing the first #GtkWindow, GTK+ calls
9554 * gdk_notify_startup_complete(). Call this function to disable
9555 * the automatic startup notification. You might do this if your
9556 * first window is a splash screen, and you want to delay notification
9557 * until after your real main window has been shown, for example.
9559 * In that example, you would disable startup notification
9560 * temporarily, show your splash screen, then re-enable it so that
9561 * showing the main window would automatically result in notification.
9566 gtk_window_set_auto_startup_notification (gboolean setting)
9568 disable_startup_notification = !setting;
9572 * gtk_window_get_window_type:
9573 * @window: a #GtkWindow
9575 * Gets the type of the window. See #GtkWindowType.
9577 * Return value: the type of the window
9582 gtk_window_get_window_type (GtkWindow *window)
9584 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9586 return window->priv->type;
9590 * gtk_window_get_mnemonics_visible:
9591 * @window: a #GtkWindow
9593 * Gets the value of the #GtkWindow:mnemonics-visible property.
9595 * Returns: %TRUE if mnemonics are supposed to be visible
9601 gtk_window_get_mnemonics_visible (GtkWindow *window)
9603 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9605 return window->priv->mnemonics_visible;
9609 * gtk_window_set_mnemonics_visible:
9610 * @window: a #GtkWindow
9611 * @setting: the new value
9613 * Sets the #GtkWindow:mnemonics-visible property.
9618 gtk_window_set_mnemonics_visible (GtkWindow *window,
9621 GtkWindowPrivate *priv;
9623 g_return_if_fail (GTK_IS_WINDOW (window));
9625 priv = window->priv;
9627 setting = setting != FALSE;
9629 if (priv->mnemonics_visible != setting)
9631 priv->mnemonics_visible = setting;
9632 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9635 priv->mnemonics_visible_set = TRUE;
9639 _gtk_window_get_wmclass (GtkWindow *window,
9640 gchar **wmclass_name,
9641 gchar **wmclass_class)
9643 GtkWindowPrivate *priv = window->priv;
9645 *wmclass_name = priv->wmclass_name;
9646 *wmclass_class = priv->wmclass_class;