1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
33 #include "gdk/gdkkeysyms.h"
37 #include "gtkprivate.h"
39 #include "gtkwindow.h"
40 #include "gtkwindow-decorate.h"
41 #include "gtkbindings.h"
42 #include "gtkkeyhash.h"
44 #include "gtkmnemonichash.h"
45 #include "gtkmenubar.h"
46 #include "gtkiconfactory.h"
47 #include "gtkicontheme.h"
48 #include "gtkmarshalers.h"
50 #include "gtkbuildable.h"
51 #include "gtkwidgetprivate.h"
53 #ifdef GDK_WINDOWING_X11
60 * @short_description: Toplevel which can contain other widgets
62 * A GtkWindow is a toplevel window which can contain other widgets.
63 * Windows normally have decorations that are under the control
64 * of the windowing system and allow the user to manipulate the window
65 * (resize it, move it, close it,...).
67 * GTK+ also allows windows to have a resize grip (a small area in the lower
68 * right or left corner) which can be clicked to reszie the window. To
69 * control whether a window has a resize grip, use
70 * gtk_window_set_has_resize_grip().
72 * <refsect2 id="GtkWindow-BUILDER-UI">
73 * <title>GtkWindow as GtkBuildable</title>
75 * The GtkWindow implementation of the GtkBuildable interface supports a
76 * custom <tag class="starttag">accel-groups</tag> element, which supports
77 * any number of <tag class="starttag">group</tag> elements representing the
78 * #GtkAccelGroup objects you want to add to your window (synonymous with
79 * gtk_window_add_accel_group().
82 * <title>A UI definition fragment with accel groups</title>
83 * <programlisting><![CDATA[
84 * <object class="GtkWindow">
86 * <group name="accelgroup1"/>
92 * <object class="GtkAccelGroup" id="accelgroup1"/>
93 * ]]></programlisting>
98 typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
99 typedef struct _GtkWindowGroupPrivate GtkWindowGroupPrivate;
101 struct _GtkWindowPrivate
103 GtkMnemonicHash *mnemonic_hash;
105 GtkWidget *default_widget;
106 GtkWidget *focus_widget;
107 GtkWindow *transient_parent;
108 GtkWindowGeometryInfo *geometry_info;
109 GtkWindowGroup *group;
111 GdkModifierType mnemonic_modifier;
114 GdkWindowTypeHint gdk_type_hint;
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;
301 #define GTK_WINDOW_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW_GROUP, GtkWindowGroupPrivate))
303 struct _GtkDeviceGrabInfo
307 guint block_others : 1;
310 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_set (GtkWidget *widget,
350 static gint gtk_window_client_event (GtkWidget *widget,
351 GdkEventClient *event);
352 static gboolean gtk_window_state_event (GtkWidget *widget,
353 GdkEventWindowState *event);
354 static void gtk_window_check_resize (GtkContainer *container);
355 static gint gtk_window_focus (GtkWidget *widget,
356 GtkDirectionType direction);
357 static void gtk_window_move_focus (GtkWidget *widget,
358 GtkDirectionType dir);
359 static void gtk_window_real_set_focus (GtkWindow *window,
361 static void gtk_window_direction_changed (GtkWidget *widget,
362 GtkTextDirection prev_dir);
363 static void gtk_window_state_changed (GtkWidget *widget,
364 GtkStateType previous_state);
366 static void gtk_window_real_activate_default (GtkWindow *window);
367 static void gtk_window_real_activate_focus (GtkWindow *window);
368 static void gtk_window_keys_changed (GtkWindow *window);
369 static gint gtk_window_draw (GtkWidget *widget,
371 static void gtk_window_unset_transient_for (GtkWindow *window);
372 static void gtk_window_transient_parent_realized (GtkWidget *parent,
374 static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
377 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
379 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
382 static void gtk_window_move_resize (GtkWindow *window);
383 static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
385 GdkGeometry *geometry_b,
387 static void gtk_window_constrain_size (GtkWindow *window,
388 GdkGeometry *geometry,
394 static void gtk_window_constrain_position (GtkWindow *window,
399 static void gtk_window_compute_hints (GtkWindow *window,
400 GdkGeometry *new_geometry,
402 static void gtk_window_compute_configure_request (GtkWindow *window,
403 GdkRectangle *request,
404 GdkGeometry *geometry,
407 static void gtk_window_set_default_size_internal (GtkWindow *window,
408 gboolean change_width,
410 gboolean change_height,
412 gboolean is_geometry);
414 static void update_themed_icon (GtkIconTheme *theme,
416 static GList *icon_list_from_theme (GtkWidget *widget,
418 static void gtk_window_realize_icon (GtkWindow *window);
419 static void gtk_window_unrealize_icon (GtkWindow *window);
420 static void resize_grip_create_window (GtkWindow *window);
421 static void resize_grip_destroy_window (GtkWindow *window);
422 static void update_grip_visibility (GtkWindow *window);
424 static void gtk_window_notify_keys_changed (GtkWindow *window);
425 static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
426 static void gtk_window_free_key_hash (GtkWindow *window);
427 static void gtk_window_on_composited_changed (GdkScreen *screen,
430 static GSList *toplevel_list = NULL;
431 static guint window_signals[LAST_SIGNAL] = { 0 };
432 static GList *default_icon_list = NULL;
433 static gchar *default_icon_name = NULL;
434 static guint default_icon_serial = 0;
435 static gboolean disable_startup_notification = FALSE;
436 static gboolean sent_startup_notification = FALSE;
438 static GQuark quark_gtk_embedded = 0;
439 static GQuark quark_gtk_window_key_hash = 0;
440 static GQuark quark_gtk_window_icon_info = 0;
441 static GQuark quark_gtk_buildable_accels = 0;
443 static GtkBuildableIface *parent_buildable_iface;
445 static void gtk_window_set_property (GObject *object,
449 static void gtk_window_get_property (GObject *object,
455 static void gtk_window_buildable_interface_init (GtkBuildableIface *iface);
456 static void gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
459 const GValue *value);
460 static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
461 GtkBuilder *builder);
462 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
465 const gchar *tagname,
466 GMarkupParser *parser,
468 static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
471 const gchar *tagname,
475 static void gtk_window_get_preferred_width (GtkWidget *widget,
478 static void gtk_window_get_preferred_height (GtkWidget *widget,
482 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
483 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
484 gtk_window_buildable_interface_init))
487 add_tab_bindings (GtkBindingSet *binding_set,
488 GdkModifierType modifiers,
489 GtkDirectionType direction)
491 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
493 GTK_TYPE_DIRECTION_TYPE, direction);
494 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
496 GTK_TYPE_DIRECTION_TYPE, direction);
500 add_arrow_bindings (GtkBindingSet *binding_set,
502 GtkDirectionType direction)
504 guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
506 gtk_binding_entry_add_signal (binding_set, keysym, 0,
508 GTK_TYPE_DIRECTION_TYPE, direction);
509 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
511 GTK_TYPE_DIRECTION_TYPE, direction);
512 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
514 GTK_TYPE_DIRECTION_TYPE, direction);
515 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
517 GTK_TYPE_DIRECTION_TYPE, direction);
521 extract_time_from_startup_id (const gchar* startup_id)
523 gchar *timestr = g_strrstr (startup_id, "_TIME");
524 guint32 retval = GDK_CURRENT_TIME;
531 /* Skip past the "_TIME" part */
535 timestamp = strtoul (timestr, &end, 0);
536 if (end != timestr && errno == 0)
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_set = gtk_window_style_set;
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 gtk_decorated_window_init (window);
1140 g_signal_connect (priv->screen, "composited-changed",
1141 G_CALLBACK (gtk_window_on_composited_changed), window);
1145 gtk_window_set_property (GObject *object,
1147 const GValue *value,
1150 GtkWindow *window = GTK_WINDOW (object);
1151 GtkWindowPrivate *priv = window->priv;
1156 priv->type = g_value_get_enum (value);
1159 gtk_window_set_title (window, g_value_get_string (value));
1162 gtk_window_set_role (window, g_value_get_string (value));
1164 case PROP_STARTUP_ID:
1165 gtk_window_set_startup_id (window, g_value_get_string (value));
1167 case PROP_RESIZABLE:
1168 gtk_window_set_resizable (window, g_value_get_boolean (value));
1171 gtk_window_set_modal (window, g_value_get_boolean (value));
1174 gtk_window_set_position (window, g_value_get_enum (value));
1176 case PROP_DEFAULT_WIDTH:
1177 gtk_window_set_default_size_internal (window,
1178 TRUE, g_value_get_int (value),
1181 case PROP_DEFAULT_HEIGHT:
1182 gtk_window_set_default_size_internal (window,
1184 TRUE, g_value_get_int (value), FALSE);
1186 case PROP_DESTROY_WITH_PARENT:
1187 gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1190 gtk_window_set_icon (window,
1191 g_value_get_object (value));
1193 case PROP_ICON_NAME:
1194 gtk_window_set_icon_name (window, g_value_get_string (value));
1197 gtk_window_set_screen (window, g_value_get_object (value));
1199 case PROP_TYPE_HINT:
1200 gtk_window_set_type_hint (window,
1201 g_value_get_enum (value));
1203 case PROP_SKIP_TASKBAR_HINT:
1204 gtk_window_set_skip_taskbar_hint (window,
1205 g_value_get_boolean (value));
1207 case PROP_SKIP_PAGER_HINT:
1208 gtk_window_set_skip_pager_hint (window,
1209 g_value_get_boolean (value));
1211 case PROP_URGENCY_HINT:
1212 gtk_window_set_urgency_hint (window,
1213 g_value_get_boolean (value));
1215 case PROP_ACCEPT_FOCUS:
1216 gtk_window_set_accept_focus (window,
1217 g_value_get_boolean (value));
1219 case PROP_FOCUS_ON_MAP:
1220 gtk_window_set_focus_on_map (window,
1221 g_value_get_boolean (value));
1223 case PROP_DECORATED:
1224 gtk_window_set_decorated (window, g_value_get_boolean (value));
1226 case PROP_DELETABLE:
1227 gtk_window_set_deletable (window, g_value_get_boolean (value));
1230 gtk_window_set_gravity (window, g_value_get_enum (value));
1232 case PROP_TRANSIENT_FOR:
1233 gtk_window_set_transient_for (window, g_value_get_object (value));
1236 gtk_window_set_opacity (window, g_value_get_double (value));
1238 case PROP_HAS_RESIZE_GRIP:
1239 gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
1241 case PROP_APPLICATION:
1242 gtk_window_set_application (window, g_value_get_object (value));
1244 case PROP_MNEMONICS_VISIBLE:
1245 gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
1248 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1254 gtk_window_get_property (GObject *object,
1259 GtkWindow *window = GTK_WINDOW (object);
1260 GtkWindowPrivate *priv = window->priv;
1264 GtkWindowGeometryInfo *info;
1266 g_value_set_enum (value, priv->type);
1269 g_value_set_string (value, priv->wm_role);
1272 g_value_set_string (value, priv->title);
1274 case PROP_RESIZABLE:
1275 g_value_set_boolean (value, priv->resizable);
1278 g_value_set_boolean (value, priv->modal);
1281 g_value_set_enum (value, priv->position);
1283 case PROP_DEFAULT_WIDTH:
1284 info = gtk_window_get_geometry_info (window, FALSE);
1286 g_value_set_int (value, -1);
1288 g_value_set_int (value, info->default_width);
1290 case PROP_DEFAULT_HEIGHT:
1291 info = gtk_window_get_geometry_info (window, FALSE);
1293 g_value_set_int (value, -1);
1295 g_value_set_int (value, info->default_height);
1297 case PROP_DESTROY_WITH_PARENT:
1298 g_value_set_boolean (value, priv->destroy_with_parent);
1301 g_value_set_object (value, gtk_window_get_icon (window));
1303 case PROP_ICON_NAME:
1304 g_value_set_string (value, gtk_window_get_icon_name (window));
1307 g_value_set_object (value, priv->screen);
1309 case PROP_IS_ACTIVE:
1310 g_value_set_boolean (value, priv->is_active);
1312 case PROP_HAS_TOPLEVEL_FOCUS:
1313 g_value_set_boolean (value, priv->has_toplevel_focus);
1315 case PROP_TYPE_HINT:
1316 g_value_set_enum (value, priv->type_hint);
1318 case PROP_SKIP_TASKBAR_HINT:
1319 g_value_set_boolean (value,
1320 gtk_window_get_skip_taskbar_hint (window));
1322 case PROP_SKIP_PAGER_HINT:
1323 g_value_set_boolean (value,
1324 gtk_window_get_skip_pager_hint (window));
1326 case PROP_URGENCY_HINT:
1327 g_value_set_boolean (value,
1328 gtk_window_get_urgency_hint (window));
1330 case PROP_ACCEPT_FOCUS:
1331 g_value_set_boolean (value,
1332 gtk_window_get_accept_focus (window));
1334 case PROP_FOCUS_ON_MAP:
1335 g_value_set_boolean (value,
1336 gtk_window_get_focus_on_map (window));
1338 case PROP_DECORATED:
1339 g_value_set_boolean (value, gtk_window_get_decorated (window));
1341 case PROP_DELETABLE:
1342 g_value_set_boolean (value, gtk_window_get_deletable (window));
1345 g_value_set_enum (value, gtk_window_get_gravity (window));
1347 case PROP_TRANSIENT_FOR:
1348 g_value_set_object (value, gtk_window_get_transient_for (window));
1351 g_value_set_double (value, gtk_window_get_opacity (window));
1353 case PROP_HAS_RESIZE_GRIP:
1354 g_value_set_boolean (value, priv->has_resize_grip);
1356 case PROP_RESIZE_GRIP_VISIBLE:
1357 g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
1359 case PROP_APPLICATION:
1360 g_value_set_object (value, gtk_window_get_application (window));
1362 case PROP_MNEMONICS_VISIBLE:
1363 g_value_set_boolean (value, priv->mnemonics_visible);
1366 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1372 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1374 parent_buildable_iface = g_type_interface_peek_parent (iface);
1375 iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1376 iface->parser_finished = gtk_window_buildable_parser_finished;
1377 iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1378 iface->custom_finished = gtk_window_buildable_custom_finished;
1382 gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
1383 GtkBuilder *builder,
1385 const GValue *value)
1387 GtkWindow *window = GTK_WINDOW (buildable);
1388 GtkWindowPrivate *priv = window->priv;
1390 if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1391 priv->builder_visible = TRUE;
1393 parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1397 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1398 GtkBuilder *builder)
1400 GtkWindow *window = GTK_WINDOW (buildable);
1401 GtkWindowPrivate *priv = window->priv;
1405 if (priv->builder_visible)
1406 gtk_widget_show (GTK_WIDGET (buildable));
1408 accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1409 for (l = accels; l; l = l->next)
1411 object = gtk_builder_get_object (builder, l->data);
1414 g_warning ("Unknown accel group %s specified in window %s",
1415 (const gchar*)l->data, gtk_buildable_get_name (buildable));
1418 gtk_window_add_accel_group (GTK_WINDOW (buildable),
1419 GTK_ACCEL_GROUP (object));
1423 g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1425 parent_buildable_iface->parser_finished (buildable, builder);
1431 } GSListSubParserData;
1434 window_start_element (GMarkupParseContext *context,
1435 const gchar *element_name,
1436 const gchar **names,
1437 const gchar **values,
1442 GSListSubParserData *data = (GSListSubParserData*)user_data;
1444 if (strcmp (element_name, "group") == 0)
1446 for (i = 0; names[i]; i++)
1448 if (strcmp (names[i], "name") == 0)
1449 data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1452 else if (strcmp (element_name, "accel-groups") == 0)
1455 g_warning ("Unsupported tag type for GtkWindow: %s\n",
1460 static const GMarkupParser window_parser =
1462 window_start_element
1466 gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
1467 GtkBuilder *builder,
1469 const gchar *tagname,
1470 GMarkupParser *parser,
1473 GSListSubParserData *parser_data;
1475 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
1476 tagname, parser, data))
1479 if (strcmp (tagname, "accel-groups") == 0)
1481 parser_data = g_slice_new0 (GSListSubParserData);
1482 parser_data->items = NULL;
1483 parser_data->object = G_OBJECT (buildable);
1485 *parser = window_parser;
1486 *data = parser_data;
1494 gtk_window_buildable_custom_finished (GtkBuildable *buildable,
1495 GtkBuilder *builder,
1497 const gchar *tagname,
1500 GSListSubParserData *data;
1502 parent_buildable_iface->custom_finished (buildable, builder, child,
1503 tagname, user_data);
1505 if (strcmp (tagname, "accel-groups") != 0)
1508 data = (GSListSubParserData*)user_data;
1510 g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
1511 data->items, (GDestroyNotify) g_slist_free);
1513 g_slice_free (GSListSubParserData, data);
1518 * @type: type of window
1520 * Creates a new #GtkWindow, which is a toplevel window that can
1521 * contain other widgets. Nearly always, the type of the window should
1522 * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1523 * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1524 * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1525 * dialogs, though in some other toolkits dialogs are called "popups".
1526 * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1527 * On X11, popup windows are not controlled by the <link
1528 * linkend="gtk-X11-arch">window manager</link>.
1530 * If you simply want an undecorated window (no window borders), use
1531 * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1533 * Return value: a new #GtkWindow.
1536 gtk_window_new (GtkWindowType type)
1538 GtkWindowPrivate *priv;
1541 g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1543 window = g_object_new (GTK_TYPE_WINDOW, NULL);
1544 priv = window->priv;
1548 return GTK_WIDGET (window);
1552 * gtk_window_set_title:
1553 * @window: a #GtkWindow
1554 * @title: title of the window
1556 * Sets the title of the #GtkWindow. The title of a window will be
1557 * displayed in its title bar; on the X Window System, the title bar
1558 * is rendered by the <link linkend="gtk-X11-arch">window
1559 * manager</link>, so exactly how the title appears to users may vary
1560 * according to a user's exact configuration. The title should help a
1561 * user distinguish this window from other windows they may have
1562 * open. A good title might include the application name and current
1563 * document filename, for example.
1567 gtk_window_set_title (GtkWindow *window,
1570 GtkWindowPrivate *priv;
1574 g_return_if_fail (GTK_IS_WINDOW (window));
1576 priv = window->priv;
1577 widget = GTK_WIDGET (window);
1579 new_title = g_strdup (title);
1580 g_free (priv->title);
1581 priv->title = new_title;
1583 if (gtk_widget_get_realized (widget))
1585 gdk_window_set_title (gtk_widget_get_window (widget),
1588 gtk_decorated_window_set_title (window, title);
1591 g_object_notify (G_OBJECT (window), "title");
1595 * gtk_window_get_title:
1596 * @window: a #GtkWindow
1598 * Retrieves the title of the window. See gtk_window_set_title().
1600 * Return value: the title of the window, or %NULL if none has
1601 * been set explicitely. The returned string is owned by the widget
1602 * and must not be modified or freed.
1604 G_CONST_RETURN gchar *
1605 gtk_window_get_title (GtkWindow *window)
1607 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1609 return window->priv->title;
1613 * gtk_window_set_wmclass:
1614 * @window: a #GtkWindow
1615 * @wmclass_name: window name hint
1616 * @wmclass_class: window class hint
1618 * Don't use this function. It sets the X Window System "class" and
1619 * "name" hints for a window. According to the ICCCM, you should
1620 * always set these to the same value for all windows in an
1621 * application, and GTK+ sets them to that value by default, so calling
1622 * this function is sort of pointless. However, you may want to call
1623 * gtk_window_set_role() on each window in your application, for the
1624 * benefit of the session manager. Setting the role allows the window
1625 * manager to restore window positions when loading a saved session.
1629 gtk_window_set_wmclass (GtkWindow *window,
1630 const gchar *wmclass_name,
1631 const gchar *wmclass_class)
1633 GtkWindowPrivate *priv;
1635 g_return_if_fail (GTK_IS_WINDOW (window));
1637 priv = window->priv;
1639 g_free (priv->wmclass_name);
1640 priv->wmclass_name = g_strdup (wmclass_name);
1642 g_free (priv->wmclass_class);
1643 priv->wmclass_class = g_strdup (wmclass_class);
1645 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1646 g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1650 * gtk_window_set_role:
1651 * @window: a #GtkWindow
1652 * @role: unique identifier for the window to be used when restoring a session
1654 * This function is only useful on X11, not with other GTK+ targets.
1656 * In combination with the window title, the window role allows a
1657 * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1658 * same" window when an application is restarted. So for example you
1659 * might set the "toolbox" role on your app's toolbox window, so that
1660 * when the user restarts their session, the window manager can put
1661 * the toolbox back in the same place.
1663 * If a window already has a unique title, you don't need to set the
1664 * role, since the WM can use the title to identify the window when
1665 * restoring the session.
1669 gtk_window_set_role (GtkWindow *window,
1672 GtkWindowPrivate *priv;
1675 g_return_if_fail (GTK_IS_WINDOW (window));
1677 priv = window->priv;
1679 new_role = g_strdup (role);
1680 g_free (priv->wm_role);
1681 priv->wm_role = new_role;
1683 if (gtk_widget_get_realized (GTK_WIDGET (window)))
1684 gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
1687 g_object_notify (G_OBJECT (window), "role");
1691 * gtk_window_set_startup_id:
1692 * @window: a #GtkWindow
1693 * @startup_id: a string with startup-notification identifier
1695 * Startup notification identifiers are used by desktop environment to
1696 * track application startup, to provide user feedback and other
1697 * features. This function changes the corresponding property on the
1698 * underlying GdkWindow. Normally, startup identifier is managed
1699 * automatically and you should only use this function in special cases
1700 * like transferring focus from other processes. You should use this
1701 * function before calling gtk_window_present() or any equivalent
1702 * function generating a window map event.
1704 * This function is only useful on X11, not with other GTK+ targets.
1709 gtk_window_set_startup_id (GtkWindow *window,
1710 const gchar *startup_id)
1712 GtkWindowPrivate *priv;
1715 g_return_if_fail (GTK_IS_WINDOW (window));
1717 priv = window->priv;
1718 widget = GTK_WIDGET (window);
1720 g_free (priv->startup_id);
1721 priv->startup_id = g_strdup (startup_id);
1723 if (gtk_widget_get_realized (widget))
1725 GdkWindow *gdk_window;
1726 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1728 gdk_window = gtk_widget_get_window (widget);
1730 #ifdef GDK_WINDOWING_X11
1731 if (timestamp != GDK_CURRENT_TIME)
1732 gdk_x11_window_set_user_time (gdk_window, timestamp);
1735 /* Here we differentiate real and "fake" startup notification IDs,
1736 * constructed on purpose just to pass interaction timestamp
1738 if (startup_id_is_fake (priv->startup_id))
1739 gtk_window_present_with_time (window, timestamp);
1742 gdk_window_set_startup_id (gdk_window,
1745 /* If window is mapped, terminate the startup-notification too */
1746 if (gtk_widget_get_mapped (widget) &&
1747 !disable_startup_notification)
1748 gdk_notify_startup_complete_with_id (priv->startup_id);
1752 g_object_notify (G_OBJECT (window), "startup-id");
1756 * gtk_window_get_role:
1757 * @window: a #GtkWindow
1759 * Returns the role of the window. See gtk_window_set_role() for
1760 * further explanation.
1762 * Return value: the role of the window if set, or %NULL. The
1763 * returned is owned by the widget and must not be modified
1766 G_CONST_RETURN gchar *
1767 gtk_window_get_role (GtkWindow *window)
1769 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1771 return window->priv->wm_role;
1775 * gtk_window_set_focus:
1776 * @window: a #GtkWindow
1777 * @focus: (allow-none): widget to be the new focus widget, or %NULL to unset
1778 * any focus widget for the toplevel window.
1780 * If @focus is not the current focus widget, and is focusable, sets
1781 * it as the focus widget for the window. If @focus is %NULL, unsets
1782 * the focus widget for this window. To set the focus to a particular
1783 * widget in the toplevel, it is usually more convenient to use
1784 * gtk_widget_grab_focus() instead of this function.
1787 gtk_window_set_focus (GtkWindow *window,
1790 GtkWindowPrivate *priv;
1793 g_return_if_fail (GTK_IS_WINDOW (window));
1795 priv = window->priv;
1799 g_return_if_fail (GTK_IS_WIDGET (focus));
1800 g_return_if_fail (gtk_widget_get_can_focus (focus));
1804 gtk_widget_grab_focus (focus);
1807 /* Clear the existing focus chain, so that when we focus into
1808 * the window again, we start at the beginnning.
1810 GtkWidget *widget = priv->focus_widget;
1813 while ((parent = gtk_widget_get_parent (widget)))
1816 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1820 _gtk_window_internal_set_focus (window, NULL);
1825 _gtk_window_internal_set_focus (GtkWindow *window,
1828 GtkWindowPrivate *priv;
1830 g_return_if_fail (GTK_IS_WINDOW (window));
1832 priv = window->priv;
1834 if ((priv->focus_widget != focus) ||
1835 (focus && !gtk_widget_has_focus (focus)))
1836 g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1840 * gtk_window_set_default:
1841 * @window: a #GtkWindow
1842 * @default_widget: (allow-none): widget to be the default, or %NULL to unset the
1843 * default widget for the toplevel.
1845 * The default widget is the widget that's activated when the user
1846 * presses Enter in a dialog (for example). This function sets or
1847 * unsets the default widget for a #GtkWindow about. When setting
1848 * (rather than unsetting) the default widget it's generally easier to
1849 * call gtk_widget_grab_focus() on the widget. Before making a widget
1850 * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1851 * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1854 gtk_window_set_default (GtkWindow *window,
1855 GtkWidget *default_widget)
1857 GtkWindowPrivate *priv;
1859 g_return_if_fail (GTK_IS_WINDOW (window));
1861 priv = window->priv;
1864 g_return_if_fail (gtk_widget_get_can_default (default_widget));
1866 if (priv->default_widget != default_widget)
1868 GtkWidget *old_default_widget = NULL;
1871 g_object_ref (default_widget);
1873 if (priv->default_widget)
1875 old_default_widget = priv->default_widget;
1877 if (priv->focus_widget != priv->default_widget ||
1878 !gtk_widget_get_receives_default (priv->default_widget))
1879 _gtk_widget_set_has_default (priv->default_widget, FALSE);
1881 gtk_widget_queue_draw (priv->default_widget);
1884 priv->default_widget = default_widget;
1886 if (priv->default_widget)
1888 if (priv->focus_widget == NULL ||
1889 !gtk_widget_get_receives_default (priv->focus_widget))
1890 _gtk_widget_set_has_default (priv->default_widget, TRUE);
1892 gtk_widget_queue_draw (priv->default_widget);
1895 if (old_default_widget)
1896 g_object_notify (G_OBJECT (old_default_widget), "has-default");
1900 g_object_notify (G_OBJECT (default_widget), "has-default");
1901 g_object_unref (default_widget);
1907 * gtk_window_get_default_widget:
1908 * @window: a #GtkWindow
1910 * Returns the default widget for @window. See gtk_window_set_default()
1913 * Returns: (transfer none): the default widget, or %NULL if there is none.
1918 gtk_window_get_default_widget (GtkWindow *window)
1920 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1922 return window->priv->default_widget;
1926 handle_keys_changed (gpointer data)
1928 GtkWindow *window = GTK_WINDOW (data);
1929 GtkWindowPrivate *priv = window->priv;
1931 if (priv->keys_changed_handler)
1933 g_source_remove (priv->keys_changed_handler);
1934 priv->keys_changed_handler = 0;
1937 g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1943 gtk_window_notify_keys_changed (GtkWindow *window)
1945 GtkWindowPrivate *priv = window->priv;
1947 if (!priv->keys_changed_handler)
1948 priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1952 * gtk_window_add_accel_group:
1953 * @window: window to attach accelerator group to
1954 * @accel_group: a #GtkAccelGroup
1956 * Associate @accel_group with @window, such that calling
1957 * gtk_accel_groups_activate() on @window will activate accelerators
1961 gtk_window_add_accel_group (GtkWindow *window,
1962 GtkAccelGroup *accel_group)
1964 g_return_if_fail (GTK_IS_WINDOW (window));
1965 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1967 _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1968 g_signal_connect_object (accel_group, "accel-changed",
1969 G_CALLBACK (gtk_window_notify_keys_changed),
1970 window, G_CONNECT_SWAPPED);
1971 gtk_window_notify_keys_changed (window);
1975 * gtk_window_remove_accel_group:
1976 * @window: a #GtkWindow
1977 * @accel_group: a #GtkAccelGroup
1979 * Reverses the effects of gtk_window_add_accel_group().
1982 gtk_window_remove_accel_group (GtkWindow *window,
1983 GtkAccelGroup *accel_group)
1985 g_return_if_fail (GTK_IS_WINDOW (window));
1986 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1988 g_signal_handlers_disconnect_by_func (accel_group,
1989 gtk_window_notify_keys_changed,
1991 _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1992 gtk_window_notify_keys_changed (window);
1995 static GtkMnemonicHash *
1996 gtk_window_get_mnemonic_hash (GtkWindow *window,
1999 GtkWindowPrivate *private = window->priv;
2001 if (!private->mnemonic_hash && create)
2002 private->mnemonic_hash = _gtk_mnemonic_hash_new ();
2004 return private->mnemonic_hash;
2008 * gtk_window_add_mnemonic:
2009 * @window: a #GtkWindow
2010 * @keyval: the mnemonic
2011 * @target: the widget that gets activated by the mnemonic
2013 * Adds a mnemonic to this window.
2016 gtk_window_add_mnemonic (GtkWindow *window,
2020 g_return_if_fail (GTK_IS_WINDOW (window));
2021 g_return_if_fail (GTK_IS_WIDGET (target));
2023 _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
2025 gtk_window_notify_keys_changed (window);
2029 * gtk_window_remove_mnemonic:
2030 * @window: a #GtkWindow
2031 * @keyval: the mnemonic
2032 * @target: the widget that gets activated by the mnemonic
2034 * Removes a mnemonic from this window.
2037 gtk_window_remove_mnemonic (GtkWindow *window,
2041 g_return_if_fail (GTK_IS_WINDOW (window));
2042 g_return_if_fail (GTK_IS_WIDGET (target));
2044 _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
2046 gtk_window_notify_keys_changed (window);
2050 * gtk_window_mnemonic_activate:
2051 * @window: a #GtkWindow
2052 * @keyval: the mnemonic
2053 * @modifier: the modifiers
2054 * @returns: %TRUE if the activation is done.
2056 * Activates the targets associated with the mnemonic.
2059 gtk_window_mnemonic_activate (GtkWindow *window,
2061 GdkModifierType modifier)
2063 GtkWindowPrivate *priv;
2065 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2067 priv = window->priv;
2069 if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
2071 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
2073 return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
2080 * gtk_window_set_mnemonic_modifier:
2081 * @window: a #GtkWindow
2082 * @modifier: the modifier mask used to activate
2083 * mnemonics on this window.
2085 * Sets the mnemonic modifier for this window.
2088 gtk_window_set_mnemonic_modifier (GtkWindow *window,
2089 GdkModifierType modifier)
2091 GtkWindowPrivate *priv;
2093 g_return_if_fail (GTK_IS_WINDOW (window));
2094 g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
2096 priv = window->priv;
2098 priv->mnemonic_modifier = modifier;
2099 gtk_window_notify_keys_changed (window);
2103 * gtk_window_get_mnemonic_modifier:
2104 * @window: a #GtkWindow
2106 * Returns the mnemonic modifier for this window. See
2107 * gtk_window_set_mnemonic_modifier().
2109 * Return value: the modifier mask used to activate
2110 * mnemonics on this window.
2113 gtk_window_get_mnemonic_modifier (GtkWindow *window)
2115 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
2117 return window->priv->mnemonic_modifier;
2121 * gtk_window_set_position:
2122 * @window: a #GtkWindow.
2123 * @position: a position constraint.
2125 * Sets a position constraint for this window. If the old or new
2126 * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
2127 * the window to be repositioned to satisfy the new constraint.
2130 gtk_window_set_position (GtkWindow *window,
2131 GtkWindowPosition position)
2133 GtkWindowPrivate *priv;
2135 g_return_if_fail (GTK_IS_WINDOW (window));
2137 priv = window->priv;
2139 if (position == GTK_WIN_POS_CENTER_ALWAYS ||
2140 priv->position == GTK_WIN_POS_CENTER_ALWAYS)
2142 GtkWindowGeometryInfo *info;
2144 info = gtk_window_get_geometry_info (window, TRUE);
2146 /* this flag causes us to re-request the CENTER_ALWAYS
2147 * constraint in gtk_window_move_resize(), see
2148 * comment in that function.
2150 info->position_constraints_changed = TRUE;
2152 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2155 priv->position = position;
2157 g_object_notify (G_OBJECT (window), "window-position");
2161 * gtk_window_activate_focus:
2162 * @window: a #GtkWindow
2164 * Activates the current focused widget within the window.
2166 * Return value: %TRUE if a widget got activated.
2169 gtk_window_activate_focus (GtkWindow *window)
2171 GtkWindowPrivate *priv;
2173 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2175 priv = window->priv;
2177 if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2178 return gtk_widget_activate (priv->focus_widget);
2184 * gtk_window_get_focus:
2185 * @window: a #GtkWindow
2187 * Retrieves the current focused widget within the window.
2188 * Note that this is the widget that would have the focus
2189 * if the toplevel window focused; if the toplevel window
2190 * is not focused then <literal>gtk_widget_has_focus (widget)</literal> will
2191 * not be %TRUE for the widget.
2193 * Return value: (transfer none): the currently focused widget, or %NULL if there is none.
2196 gtk_window_get_focus (GtkWindow *window)
2198 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2200 return window->priv->focus_widget;
2204 * gtk_window_activate_default:
2205 * @window: a #GtkWindow
2207 * Activates the default widget for the window, unless the current
2208 * focused widget has been configured to receive the default action
2209 * (see gtk_widget_set_receives_default()), in which case the
2210 * focused widget is activated.
2212 * Return value: %TRUE if a widget got activated.
2215 gtk_window_activate_default (GtkWindow *window)
2217 GtkWindowPrivate *priv;
2219 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2221 priv = window->priv;
2223 if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) &&
2224 (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget)))
2225 return gtk_widget_activate (priv->default_widget);
2226 else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget))
2227 return gtk_widget_activate (priv->focus_widget);
2233 * gtk_window_set_modal:
2234 * @window: a #GtkWindow
2235 * @modal: whether the window is modal
2237 * Sets a window modal or non-modal. Modal windows prevent interaction
2238 * with other windows in the same application. To keep modal dialogs
2239 * on top of main application windows, use
2240 * gtk_window_set_transient_for() to make the dialog transient for the
2241 * parent; most <link linkend="gtk-X11-arch">window managers</link>
2242 * will then disallow lowering the dialog below the parent.
2247 gtk_window_set_modal (GtkWindow *window,
2250 GtkWindowPrivate *priv;
2253 g_return_if_fail (GTK_IS_WINDOW (window));
2255 priv = window->priv;
2257 modal = modal != FALSE;
2258 if (priv->modal == modal)
2261 priv->modal = modal;
2262 widget = GTK_WIDGET (window);
2264 /* adjust desired modality state */
2265 if (gtk_widget_get_realized (widget))
2268 gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE);
2270 gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE);
2273 if (gtk_widget_get_visible (widget))
2276 gtk_grab_add (widget);
2278 gtk_grab_remove (widget);
2281 g_object_notify (G_OBJECT (window), "modal");
2285 * gtk_window_get_modal:
2286 * @window: a #GtkWindow
2288 * Returns whether the window is modal. See gtk_window_set_modal().
2290 * Return value: %TRUE if the window is set to be modal and
2291 * establishes a grab when shown
2294 gtk_window_get_modal (GtkWindow *window)
2296 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2298 return window->priv->modal;
2302 * gtk_window_list_toplevels:
2304 * Returns a list of all existing toplevel windows. The widgets
2305 * in the list are not individually referenced. If you want
2306 * to iterate through the list and perform actions involving
2307 * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2308 * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2309 * then unref all the widgets afterwards.
2311 * Return value: (element-type GtkWidget) (transfer container): list of toplevel widgets
2314 gtk_window_list_toplevels (void)
2319 for (slist = toplevel_list; slist; slist = slist->next)
2320 list = g_list_prepend (list, slist->data);
2326 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2328 GList *embedded_windows;
2330 g_return_if_fail (GTK_IS_WINDOW (window));
2332 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2333 if (embedded_windows)
2334 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2335 embedded_windows = g_list_prepend (embedded_windows,
2336 GUINT_TO_POINTER (xid));
2338 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2341 (GDestroyNotify) g_list_free : NULL);
2345 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2347 GList *embedded_windows;
2350 g_return_if_fail (GTK_IS_WINDOW (window));
2352 embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2353 if (embedded_windows)
2354 g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2356 node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2359 embedded_windows = g_list_remove_link (embedded_windows, node);
2360 g_list_free_1 (node);
2363 g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2366 (GDestroyNotify) g_list_free : NULL);
2370 gtk_window_dispose (GObject *object)
2372 GtkWindow *window = GTK_WINDOW (object);
2374 gtk_window_set_focus (window, NULL);
2375 gtk_window_set_default (window, NULL);
2377 G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2381 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2383 gtk_widget_destroy (GTK_WIDGET (child));
2387 connect_parent_destroyed (GtkWindow *window)
2389 GtkWindowPrivate *priv = window->priv;
2391 if (priv->transient_parent)
2393 g_signal_connect (priv->transient_parent,
2395 G_CALLBACK (parent_destroyed_callback),
2401 disconnect_parent_destroyed (GtkWindow *window)
2403 GtkWindowPrivate *priv = window->priv;
2405 if (priv->transient_parent)
2407 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2408 parent_destroyed_callback,
2414 gtk_window_transient_parent_realized (GtkWidget *parent,
2417 if (gtk_widget_get_realized (window))
2418 gdk_window_set_transient_for (gtk_widget_get_window (window),
2419 gtk_widget_get_window (parent));
2423 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2426 if (gtk_widget_get_realized (window))
2427 gdk_property_delete (gtk_widget_get_window (window),
2428 gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2432 gtk_window_transient_parent_screen_changed (GtkWindow *parent,
2436 gtk_window_set_screen (window, parent->priv->screen);
2440 gtk_window_unset_transient_for (GtkWindow *window)
2442 GtkWindowPrivate *priv = window->priv;
2444 if (priv->transient_parent)
2446 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2447 gtk_window_transient_parent_realized,
2449 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2450 gtk_window_transient_parent_unrealized,
2452 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2453 gtk_window_transient_parent_screen_changed,
2455 g_signal_handlers_disconnect_by_func (priv->transient_parent,
2456 gtk_widget_destroyed,
2457 &priv->transient_parent);
2459 if (priv->destroy_with_parent)
2460 disconnect_parent_destroyed (window);
2462 priv->transient_parent = NULL;
2464 if (priv->transient_parent_group)
2466 priv->transient_parent_group = FALSE;
2467 gtk_window_group_remove_window (priv->group,
2474 * gtk_window_set_transient_for:
2475 * @window: a #GtkWindow
2476 * @parent: (allow-none): parent window, or %NULL
2478 * Dialog windows should be set transient for the main application
2479 * window they were spawned from. This allows <link
2480 * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2481 * dialog on top of the main window, or center the dialog over the
2482 * main window. gtk_dialog_new_with_buttons() and other convenience
2483 * functions in GTK+ will sometimes call
2484 * gtk_window_set_transient_for() on your behalf.
2486 * Passing %NULL for @parent unsets the current transient window.
2488 * On Windows, this function puts the child window on top of the parent,
2489 * much as the window manager would have done on X.
2492 gtk_window_set_transient_for (GtkWindow *window,
2495 GtkWindowPrivate *priv;
2497 g_return_if_fail (GTK_IS_WINDOW (window));
2498 g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2499 g_return_if_fail (window != parent);
2501 priv = window->priv;
2503 if (priv->transient_parent)
2505 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2506 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) &&
2507 (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent))))
2508 gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent),
2509 GTK_WIDGET (window));
2511 gtk_window_unset_transient_for (window);
2514 priv->transient_parent = parent;
2518 g_signal_connect (parent, "destroy",
2519 G_CALLBACK (gtk_widget_destroyed),
2520 &priv->transient_parent);
2521 g_signal_connect (parent, "realize",
2522 G_CALLBACK (gtk_window_transient_parent_realized),
2524 g_signal_connect (parent, "unrealize",
2525 G_CALLBACK (gtk_window_transient_parent_unrealized),
2527 g_signal_connect (parent, "notify::screen",
2528 G_CALLBACK (gtk_window_transient_parent_screen_changed),
2531 gtk_window_set_screen (window, parent->priv->screen);
2533 if (priv->destroy_with_parent)
2534 connect_parent_destroyed (window);
2536 if (gtk_widget_get_realized (GTK_WIDGET (window)) &&
2537 gtk_widget_get_realized (GTK_WIDGET (parent)))
2538 gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2539 GTK_WIDGET (window));
2541 if (parent->priv->group)
2543 gtk_window_group_add_window (parent->priv->group, window);
2544 priv->transient_parent_group = TRUE;
2550 * gtk_window_get_transient_for:
2551 * @window: a #GtkWindow
2553 * Fetches the transient parent for this window. See
2554 * gtk_window_set_transient_for().
2556 * Return value: (transfer none): the transient parent for this window, or %NULL
2557 * if no transient parent has been set.
2560 gtk_window_get_transient_for (GtkWindow *window)
2562 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2564 return window->priv->transient_parent;
2568 * gtk_window_set_opacity:
2569 * @window: a #GtkWindow
2570 * @opacity: desired opacity, between 0 and 1
2572 * Request the windowing system to make @window partially transparent,
2573 * with opacity 0 being fully transparent and 1 fully opaque. (Values
2574 * of the opacity parameter are clamped to the [0,1] range.) On X11
2575 * this has any effect only on X screens with a compositing manager
2576 * running. See gtk_widget_is_composited(). On Windows it should work
2579 * Note that setting a window's opacity after the window has been
2580 * shown causes it to flicker once on Windows.
2585 gtk_window_set_opacity (GtkWindow *window,
2588 GtkWindowPrivate *priv;
2590 g_return_if_fail (GTK_IS_WINDOW (window));
2592 priv = window->priv;
2596 else if (opacity > 1.0)
2599 priv->opacity_set = TRUE;
2600 priv->opacity = opacity;
2602 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2603 gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)),
2608 * gtk_window_get_opacity:
2609 * @window: a #GtkWindow
2611 * Fetches the requested opacity for this window. See
2612 * gtk_window_set_opacity().
2614 * Return value: the requested opacity for this window.
2619 gtk_window_get_opacity (GtkWindow *window)
2621 g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2623 return window->priv->opacity;
2627 * gtk_window_get_application:
2628 * @window: a #GtkWindow
2630 * Gets the #GtkApplication associated with the window (if any).
2632 * Return value: a #GtkApplication, or %NULL
2637 gtk_window_get_application (GtkWindow *window)
2639 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2641 return window->priv->application;
2645 gtk_window_release_application (GtkWindow *window)
2647 if (window->priv->application)
2649 GtkApplication *application;
2651 /* steal reference into temp variable */
2652 application = window->priv->application;
2653 window->priv->application = NULL;
2655 gtk_application_remove_window (application, window);
2656 g_object_unref (application);
2661 * gtk_window_set_application:
2662 * @window: a #GtkWindow
2663 * @application: a #GtkApplication, or %NULL
2665 * Sets or unsets the #GtkApplication associated with the window.
2667 * The application will be kept alive for at least as long as the window
2673 gtk_window_set_application (GtkWindow *window,
2674 GtkApplication *application)
2676 GtkWindowPrivate *priv;
2678 g_return_if_fail (GTK_IS_WINDOW (window));
2680 priv = window->priv;
2681 if (priv->application != application)
2683 gtk_window_release_application (window);
2685 priv->application = application;
2687 if (priv->application != NULL)
2689 g_object_ref (priv->application);
2691 gtk_application_add_window (priv->application, window);
2694 g_object_notify (G_OBJECT (window), "application");
2699 * gtk_window_set_type_hint:
2700 * @window: a #GtkWindow
2701 * @hint: the window type
2703 * By setting the type hint for the window, you allow the window
2704 * manager to decorate and handle the window in a way which is
2705 * suitable to the function of the window in your application.
2707 * This function should be called before the window becomes visible.
2709 * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2710 * will sometimes call gtk_window_set_type_hint() on your behalf.
2714 gtk_window_set_type_hint (GtkWindow *window,
2715 GdkWindowTypeHint hint)
2717 GtkWindowPrivate *priv;
2719 g_return_if_fail (GTK_IS_WINDOW (window));
2720 g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2722 priv = window->priv;
2724 if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2725 priv->gdk_type_hint = hint;
2727 priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2729 priv->reset_type_hint = TRUE;
2730 priv->type_hint = hint;
2734 * gtk_window_get_type_hint:
2735 * @window: a #GtkWindow
2737 * Gets the type hint for this window. See gtk_window_set_type_hint().
2739 * Return value: the type hint for @window.
2742 gtk_window_get_type_hint (GtkWindow *window)
2744 g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2746 return window->priv->type_hint;
2750 * gtk_window_set_skip_taskbar_hint:
2751 * @window: a #GtkWindow
2752 * @setting: %TRUE to keep this window from appearing in the task bar
2754 * Windows may set a hint asking the desktop environment not to display
2755 * the window in the task bar. This function sets this hint.
2760 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2763 GtkWindowPrivate *priv;
2765 g_return_if_fail (GTK_IS_WINDOW (window));
2767 priv = window->priv;
2769 setting = setting != FALSE;
2771 if (priv->skips_taskbar != setting)
2773 priv->skips_taskbar = setting;
2774 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2775 gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2776 priv->skips_taskbar);
2777 g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2782 * gtk_window_get_skip_taskbar_hint:
2783 * @window: a #GtkWindow
2785 * Gets the value set by gtk_window_set_skip_taskbar_hint()
2787 * Return value: %TRUE if window shouldn't be in taskbar
2792 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2794 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2796 return window->priv->skips_taskbar;
2800 * gtk_window_set_skip_pager_hint:
2801 * @window: a #GtkWindow
2802 * @setting: %TRUE to keep this window from appearing in the pager
2804 * Windows may set a hint asking the desktop environment not to display
2805 * the window in the pager. This function sets this hint.
2806 * (A "pager" is any desktop navigation tool such as a workspace
2807 * switcher that displays a thumbnail representation of the windows
2813 gtk_window_set_skip_pager_hint (GtkWindow *window,
2816 GtkWindowPrivate *priv;
2818 g_return_if_fail (GTK_IS_WINDOW (window));
2820 priv = window->priv;
2822 setting = setting != FALSE;
2824 if (priv->skips_pager != setting)
2826 priv->skips_pager = setting;
2827 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2828 gdk_window_set_skip_pager_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2830 g_object_notify (G_OBJECT (window), "skip-pager-hint");
2835 * gtk_window_get_skip_pager_hint:
2836 * @window: a #GtkWindow
2838 * Gets the value set by gtk_window_set_skip_pager_hint().
2840 * Return value: %TRUE if window shouldn't be in pager
2845 gtk_window_get_skip_pager_hint (GtkWindow *window)
2847 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2849 return window->priv->skips_pager;
2853 * gtk_window_set_urgency_hint:
2854 * @window: a #GtkWindow
2855 * @setting: %TRUE to mark this window as urgent
2857 * Windows may set a hint asking the desktop environment to draw
2858 * the users attention to the window. This function sets this hint.
2863 gtk_window_set_urgency_hint (GtkWindow *window,
2866 GtkWindowPrivate *priv;
2868 g_return_if_fail (GTK_IS_WINDOW (window));
2870 priv = window->priv;
2872 setting = setting != FALSE;
2874 if (priv->urgent != setting)
2876 priv->urgent = setting;
2877 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2878 gdk_window_set_urgency_hint (gtk_widget_get_window (GTK_WIDGET (window)),
2880 g_object_notify (G_OBJECT (window), "urgency-hint");
2885 * gtk_window_get_urgency_hint:
2886 * @window: a #GtkWindow
2888 * Gets the value set by gtk_window_set_urgency_hint()
2890 * Return value: %TRUE if window is urgent
2895 gtk_window_get_urgency_hint (GtkWindow *window)
2897 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2899 return window->priv->urgent;
2903 * gtk_window_set_accept_focus:
2904 * @window: a #GtkWindow
2905 * @setting: %TRUE to let this window receive input focus
2907 * Windows may set a hint asking the desktop environment not to receive
2908 * the input focus. This function sets this hint.
2913 gtk_window_set_accept_focus (GtkWindow *window,
2916 GtkWindowPrivate *priv;
2918 g_return_if_fail (GTK_IS_WINDOW (window));
2920 priv = window->priv;
2922 setting = setting != FALSE;
2924 if (priv->accept_focus != setting)
2926 priv->accept_focus = setting;
2927 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2928 gdk_window_set_accept_focus (gtk_widget_get_window (GTK_WIDGET (window)),
2929 priv->accept_focus);
2930 g_object_notify (G_OBJECT (window), "accept-focus");
2935 * gtk_window_get_accept_focus:
2936 * @window: a #GtkWindow
2938 * Gets the value set by gtk_window_set_accept_focus().
2940 * Return value: %TRUE if window should receive the input focus
2945 gtk_window_get_accept_focus (GtkWindow *window)
2947 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2949 return window->priv->accept_focus;
2953 * gtk_window_set_focus_on_map:
2954 * @window: a #GtkWindow
2955 * @setting: %TRUE to let this window receive input focus on map
2957 * Windows may set a hint asking the desktop environment not to receive
2958 * the input focus when the window is mapped. This function sets this
2964 gtk_window_set_focus_on_map (GtkWindow *window,
2967 GtkWindowPrivate *priv;
2969 g_return_if_fail (GTK_IS_WINDOW (window));
2971 priv = window->priv;
2973 setting = setting != FALSE;
2975 if (priv->focus_on_map != setting)
2977 priv->focus_on_map = setting;
2978 if (gtk_widget_get_realized (GTK_WIDGET (window)))
2979 gdk_window_set_focus_on_map (gtk_widget_get_window (GTK_WIDGET (window)),
2980 priv->focus_on_map);
2981 g_object_notify (G_OBJECT (window), "focus-on-map");
2986 * gtk_window_get_focus_on_map:
2987 * @window: a #GtkWindow
2989 * Gets the value set by gtk_window_set_focus_on_map().
2991 * Return value: %TRUE if window should receive the input focus when
2997 gtk_window_get_focus_on_map (GtkWindow *window)
2999 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3001 return window->priv->focus_on_map;
3005 * gtk_window_set_destroy_with_parent:
3006 * @window: a #GtkWindow
3007 * @setting: whether to destroy @window with its transient parent
3009 * If @setting is %TRUE, then destroying the transient parent of @window
3010 * will also destroy @window itself. This is useful for dialogs that
3011 * shouldn't persist beyond the lifetime of the main window they're
3012 * associated with, for example.
3015 gtk_window_set_destroy_with_parent (GtkWindow *window,
3018 GtkWindowPrivate *priv;
3020 g_return_if_fail (GTK_IS_WINDOW (window));
3022 priv = window->priv;
3024 if (priv->destroy_with_parent == (setting != FALSE))
3027 if (priv->destroy_with_parent)
3029 disconnect_parent_destroyed (window);
3033 connect_parent_destroyed (window);
3036 priv->destroy_with_parent = setting;
3038 g_object_notify (G_OBJECT (window), "destroy-with-parent");
3042 * gtk_window_get_destroy_with_parent:
3043 * @window: a #GtkWindow
3045 * Returns whether the window will be destroyed with its transient parent. See
3046 * gtk_window_set_destroy_with_parent ().
3048 * Return value: %TRUE if the window will be destroyed with its transient parent.
3051 gtk_window_get_destroy_with_parent (GtkWindow *window)
3053 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3055 return window->priv->destroy_with_parent;
3058 static GtkWindowGeometryInfo*
3059 gtk_window_get_geometry_info (GtkWindow *window,
3062 GtkWindowPrivate *priv = window->priv;
3063 GtkWindowGeometryInfo *info;
3065 info = priv->geometry_info;
3066 if (!info && create)
3068 info = g_new0 (GtkWindowGeometryInfo, 1);
3070 info->default_width = -1;
3071 info->default_height = -1;
3072 info->resize_width = -1;
3073 info->resize_height = -1;
3074 info->initial_x = 0;
3075 info->initial_y = 0;
3076 info->initial_pos_set = FALSE;
3077 info->default_is_geometry = FALSE;
3078 info->position_constraints_changed = FALSE;
3079 info->last.configure_request.x = 0;
3080 info->last.configure_request.y = 0;
3081 info->last.configure_request.width = -1;
3082 info->last.configure_request.height = -1;
3083 info->widget = NULL;
3085 priv->geometry_info = info;
3092 * gtk_window_set_geometry_hints:
3093 * @window: a #GtkWindow
3094 * @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
3095 * @geometry: (allow-none): struct containing geometry information or %NULL
3096 * @geom_mask: mask indicating which struct fields should be paid attention to
3098 * This function sets up hints about how a window can be resized by
3099 * the user. You can set a minimum and maximum size; allowed resize
3100 * increments (e.g. for xterm, you can only resize by the size of a
3101 * character); aspect ratios; and more. See the #GdkGeometry struct.
3105 gtk_window_set_geometry_hints (GtkWindow *window,
3106 GtkWidget *geometry_widget,
3107 GdkGeometry *geometry,
3108 GdkWindowHints geom_mask)
3110 GtkWindowGeometryInfo *info;
3112 g_return_if_fail (GTK_IS_WINDOW (window));
3113 g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
3115 info = gtk_window_get_geometry_info (window, TRUE);
3118 g_signal_handlers_disconnect_by_func (info->widget,
3119 gtk_widget_destroyed,
3122 info->widget = geometry_widget;
3124 g_signal_connect (geometry_widget, "destroy",
3125 G_CALLBACK (gtk_widget_destroyed),
3129 info->geometry = *geometry;
3131 /* We store gravity in priv->gravity not in the hints. */
3132 info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
3134 if (geom_mask & GDK_HINT_WIN_GRAVITY)
3136 gtk_window_set_gravity (window, geometry->win_gravity);
3139 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3143 * gtk_window_set_decorated:
3144 * @window: a #GtkWindow
3145 * @setting: %TRUE to decorate the window
3147 * By default, windows are decorated with a title bar, resize
3148 * controls, etc. Some <link linkend="gtk-X11-arch">window
3149 * managers</link> allow GTK+ to disable these decorations, creating a
3150 * borderless window. If you set the decorated property to %FALSE
3151 * using this function, GTK+ will do its best to convince the window
3152 * manager not to decorate the window. Depending on the system, this
3153 * function may not have any effect when called on a window that is
3154 * already visible, so you should call it before calling gtk_window_show().
3156 * On Windows, this function always works, since there's no window manager
3161 gtk_window_set_decorated (GtkWindow *window,
3164 GtkWindowPrivate *priv;
3165 GdkWindow *gdk_window;
3167 g_return_if_fail (GTK_IS_WINDOW (window));
3169 priv = window->priv;
3171 setting = setting != FALSE;
3173 if (setting == priv->decorated)
3176 priv->decorated = setting;
3178 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3181 if (priv->decorated)
3182 gdk_window_set_decorations (gdk_window,
3185 gdk_window_set_decorations (gdk_window,
3189 g_object_notify (G_OBJECT (window), "decorated");
3193 * gtk_window_get_decorated:
3194 * @window: a #GtkWindow
3196 * Returns whether the window has been set to have decorations
3197 * such as a title bar via gtk_window_set_decorated().
3199 * Return value: %TRUE if the window has been set to have decorations
3202 gtk_window_get_decorated (GtkWindow *window)
3204 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3206 return window->priv->decorated;
3210 * gtk_window_set_deletable:
3211 * @window: a #GtkWindow
3212 * @setting: %TRUE to decorate the window as deletable
3214 * By default, windows have a close button in the window frame. Some
3215 * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to
3216 * disable this button. If you set the deletable property to %FALSE
3217 * using this function, GTK+ will do its best to convince the window
3218 * manager not to show a close button. Depending on the system, this
3219 * function may not have any effect when called on a window that is
3220 * already visible, so you should call it before calling gtk_window_show().
3222 * On Windows, this function always works, since there's no window manager
3228 gtk_window_set_deletable (GtkWindow *window,
3231 GtkWindowPrivate *priv;
3232 GdkWindow *gdk_window;
3234 g_return_if_fail (GTK_IS_WINDOW (window));
3236 priv = window->priv;
3238 setting = setting != FALSE;
3240 if (setting == priv->deletable)
3243 priv->deletable = setting;
3245 gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
3248 if (priv->deletable)
3249 gdk_window_set_functions (gdk_window,
3252 gdk_window_set_functions (gdk_window,
3253 GDK_FUNC_ALL | GDK_FUNC_CLOSE);
3256 g_object_notify (G_OBJECT (window), "deletable");
3260 * gtk_window_get_deletable:
3261 * @window: a #GtkWindow
3263 * Returns whether the window has been set to have a close button
3264 * via gtk_window_set_deletable().
3266 * Return value: %TRUE if the window has been set to have a close button
3271 gtk_window_get_deletable (GtkWindow *window)
3273 g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3275 return window->priv->deletable;
3278 static GtkWindowIconInfo*
3279 get_icon_info (GtkWindow *window)
3281 return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3285 free_icon_info (GtkWindowIconInfo *info)
3287 g_free (info->icon_name);
3288 g_slice_free (GtkWindowIconInfo, info);
3292 static GtkWindowIconInfo*
3293 ensure_icon_info (GtkWindow *window)
3295 GtkWindowIconInfo *info;
3297 info = get_icon_info (window);
3301 info = g_slice_new0 (GtkWindowIconInfo);
3302 g_object_set_qdata_full (G_OBJECT (window),
3303 quark_gtk_window_icon_info,
3305 (GDestroyNotify)free_icon_info);
3312 icon_list_from_theme (GtkWidget *widget,
3317 GtkIconTheme *icon_theme;
3322 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3324 sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3327 for (i = 0; sizes[i]; i++)
3330 * We need an EWMH extension to handle scalable icons
3331 * by passing their name to the WM. For now just use a
3335 icon = gtk_icon_theme_load_icon (icon_theme, name,
3338 icon = gtk_icon_theme_load_icon (icon_theme, name,
3341 list = g_list_append (list, icon);
3351 gtk_window_realize_icon (GtkWindow *window)
3353 GtkWindowPrivate *priv = window->priv;
3355 GtkWindowIconInfo *info;
3356 GdkWindow *gdk_window;
3359 widget = GTK_WIDGET (window);
3360 gdk_window = gtk_widget_get_window (widget);
3362 g_return_if_fail (gdk_window != NULL);
3364 /* no point setting an icon on override-redirect */
3365 if (priv->type == GTK_WINDOW_POPUP)
3370 info = ensure_icon_info (window);
3375 info->using_default_icon = FALSE;
3376 info->using_parent_icon = FALSE;
3377 info->using_themed_icon = FALSE;
3379 icon_list = info->icon_list;
3381 /* Look up themed icon */
3382 if (icon_list == NULL && info->icon_name)
3384 icon_list = icon_list_from_theme (widget, info->icon_name);
3386 info->using_themed_icon = TRUE;
3389 /* Inherit from transient parent */
3390 if (icon_list == NULL && priv->transient_parent)
3392 icon_list = ensure_icon_info (priv->transient_parent)->icon_list;
3394 info->using_parent_icon = TRUE;
3397 /* Inherit from default */
3398 if (icon_list == NULL)
3400 icon_list = default_icon_list;
3402 info->using_default_icon = TRUE;
3405 /* Look up themed icon */
3406 if (icon_list == NULL && default_icon_name)
3408 icon_list = icon_list_from_theme (widget, default_icon_name);
3409 info->using_default_icon = TRUE;
3410 info->using_themed_icon = TRUE;
3413 info->realized = TRUE;
3415 if (info->using_themed_icon)
3417 GtkIconTheme *icon_theme;
3419 g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3420 g_list_free (icon_list);
3422 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3423 g_signal_connect (icon_theme, "changed",
3424 G_CALLBACK (update_themed_icon), window);
3429 gtk_window_unrealize_icon (GtkWindow *window)
3431 GtkWindowIconInfo *info;
3433 info = get_icon_info (window);
3438 if (info->using_themed_icon)
3440 GtkIconTheme *icon_theme;
3442 icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3444 g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3447 /* We don't clear the properties on the window, just figure the
3448 * window is going away.
3451 info->realized = FALSE;
3456 * gtk_window_set_icon_list:
3457 * @window: a #GtkWindow
3458 * @list: (element-type GdkPixbuf) (transfer container): list of #GdkPixbuf
3460 * Sets up the icon representing a #GtkWindow. The icon is used when
3461 * the window is minimized (also known as iconified). Some window
3462 * managers or desktop environments may also place it in the window
3463 * frame, or display it in other contexts.
3465 * gtk_window_set_icon_list() allows you to pass in the same icon in
3466 * several hand-drawn sizes. The list should contain the natural sizes
3467 * your icon is available in; that is, don't scale the image before
3468 * passing it to GTK+. Scaling is postponed until the last minute,
3469 * when the desired final size is known, to allow best quality.
3471 * By passing several sizes, you may improve the final image quality
3472 * of the icon, by reducing or eliminating automatic image scaling.
3474 * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3475 * larger images (64x64, 128x128) if you have them.
3477 * See also gtk_window_set_default_icon_list() to set the icon
3478 * for all windows in your application in one go.
3480 * Note that transient windows (those who have been set transient for another
3481 * window using gtk_window_set_transient_for()) will inherit their
3482 * icon from their transient parent. So there's no need to explicitly
3483 * set the icon on transient windows.
3486 gtk_window_set_icon_list (GtkWindow *window,
3489 GtkWindowIconInfo *info;
3491 g_return_if_fail (GTK_IS_WINDOW (window));
3493 info = ensure_icon_info (window);
3495 if (info->icon_list == list) /* check for NULL mostly */
3498 g_list_foreach (list,
3499 (GFunc) g_object_ref, NULL);
3501 g_list_foreach (info->icon_list,
3502 (GFunc) g_object_unref, NULL);
3504 g_list_free (info->icon_list);
3506 info->icon_list = g_list_copy (list);
3508 g_object_notify (G_OBJECT (window), "icon");
3510 gtk_window_unrealize_icon (window);
3512 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3513 gtk_window_realize_icon (window);
3515 /* We could try to update our transient children, but I don't think
3516 * it's really worth it. If we did it, the best way would probably
3517 * be to have children connect to notify::icon-list
3522 * gtk_window_get_icon_list:
3523 * @window: a #GtkWindow
3525 * Retrieves the list of icons set by gtk_window_set_icon_list().
3526 * The list is copied, but the reference count on each
3527 * member won't be incremented.
3529 * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3532 gtk_window_get_icon_list (GtkWindow *window)
3534 GtkWindowIconInfo *info;
3536 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3538 info = get_icon_info (window);
3541 return g_list_copy (info->icon_list);
3547 * gtk_window_set_icon:
3548 * @window: a #GtkWindow
3549 * @icon: (allow-none): icon image, or %NULL
3551 * Sets up the icon representing a #GtkWindow. This icon is used when
3552 * the window is minimized (also known as iconified). Some window
3553 * managers or desktop environments may also place it in the window
3554 * frame, or display it in other contexts.
3556 * The icon should be provided in whatever size it was naturally
3557 * drawn; that is, don't scale the image before passing it to
3558 * GTK+. Scaling is postponed until the last minute, when the desired
3559 * final size is known, to allow best quality.
3561 * If you have your icon hand-drawn in multiple sizes, use
3562 * gtk_window_set_icon_list(). Then the best size will be used.
3564 * This function is equivalent to calling gtk_window_set_icon_list()
3565 * with a 1-element list.
3567 * See also gtk_window_set_default_icon_list() to set the icon
3568 * for all windows in your application in one go.
3571 gtk_window_set_icon (GtkWindow *window,
3576 g_return_if_fail (GTK_IS_WINDOW (window));
3577 g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3582 list = g_list_append (list, icon);
3584 gtk_window_set_icon_list (window, list);
3590 update_themed_icon (GtkIconTheme *icon_theme,
3593 g_object_notify (G_OBJECT (window), "icon");
3595 gtk_window_unrealize_icon (window);
3597 if (gtk_widget_get_realized (GTK_WIDGET (window)))
3598 gtk_window_realize_icon (window);
3602 * gtk_window_set_icon_name:
3603 * @window: a #GtkWindow
3604 * @name: (allow-none): the name of the themed icon
3606 * Sets the icon for the window from a named themed icon. See
3607 * the docs for #GtkIconTheme for more details.
3609 * Note that this has nothing to do with the WM_ICON_NAME
3610 * property which is mentioned in the ICCCM.
3615 gtk_window_set_icon_name (GtkWindow *window,
3618 GtkWindowIconInfo *info;
3621 g_return_if_fail (GTK_IS_WINDOW (window));
3623 info = ensure_icon_info (window);
3625 if (g_strcmp0 (info->icon_name, name) == 0)
3628 tmp = info->icon_name;
3629 info->icon_name = g_strdup (name);
3632 g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3633 g_list_free (info->icon_list);
3634 info->icon_list = NULL;
3636 update_themed_icon (NULL, window);
3638 g_object_notify (G_OBJECT (window), "icon-name");
3642 * gtk_window_get_icon_name:
3643 * @window: a #GtkWindow
3645 * Returns the name of the themed icon for the window,
3646 * see gtk_window_set_icon_name().
3648 * Returns: the icon name or %NULL if the window has
3654 gtk_window_get_icon_name (GtkWindow *window)
3656 GtkWindowIconInfo *info;
3658 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3660 info = ensure_icon_info (window);
3662 return info->icon_name;
3666 * gtk_window_get_icon:
3667 * @window: a #GtkWindow
3669 * Gets the value set by gtk_window_set_icon() (or if you've
3670 * called gtk_window_set_icon_list(), gets the first icon in
3673 * Return value: (transfer none): icon for window
3676 gtk_window_get_icon (GtkWindow *window)
3678 GtkWindowIconInfo *info;
3680 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3682 info = get_icon_info (window);
3683 if (info && info->icon_list)
3684 return GDK_PIXBUF (info->icon_list->data);
3689 /* Load pixbuf, printing warning on failure if error == NULL
3692 load_pixbuf_verbosely (const char *filename,
3695 GError *local_err = NULL;
3698 pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3706 g_warning ("Error loading icon from file '%s':\n\t%s",
3707 filename, local_err->message);
3708 g_error_free (local_err);
3716 * gtk_window_set_icon_from_file:
3717 * @window: a #GtkWindow
3718 * @filename: location of icon file
3719 * @err: (allow-none): location to store error, or %NULL.
3721 * Sets the icon for @window.
3722 * Warns on failure if @err is %NULL.
3724 * This function is equivalent to calling gtk_window_set_icon()
3725 * with a pixbuf created by loading the image from @filename.
3727 * Returns: %TRUE if setting the icon succeeded.
3732 gtk_window_set_icon_from_file (GtkWindow *window,
3733 const gchar *filename,
3736 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3740 gtk_window_set_icon (window, pixbuf);
3741 g_object_unref (pixbuf);
3750 * gtk_window_set_default_icon_list:
3751 * @list: (element-type GdkPixbuf) (transfer container): a list of #GdkPixbuf
3753 * Sets an icon list to be used as fallback for windows that haven't
3754 * had gtk_window_set_icon_list() called on them to set up a
3755 * window-specific icon list. This function allows you to set up the
3756 * icon for all windows in your app at once.
3758 * See gtk_window_set_icon_list() for more details.
3762 gtk_window_set_default_icon_list (GList *list)
3766 if (list == default_icon_list)
3769 /* Update serial so we don't used cached pixmaps/masks
3771 default_icon_serial++;
3773 g_list_foreach (list,
3774 (GFunc) g_object_ref, NULL);
3776 g_list_foreach (default_icon_list,
3777 (GFunc) g_object_unref, NULL);
3779 g_list_free (default_icon_list);
3781 default_icon_list = g_list_copy (list);
3783 /* Update all toplevels */
3784 toplevels = gtk_window_list_toplevels ();
3785 tmp_list = toplevels;
3786 while (tmp_list != NULL)
3788 GtkWindowIconInfo *info;
3789 GtkWindow *w = tmp_list->data;
3791 info = get_icon_info (w);
3792 if (info && info->using_default_icon)
3794 gtk_window_unrealize_icon (w);
3795 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3796 gtk_window_realize_icon (w);
3799 tmp_list = tmp_list->next;
3801 g_list_free (toplevels);
3805 * gtk_window_set_default_icon:
3808 * Sets an icon to be used as fallback for windows that haven't
3809 * had gtk_window_set_icon() called on them from a pixbuf.
3814 gtk_window_set_default_icon (GdkPixbuf *icon)
3818 g_return_if_fail (GDK_IS_PIXBUF (icon));
3820 list = g_list_prepend (NULL, icon);
3821 gtk_window_set_default_icon_list (list);
3826 * gtk_window_set_default_icon_name:
3827 * @name: the name of the themed icon
3829 * Sets an icon to be used as fallback for windows that haven't
3830 * had gtk_window_set_icon_list() called on them from a named
3831 * themed icon, see gtk_window_set_icon_name().
3836 gtk_window_set_default_icon_name (const gchar *name)
3841 /* Update serial so we don't used cached pixmaps/masks
3843 default_icon_serial++;
3845 g_free (default_icon_name);
3846 default_icon_name = g_strdup (name);
3848 g_list_foreach (default_icon_list,
3849 (GFunc) g_object_unref, NULL);
3851 g_list_free (default_icon_list);
3852 default_icon_list = NULL;
3854 /* Update all toplevels */
3855 toplevels = gtk_window_list_toplevels ();
3856 tmp_list = toplevels;
3857 while (tmp_list != NULL)
3859 GtkWindowIconInfo *info;
3860 GtkWindow *w = tmp_list->data;
3862 info = get_icon_info (w);
3863 if (info && info->using_default_icon && info->using_themed_icon)
3865 gtk_window_unrealize_icon (w);
3866 if (gtk_widget_get_realized (GTK_WIDGET (w)))
3867 gtk_window_realize_icon (w);
3870 tmp_list = tmp_list->next;
3872 g_list_free (toplevels);
3876 * gtk_window_get_default_icon_name:
3878 * Returns the fallback icon name for windows that has been set
3879 * with gtk_window_set_default_icon_name(). The returned
3880 * string is owned by GTK+ and should not be modified. It
3881 * is only valid until the next call to
3882 * gtk_window_set_default_icon_name().
3884 * Returns: the fallback icon name for windows
3889 gtk_window_get_default_icon_name (void)
3891 return default_icon_name;
3895 * gtk_window_set_default_icon_from_file:
3896 * @filename: location of icon file
3897 * @err: (allow-none): location to store error, or %NULL.
3899 * Sets an icon to be used as fallback for windows that haven't
3900 * had gtk_window_set_icon_list() called on them from a file
3901 * on disk. Warns on failure if @err is %NULL.
3903 * Returns: %TRUE if setting the icon succeeded.
3908 gtk_window_set_default_icon_from_file (const gchar *filename,
3911 GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3915 gtk_window_set_default_icon (pixbuf);
3916 g_object_unref (pixbuf);
3925 * gtk_window_get_default_icon_list:
3927 * Gets the value set by gtk_window_set_default_icon_list().
3928 * The list is a copy and should be freed with g_list_free(),
3929 * but the pixbufs in the list have not had their reference count
3932 * Return value: (element-type GdkPixbuf) (transfer container): copy of default icon list
3935 gtk_window_get_default_icon_list (void)
3937 return g_list_copy (default_icon_list);
3941 gtk_window_set_default_size_internal (GtkWindow *window,
3942 gboolean change_width,
3944 gboolean change_height,
3946 gboolean is_geometry)
3948 GtkWindowGeometryInfo *info;
3950 g_return_if_fail (change_width == FALSE || width >= -1);
3951 g_return_if_fail (change_height == FALSE || height >= -1);
3953 info = gtk_window_get_geometry_info (window, TRUE);
3955 g_object_freeze_notify (G_OBJECT (window));
3957 info->default_is_geometry = is_geometry != FALSE;
3967 info->default_width = width;
3969 g_object_notify (G_OBJECT (window), "default-width");
3980 info->default_height = height;
3982 g_object_notify (G_OBJECT (window), "default-height");
3985 g_object_thaw_notify (G_OBJECT (window));
3987 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3991 * gtk_window_set_default_size:
3992 * @window: a #GtkWindow
3993 * @width: width in pixels, or -1 to unset the default width
3994 * @height: height in pixels, or -1 to unset the default height
3996 * Sets the default size of a window. If the window's "natural" size
3997 * (its size request) is larger than the default, the default will be
3998 * ignored. More generally, if the default size does not obey the
3999 * geometry hints for the window (gtk_window_set_geometry_hints() can
4000 * be used to set these explicitly), the default size will be clamped
4001 * to the nearest permitted size.
4003 * Unlike gtk_widget_set_size_request(), which sets a size request for
4004 * a widget and thus would keep users from shrinking the window, this
4005 * function only sets the initial size, just as if the user had
4006 * resized the window themselves. Users can still shrink the window
4007 * again as they normally would. Setting a default size of -1 means to
4008 * use the "natural" default size (the size request of the window).
4010 * For more control over a window's initial size and how resizing works,
4011 * investigate gtk_window_set_geometry_hints().
4013 * For some uses, gtk_window_resize() is a more appropriate function.
4014 * gtk_window_resize() changes the current size of the window, rather
4015 * than the size to be used on initial display. gtk_window_resize() always
4016 * affects the window itself, not the geometry widget.
4018 * The default size of a window only affects the first time a window is
4019 * shown; if a window is hidden and re-shown, it will remember the size
4020 * it had prior to hiding, rather than using the default size.
4022 * Windows can't actually be 0x0 in size, they must be at least 1x1, but
4023 * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
4026 gtk_window_set_default_size (GtkWindow *window,
4030 g_return_if_fail (GTK_IS_WINDOW (window));
4031 g_return_if_fail (width >= -1);
4032 g_return_if_fail (height >= -1);
4034 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
4038 * gtk_window_set_default_geometry:
4039 * @window: a #GtkWindow
4040 * @width: width in resize increments, or -1 to unset the default width
4041 * @height: height in resize increments, or -1 to unset the default height
4043 * Like gtk_window_set_default_size(), but @width and @height are interpreted
4044 * in terms of the base size and increment set with
4045 * gtk_window_set_geometry_hints.
4050 gtk_window_set_default_geometry (GtkWindow *window,
4054 g_return_if_fail (GTK_IS_WINDOW (window));
4055 g_return_if_fail (width >= -1);
4056 g_return_if_fail (height >= -1);
4058 gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
4062 * gtk_window_get_default_size:
4063 * @window: a #GtkWindow
4064 * @width: (out) (allow-none): location to store the default width, or %NULL
4065 * @height: (out) (allow-none): location to store the default height, or %NULL
4067 * Gets the default size of the window. A value of -1 for the width or
4068 * height indicates that a default size has not been explicitly set
4069 * for that dimension, so the "natural" size of the window will be
4074 gtk_window_get_default_size (GtkWindow *window,
4078 GtkWindowGeometryInfo *info;
4080 g_return_if_fail (GTK_IS_WINDOW (window));
4082 info = gtk_window_get_geometry_info (window, FALSE);
4085 *width = info ? info->default_width : -1;
4088 *height = info ? info->default_height : -1;
4092 * gtk_window_resize:
4093 * @window: a #GtkWindow
4094 * @width: width in pixels to resize the window to
4095 * @height: height in pixels to resize the window to
4097 * Resizes the window as if the user had done so, obeying geometry
4098 * constraints. The default geometry constraint is that windows may
4099 * not be smaller than their size request; to override this
4100 * constraint, call gtk_widget_set_size_request() to set the window's
4101 * request to a smaller value.
4103 * If gtk_window_resize() is called before showing a window for the
4104 * first time, it overrides any default size set with
4105 * gtk_window_set_default_size().
4107 * Windows may not be resized smaller than 1 by 1 pixels.
4111 gtk_window_resize (GtkWindow *window,
4115 GtkWindowGeometryInfo *info;
4117 g_return_if_fail (GTK_IS_WINDOW (window));
4118 g_return_if_fail (width > 0);
4119 g_return_if_fail (height > 0);
4121 info = gtk_window_get_geometry_info (window, TRUE);
4123 info->resize_width = width;
4124 info->resize_height = height;
4125 info->resize_is_geometry = FALSE;
4127 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4131 * gtk_window_resize_to_geometry:
4132 * @window: a #GtkWindow
4133 * @width: width in resize increments to resize the window to
4134 * @height: height in resize increments to resize the window to
4136 * Like gtk_window_resize(), but @width and @height are interpreted
4137 * in terms of the base size and increment set with
4138 * gtk_window_set_geometry_hints.
4143 gtk_window_resize_to_geometry (GtkWindow *window,
4147 GtkWindowGeometryInfo *info;
4149 g_return_if_fail (GTK_IS_WINDOW (window));
4150 g_return_if_fail (width > 0);
4151 g_return_if_fail (height > 0);
4153 info = gtk_window_get_geometry_info (window, TRUE);
4155 info->resize_width = width;
4156 info->resize_height = height;
4157 info->resize_is_geometry = TRUE;
4159 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4163 * gtk_window_get_size:
4164 * @window: a #GtkWindow
4165 * @width: (out) (allow-none): return location for width, or %NULL
4166 * @height: (out) (allow-none): return location for height, or %NULL
4168 * Obtains the current size of @window. If @window is not onscreen,
4169 * it returns the size GTK+ will suggest to the <link
4170 * linkend="gtk-X11-arch">window manager</link> for the initial window
4171 * size (but this is not reliably the same as the size the window
4172 * manager will actually select). The size obtained by
4173 * gtk_window_get_size() is the last size received in a
4174 * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4175 * rather than querying the X server for the size. As a result, if you
4176 * call gtk_window_resize() then immediately call
4177 * gtk_window_get_size(), the size won't have taken effect yet. After
4178 * the window manager processes the resize request, GTK+ receives
4179 * notification that the size has changed via a configure event, and
4180 * the size of the window gets updated.
4182 * Note 1: Nearly any use of this function creates a race condition,
4183 * because the size of the window may change between the time that you
4184 * get the size and the time that you perform some action assuming
4185 * that size is the current size. To avoid race conditions, connect to
4186 * "configure-event" on the window and adjust your size-dependent
4187 * state to match the size delivered in the #GdkEventConfigure.
4189 * Note 2: The returned size does <emphasis>not</emphasis> include the
4190 * size of the window manager decorations (aka the window frame or
4191 * border). Those are not drawn by GTK+ and GTK+ has no reliable
4192 * method of determining their size.
4194 * Note 3: If you are getting a window size in order to position
4195 * the window onscreen, there may be a better way. The preferred
4196 * way is to simply set the window's semantic type with
4197 * gtk_window_set_type_hint(), which allows the window manager to
4198 * e.g. center dialogs. Also, if you set the transient parent of
4199 * dialogs with gtk_window_set_transient_for() window managers
4200 * will often center the dialog over its parent window. It's
4201 * much preferred to let the window manager handle these
4202 * things rather than doing it yourself, because all apps will
4203 * behave consistently and according to user prefs if the window
4204 * manager handles it. Also, the window manager can take the size
4205 * of the window decorations/border into account, while your
4206 * application cannot.
4208 * In any case, if you insist on application-specified window
4209 * positioning, there's <emphasis>still</emphasis> a better way than
4210 * doing it yourself - gtk_window_set_position() will frequently
4211 * handle the details for you.
4215 gtk_window_get_size (GtkWindow *window,
4221 g_return_if_fail (GTK_IS_WINDOW (window));
4223 if (width == NULL && height == NULL)
4226 if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4228 w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window)));
4229 h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window)));
4233 GdkRectangle configure_request;
4235 gtk_window_compute_configure_request (window,
4239 w = configure_request.width;
4240 h = configure_request.height;
4251 * @window: a #GtkWindow
4252 * @x: X coordinate to move window to
4253 * @y: Y coordinate to move window to
4255 * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4256 * @window to the given position. Window managers are free to ignore
4257 * this; most window managers ignore requests for initial window
4258 * positions (instead using a user-defined placement algorithm) and
4259 * honor requests after the window has already been shown.
4261 * Note: the position is the position of the gravity-determined
4262 * reference point for the window. The gravity determines two things:
4263 * first, the location of the reference point in root window
4264 * coordinates; and second, which point on the window is positioned at
4265 * the reference point.
4267 * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4268 * point is simply the @x, @y supplied to gtk_window_move(). The
4269 * top-left corner of the window decorations (aka window frame or
4270 * border) will be placed at @x, @y. Therefore, to position a window
4271 * at the top left of the screen, you want to use the default gravity
4272 * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4274 * To position a window at the bottom right corner of the screen, you
4275 * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4276 * point is at @x + the window width and @y + the window height, and
4277 * the bottom-right corner of the window border will be placed at that
4278 * reference point. So, to place a window in the bottom right corner
4279 * you would first set gravity to south east, then write:
4280 * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4281 * gdk_screen_height () - window_height)</literal> (note that this
4282 * example does not take multi-head scenarios into account).
4284 * The Extended Window Manager Hints specification at <ulink
4285 * url="http://www.freedesktop.org/Standards/wm-spec">
4286 * http://www.freedesktop.org/Standards/wm-spec</ulink> has a
4287 * nice table of gravities in the "implementation notes" section.
4289 * The gtk_window_get_position() documentation may also be relevant.
4292 gtk_window_move (GtkWindow *window,
4296 GtkWindowPrivate *priv;
4297 GtkWindowGeometryInfo *info;
4300 g_return_if_fail (GTK_IS_WINDOW (window));
4302 priv = window->priv;
4303 widget = GTK_WIDGET (window);
4305 info = gtk_window_get_geometry_info (window, TRUE);
4307 if (gtk_widget_get_mapped (widget))
4309 GtkAllocation allocation;
4311 gtk_widget_get_allocation (widget, &allocation);
4313 /* we have now sent a request with this position
4314 * with currently-active constraints, so toggle flag.
4316 info->position_constraints_changed = FALSE;
4318 /* we only constrain if mapped - if not mapped,
4319 * then gtk_window_compute_configure_request()
4320 * will apply the constraints later, and we
4321 * don't want to lose information about
4322 * what position the user set before then.
4323 * i.e. if you do a move() then turn off POS_CENTER
4324 * then show the window, your move() will work.
4326 gtk_window_constrain_position (window,
4327 allocation.width, allocation.height,
4330 /* Note that this request doesn't go through our standard request
4331 * framework, e.g. doesn't increment configure_request_count,
4332 * doesn't set info->last, etc.; that's because
4333 * we don't save the info needed to arrive at this same request
4336 * To gtk_window_move_resize(), this will end up looking exactly
4337 * the same as the position being changed by the window
4341 /* FIXME are we handling gravity properly for framed windows? */
4343 gdk_window_move (priv->frame,
4344 x - priv->frame_left,
4345 y - priv->frame_top);
4347 gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)),
4352 /* Save this position to apply on mapping */
4353 info->initial_x = x;
4354 info->initial_y = y;
4355 info->initial_pos_set = TRUE;
4360 * gtk_window_get_position:
4361 * @window: a #GtkWindow
4362 * @root_x: (out): return location for X coordinate of gravity-determined reference point
4363 * @root_y: (out): return location for Y coordinate of gravity-determined reference point
4365 * This function returns the position you need to pass to
4366 * gtk_window_move() to keep @window in its current position. This
4367 * means that the meaning of the returned value varies with window
4368 * gravity. See gtk_window_move() for more details.
4370 * If you haven't changed the window gravity, its gravity will be
4371 * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4372 * gets the position of the top-left corner of the window manager
4373 * frame for the window. gtk_window_move() sets the position of this
4374 * same top-left corner.
4376 * gtk_window_get_position() is not 100% reliable because the X Window System
4377 * does not specify a way to obtain the geometry of the
4378 * decorations placed on a window by the window manager.
4379 * Thus GTK+ is using a "best guess" that works with most
4382 * Moreover, nearly all window managers are historically broken with
4383 * respect to their handling of window gravity. So moving a window to
4384 * its current position as returned by gtk_window_get_position() tends
4385 * to result in moving the window slightly. Window managers are
4386 * slowly getting better over time.
4388 * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4389 * frame is not relevant, and thus gtk_window_get_position() will
4390 * always produce accurate results. However you can't use static
4391 * gravity to do things like place a window in a corner of the screen,
4392 * because static gravity ignores the window manager decorations.
4394 * If you are saving and restoring your application's window
4395 * positions, you should know that it's impossible for applications to
4396 * do this without getting it somewhat wrong because applications do
4397 * not have sufficient knowledge of window manager state. The Correct
4398 * Mechanism is to support the session management protocol (see the
4399 * "GnomeClient" object in the GNOME libraries for example) and allow
4400 * the window manager to save your window sizes and positions.
4405 gtk_window_get_position (GtkWindow *window,
4409 GtkWindowPrivate *priv;
4411 GdkWindow *gdk_window;
4413 g_return_if_fail (GTK_IS_WINDOW (window));
4415 priv = window->priv;
4416 widget = GTK_WIDGET (window);
4417 gdk_window = gtk_widget_get_window (widget);
4419 if (priv->gravity == GDK_GRAVITY_STATIC)
4421 if (gtk_widget_get_mapped (widget))
4423 /* This does a server round-trip, which is sort of wrong;
4424 * but a server round-trip is inevitable for
4425 * gdk_window_get_frame_extents() in the usual
4426 * NorthWestGravity case below, so not sure what else to
4427 * do. We should likely be consistent about whether we get
4428 * the client-side info or the server-side info.
4430 gdk_window_get_origin (gdk_window, root_x, root_y);
4434 GdkRectangle configure_request;
4436 gtk_window_compute_configure_request (window,
4440 *root_x = configure_request.x;
4441 *root_y = configure_request.y;
4446 GdkRectangle frame_extents;
4451 if (gtk_widget_get_mapped (widget))
4454 gdk_window_get_frame_extents (priv->frame, &frame_extents);
4456 gdk_window_get_frame_extents (gdk_window, &frame_extents);
4457 x = frame_extents.x;
4458 y = frame_extents.y;
4459 gtk_window_get_size (window, &w, &h);
4463 /* We just say the frame has 0 size on all sides.
4464 * Not sure what else to do.
4466 gtk_window_compute_configure_request (window,
4469 x = frame_extents.x;
4470 y = frame_extents.y;
4471 w = frame_extents.width;
4472 h = frame_extents.height;
4475 switch (priv->gravity)
4477 case GDK_GRAVITY_NORTH:
4478 case GDK_GRAVITY_CENTER:
4479 case GDK_GRAVITY_SOUTH:
4480 /* Find center of frame. */
4481 x += frame_extents.width / 2;
4482 /* Center client window on that point. */
4486 case GDK_GRAVITY_SOUTH_EAST:
4487 case GDK_GRAVITY_EAST:
4488 case GDK_GRAVITY_NORTH_EAST:
4489 /* Find right edge of frame */
4490 x += frame_extents.width;
4491 /* Align left edge of client at that point. */
4498 switch (priv->gravity)
4500 case GDK_GRAVITY_WEST:
4501 case GDK_GRAVITY_CENTER:
4502 case GDK_GRAVITY_EAST:
4503 /* Find center of frame. */
4504 y += frame_extents.height / 2;
4505 /* Center client window there. */
4508 case GDK_GRAVITY_SOUTH_WEST:
4509 case GDK_GRAVITY_SOUTH:
4510 case GDK_GRAVITY_SOUTH_EAST:
4511 /* Find south edge of frame */
4512 y += frame_extents.height;
4513 /* Place bottom edge of client there */
4528 * gtk_window_reshow_with_initial_size:
4529 * @window: a #GtkWindow
4531 * Hides @window, then reshows it, resetting the
4532 * default size and position of the window. Used
4533 * by GUI builders only.
4536 gtk_window_reshow_with_initial_size (GtkWindow *window)
4540 g_return_if_fail (GTK_IS_WINDOW (window));
4542 widget = GTK_WIDGET (window);
4544 gtk_widget_hide (widget);
4545 gtk_widget_unrealize (widget);
4546 gtk_widget_show (widget);
4550 gtk_window_destroy (GtkWidget *widget)
4552 GtkWindow *window = GTK_WINDOW (widget);
4553 GtkWindowPrivate *priv = window->priv;
4555 toplevel_list = g_slist_remove (toplevel_list, window);
4557 if (priv->transient_parent)
4558 gtk_window_set_transient_for (window, NULL);
4560 /* frees the icons */
4561 gtk_window_set_icon_list (window, NULL);
4563 if (priv->has_user_ref_count)
4565 priv->has_user_ref_count = FALSE;
4566 g_object_unref (window);
4570 gtk_window_group_remove_window (priv->group, window);
4572 gtk_window_free_key_hash (window);
4574 GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4578 gtk_window_finalize (GObject *object)
4580 GtkWindow *window = GTK_WINDOW (object);
4581 GtkWindowPrivate *priv = window->priv;
4582 GtkMnemonicHash *mnemonic_hash;
4584 g_free (priv->title);
4585 g_free (priv->wmclass_name);
4586 g_free (priv->wmclass_class);
4587 g_free (priv->wm_role);
4588 gtk_window_release_application (window);
4590 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4592 _gtk_mnemonic_hash_free (mnemonic_hash);
4594 if (priv->geometry_info)
4596 if (priv->geometry_info->widget)
4597 g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4598 gtk_widget_destroyed,
4599 &priv->geometry_info->widget);
4600 g_free (priv->geometry_info);
4603 if (priv->keys_changed_handler)
4605 g_source_remove (priv->keys_changed_handler);
4606 priv->keys_changed_handler = 0;
4610 g_signal_handlers_disconnect_by_func (priv->screen,
4611 gtk_window_on_composited_changed, window);
4613 g_free (priv->startup_id);
4615 G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4619 gtk_window_show (GtkWidget *widget)
4621 GtkWindow *window = GTK_WINDOW (widget);
4622 GtkWindowPrivate *priv = window->priv;
4623 GtkContainer *container = GTK_CONTAINER (window);
4624 gboolean need_resize;
4626 _gtk_widget_set_visible_flag (widget, TRUE);
4628 need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4629 _gtk_container_set_need_resize (container, FALSE);
4633 GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4634 GtkAllocation allocation = { 0, 0 };
4635 GdkRectangle configure_request;
4636 GdkGeometry new_geometry;
4638 gboolean was_realized;
4640 /* We are going to go ahead and perform this configure request
4641 * and then emulate a configure notify by going ahead and
4642 * doing a size allocate. Sort of a synchronous
4643 * mini-copy of gtk_window_move_resize() here.
4645 gtk_window_compute_configure_request (window,
4650 /* We update this because we are going to go ahead
4651 * and gdk_window_resize() below, rather than
4654 info->last.configure_request.width = configure_request.width;
4655 info->last.configure_request.height = configure_request.height;
4657 /* and allocate the window - this is normally done
4658 * in move_resize in response to configure notify
4660 allocation.width = configure_request.width;
4661 allocation.height = configure_request.height;
4662 gtk_widget_size_allocate (widget, &allocation);
4664 /* Then we guarantee we have a realize */
4665 was_realized = FALSE;
4666 if (!gtk_widget_get_realized (widget))
4668 gtk_widget_realize (widget);
4669 was_realized = TRUE;
4672 /* Must be done after the windows are realized,
4673 * so that the decorations can be read
4675 gtk_decorated_window_calculate_frame_size (window);
4677 /* We only send configure request if we didn't just finish
4678 * creating the window; if we just created the window
4679 * then we created it with widget->allocation anyhow.
4682 gdk_window_move_resize (gtk_widget_get_window (widget),
4683 configure_request.x,
4684 configure_request.y,
4685 configure_request.width,
4686 configure_request.height);
4689 gtk_container_check_resize (container);
4691 gtk_widget_map (widget);
4693 /* Try to make sure that we have some focused widget
4695 if (!priv->focus_widget && !GTK_IS_PLUG (window))
4696 gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4699 gtk_grab_add (widget);
4703 gtk_window_hide (GtkWidget *widget)
4705 GtkWindow *window = GTK_WINDOW (widget);
4706 GtkWindowPrivate *priv = window->priv;
4708 _gtk_widget_set_visible_flag (widget, FALSE);
4709 gtk_widget_unmap (widget);
4712 gtk_grab_remove (widget);
4716 gtk_window_map (GtkWidget *widget)
4719 GtkWindow *window = GTK_WINDOW (widget);
4720 GtkWindowPrivate *priv = window->priv;
4721 GdkWindow *toplevel;
4722 GdkWindow *gdk_window;
4723 gboolean auto_mnemonics;
4725 gdk_window = gtk_widget_get_window (widget);
4727 gtk_widget_set_mapped (widget, TRUE);
4729 child = gtk_bin_get_child (&(window->bin));
4731 gtk_widget_get_visible (child) &&
4732 !gtk_widget_get_mapped (child))
4733 gtk_widget_map (child);
4736 toplevel = priv->frame;
4738 toplevel = gdk_window;
4740 if (priv->maximize_initially)
4741 gdk_window_maximize (toplevel);
4743 gdk_window_unmaximize (toplevel);
4745 if (priv->stick_initially)
4746 gdk_window_stick (toplevel);
4748 gdk_window_unstick (toplevel);
4750 if (priv->iconify_initially)
4751 gdk_window_iconify (toplevel);
4753 gdk_window_deiconify (toplevel);
4755 if (priv->fullscreen_initially)
4756 gdk_window_fullscreen (toplevel);
4758 gdk_window_unfullscreen (toplevel);
4760 gdk_window_set_keep_above (toplevel, priv->above_initially);
4762 gdk_window_set_keep_below (toplevel, priv->below_initially);
4764 /* No longer use the default settings */
4765 priv->need_default_size = FALSE;
4766 priv->need_default_position = FALSE;
4768 if (priv->reset_type_hint)
4770 /* We should only reset the type hint when the application
4771 * used gtk_window_set_type_hint() to change the hint.
4772 * Some applications use X directly to change the properties;
4773 * in that case, we shouldn't overwrite what they did.
4775 gdk_window_set_type_hint (gdk_window, priv->type_hint);
4776 priv->reset_type_hint = FALSE;
4779 gdk_window_show (gdk_window);
4782 gdk_window_show (priv->frame);
4784 if (priv->grip_window)
4785 gdk_window_show (priv->grip_window);
4787 if (!disable_startup_notification)
4789 /* Do we have a custom startup-notification id? */
4790 if (priv->startup_id != NULL)
4792 /* Make sure we have a "real" id */
4793 if (!startup_id_is_fake (priv->startup_id))
4794 gdk_notify_startup_complete_with_id (priv->startup_id);
4796 g_free (priv->startup_id);
4797 priv->startup_id = NULL;
4799 else if (!sent_startup_notification)
4801 sent_startup_notification = TRUE;
4802 gdk_notify_startup_complete ();
4806 /* if auto-mnemonics is enabled and mnemonics visible is not already set
4807 * (as in the case of popup menus), then hide mnemonics initially
4809 g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4810 &auto_mnemonics, NULL);
4811 if (auto_mnemonics && !priv->mnemonics_visible_set)
4812 gtk_window_set_mnemonics_visible (window, FALSE);
4816 gtk_window_map_event (GtkWidget *widget,
4819 if (!gtk_widget_get_mapped (widget))
4821 /* we should be be unmapped, but are getting a MapEvent, this may happen
4822 * to toplevel XWindows if mapping was intercepted by a window manager
4823 * and an unmap request occoured while the MapRequestEvent was still
4824 * being handled. we work around this situaiton here by re-requesting
4825 * the window being unmapped. more details can be found in:
4826 * http://bugzilla.gnome.org/show_bug.cgi?id=316180
4828 gdk_window_hide (gtk_widget_get_window (widget));
4834 gtk_window_unmap (GtkWidget *widget)
4836 GtkWindow *window = GTK_WINDOW (widget);
4837 GtkWindowPrivate *priv = window->priv;
4838 GtkWindowGeometryInfo *info;
4839 GdkWindow *gdk_window;
4840 GdkWindowState state;
4842 gdk_window = gtk_widget_get_window (widget);
4844 gtk_widget_set_mapped (widget, FALSE);
4846 gdk_window_withdraw (priv->frame);
4848 gdk_window_withdraw (gdk_window);
4850 priv->configure_request_count = 0;
4851 priv->configure_notify_received = FALSE;
4853 /* on unmap, we reset the default positioning of the window,
4854 * so it's placed again, but we don't reset the default
4855 * size of the window, so it's remembered.
4857 priv->need_default_position = TRUE;
4859 info = gtk_window_get_geometry_info (window, FALSE);
4862 info->initial_pos_set = FALSE;
4863 info->position_constraints_changed = FALSE;
4866 state = gdk_window_get_state (gdk_window);
4867 priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4868 priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4869 priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4870 priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4871 priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4875 gtk_window_realize (GtkWidget *widget)
4877 GtkAllocation allocation;
4880 GdkWindow *parent_window;
4881 GdkWindow *gdk_window;
4882 GdkWindowAttr attributes;
4883 gint attributes_mask;
4884 GtkWindowPrivate *priv;
4886 window = GTK_WINDOW (widget);
4887 priv = window->priv;
4889 gtk_widget_get_allocation (widget, &allocation);
4891 /* ensure widget tree is properly size allocated */
4892 if (allocation.x == -1 &&
4893 allocation.y == -1 &&
4894 allocation.width == 1 &&
4895 allocation.height == 1)
4897 GtkRequisition requisition;
4901 allocation.width = 200;
4902 allocation.height = 200;
4904 gtk_widget_get_preferred_size (widget, &requisition, NULL);
4905 if (requisition.width || requisition.height)
4907 /* non-empty window */
4908 allocation.width = requisition.width;
4909 allocation.height = requisition.height;
4911 gtk_widget_size_allocate (widget, &allocation);
4913 _gtk_container_queue_resize (GTK_CONTAINER (widget));
4915 g_return_if_fail (!gtk_widget_get_realized (widget));
4918 gtk_widget_set_realized (widget, TRUE);
4922 case GTK_WINDOW_TOPLEVEL:
4923 attributes.window_type = GDK_WINDOW_TOPLEVEL;
4925 case GTK_WINDOW_POPUP:
4926 attributes.window_type = GDK_WINDOW_TEMP;
4929 g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4933 attributes.title = priv->title;
4934 attributes.wmclass_name = priv->wmclass_name;
4935 attributes.wmclass_class = priv->wmclass_class;
4936 attributes.wclass = GDK_INPUT_OUTPUT;
4937 attributes.visual = gtk_widget_get_visual (widget);
4939 if (priv->has_frame)
4941 gtk_widget_get_allocation (widget, &allocation);
4942 attributes.width = allocation.width + priv->frame_left + priv->frame_right;
4943 attributes.height = allocation.height + priv->frame_top + priv->frame_bottom;
4944 attributes.event_mask = (GDK_EXPOSURE_MASK |
4945 GDK_KEY_PRESS_MASK |
4946 GDK_ENTER_NOTIFY_MASK |
4947 GDK_LEAVE_NOTIFY_MASK |
4948 GDK_FOCUS_CHANGE_MASK |
4949 GDK_STRUCTURE_MASK |
4950 GDK_BUTTON_MOTION_MASK |
4951 GDK_POINTER_MOTION_HINT_MASK |
4952 GDK_BUTTON_PRESS_MASK |
4953 GDK_BUTTON_RELEASE_MASK);
4955 attributes_mask = GDK_WA_VISUAL;
4957 priv->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4958 &attributes, attributes_mask);
4960 if (priv->opacity_set)
4961 gdk_window_set_opacity (priv->frame, priv->opacity);
4963 gdk_window_set_user_data (priv->frame, widget);
4965 attributes.window_type = GDK_WINDOW_CHILD;
4966 attributes.x = priv->frame_left;
4967 attributes.y = priv->frame_top;
4969 attributes_mask = GDK_WA_X | GDK_WA_Y;
4971 parent_window = priv->frame;
4973 g_signal_connect (window,
4975 G_CALLBACK (gtk_window_event),
4980 attributes_mask = 0;
4981 parent_window = gtk_widget_get_root_window (widget);
4984 gtk_widget_get_allocation (widget, &allocation);
4985 attributes.width = allocation.width;
4986 attributes.height = allocation.height;
4987 attributes.event_mask = gtk_widget_get_events (widget);
4988 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4989 GDK_KEY_PRESS_MASK |
4990 GDK_KEY_RELEASE_MASK |
4991 GDK_ENTER_NOTIFY_MASK |
4992 GDK_LEAVE_NOTIFY_MASK |
4993 GDK_FOCUS_CHANGE_MASK |
4994 GDK_STRUCTURE_MASK);
4995 attributes.type_hint = priv->type_hint;
4997 attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4998 attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4999 attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
5001 gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
5002 gtk_widget_set_window (widget, gdk_window);
5004 if (!priv->has_frame && priv->opacity_set)
5005 gdk_window_set_opacity (gdk_window, priv->opacity);
5007 gdk_window_enable_synchronized_configure (gdk_window);
5009 gdk_window_set_user_data (gdk_window, window);
5011 gtk_widget_style_attach (widget);
5012 style = gtk_widget_get_style (widget);
5013 gtk_style_set_background (style, gdk_window, GTK_STATE_NORMAL);
5015 gtk_style_set_background (style, priv->frame, GTK_STATE_NORMAL);
5017 if (priv->transient_parent &&
5018 gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
5019 gdk_window_set_transient_for (gdk_window,
5020 gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
5023 gdk_window_set_role (gdk_window, priv->wm_role);
5025 if (!priv->decorated)
5026 gdk_window_set_decorations (gdk_window, 0);
5028 if (!priv->deletable)
5029 gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
5031 if (gtk_window_get_skip_pager_hint (window))
5032 gdk_window_set_skip_pager_hint (gdk_window, TRUE);
5034 if (gtk_window_get_skip_taskbar_hint (window))
5035 gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
5037 if (gtk_window_get_accept_focus (window))
5038 gdk_window_set_accept_focus (gdk_window, TRUE);
5040 gdk_window_set_accept_focus (gdk_window, FALSE);
5042 if (gtk_window_get_focus_on_map (window))
5043 gdk_window_set_focus_on_map (gdk_window, TRUE);
5045 gdk_window_set_focus_on_map (gdk_window, FALSE);
5048 gdk_window_set_modal_hint (gdk_window, TRUE);
5050 gdk_window_set_modal_hint (gdk_window, FALSE);
5052 if (priv->startup_id)
5054 #ifdef GDK_WINDOWING_X11
5055 guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
5056 if (timestamp != GDK_CURRENT_TIME)
5057 gdk_x11_window_set_user_time (gdk_window, timestamp);
5059 if (!startup_id_is_fake (priv->startup_id))
5060 gdk_window_set_startup_id (gdk_window, priv->startup_id);
5064 gtk_window_realize_icon (window);
5066 if (priv->has_resize_grip)
5067 resize_grip_create_window (window);
5071 gtk_window_unrealize (GtkWidget *widget)
5073 GtkWindow *window = GTK_WINDOW (widget);
5074 GtkWindowPrivate *priv = window->priv;
5075 GtkWindowGeometryInfo *info;
5077 /* On unrealize, we reset the size of the window such
5078 * that we will re-apply the default sizing stuff
5079 * next time we show the window.
5081 * Default positioning is reset on unmap, instead of unrealize.
5083 priv->need_default_size = TRUE;
5084 info = gtk_window_get_geometry_info (window, FALSE);
5087 info->resize_width = -1;
5088 info->resize_height = -1;
5089 info->last.configure_request.x = 0;
5090 info->last.configure_request.y = 0;
5091 info->last.configure_request.width = -1;
5092 info->last.configure_request.height = -1;
5093 /* be sure we reset geom hints on re-realize */
5094 info->last.flags = 0;
5099 gdk_window_set_user_data (priv->frame, NULL);
5100 gdk_window_destroy (priv->frame);
5105 gtk_window_unrealize_icon (window);
5107 if (priv->grip_window != NULL)
5108 resize_grip_destroy_window (window);
5110 GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5113 static GdkWindowEdge
5114 get_grip_edge (GtkWidget *widget)
5116 return gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR
5117 ? GDK_WINDOW_EDGE_SOUTH_EAST
5118 : GDK_WINDOW_EDGE_SOUTH_WEST;
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 gdk_cursor_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_edge (GTK_WIDGET (window)) == GDK_WINDOW_EDGE_SOUTH_EAST)
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_set (GtkWidget *widget,
5464 GtkWindow *window = GTK_WINDOW (widget);
5465 GtkWindowPrivate *priv = window->priv;
5468 if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5470 gdk_window_move_resize (priv->grip_window,
5472 rect.width, rect.height);
5474 set_grip_shape (window);
5475 gtk_widget_queue_resize (widget);
5480 resize_grip_create_window (GtkWindow *window)
5483 GtkWindowPrivate *priv;
5484 GdkWindowAttr attributes;
5485 gint attributes_mask;
5488 priv = window->priv;
5489 widget = GTK_WIDGET (window);
5491 g_return_if_fail (gtk_widget_get_realized (widget));
5492 g_return_if_fail (priv->grip_window == NULL);
5494 gtk_window_get_resize_grip_area (window, &rect);
5496 attributes.x = rect.x;
5497 attributes.y = rect.y;
5498 attributes.width = rect.width;
5499 attributes.height = rect.height;
5500 attributes.window_type = GDK_WINDOW_CHILD;
5501 attributes.wclass = GDK_INPUT_OUTPUT;
5502 attributes.event_mask = gtk_widget_get_events (widget) |
5504 GDK_BUTTON_PRESS_MASK;
5506 attributes_mask = GDK_WA_X | GDK_WA_Y;
5508 priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5512 gdk_window_set_user_data (priv->grip_window, widget);
5514 gdk_window_raise (priv->grip_window);
5516 set_grip_shape (window);
5517 update_grip_visibility (window);
5521 resize_grip_destroy_window (GtkWindow *window)
5523 GtkWindowPrivate *priv = window->priv;
5525 gdk_window_set_user_data (priv->grip_window, NULL);
5526 gdk_window_destroy (priv->grip_window);
5527 priv->grip_window = NULL;
5528 update_grip_visibility (window);
5532 * gtk_window_set_has_resize_grip:
5533 * @window: a #GtkWindow
5534 * @value: %TRUE to allow a resize grip
5536 * Sets whether @window has a corner resize grip.
5538 * Note that the resize grip is only shown if the window
5539 * is actually resizable and not maximized. Use
5540 * gtk_window_resize_grip_is_visible() to find out if the
5541 * resize grip is currently shown.
5546 gtk_window_set_has_resize_grip (GtkWindow *window,
5549 GtkWidget *widget = GTK_WIDGET (window);
5550 GtkWindowPrivate *priv = window->priv;
5552 value = value != FALSE;
5554 if (value != priv->has_resize_grip)
5556 priv->has_resize_grip = value;
5557 gtk_widget_queue_draw (widget);
5559 if (gtk_widget_get_realized (widget))
5561 if (priv->has_resize_grip && priv->grip_window == NULL)
5562 resize_grip_create_window (window);
5563 else if (!priv->has_resize_grip && priv->grip_window != NULL)
5564 resize_grip_destroy_window (window);
5567 g_object_notify (G_OBJECT (window), "has-resize-grip");
5572 update_grip_visibility (GtkWindow *window)
5574 GtkWindowPrivate *priv = window->priv;
5577 val = gtk_window_resize_grip_is_visible (window);
5579 if (priv->grip_window != NULL)
5583 gdk_window_show (priv->grip_window);
5584 set_grip_cursor (window);
5588 gdk_window_hide (priv->grip_window);
5592 if (priv->resize_grip_visible != val)
5594 priv->resize_grip_visible = val;
5596 g_object_notify (G_OBJECT (window), "resize-grip-visible");
5601 * gtk_window_resize_grip_is_visible:
5602 * @window: a #GtkWindow
5604 * Determines whether a resize grip is visible for the specified window.
5606 * Returns %TRUE if a resize grip exists and is visible.
5611 gtk_window_resize_grip_is_visible (GtkWindow *window)
5614 GtkWindowPrivate *priv;
5617 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5619 priv = window->priv;
5620 widget = GTK_WIDGET (window);
5622 if (priv->type == GTK_WINDOW_POPUP)
5625 if (!priv->resizable)
5628 if (gtk_widget_get_realized (widget))
5630 GdkWindowState state;
5632 state = gdk_window_get_state (gtk_widget_get_window (widget));
5634 if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5638 if (!get_drag_edge (widget, &edge))
5641 return window->priv->has_resize_grip;
5645 * gtk_window_get_has_resize_grip:
5646 * @window: a #GtkWindow
5648 * Determines whether the window may have a resize grip.
5650 * Returns: %TRUE if the window has a resize grip.
5655 gtk_window_get_has_resize_grip (GtkWindow *window)
5657 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5659 return window->priv->has_resize_grip;
5663 * gtk_window_get_resize_grip_area:
5664 * @window: a #GtkWindow
5665 * @rect: a pointer to a #GdkRectangle which we should store the
5668 * If a window has a resize grip, this will retrieve the grip
5669 * position, width and height into the specified #GdkRectangle.
5671 * Returns: %TRUE if the resize grip's area was retrieved.
5676 gtk_window_get_resize_grip_area (GtkWindow *window,
5679 GtkWidget *widget = GTK_WIDGET (window);
5680 GtkAllocation allocation;
5685 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5687 if (!window->priv->has_resize_grip)
5690 gtk_widget_get_allocation (widget, &allocation);
5691 style = gtk_widget_get_style (widget);
5693 gtk_widget_style_get (widget,
5694 "resize-grip-width", &grip_width,
5695 "resize-grip-height", &grip_height,
5698 if (grip_width > allocation.width)
5699 grip_width = allocation.width;
5701 if (grip_height > allocation.height)
5702 grip_height = allocation.height;
5704 rect->width = grip_width;
5705 rect->height = grip_height;
5706 rect->y = allocation.y + allocation.height - grip_height;
5708 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5709 rect->x = allocation.x + allocation.width - grip_width;
5711 rect->x = allocation.x;
5716 /* the accel_key and accel_mods fields of the key have to be setup
5717 * upon calling this function. it'll then return whether that key
5718 * is at all used as accelerator, and if so will OR in the
5719 * accel_flags member of the key.
5722 _gtk_window_query_nonaccels (GtkWindow *window,
5724 GdkModifierType accel_mods)
5726 GtkWindowPrivate *priv;
5728 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5730 priv = window->priv;
5732 /* movement keys are considered locked accels */
5735 static const guint bindings[] = {
5736 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,
5737 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,
5741 for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5742 if (bindings[i] == accel_key)
5746 /* mnemonics are considered locked accels */
5747 if (accel_mods == priv->mnemonic_modifier)
5749 GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5750 if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5758 * gtk_window_propagate_key_event:
5759 * @window: a #GtkWindow
5760 * @event: a #GdkEventKey
5762 * Propagate a key press or release event to the focus widget and
5763 * up the focus container chain until a widget handles @event.
5764 * This is normally called by the default ::key_press_event and
5765 * ::key_release_event handlers for toplevel windows,
5766 * however in some cases it may be useful to call this directly when
5767 * overriding the standard key handling for a toplevel window.
5769 * Return value: %TRUE if a widget in the focus chain handled the event.
5774 gtk_window_propagate_key_event (GtkWindow *window,
5777 GtkWindowPrivate *priv;
5778 gboolean handled = FALSE;
5779 GtkWidget *widget, *focus;
5781 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5783 priv = window->priv;
5784 widget = GTK_WIDGET (window);
5786 focus = priv->focus_widget;
5788 g_object_ref (focus);
5791 focus && focus != widget &&
5792 gtk_widget_get_toplevel (focus) == widget)
5796 if (gtk_widget_is_sensitive (focus))
5797 handled = gtk_widget_event (focus, (GdkEvent*) event);
5799 parent = gtk_widget_get_parent (focus);
5801 g_object_ref (parent);
5803 g_object_unref (focus);
5809 g_object_unref (focus);
5815 gtk_window_key_press_event (GtkWidget *widget,
5818 GtkWindow *window = GTK_WINDOW (widget);
5819 gboolean handled = FALSE;
5821 /* handle mnemonics and accelerators */
5823 handled = gtk_window_activate_key (window, event);
5825 /* handle focus widget key events */
5827 handled = gtk_window_propagate_key_event (window, event);
5829 /* Chain up, invokes binding set */
5831 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5837 gtk_window_key_release_event (GtkWidget *widget,
5840 GtkWindow *window = GTK_WINDOW (widget);
5841 gboolean handled = FALSE;
5843 /* handle focus widget key events */
5845 handled = gtk_window_propagate_key_event (window, event);
5847 /* Chain up, invokes binding set */
5849 handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5855 gtk_window_button_press_event (GtkWidget *widget,
5856 GdkEventButton *event)
5858 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5861 if (event->window == priv->grip_window)
5863 if (get_drag_edge (widget, &edge))
5864 gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5878 gtk_window_real_activate_default (GtkWindow *window)
5880 gtk_window_activate_default (window);
5884 gtk_window_real_activate_focus (GtkWindow *window)
5886 gtk_window_activate_focus (window);
5890 gtk_window_enter_notify_event (GtkWidget *widget,
5891 GdkEventCrossing *event)
5897 gtk_window_leave_notify_event (GtkWidget *widget,
5898 GdkEventCrossing *event)
5904 do_focus_change (GtkWidget *widget,
5908 GdkDeviceManager *device_manager;
5911 g_object_ref (widget);
5913 device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5914 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5915 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5916 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5918 for (d = devices; d; d = d->next)
5920 GdkDevice *dev = d->data;
5923 if (dev->source != GDK_SOURCE_KEYBOARD)
5926 /* Skip non-master keyboards that haven't
5927 * selected for events from this window
5929 window = gtk_widget_get_window (widget);
5930 if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5931 window && !gdk_window_get_device_events (window, dev))
5934 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5936 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5937 fevent->focus_change.window = window;
5939 g_object_ref (window);
5940 fevent->focus_change.in = in;
5941 gdk_event_set_device (fevent, dev);
5943 gtk_widget_send_focus_change (widget, fevent);
5945 gdk_event_free (fevent);
5948 g_list_free (devices);
5949 g_object_unref (widget);
5953 gtk_window_focus_in_event (GtkWidget *widget,
5954 GdkEventFocus *event)
5956 GtkWindow *window = GTK_WINDOW (widget);
5958 /* It appears spurious focus in events can occur when
5959 * the window is hidden. So we'll just check to see if
5960 * the window is visible before actually handling the
5963 if (gtk_widget_get_visible (widget))
5965 _gtk_window_set_has_toplevel_focus (window, TRUE);
5966 _gtk_window_set_is_active (window, TRUE);
5973 gtk_window_focus_out_event (GtkWidget *widget,
5974 GdkEventFocus *event)
5976 GtkWindow *window = GTK_WINDOW (widget);
5977 gboolean auto_mnemonics;
5979 _gtk_window_set_has_toplevel_focus (window, FALSE);
5980 _gtk_window_set_is_active (window, FALSE);
5982 /* set the mnemonic-visible property to false */
5983 g_object_get (gtk_widget_get_settings (widget),
5984 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5986 gtk_window_set_mnemonics_visible (window, FALSE);
5991 static GdkAtom atom_rcfiles = GDK_NONE;
5992 static GdkAtom atom_iconthemes = GDK_NONE;
5995 send_client_message_to_embedded_windows (GtkWidget *widget,
5996 GdkAtom message_type)
5998 GList *embedded_windows;
6000 embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
6001 if (embedded_windows)
6003 GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
6006 for (i = 0; i < 5; i++)
6007 send_event->client.data.l[i] = 0;
6008 send_event->client.data_format = 32;
6009 send_event->client.message_type = message_type;
6011 while (embedded_windows)
6013 GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
6014 gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
6015 embedded_windows = embedded_windows->next;
6018 gdk_event_free (send_event);
6023 gtk_window_client_event (GtkWidget *widget,
6024 GdkEventClient *event)
6028 atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
6029 atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
6032 if (event->message_type == atom_rcfiles)
6034 send_client_message_to_embedded_windows (widget, atom_rcfiles);
6035 gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
6038 if (event->message_type == atom_iconthemes)
6040 send_client_message_to_embedded_windows (widget, atom_iconthemes);
6041 _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));
6048 gtk_window_check_resize (GtkContainer *container)
6050 if (gtk_widget_get_visible (GTK_WIDGET (container)))
6051 gtk_window_move_resize (GTK_WINDOW (container));
6055 gtk_window_focus (GtkWidget *widget,
6056 GtkDirectionType direction)
6058 GtkWindowPrivate *priv;
6061 GtkContainer *container;
6063 GtkWidget *old_focus_child;
6066 container = GTK_CONTAINER (widget);
6067 window = GTK_WINDOW (widget);
6068 priv = window->priv;
6069 bin = GTK_BIN (widget);
6071 old_focus_child = gtk_container_get_focus_child (container);
6073 /* We need a special implementation here to deal properly with wrapping
6074 * around in the tab chain without the danger of going into an
6077 if (old_focus_child)
6079 if (gtk_widget_child_focus (old_focus_child, direction))
6083 if (priv->focus_widget)
6085 if (direction == GTK_DIR_LEFT ||
6086 direction == GTK_DIR_RIGHT ||
6087 direction == GTK_DIR_UP ||
6088 direction == GTK_DIR_DOWN)
6093 /* Wrapped off the end, clear the focus setting for the toplpevel */
6094 parent = gtk_widget_get_parent (priv->focus_widget);
6097 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
6098 parent = gtk_widget_get_parent (parent);
6101 gtk_window_set_focus (GTK_WINDOW (container), NULL);
6104 /* Now try to focus the first widget in the window */
6105 child = gtk_bin_get_child (bin);
6108 if (gtk_widget_child_focus (child, direction))
6116 gtk_window_move_focus (GtkWidget *widget,
6117 GtkDirectionType dir)
6119 gtk_widget_child_focus (widget, dir);
6121 if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
6122 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
6126 gtk_window_real_set_focus (GtkWindow *window,
6129 GtkWindowPrivate *priv = window->priv;
6130 GtkWidget *old_focus = priv->focus_widget;
6131 gboolean had_default = FALSE;
6132 gboolean focus_had_default = FALSE;
6133 gboolean old_focus_had_default = FALSE;
6137 g_object_ref (old_focus);
6138 g_object_freeze_notify (G_OBJECT (old_focus));
6139 old_focus_had_default = gtk_widget_has_default (old_focus);
6143 g_object_ref (focus);
6144 g_object_freeze_notify (G_OBJECT (focus));
6145 focus_had_default = gtk_widget_has_default (focus);
6148 if (priv->default_widget)
6149 had_default = gtk_widget_has_default (priv->default_widget);
6151 if (priv->focus_widget)
6153 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6154 (priv->focus_widget != priv->default_widget))
6156 _gtk_widget_set_has_default (priv->focus_widget, FALSE);
6157 gtk_widget_queue_draw (priv->focus_widget);
6159 if (priv->default_widget)
6160 _gtk_widget_set_has_default (priv->default_widget, TRUE);
6163 priv->focus_widget = NULL;
6165 if (priv->has_focus)
6166 do_focus_change (old_focus, FALSE);
6168 g_object_notify (G_OBJECT (old_focus), "is-focus");
6171 /* The above notifications may have set a new focus widget,
6172 * if so, we don't want to override it.
6174 if (focus && !priv->focus_widget)
6176 priv->focus_widget = focus;
6178 if (gtk_widget_get_receives_default (priv->focus_widget) &&
6179 (priv->focus_widget != priv->default_widget))
6181 if (gtk_widget_get_can_default (priv->focus_widget))
6182 _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6184 if (priv->default_widget)
6185 _gtk_widget_set_has_default (priv->default_widget, FALSE);
6188 if (priv->has_focus)
6189 do_focus_change (priv->focus_widget, TRUE);
6191 g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6194 /* If the default widget changed, a redraw will have been queued
6195 * on the old and new default widgets by gtk_window_set_default(), so
6196 * we only have to worry about the case where it didn't change.
6197 * We'll sometimes queue a draw twice on the new widget but that
6200 if (priv->default_widget &&
6201 (had_default != gtk_widget_has_default (priv->default_widget)))
6202 gtk_widget_queue_draw (priv->default_widget);
6206 if (old_focus_had_default != gtk_widget_has_default (old_focus))
6207 gtk_widget_queue_draw (old_focus);
6209 g_object_thaw_notify (G_OBJECT (old_focus));
6210 g_object_unref (old_focus);
6214 if (focus_had_default != gtk_widget_has_default (focus))
6215 gtk_widget_queue_draw (focus);
6217 g_object_thaw_notify (G_OBJECT (focus));
6218 g_object_unref (focus);
6224 gtk_window_get_preferred_width (GtkWidget *widget,
6232 window = GTK_WINDOW (widget);
6233 child = gtk_bin_get_child (GTK_BIN (window));
6235 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6236 *minimum_size = border_width * 2;
6237 *natural_size = border_width * 2;
6239 if (child && gtk_widget_get_visible (child))
6241 gint child_min, child_nat;
6242 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6244 *minimum_size += child_min;
6245 *natural_size += child_nat;
6250 gtk_window_get_preferred_height (GtkWidget *widget,
6258 window = GTK_WINDOW (widget);
6259 child = gtk_bin_get_child (GTK_BIN (window));
6261 border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6262 *minimum_size = border_width * 2;
6263 *natural_size = border_width * 2;
6265 if (child && gtk_widget_get_visible (child))
6267 gint child_min, child_nat;
6268 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6270 *minimum_size += child_min;
6271 *natural_size += child_nat;
6277 * _gtk_window_unset_focus_and_default:
6278 * @window: a #GtkWindow
6279 * @widget: a widget inside of @window
6281 * Checks whether the focus and default widgets of @window are
6282 * @widget or a descendent of @widget, and if so, unset them.
6285 _gtk_window_unset_focus_and_default (GtkWindow *window,
6289 GtkWindowPrivate *priv = window->priv;
6293 g_object_ref (window);
6294 g_object_ref (widget);
6296 parent = gtk_widget_get_parent (widget);
6297 if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6299 child = priv->focus_widget;
6301 while (child && child != widget)
6302 child = gtk_widget_get_parent (child);
6304 if (child == widget)
6305 gtk_window_set_focus (GTK_WINDOW (window), NULL);
6308 child = priv->default_widget;
6310 while (child && child != widget)
6311 child = gtk_widget_get_parent (child);
6313 if (child == widget)
6314 gtk_window_set_default (window, NULL);
6316 g_object_unref (widget);
6317 g_object_unref (window);
6320 /*********************************
6321 * Functions related to resizing *
6322 *********************************/
6325 geometry_size_to_pixels (GdkGeometry *geometry,
6330 gint base_width = 0;
6331 gint base_height = 0;
6333 gint min_height = 0;
6335 gint height_inc = 1;
6337 if (flags & GDK_HINT_BASE_SIZE)
6339 base_width = geometry->base_width;
6340 base_height = geometry->base_height;
6342 if (flags & GDK_HINT_MIN_SIZE)
6344 min_width = geometry->min_width;
6345 min_height = geometry->min_height;
6347 if (flags & GDK_HINT_RESIZE_INC)
6349 width_inc = geometry->width_inc;
6350 height_inc = geometry->height_inc;
6354 *width = MAX (*width * width_inc + base_width, min_width);
6356 *height = MAX (*height * height_inc + base_height, min_height);
6359 /* This function doesn't constrain to geometry hints */
6361 gtk_window_compute_configure_request_size (GtkWindow *window,
6362 GdkGeometry *geometry,
6367 GtkWindowPrivate *priv = window->priv;
6368 GtkRequisition requisition;
6369 GtkWindowGeometryInfo *info;
6373 * - we've done a size request
6376 widget = GTK_WIDGET (window);
6378 info = gtk_window_get_geometry_info (window, FALSE);
6380 if (priv->need_default_size)
6382 gtk_widget_get_preferred_size (widget, &requisition, NULL);
6384 /* Default to requisition */
6385 *width = requisition.width;
6386 *height = requisition.height;
6388 /* If window is empty so requests 0, default to random nonzero size */
6389 if (*width == 0 && *height == 0)
6395 /* Override requisition with default size */
6399 if (info->default_width > 0)
6400 *width = info->default_width;
6401 if (info->default_height > 0)
6402 *height = info->default_height;
6404 if (info->default_is_geometry)
6405 geometry_size_to_pixels (geometry, flags,
6406 info->default_width > 0 ? width : NULL,
6407 info->default_height > 0 ? height : NULL);
6412 GtkAllocation allocation;
6414 gtk_widget_get_allocation (widget, &allocation);
6416 /* Default to keeping current size */
6417 *width = allocation.width;
6418 *height = allocation.height;
6421 /* Override any size with gtk_window_resize() values */
6424 if (info->resize_width > 0)
6425 *width = info->resize_width;
6426 if (info->resize_height > 0)
6427 *height = info->resize_height;
6429 if (info->resize_is_geometry)
6430 geometry_size_to_pixels (geometry, flags,
6431 info->resize_width > 0 ? width : NULL,
6432 info->resize_height > 0 ? height : NULL);
6435 /* Don't ever request zero width or height, its not supported by
6436 gdk. The size allocation code will round it to 1 anyway but if
6437 we do it then the value returned from this function will is
6438 not comparable to the size allocation read from the GtkWindow. */
6439 *width = MAX (*width, 1);
6440 *height = MAX (*height, 1);
6443 static GtkWindowPosition
6444 get_effective_position (GtkWindow *window)
6446 GtkWindowPrivate *priv = window->priv;
6447 GtkWindowPosition pos = priv->position;
6449 if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6450 (priv->transient_parent == NULL ||
6451 !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6452 pos = GTK_WIN_POS_NONE;
6458 get_center_monitor_of_window (GtkWindow *window)
6460 /* We could try to sort out the relative positions of the monitors and
6461 * stuff, or we could just be losers and assume you have a row
6462 * or column of monitors.
6464 return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6468 get_monitor_containing_pointer (GtkWindow *window)
6472 GdkScreen *window_screen;
6473 GdkScreen *pointer_screen;
6474 GdkDisplay *display;
6475 GdkDeviceManager *device_manager;
6478 window_screen = gtk_window_check_screen (window);
6479 display = gdk_screen_get_display (window_screen);
6480 device_manager = gdk_display_get_device_manager (display);
6481 pointer = gdk_device_manager_get_client_pointer (device_manager);
6483 gdk_display_get_device_state (display, pointer,
6487 if (pointer_screen == window_screen)
6488 monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6496 center_window_on_monitor (GtkWindow *window,
6502 GdkRectangle monitor;
6505 monitor_num = get_monitor_containing_pointer (window);
6507 if (monitor_num == -1)
6508 monitor_num = get_center_monitor_of_window (window);
6510 gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6511 monitor_num, &monitor);
6513 *x = (monitor.width - w) / 2 + monitor.x;
6514 *y = (monitor.height - h) / 2 + monitor.y;
6516 /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6517 * and WM decorations.
6531 if (extent > clamp_extent)
6533 *base = clamp_base + clamp_extent/2 - extent/2;
6534 else if (*base < clamp_base)
6536 else if (*base + extent > clamp_base + clamp_extent)
6537 *base = clamp_base + clamp_extent - extent;
6541 clamp_window_to_rectangle (gint *x,
6545 const GdkRectangle *rect)
6547 #ifdef DEBUGGING_OUTPUT
6548 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);
6551 /* If it is too large, center it. If it fits on the monitor but is
6552 * partially outside, move it to the closest edge. Do this
6553 * separately in x and y directions.
6555 clamp (x, w, rect->x, rect->width);
6556 clamp (y, h, rect->y, rect->height);
6557 #ifdef DEBUGGING_OUTPUT
6558 g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6564 gtk_window_compute_configure_request (GtkWindow *window,
6565 GdkRectangle *request,
6566 GdkGeometry *geometry,
6569 GtkWindowPrivate *priv = window->priv;
6570 GdkGeometry new_geometry;
6574 GtkWindowPosition pos;
6575 GtkWidget *parent_widget;
6576 GtkWindowGeometryInfo *info;
6580 widget = GTK_WIDGET (window);
6582 screen = gtk_window_check_screen (window);
6584 gtk_window_compute_hints (window, &new_geometry, &new_flags);
6585 gtk_window_compute_configure_request_size (window,
6586 &new_geometry, new_flags,
6587 (guint *)&w, (guint *)&h);
6589 gtk_window_constrain_size (window,
6590 &new_geometry, new_flags,
6594 parent_widget = (GtkWidget*) priv->transient_parent;
6596 pos = get_effective_position (window);
6597 info = gtk_window_get_geometry_info (window, FALSE);
6599 /* by default, don't change position requested */
6602 x = info->last.configure_request.x;
6603 y = info->last.configure_request.y;
6612 if (priv->need_default_position)
6615 /* FIXME this all interrelates with window gravity.
6616 * For most of them I think we want to set GRAVITY_CENTER.
6618 * Not sure how to go about that.
6623 /* here we are only handling CENTER_ALWAYS
6624 * as it relates to default positioning,
6625 * where it's equivalent to simply CENTER
6627 case GTK_WIN_POS_CENTER_ALWAYS:
6628 case GTK_WIN_POS_CENTER:
6629 center_window_on_monitor (window, w, h, &x, &y);
6632 case GTK_WIN_POS_CENTER_ON_PARENT:
6634 GtkAllocation allocation;
6635 GdkWindow *gdk_window;
6637 GdkRectangle monitor;
6640 g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6642 gdk_window = gtk_widget_get_window (parent_widget);
6644 if (gdk_window != NULL)
6645 monitor_num = gdk_screen_get_monitor_at_window (screen,
6650 gdk_window_get_origin (gdk_window,
6653 gtk_widget_get_allocation (parent_widget, &allocation);
6654 x = ox + (allocation.width - w) / 2;
6655 y = oy + (allocation.height - h) / 2;
6657 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6658 * WM decorations. If parent wasn't on a monitor, just
6661 if (monitor_num >= 0)
6663 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6664 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6669 case GTK_WIN_POS_MOUSE:
6671 gint screen_width = gdk_screen_get_width (screen);
6672 gint screen_height = gdk_screen_get_height (screen);
6674 GdkRectangle monitor;
6675 GdkDisplay *display;
6676 GdkDeviceManager *device_manager;
6678 GdkScreen *pointer_screen;
6681 display = gdk_screen_get_display (screen);
6682 device_manager = gdk_display_get_device_manager (display);
6683 pointer = gdk_device_manager_get_client_pointer (device_manager);
6685 gdk_display_get_device_state (display, pointer,
6689 if (pointer_screen == screen)
6690 monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6696 x = CLAMP (x, 0, screen_width - w);
6697 y = CLAMP (y, 0, screen_height - h);
6699 /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6700 * WM decorations. Don't try to figure out what's going
6701 * on if the mouse wasn't inside a monitor.
6703 if (monitor_num >= 0)
6705 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6706 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6714 } /* if (priv->need_default_position) */
6716 if (priv->need_default_position && info &&
6717 info->initial_pos_set)
6719 x = info->initial_x;
6720 y = info->initial_y;
6721 gtk_window_constrain_position (window, w, h, &x, &y);
6727 request->height = h;
6730 *geometry = new_geometry;
6736 gtk_window_constrain_position (GtkWindow *window,
6742 GtkWindowPrivate *priv = window->priv;
6744 /* See long comments in gtk_window_move_resize()
6745 * on when it's safe to call this function.
6747 if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6749 gint center_x, center_y;
6751 center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
6759 gtk_window_move_resize (GtkWindow *window)
6763 * First we determine whether any information has changed that would
6764 * cause us to revise our last configure request. If we would send
6765 * a different configure request from last time, then
6766 * configure_request_size_changed = TRUE or
6767 * configure_request_pos_changed = TRUE. configure_request_size_changed
6768 * may be true due to new hints, a gtk_window_resize(), or whatever.
6769 * configure_request_pos_changed may be true due to gtk_window_set_position()
6770 * or gtk_window_move().
6772 * If the configure request has changed, we send off a new one. To
6773 * ensure GTK+ invariants are maintained (resize queue does what it
6774 * should), we go ahead and size_allocate the requested size in this
6777 * If the configure request has not changed, we don't ever resend
6778 * it, because it could mean fighting the user or window manager.
6781 * To prepare the configure request, we come up with a base size/pos:
6782 * - the one from gtk_window_move()/gtk_window_resize()
6783 * - else default_width, default_height if we haven't ever
6785 * - else the size request if we haven't ever been mapped,
6786 * as a substitute default size
6787 * - else the current size of the window, as received from
6788 * configure notifies (i.e. the current allocation)
6790 * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6791 * the position request to be centered.
6793 GtkWindowPrivate *priv = window->priv;
6794 GtkAllocation allocation;
6796 GtkContainer *container;
6797 GtkWindowGeometryInfo *info;
6798 GdkGeometry new_geometry;
6799 GdkWindow *gdk_window;
6801 GdkRectangle new_request;
6802 gboolean configure_request_size_changed;
6803 gboolean configure_request_pos_changed;
6804 gboolean hints_changed; /* do we need to send these again */
6805 GtkWindowLastGeometryInfo saved_last_info;
6807 widget = GTK_WIDGET (window);
6808 gdk_window = gtk_widget_get_window (widget);
6809 container = GTK_CONTAINER (widget);
6810 info = gtk_window_get_geometry_info (window, TRUE);
6812 configure_request_size_changed = FALSE;
6813 configure_request_pos_changed = FALSE;
6815 gtk_window_compute_configure_request (window, &new_request,
6816 &new_geometry, &new_flags);
6818 /* This check implies the invariant that we never set info->last
6819 * without setting the hints and sending off a configure request.
6821 * If we change info->last without sending the request, we may
6824 if (info->last.configure_request.x != new_request.x ||
6825 info->last.configure_request.y != new_request.y)
6826 configure_request_pos_changed = TRUE;
6828 if ((info->last.configure_request.width != new_request.width ||
6829 info->last.configure_request.height != new_request.height))
6830 configure_request_size_changed = TRUE;
6832 hints_changed = FALSE;
6834 if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6835 &new_geometry, new_flags))
6837 hints_changed = TRUE;
6840 /* Position Constraints
6841 * ====================
6843 * POS_CENTER_ALWAYS is conceptually a constraint rather than
6844 * a default. The other POS_ values are used only when the
6845 * window is shown, not after that.
6847 * However, we can't implement a position constraint as
6848 * "anytime the window size changes, center the window"
6849 * because this may well end up fighting the WM or user. In
6850 * fact it gets in an infinite loop with at least one WM.
6852 * Basically, applications are in no way in a position to
6853 * constrain the position of a window, with one exception:
6854 * override redirect windows. (Really the intended purpose
6855 * of CENTER_ALWAYS anyhow, I would think.)
6857 * So the way we implement this "constraint" is to say that when WE
6858 * cause a move or resize, i.e. we make a configure request changing
6859 * window size, we recompute the CENTER_ALWAYS position to reflect
6860 * the new window size, and include it in our request. Also, if we
6861 * just turned on CENTER_ALWAYS we snap to center with a new
6862 * request. Otherwise, if we are just NOTIFIED of a move or resize
6863 * done by someone else e.g. the window manager, we do NOT send a
6864 * new configure request.
6866 * For override redirect windows, this works fine; all window
6867 * sizes are from our configure requests. For managed windows,
6868 * it is at least semi-sane, though who knows what the
6869 * app author is thinking.
6872 /* This condition should be kept in sync with the condition later on
6873 * that determines whether we send a configure request. i.e. we
6874 * should do this position constraining anytime we were going to
6875 * send a configure request anyhow, plus when constraints have
6878 if (configure_request_pos_changed ||
6879 configure_request_size_changed ||
6881 info->position_constraints_changed)
6883 /* We request the constrained position if:
6884 * - we were changing position, and need to clamp
6885 * the change to the constraint
6886 * - we're changing the size anyway
6887 * - set_position() was called to toggle CENTER_ALWAYS on
6890 gtk_window_constrain_position (window,
6896 /* Update whether we need to request a move */
6897 if (info->last.configure_request.x != new_request.x ||
6898 info->last.configure_request.y != new_request.y)
6899 configure_request_pos_changed = TRUE;
6901 configure_request_pos_changed = FALSE;
6905 if (priv->type == GTK_WINDOW_TOPLEVEL)
6907 int notify_x, notify_y;
6909 /* this is the position from the last configure notify */
6910 gdk_window_get_position (widget->window, ¬ify_x, ¬ify_y);
6912 g_message ("--- %s ---\n"
6913 "last : %d,%d\t%d x %d\n"
6914 "this : %d,%d\t%d x %d\n"
6915 "alloc : %d,%d\t%d x %d\n"
6917 "resize: \t%d x %d\n"
6918 "size_changed: %d pos_changed: %d hints_changed: %d\n"
6919 "configure_notify_received: %d\n"
6920 "configure_request_count: %d\n"
6921 "position_constraints_changed: %d\n",
6922 priv->title ? priv->title : "(no title)",
6923 info->last.configure_request.x,
6924 info->last.configure_request.y,
6925 info->last.configure_request.width,
6926 info->last.configure_request.height,
6932 widget->allocation.width,
6933 widget->allocation.height,
6934 widget->requisition.width,
6935 widget->requisition.height,
6937 info->resize_height,
6938 configure_request_pos_changed,
6939 configure_request_size_changed,
6941 priv->configure_notify_received,
6942 priv->configure_request_count,
6943 info->position_constraints_changed);
6947 saved_last_info = info->last;
6948 info->last.geometry = new_geometry;
6949 info->last.flags = new_flags;
6950 info->last.configure_request = new_request;
6952 /* need to set PPosition so the WM will look at our position,
6953 * but we don't want to count PPosition coming and going as a hints
6954 * change for future iterations. So we saved info->last prior to
6958 /* Also, if the initial position was explicitly set, then we always
6959 * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6963 /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6964 * this is an initial map
6967 if ((configure_request_pos_changed ||
6968 info->initial_pos_set ||
6969 (priv->need_default_position &&
6970 get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6971 (new_flags & GDK_HINT_POS) == 0)
6973 new_flags |= GDK_HINT_POS;
6974 hints_changed = TRUE;
6977 /* Set hints if necessary
6980 gdk_window_set_geometry_hints (gdk_window,
6984 gtk_widget_get_allocation (widget, &allocation);
6986 /* handle resizing/moving and widget tree allocation
6988 if (priv->configure_notify_received)
6990 /* If we have received a configure event since
6991 * the last time in this function, we need to
6992 * accept our new size and size_allocate child widgets.
6993 * (see gtk_window_configure_event() for more details).
6995 * 1 or more configure notifies may have been received.
6996 * Also, configure_notify_received will only be TRUE
6997 * if all expected configure notifies have been received
6998 * (one per configure request), as an optimization.
7001 priv->configure_notify_received = FALSE;
7003 /* gtk_window_configure_event() filled in widget->allocation */
7004 gtk_widget_size_allocate (widget, &allocation);
7006 set_grip_position (window);
7007 update_grip_visibility (window);
7009 gdk_window_process_updates (gdk_window, TRUE);
7011 gdk_window_configure_finished (gdk_window);
7013 /* If the configure request changed, it means that
7015 * 1) coincidentally changed hints or widget properties
7016 * impacting the configure request before getting
7017 * a configure notify, or
7018 * 2) some broken widget is changing its size request
7019 * during size allocation, resulting in
7020 * a false appearance of changed configure request.
7022 * For 1), we could just go ahead and ask for the
7023 * new size right now, but doing that for 2)
7024 * might well be fighting the user (and can even
7025 * trigger a loop). Since we really don't want to
7026 * do that, we requeue a resize in hopes that
7027 * by the time it gets handled, the child has seen
7028 * the light and is willing to go along with the
7029 * new size. (this happens for the zvt widget, since
7030 * the size_allocate() above will have stored the
7031 * requisition corresponding to the new size in the
7034 * This doesn't buy us anything for 1), but it shouldn't
7035 * hurt us too badly, since it is what would have
7036 * happened if we had gotten the configure event before
7037 * the new size had been set.
7040 if (configure_request_size_changed ||
7041 configure_request_pos_changed)
7043 /* Don't change the recorded last info after all, because we
7044 * haven't actually updated to the new info yet - we decided
7045 * to postpone our configure request until later.
7047 info->last = saved_last_info;
7049 gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
7052 return; /* Bail out, we didn't really process the move/resize */
7054 else if ((configure_request_size_changed || hints_changed) &&
7055 (allocation.width != new_request.width || allocation.height != new_request.height))
7058 /* We are in one of the following situations:
7059 * A. configure_request_size_changed
7060 * our requisition has changed and we need a different window size,
7061 * so we request it from the window manager.
7062 * B. !configure_request_size_changed && hints_changed
7063 * the window manager rejects our size, but we have just changed the
7064 * window manager hints, so there's a chance our request will
7065 * be honoured this time, so we try again.
7067 * However, if the new requisition is the same as the current allocation,
7068 * we don't request it again, since we won't get a ConfigureNotify back from
7069 * the window manager unless it decides to change our requisition. If
7070 * we don't get the ConfigureNotify back, the resize queue will never be run.
7073 /* Now send the configure request */
7074 if (configure_request_pos_changed)
7078 gdk_window_move_resize (priv->frame,
7079 new_request.x - priv->frame_left,
7080 new_request.y - priv->frame_top,
7081 new_request.width + priv->frame_left + priv->frame_right,
7082 new_request.height + priv->frame_top + priv->frame_bottom);
7083 gdk_window_resize (gdk_window,
7084 new_request.width, new_request.height);
7087 gdk_window_move_resize (gdk_window,
7088 new_request.x, new_request.y,
7089 new_request.width, new_request.height);
7091 else /* only size changed */
7094 gdk_window_resize (priv->frame,
7095 new_request.width + priv->frame_left + priv->frame_right,
7096 new_request.height + priv->frame_top + priv->frame_bottom);
7097 gdk_window_resize (gdk_window,
7098 new_request.width, new_request.height);
7101 if (priv->type == GTK_WINDOW_POPUP)
7103 GtkAllocation allocation;
7105 /* Directly size allocate for override redirect (popup) windows. */
7108 allocation.width = new_request.width;
7109 allocation.height = new_request.height;
7111 gtk_widget_size_allocate (widget, &allocation);
7113 gdk_window_process_updates (gdk_window, TRUE);
7115 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7116 gtk_widget_queue_draw (widget);
7120 /* Increment the number of have-not-yet-received-notify requests */
7121 priv->configure_request_count += 1;
7122 gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
7124 /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
7125 * configure event in response to our resizing request.
7126 * the configure event will cause a new resize with
7127 * ->configure_notify_received=TRUE.
7128 * until then, we want to
7129 * - discard expose events
7130 * - coalesce resizes for our children
7131 * - defer any window resizes until the configure event arrived
7132 * to achieve this, we queue a resize for the window, but remove its
7133 * resizing handler, so resizing will not be handled from the next
7134 * idle handler but when the configure event arrives.
7136 * FIXME: we should also dequeue the pending redraws here, since
7137 * we handle those ourselves upon ->configure_notify_received==TRUE.
7139 if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
7141 gtk_widget_queue_resize_no_redraw (widget);
7142 _gtk_container_dequeue_resize_handler (container);
7148 /* Handle any position changes.
7150 if (configure_request_pos_changed)
7154 gdk_window_move (priv->frame,
7155 new_request.x - priv->frame_left,
7156 new_request.y - priv->frame_top);
7159 gdk_window_move (gdk_window,
7160 new_request.x, new_request.y);
7163 /* And run the resize queue.
7165 gtk_container_resize_children (container);
7168 /* We have now processed a move/resize since the last position
7169 * constraint change, setting of the initial position, or resize.
7170 * (Not resetting these flags here can lead to infinite loops for
7171 * GTK_RESIZE_IMMEDIATE containers)
7173 info->position_constraints_changed = FALSE;
7174 info->initial_pos_set = FALSE;
7175 info->resize_width = -1;
7176 info->resize_height = -1;
7179 /* Compare two sets of Geometry hints for equality.
7182 gtk_window_compare_hints (GdkGeometry *geometry_a,
7184 GdkGeometry *geometry_b,
7187 if (flags_a != flags_b)
7190 if ((flags_a & GDK_HINT_MIN_SIZE) &&
7191 (geometry_a->min_width != geometry_b->min_width ||
7192 geometry_a->min_height != geometry_b->min_height))
7195 if ((flags_a & GDK_HINT_MAX_SIZE) &&
7196 (geometry_a->max_width != geometry_b->max_width ||
7197 geometry_a->max_height != geometry_b->max_height))
7200 if ((flags_a & GDK_HINT_BASE_SIZE) &&
7201 (geometry_a->base_width != geometry_b->base_width ||
7202 geometry_a->base_height != geometry_b->base_height))
7205 if ((flags_a & GDK_HINT_ASPECT) &&
7206 (geometry_a->min_aspect != geometry_b->min_aspect ||
7207 geometry_a->max_aspect != geometry_b->max_aspect))
7210 if ((flags_a & GDK_HINT_RESIZE_INC) &&
7211 (geometry_a->width_inc != geometry_b->width_inc ||
7212 geometry_a->height_inc != geometry_b->height_inc))
7215 if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7216 geometry_a->win_gravity != geometry_b->win_gravity)
7223 _gtk_window_constrain_size (GtkWindow *window,
7229 GtkWindowPrivate *priv;
7230 GtkWindowGeometryInfo *info;
7232 g_return_if_fail (GTK_IS_WINDOW (window));
7234 priv = window->priv;
7236 info = priv->geometry_info;
7239 GdkWindowHints flags = info->last.flags;
7240 GdkGeometry *geometry = &info->last.geometry;
7242 gtk_window_constrain_size (window,
7253 gtk_window_constrain_size (GtkWindow *window,
7254 GdkGeometry *geometry,
7261 gdk_window_constrain_size (geometry, flags, width, height,
7262 new_width, new_height);
7265 /* Compute the set of geometry hints and flags for a window
7266 * based on the application set geometry, and requisition
7267 * of the window. gtk_widget_get_preferred_size() must have been
7271 gtk_window_compute_hints (GtkWindow *window,
7272 GdkGeometry *new_geometry,
7275 GtkWindowPrivate *priv = window->priv;
7277 gint extra_width = 0;
7278 gint extra_height = 0;
7279 GtkWindowGeometryInfo *geometry_info;
7280 GtkRequisition requisition;
7282 widget = GTK_WIDGET (window);
7284 gtk_widget_get_preferred_size (widget, &requisition, NULL);
7285 geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7289 *new_flags = geometry_info->mask;
7290 *new_geometry = geometry_info->geometry;
7297 if (geometry_info && geometry_info->widget)
7299 /* If the geometry widget is set, then the hints really apply to that
7300 * widget. This is pretty much meaningless unless the window layout
7301 * is such that the rest of the window adds fixed size borders to
7302 * the geometry widget. Our job is to figure the size of the borders;
7303 * We do that by asking how big the toplevel would be if the
7304 * geometry widget was *really big*.
7307 * |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7308 * |GGGGG B| in the border can confuse things
7314 * |AAAAAAAAA | When the geometry widget is large, things are
7315 * |GGGGGGGGGGB| clearer.
7320 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7321 GtkRequisition requisition;
7322 int current_width, current_height;
7324 _gtk_widget_override_size_request (geometry_info->widget,
7325 TEMPORARY_SIZE, TEMPORARY_SIZE,
7326 ¤t_width, ¤t_height);
7327 gtk_widget_get_preferred_size (widget,
7328 &requisition, NULL);
7329 _gtk_widget_restore_size_request (geometry_info->widget,
7330 current_width, current_height);
7332 extra_width = requisition.width - TEMPORARY_SIZE;
7333 extra_height = requisition.height - TEMPORARY_SIZE;
7335 if (extra_width < 0 || extra_width < 0)
7337 g_warning("Toplevel size doesn't seem to directly depend on the "
7338 "size of the geometry widget from gtk_window_set_geometry_hints(). "
7339 "The geometry widget might not be in the window, or it might not "
7340 "be packed into the window appropriately");
7341 extra_width = MAX(extra_width, 0);
7342 extra_height = MAX(extra_height, 0);
7344 #undef TEMPORARY_SIZE
7347 /* We don't want to set GDK_HINT_POS in here, we just set it
7348 * in gtk_window_move_resize() when we want the position
7352 if (*new_flags & GDK_HINT_BASE_SIZE)
7354 new_geometry->base_width += extra_width;
7355 new_geometry->base_height += extra_height;
7359 /* For simplicity, we always set the base hint, even when we
7360 * don't expect it to have any visible effect.
7361 * (Note: geometry_size_to_pixels() depends on this.)
7363 *new_flags |= GDK_HINT_BASE_SIZE;
7365 new_geometry->base_width = extra_width;
7366 new_geometry->base_height = extra_height;
7368 /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7369 * base size is the minimum size */
7370 if (*new_flags & GDK_HINT_MIN_SIZE)
7372 if (new_geometry->min_width > 0)
7373 new_geometry->base_width += new_geometry->min_width;
7374 if (new_geometry->min_height > 0)
7375 new_geometry->base_height += new_geometry->min_height;
7379 if (*new_flags & GDK_HINT_MIN_SIZE)
7381 if (new_geometry->min_width < 0)
7382 new_geometry->min_width = requisition.width;
7384 new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7386 if (new_geometry->min_height < 0)
7387 new_geometry->min_height = requisition.height;
7389 new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7393 *new_flags |= GDK_HINT_MIN_SIZE;
7395 new_geometry->min_width = requisition.width;
7396 new_geometry->min_height = requisition.height;
7399 if (*new_flags & GDK_HINT_MAX_SIZE)
7401 if (new_geometry->max_width < 0)
7402 new_geometry->max_width = requisition.width;
7404 new_geometry->max_width += extra_width;
7406 if (new_geometry->max_height < 0)
7407 new_geometry->max_height = requisition.height;
7409 new_geometry->max_height += extra_height;
7411 else if (!priv->resizable)
7413 *new_flags |= GDK_HINT_MAX_SIZE;
7415 new_geometry->max_width = requisition.width;
7416 new_geometry->max_height = requisition.height;
7419 *new_flags |= GDK_HINT_WIN_GRAVITY;
7420 new_geometry->win_gravity = priv->gravity;
7423 /***********************
7424 * Redrawing functions *
7425 ***********************/
7428 gtk_window_draw (GtkWidget *widget,
7431 GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7432 gboolean ret = FALSE;
7434 if (!gtk_widget_get_app_paintable (widget))
7435 gtk_paint_flat_box (gtk_widget_get_style (widget),
7438 GTK_SHADOW_NONE, widget, "base",
7440 gtk_widget_get_allocated_width (widget),
7441 gtk_widget_get_allocated_height (widget));
7443 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7444 ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7446 if (priv->grip_window != NULL &&
7447 gtk_cairo_should_draw_window (cr, priv->grip_window))
7452 gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7453 gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7454 gtk_paint_resize_grip (gtk_widget_get_style (widget),
7456 gtk_widget_get_state (widget),
7459 get_grip_edge (widget),
7461 rect.width, rect.height);
7469 * gtk_window_set_has_frame:
7470 * @window: a #GtkWindow
7471 * @setting: a boolean
7473 * (Note: this is a special-purpose function for the framebuffer port,
7474 * that causes GTK+ to draw its own window border. For most applications,
7475 * you want gtk_window_set_decorated() instead, which tells the window
7476 * manager whether to draw the window border.)
7478 * If this function is called on a window with setting of %TRUE, before
7479 * it is realized or showed, it will have a "frame" window around
7480 * @window->window, accessible in @window->frame. Using the signal
7481 * frame_event you can receive all events targeted at the frame.
7483 * This function is used by the linux-fb port to implement managed
7484 * windows, but it could conceivably be used by X-programs that
7485 * want to do their own window decorations.
7489 gtk_window_set_has_frame (GtkWindow *window,
7492 GtkWindowPrivate *priv;
7494 g_return_if_fail (GTK_IS_WINDOW (window));
7495 g_return_if_fail (!gtk_widget_get_realized (GTK_WIDGET (window)));
7497 priv = window->priv;
7499 priv->has_frame = setting != FALSE;
7503 * gtk_window_get_has_frame:
7504 * @window: a #GtkWindow
7506 * Accessor for whether the window has a frame window exterior to
7507 * @window->window. Gets the value set by gtk_window_set_has_frame ().
7509 * Return value: %TRUE if a frame has been added to the window
7510 * via gtk_window_set_has_frame().
7513 gtk_window_get_has_frame (GtkWindow *window)
7515 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7517 return window->priv->has_frame;
7521 * gtk_window_set_frame_dimensions:
7522 * @window: a #GtkWindow that has a frame
7523 * @left: The width of the left border
7524 * @top: The height of the top border
7525 * @right: The width of the right border
7526 * @bottom: The height of the bottom border
7528 * (Note: this is a special-purpose function intended for the framebuffer
7529 * port; see gtk_window_set_has_frame(). It will have no effect on the
7530 * window border drawn by the window manager, which is the normal
7531 * case when using the X Window system.)
7533 * For windows with frames (see gtk_window_set_has_frame()) this function
7534 * can be used to change the size of the frame border.
7537 gtk_window_set_frame_dimensions (GtkWindow *window,
7543 GtkWindowPrivate *priv;
7544 GtkAllocation allocation;
7547 g_return_if_fail (GTK_IS_WINDOW (window));
7549 priv = window->priv;
7550 widget = GTK_WIDGET (window);
7552 if (priv->frame_left == left &&
7553 priv->frame_top == top &&
7554 priv->frame_right == right &&
7555 priv->frame_bottom == bottom)
7558 priv->frame_left = left;
7559 priv->frame_top = top;
7560 priv->frame_right = right;
7561 priv->frame_bottom = bottom;
7563 if (gtk_widget_get_realized (widget) && priv->frame)
7565 gtk_widget_get_allocation (widget, &allocation);
7567 gint width = allocation.width + left + right;
7568 gint height = allocation.height + top + bottom;
7569 gdk_window_resize (priv->frame, width, height);
7570 gtk_decorated_window_move_resize_window (window,
7578 * gtk_window_present:
7579 * @window: a #GtkWindow
7581 * Presents a window to the user. This may mean raising the window
7582 * in the stacking order, deiconifying it, moving it to the current
7583 * desktop, and/or giving it the keyboard focus, possibly dependent
7584 * on the user's platform, window manager, and preferences.
7586 * If @window is hidden, this function calls gtk_widget_show()
7589 * This function should be used when the user tries to open a window
7590 * that's already open. Say for example the preferences dialog is
7591 * currently open, and the user chooses Preferences from the menu
7592 * a second time; use gtk_window_present() to move the already-open dialog
7593 * where the user can see it.
7595 * If you are calling this function in response to a user interaction,
7596 * it is preferable to use gtk_window_present_with_time().
7600 gtk_window_present (GtkWindow *window)
7602 gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7606 * gtk_window_present_with_time:
7607 * @window: a #GtkWindow
7608 * @timestamp: the timestamp of the user interaction (typically a
7609 * button or key press event) which triggered this call
7611 * Presents a window to the user in response to a user interaction.
7612 * If you need to present a window without a timestamp, use
7613 * gtk_window_present(). See gtk_window_present() for details.
7618 gtk_window_present_with_time (GtkWindow *window,
7622 GdkWindow *gdk_window;
7624 g_return_if_fail (GTK_IS_WINDOW (window));
7626 widget = GTK_WIDGET (window);
7628 if (gtk_widget_get_visible (widget))
7630 gdk_window = gtk_widget_get_window (widget);
7632 g_assert (gdk_window != NULL);
7634 gdk_window_show (gdk_window);
7636 /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7637 if (timestamp == GDK_CURRENT_TIME)
7639 #ifdef GDK_WINDOWING_X11
7640 GdkDisplay *display;
7642 display = gtk_widget_get_display (GTK_WIDGET (window));
7643 timestamp = gdk_x11_display_get_user_time (display);
7645 timestamp = gtk_get_current_event_time ();
7649 gdk_window_focus (gdk_window, timestamp);
7653 gtk_widget_show (widget);
7658 * gtk_window_iconify:
7659 * @window: a #GtkWindow
7661 * Asks to iconify (i.e. minimize) the specified @window. Note that
7662 * you shouldn't assume the window is definitely iconified afterward,
7663 * because other entities (e.g. the user or <link
7664 * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7665 * again, or there may not be a window manager in which case
7666 * iconification isn't possible, etc. But normally the window will end
7667 * up iconified. Just don't write code that crashes if not.
7669 * It's permitted to call this function before showing a window,
7670 * in which case the window will be iconified before it ever appears
7673 * You can track iconification via the "window-state-event" signal
7678 gtk_window_iconify (GtkWindow *window)
7680 GtkWindowPrivate *priv;
7682 GdkWindow *toplevel;
7684 g_return_if_fail (GTK_IS_WINDOW (window));
7686 priv = window->priv;
7687 widget = GTK_WIDGET (window);
7689 priv->iconify_initially = TRUE;
7692 toplevel = priv->frame;
7694 toplevel = gtk_widget_get_window (widget);
7696 if (toplevel != NULL)
7697 gdk_window_iconify (toplevel);
7701 * gtk_window_deiconify:
7702 * @window: a #GtkWindow
7704 * Asks to deiconify (i.e. unminimize) the specified @window. Note
7705 * that you shouldn't assume the window is definitely deiconified
7706 * afterward, because other entities (e.g. the user or <link
7707 * linkend="gtk-X11-arch">window manager</link>) could iconify it
7708 * again before your code which assumes deiconification gets to run.
7710 * You can track iconification via the "window-state-event" signal
7714 gtk_window_deiconify (GtkWindow *window)
7716 GtkWindowPrivate *priv;
7718 GdkWindow *toplevel;
7720 g_return_if_fail (GTK_IS_WINDOW (window));
7722 priv = window->priv;
7723 widget = GTK_WIDGET (window);
7725 priv->iconify_initially = FALSE;
7728 toplevel = priv->frame;
7730 toplevel = gtk_widget_get_window (widget);
7732 if (toplevel != NULL)
7733 gdk_window_deiconify (toplevel);
7738 * @window: a #GtkWindow
7740 * Asks to stick @window, which means that it will appear on all user
7741 * desktops. Note that you shouldn't assume the window is definitely
7742 * stuck afterward, because other entities (e.g. the user or <link
7743 * linkend="gtk-X11-arch">window manager</link>) could unstick it
7744 * again, and some window managers do not support sticking
7745 * windows. But normally the window will end up stuck. Just don't
7746 * write code that crashes if not.
7748 * It's permitted to call this function before showing a window.
7750 * You can track stickiness via the "window-state-event" signal
7755 gtk_window_stick (GtkWindow *window)
7757 GtkWindowPrivate *priv;
7759 GdkWindow *toplevel;
7761 g_return_if_fail (GTK_IS_WINDOW (window));
7763 priv = window->priv;
7764 widget = GTK_WIDGET (window);
7766 priv->stick_initially = TRUE;
7769 toplevel = priv->frame;
7771 toplevel = gtk_widget_get_window (widget);
7773 if (toplevel != NULL)
7774 gdk_window_stick (toplevel);
7778 * gtk_window_unstick:
7779 * @window: a #GtkWindow
7781 * Asks to unstick @window, which means that it will appear on only
7782 * one of the user's desktops. Note that you shouldn't assume the
7783 * window is definitely unstuck afterward, because other entities
7784 * (e.g. the user or <link linkend="gtk-X11-arch">window
7785 * manager</link>) could stick it again. But normally the window will
7786 * end up stuck. Just don't write code that crashes if not.
7788 * You can track stickiness via the "window-state-event" signal
7793 gtk_window_unstick (GtkWindow *window)
7795 GtkWindowPrivate *priv;
7797 GdkWindow *toplevel;
7799 g_return_if_fail (GTK_IS_WINDOW (window));
7801 priv = window->priv;
7802 widget = GTK_WIDGET (window);
7804 priv->stick_initially = FALSE;
7807 toplevel = priv->frame;
7809 toplevel = gtk_widget_get_window (widget);
7811 if (toplevel != NULL)
7812 gdk_window_unstick (toplevel);
7816 * gtk_window_maximize:
7817 * @window: a #GtkWindow
7819 * Asks to maximize @window, so that it becomes full-screen. Note that
7820 * you shouldn't assume the window is definitely maximized afterward,
7821 * because other entities (e.g. the user or <link
7822 * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7823 * again, and not all window managers support maximization. But
7824 * normally the window will end up maximized. Just don't write code
7825 * that crashes if not.
7827 * It's permitted to call this function before showing a window,
7828 * in which case the window will be maximized when it appears onscreen
7831 * You can track maximization via the "window-state-event" signal
7836 gtk_window_maximize (GtkWindow *window)
7838 GtkWindowPrivate *priv;
7840 GdkWindow *toplevel;
7842 g_return_if_fail (GTK_IS_WINDOW (window));
7844 priv = window->priv;
7845 widget = GTK_WIDGET (window);
7847 priv->maximize_initially = TRUE;
7850 toplevel = priv->frame;
7852 toplevel = gtk_widget_get_window (widget);
7854 if (toplevel != NULL)
7855 gdk_window_maximize (toplevel);
7859 * gtk_window_unmaximize:
7860 * @window: a #GtkWindow
7862 * Asks to unmaximize @window. Note that you shouldn't assume the
7863 * window is definitely unmaximized afterward, because other entities
7864 * (e.g. the user or <link linkend="gtk-X11-arch">window
7865 * manager</link>) could maximize it again, and not all window
7866 * managers honor requests to unmaximize. But normally the window will
7867 * end up unmaximized. Just don't write code that crashes if not.
7869 * You can track maximization via the "window-state-event" signal
7874 gtk_window_unmaximize (GtkWindow *window)
7876 GtkWindowPrivate *priv;
7878 GdkWindow *toplevel;
7880 g_return_if_fail (GTK_IS_WINDOW (window));
7882 priv = window->priv;
7883 widget = GTK_WIDGET (window);
7885 priv->maximize_initially = FALSE;
7888 toplevel = priv->frame;
7890 toplevel = gtk_widget_get_window (widget);
7892 if (toplevel != NULL)
7893 gdk_window_unmaximize (toplevel);
7897 * gtk_window_fullscreen:
7898 * @window: a #GtkWindow
7900 * Asks to place @window in the fullscreen state. Note that you
7901 * shouldn't assume the window is definitely full screen afterward,
7902 * because other entities (e.g. the user or <link
7903 * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7904 * again, and not all window managers honor requests to fullscreen
7905 * windows. But normally the window will end up fullscreen. Just
7906 * don't write code that crashes if not.
7908 * You can track the fullscreen state via the "window-state-event" signal
7914 gtk_window_fullscreen (GtkWindow *window)
7916 GtkWindowPrivate *priv;
7918 GdkWindow *toplevel;
7920 g_return_if_fail (GTK_IS_WINDOW (window));
7922 priv = window->priv;
7923 widget = GTK_WIDGET (window);
7925 priv->fullscreen_initially = TRUE;
7928 toplevel = priv->frame;
7930 toplevel = gtk_widget_get_window (widget);
7932 if (toplevel != NULL)
7933 gdk_window_fullscreen (toplevel);
7937 * gtk_window_unfullscreen:
7938 * @window: a #GtkWindow
7940 * Asks to toggle off the fullscreen state for @window. Note that you
7941 * shouldn't assume the window is definitely not full screen
7942 * afterward, because other entities (e.g. the user or <link
7943 * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7944 * again, and not all window managers honor requests to unfullscreen
7945 * windows. But normally the window will end up restored to its normal
7946 * state. Just don't write code that crashes if not.
7948 * You can track the fullscreen state via the "window-state-event" signal
7954 gtk_window_unfullscreen (GtkWindow *window)
7957 GdkWindow *toplevel;
7958 GtkWindowPrivate *priv;
7960 g_return_if_fail (GTK_IS_WINDOW (window));
7962 priv = window->priv;
7963 widget = GTK_WIDGET (window);
7965 priv->fullscreen_initially = FALSE;
7968 toplevel = priv->frame;
7970 toplevel = gtk_widget_get_window (widget);
7972 if (toplevel != NULL)
7973 gdk_window_unfullscreen (toplevel);
7977 * gtk_window_set_keep_above:
7978 * @window: a #GtkWindow
7979 * @setting: whether to keep @window above other windows
7981 * Asks to keep @window above, so that it stays on top. Note that
7982 * you shouldn't assume the window is definitely above afterward,
7983 * because other entities (e.g. the user or <link
7984 * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7985 * and not all window managers support keeping windows above. But
7986 * normally the window will end kept above. Just don't write code
7987 * that crashes if not.
7989 * It's permitted to call this function before showing a window,
7990 * in which case the window will be kept above when it appears onscreen
7993 * You can track the above state via the "window-state-event" signal
7996 * Note that, according to the <ulink
7997 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
7998 * Manager Hints</ulink> specification, the above state is mainly meant
7999 * for user preferences and should not be used by applications e.g. for
8000 * drawing attention to their dialogs.
8005 gtk_window_set_keep_above (GtkWindow *window,
8009 GtkWindowPrivate *priv;
8010 GdkWindow *toplevel;
8012 g_return_if_fail (GTK_IS_WINDOW (window));
8014 priv = window->priv;
8015 widget = GTK_WIDGET (window);
8017 priv->above_initially = setting != FALSE;
8019 priv->below_initially = FALSE;
8022 toplevel = priv->frame;
8024 toplevel = gtk_widget_get_window (widget);
8026 if (toplevel != NULL)
8027 gdk_window_set_keep_above (toplevel, setting);
8031 * gtk_window_set_keep_below:
8032 * @window: a #GtkWindow
8033 * @setting: whether to keep @window below other windows
8035 * Asks to keep @window below, so that it stays in bottom. Note that
8036 * you shouldn't assume the window is definitely below afterward,
8037 * because other entities (e.g. the user or <link
8038 * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
8039 * and not all window managers support putting windows below. But
8040 * normally the window will be kept below. Just don't write code
8041 * that crashes if not.
8043 * It's permitted to call this function before showing a window,
8044 * in which case the window will be kept below when it appears onscreen
8047 * You can track the below state via the "window-state-event" signal
8050 * Note that, according to the <ulink
8051 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
8052 * Manager Hints</ulink> specification, the above state is mainly meant
8053 * for user preferences and should not be used by applications e.g. for
8054 * drawing attention to their dialogs.
8059 gtk_window_set_keep_below (GtkWindow *window,
8063 GtkWindowPrivate *priv;
8064 GdkWindow *toplevel;
8066 g_return_if_fail (GTK_IS_WINDOW (window));
8068 priv = window->priv;
8069 widget = GTK_WIDGET (window);
8071 priv->below_initially = setting != FALSE;
8073 priv->above_initially = FALSE;
8076 toplevel = priv->frame;
8078 toplevel = gtk_widget_get_window (widget);
8080 if (toplevel != NULL)
8081 gdk_window_set_keep_below (toplevel, setting);
8085 * gtk_window_set_resizable:
8086 * @window: a #GtkWindow
8087 * @resizable: %TRUE if the user can resize this window
8089 * Sets whether the user can resize a window. Windows are user resizable
8093 gtk_window_set_resizable (GtkWindow *window,
8096 GtkWindowPrivate *priv;
8098 g_return_if_fail (GTK_IS_WINDOW (window));
8100 priv = window->priv;
8102 resizable = (resizable != FALSE);
8104 if (priv->resizable != resizable)
8106 priv->resizable = (resizable != FALSE);
8108 update_grip_visibility (window);
8110 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8112 g_object_notify (G_OBJECT (window), "resizable");
8117 * gtk_window_get_resizable:
8118 * @window: a #GtkWindow
8120 * Gets the value set by gtk_window_set_resizable().
8122 * Return value: %TRUE if the user can resize the window
8125 gtk_window_get_resizable (GtkWindow *window)
8127 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8129 return window->priv->resizable;
8133 * gtk_window_set_gravity:
8134 * @window: a #GtkWindow
8135 * @gravity: window gravity
8137 * Window gravity defines the meaning of coordinates passed to
8138 * gtk_window_move(). See gtk_window_move() and #GdkGravity for
8141 * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
8142 * typically "do what you mean."
8146 gtk_window_set_gravity (GtkWindow *window,
8149 GtkWindowPrivate *priv;
8151 g_return_if_fail (GTK_IS_WINDOW (window));
8153 priv = window->priv;
8155 if (gravity != priv->gravity)
8157 priv->gravity = gravity;
8159 /* gtk_window_move_resize() will adapt gravity
8161 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
8163 g_object_notify (G_OBJECT (window), "gravity");
8168 * gtk_window_get_gravity:
8169 * @window: a #GtkWindow
8171 * Gets the value set by gtk_window_set_gravity().
8173 * Return value: (transfer none): window gravity
8176 gtk_window_get_gravity (GtkWindow *window)
8178 g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
8180 return window->priv->gravity;
8184 * gtk_window_begin_resize_drag:
8185 * @window: a #GtkWindow
8186 * @button: mouse button that initiated the drag
8187 * @edge: position of the resize control
8188 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8189 * @root_y: Y position where the user clicked to initiate the drag
8190 * @timestamp: timestamp from the click event that initiated the drag
8192 * Starts resizing a window. This function is used if an application
8193 * has window resizing controls. When GDK can support it, the resize
8194 * will be done using the standard mechanism for the <link
8195 * linkend="gtk-X11-arch">window manager</link> or windowing
8196 * system. Otherwise, GDK will try to emulate window resizing,
8197 * potentially not all that well, depending on the windowing system.
8201 gtk_window_begin_resize_drag (GtkWindow *window,
8208 GtkWindowPrivate *priv;
8210 GdkWindow *toplevel;
8212 g_return_if_fail (GTK_IS_WINDOW (window));
8213 widget = GTK_WIDGET (window);
8214 g_return_if_fail (gtk_widget_get_visible (widget));
8216 priv = window->priv;
8219 toplevel = priv->frame;
8221 toplevel = gtk_widget_get_window (widget);
8223 gdk_window_begin_resize_drag (toplevel,
8230 * gtk_window_get_frame_dimensions:
8231 * @window: a #GtkWindow
8232 * @left: (out) (allow-none): location to store the width of the frame at the left, or %NULL
8233 * @top: (out) (allow-none): location to store the height of the frame at the top, or %NULL
8234 * @right: (out) (allow-none): location to store the width of the frame at the returns, or %NULL
8235 * @bottom: (out) (allow-none): location to store the height of the frame at the bottom, or %NULL
8237 * (Note: this is a special-purpose function intended for the
8238 * framebuffer port; see gtk_window_set_has_frame(). It will not
8239 * return the size of the window border drawn by the <link
8240 * linkend="gtk-X11-arch">window manager</link>, which is the normal
8241 * case when using a windowing system. See
8242 * gdk_window_get_frame_extents() to get the standard window border
8245 * Retrieves the dimensions of the frame window for this toplevel.
8246 * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
8249 gtk_window_get_frame_dimensions (GtkWindow *window,
8255 GtkWindowPrivate *priv;
8257 g_return_if_fail (GTK_IS_WINDOW (window));
8259 priv = window->priv;
8262 *left = priv->frame_left;
8264 *top = priv->frame_top;
8266 *right = priv->frame_right;
8268 *bottom = priv->frame_bottom;
8272 * gtk_window_begin_move_drag:
8273 * @window: a #GtkWindow
8274 * @button: mouse button that initiated the drag
8275 * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
8276 * @root_y: Y position where the user clicked to initiate the drag
8277 * @timestamp: timestamp from the click event that initiated the drag
8279 * Starts moving a window. This function is used if an application has
8280 * window movement grips. When GDK can support it, the window movement
8281 * will be done using the standard mechanism for the <link
8282 * linkend="gtk-X11-arch">window manager</link> or windowing
8283 * system. Otherwise, GDK will try to emulate window movement,
8284 * potentially not all that well, depending on the windowing system.
8288 gtk_window_begin_move_drag (GtkWindow *window,
8294 GtkWindowPrivate *priv;
8296 GdkWindow *toplevel;
8298 g_return_if_fail (GTK_IS_WINDOW (window));
8299 widget = GTK_WIDGET (window);
8300 g_return_if_fail (gtk_widget_get_visible (widget));
8302 priv = window->priv;
8305 toplevel = priv->frame;
8307 toplevel = gtk_widget_get_window (widget);
8309 gdk_window_begin_move_drag (toplevel,
8316 * gtk_window_set_screen:
8317 * @window: a #GtkWindow.
8318 * @screen: a #GdkScreen.
8320 * Sets the #GdkScreen where the @window is displayed; if
8321 * the window is already mapped, it will be unmapped, and
8322 * then remapped on the new screen.
8327 gtk_window_set_screen (GtkWindow *window,
8330 GtkWindowPrivate *priv;
8332 GdkScreen *previous_screen;
8333 gboolean was_mapped;
8335 g_return_if_fail (GTK_IS_WINDOW (window));
8336 g_return_if_fail (GDK_IS_SCREEN (screen));
8338 priv = window->priv;
8340 if (screen == priv->screen)
8343 widget = GTK_WIDGET (window);
8345 previous_screen = priv->screen;
8346 was_mapped = gtk_widget_get_mapped (widget);
8349 gtk_widget_unmap (widget);
8350 if (gtk_widget_get_realized (widget))
8351 gtk_widget_unrealize (widget);
8353 gtk_window_free_key_hash (window);
8354 priv->screen = screen;
8355 gtk_widget_reset_rc_styles (widget);
8356 if (screen != previous_screen)
8358 g_signal_handlers_disconnect_by_func (previous_screen,
8359 gtk_window_on_composited_changed, window);
8360 g_signal_connect (screen, "composited-changed",
8361 G_CALLBACK (gtk_window_on_composited_changed), window);
8363 _gtk_widget_propagate_screen_changed (widget, previous_screen);
8364 _gtk_widget_propagate_composited_changed (widget);
8366 g_object_notify (G_OBJECT (window), "screen");
8369 gtk_widget_map (widget);
8373 gtk_window_on_composited_changed (GdkScreen *screen,
8376 gtk_widget_queue_draw (GTK_WIDGET (window));
8378 _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8382 gtk_window_check_screen (GtkWindow *window)
8384 GtkWindowPrivate *priv = window->priv;
8387 return priv->screen;
8390 g_warning ("Screen for GtkWindow not set; you must always set\n"
8391 "a screen for a GtkWindow before using the window");
8397 * gtk_window_get_screen:
8398 * @window: a #GtkWindow.
8400 * Returns the #GdkScreen associated with @window.
8402 * Return value: (transfer none): a #GdkScreen.
8407 gtk_window_get_screen (GtkWindow *window)
8409 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8411 return window->priv->screen;
8415 * gtk_window_is_active:
8416 * @window: a #GtkWindow
8418 * Returns whether the window is part of the current active toplevel.
8419 * (That is, the toplevel window receiving keystrokes.)
8420 * The return value is %TRUE if the window is active toplevel
8421 * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8422 * You might use this function if you wanted to draw a widget
8423 * differently in an active window from a widget in an inactive window.
8424 * See gtk_window_has_toplevel_focus()
8426 * Return value: %TRUE if the window part of the current active window.
8431 gtk_window_is_active (GtkWindow *window)
8433 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8435 return window->priv->is_active;
8439 * gtk_window_has_toplevel_focus:
8440 * @window: a #GtkWindow
8442 * Returns whether the input focus is within this GtkWindow.
8443 * For real toplevel windows, this is identical to gtk_window_is_active(),
8444 * but for embedded windows, like #GtkPlug, the results will differ.
8446 * Return value: %TRUE if the input focus is within this GtkWindow
8451 gtk_window_has_toplevel_focus (GtkWindow *window)
8453 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8455 return window->priv->has_toplevel_focus;
8459 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8461 g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8465 gtk_window_group_get_type (void)
8467 static GType window_group_type = 0;
8469 if (!window_group_type)
8471 const GTypeInfo window_group_info =
8473 sizeof (GtkWindowGroupClass),
8474 NULL, /* base_init */
8475 NULL, /* base_finalize */
8476 (GClassInitFunc) gtk_window_group_class_init,
8477 NULL, /* class_finalize */
8478 NULL, /* class_data */
8479 sizeof (GtkWindowGroup),
8480 0, /* n_preallocs */
8481 (GInstanceInitFunc) NULL,
8484 window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"),
8485 &window_group_info, 0);
8488 return window_group_type;
8492 * gtk_window_group_new:
8494 * Creates a new #GtkWindowGroup object. Grabs added with
8495 * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8497 * Return value: a new #GtkWindowGroup.
8500 gtk_window_group_new (void)
8502 return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8506 window_group_cleanup_grabs (GtkWindowGroup *group,
8509 GtkWindowGroupPrivate *priv;
8510 GtkDeviceGrabInfo *info;
8512 GSList *to_remove = NULL;
8514 tmp_list = group->grabs;
8517 if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8518 to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8519 tmp_list = tmp_list->next;
8524 gtk_grab_remove (to_remove->data);
8525 g_object_unref (to_remove->data);
8526 to_remove = g_slist_delete_link (to_remove, to_remove);
8529 priv = GTK_WINDOW_GROUP_GET_PRIVATE (group);
8530 tmp_list = priv->device_grabs;
8534 info = tmp_list->data;
8536 if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8537 to_remove = g_slist_prepend (to_remove, info);
8539 tmp_list = tmp_list->next;
8544 info = to_remove->data;
8546 gtk_device_grab_remove (info->widget, info->device);
8547 to_remove = g_slist_delete_link (to_remove, to_remove);
8552 * gtk_window_group_add_window:
8553 * @window_group: a #GtkWindowGroup
8554 * @window: the #GtkWindow to add
8556 * Adds a window to a #GtkWindowGroup.
8559 gtk_window_group_add_window (GtkWindowGroup *window_group,
8562 GtkWindowPrivate *priv;
8564 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8565 g_return_if_fail (GTK_IS_WINDOW (window));
8567 priv = window->priv;
8569 if (priv->group != window_group)
8571 g_object_ref (window);
8572 g_object_ref (window_group);
8575 gtk_window_group_remove_window (priv->group, window);
8577 window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8579 priv->group = window_group;
8581 g_object_unref (window);
8586 * gtk_window_group_remove_window:
8587 * @window_group: a #GtkWindowGroup
8588 * @window: the #GtkWindow to remove
8590 * Removes a window from a #GtkWindowGroup.
8593 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8596 GtkWindowPrivate *priv;
8598 g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8599 g_return_if_fail (GTK_IS_WINDOW (window));
8600 priv = window->priv;
8601 g_return_if_fail (priv->group == window_group);
8603 g_object_ref (window);
8605 window_group_cleanup_grabs (window_group, window);
8608 g_object_unref (window_group);
8609 g_object_unref (window);
8613 * gtk_window_group_list_windows:
8614 * @window_group: a #GtkWindowGroup
8616 * Returns a list of the #GtkWindows that belong to @window_group.
8618 * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
8619 * windows inside the group.
8624 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8626 GList *toplevels, *toplevel, *group_windows;
8628 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8630 group_windows = NULL;
8631 toplevels = gtk_window_list_toplevels ();
8633 for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8635 GtkWindow *window = toplevel->data;
8637 if (window_group == window->priv->group)
8638 group_windows = g_list_prepend (group_windows, window);
8641 return g_list_reverse (group_windows);
8645 * gtk_window_get_group:
8646 * @window: (allow-none): a #GtkWindow, or %NULL
8648 * Returns the group for @window or the default group, if
8649 * @window is %NULL or if @window does not have an explicit
8652 * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8657 gtk_window_get_group (GtkWindow *window)
8659 if (window && window->priv->group)
8660 return window->priv->group;
8663 static GtkWindowGroup *default_group = NULL;
8666 default_group = gtk_window_group_new ();
8668 return default_group;
8673 * gtk_window_has_group:
8674 * @window: a #GtkWindow
8676 * Returns whether @window has an explicit window group.
8678 * Return value: %TRUE if @window has an explicit window group.
8683 gtk_window_has_group (GtkWindow *window)
8685 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8687 return window->priv->group != NULL;
8691 * gtk_window_group_get_current_grab:
8692 * @window_group: a #GtkWindowGroup
8694 * Gets the current grab widget of the given group,
8695 * see gtk_grab_add().
8697 * Returns: the current grab widget of the group
8702 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8704 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8706 if (window_group->grabs)
8707 return GTK_WIDGET (window_group->grabs->data);
8712 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8715 gboolean block_others)
8717 GtkWindowGroupPrivate *priv;
8718 GtkDeviceGrabInfo *info;
8720 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8722 info = g_slice_new0 (GtkDeviceGrabInfo);
8723 info->widget = widget;
8724 info->device = device;
8725 info->block_others = block_others;
8727 priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8731 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8735 GtkWindowGroupPrivate *priv;
8736 GtkDeviceGrabInfo *info;
8737 GSList *list, *node = NULL;
8738 GdkDevice *other_device;
8740 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8741 other_device = gdk_device_get_associated_device (device);
8742 list = priv->device_grabs;
8748 if (info->widget == widget &&
8749 (info->device == device ||
8750 info->device == other_device))
8763 priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8764 g_slice_free (GtkDeviceGrabInfo, info);
8769 * gtk_window_group_get_current_device_grab:
8770 * @window_group: a #GtkWindowGroup
8771 * @device: a #GdkDevice
8773 * Returns the current grab widget for @device, or %NULL if none.
8775 * Returns: The grab widget, or %NULL
8780 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8783 GtkWindowGroupPrivate *priv;
8784 GtkDeviceGrabInfo *info;
8785 GdkDevice *other_device;
8788 g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8789 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8791 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8792 list = priv->device_grabs;
8793 other_device = gdk_device_get_associated_device (device);
8800 if (info->device == device ||
8801 info->device == other_device)
8802 return info->widget;
8809 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8813 GtkWindowGroupPrivate *priv;
8814 GtkDeviceGrabInfo *info;
8815 GdkDevice *other_device;
8818 priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group);
8819 other_device = gdk_device_get_associated_device (device);
8820 list = priv->device_grabs;
8827 /* Look for blocking grabs on other device pairs
8828 * that have the passed widget within the GTK+ grab.
8830 if (info->block_others &&
8831 info->device != device &&
8832 info->device != other_device &&
8833 (info->widget == widget ||
8834 gtk_widget_is_ancestor (widget, info->widget)))
8842 Derived from XParseGeometry() in XFree86
8844 Copyright 1985, 1986, 1987,1998 The Open Group
8846 All Rights Reserved.
8848 The above copyright notice and this permission notice shall be included
8849 in all copies or substantial portions of the Software.
8851 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8852 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8853 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8854 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8855 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8856 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8857 OTHER DEALINGS IN THE SOFTWARE.
8859 Except as contained in this notice, the name of The Open Group shall
8860 not be used in advertising or otherwise to promote the sale, use or
8861 other dealings in this Software without prior written authorization
8862 from The Open Group.
8867 * XParseGeometry parses strings of the form
8868 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8869 * width, height, xoffset, and yoffset are unsigned integers.
8870 * Example: "=80x24+300-49"
8871 * The equal sign is optional.
8872 * It returns a bitmask that indicates which of the four values
8873 * were actually found in the string. For each value found,
8874 * the corresponding argument is updated; for each value
8875 * not found, the corresponding argument is left unchanged.
8878 /* The following code is from Xlib, and is minimally modified, so we
8879 * can track any upstream changes if required. Don't change this
8880 * code. Or if you do, put in a huge comment marking which thing
8885 read_int (gchar *string,
8893 else if (*string == '-')
8899 for (; (*string >= '0') && (*string <= '9'); string++)
8901 result = (result * 10) + (*string - '0');
8913 * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
8914 * value (x, y, width, height) was found in the parsed string.
8916 #define NoValue 0x0000
8917 #define XValue 0x0001
8918 #define YValue 0x0002
8919 #define WidthValue 0x0004
8920 #define HeightValue 0x0008
8921 #define AllValues 0x000F
8922 #define XNegative 0x0010
8923 #define YNegative 0x0020
8925 /* Try not to reformat/modify, so we can compare/sync with X sources */
8927 gtk_XParseGeometry (const char *string,
8930 unsigned int *width,
8931 unsigned int *height)
8935 unsigned int tempWidth, tempHeight;
8937 char *nextCharacter;
8939 /* These initializations are just to silence gcc */
8945 if ( (string == NULL) || (*string == '\0')) return(mask);
8947 string++; /* ignore possible '=' at beg of geometry spec */
8949 strind = (char *)string;
8950 if (*strind != '+' && *strind != '-' && *strind != 'x') {
8951 tempWidth = read_int(strind, &nextCharacter);
8952 if (strind == nextCharacter)
8954 strind = nextCharacter;
8958 if (*strind == 'x' || *strind == 'X') {
8960 tempHeight = read_int(strind, &nextCharacter);
8961 if (strind == nextCharacter)
8963 strind = nextCharacter;
8964 mask |= HeightValue;
8967 if ((*strind == '+') || (*strind == '-')) {
8968 if (*strind == '-') {
8970 tempX = -read_int(strind, &nextCharacter);
8971 if (strind == nextCharacter)
8973 strind = nextCharacter;
8979 tempX = read_int(strind, &nextCharacter);
8980 if (strind == nextCharacter)
8982 strind = nextCharacter;
8985 if ((*strind == '+') || (*strind == '-')) {
8986 if (*strind == '-') {
8988 tempY = -read_int(strind, &nextCharacter);
8989 if (strind == nextCharacter)
8991 strind = nextCharacter;
8998 tempY = read_int(strind, &nextCharacter);
8999 if (strind == nextCharacter)
9001 strind = nextCharacter;
9007 /* If strind isn't at the end of the string the it's an invalid
9008 geometry specification. */
9010 if (*strind != '\0') return (0);
9016 if (mask & WidthValue)
9018 if (mask & HeightValue)
9019 *height = tempHeight;
9024 * gtk_window_parse_geometry:
9025 * @window: a #GtkWindow
9026 * @geometry: geometry string
9028 * Parses a standard X Window System geometry string - see the
9029 * manual page for X (type 'man X') for details on this.
9030 * gtk_window_parse_geometry() does work on all GTK+ ports
9031 * including Win32 but is primarily intended for an X environment.
9033 * If either a size or a position can be extracted from the
9034 * geometry string, gtk_window_parse_geometry() returns %TRUE
9035 * and calls gtk_window_set_default_size() and/or gtk_window_move()
9036 * to resize/move the window.
9038 * If gtk_window_parse_geometry() returns %TRUE, it will also
9039 * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
9040 * indicating to the window manager that the size/position of
9041 * the window was user-specified. This causes most window
9042 * managers to honor the geometry.
9044 * Note that for gtk_window_parse_geometry() to work as expected, it has
9045 * to be called when the window has its "final" size, i.e. after calling
9046 * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
9049 * #include <gtk/gtk.h>
9052 * fill_with_content (GtkWidget *vbox)
9054 * /* fill with content... */
9058 * main (int argc, char *argv[])
9060 * GtkWidget *window, *vbox;
9061 * GdkGeometry size_hints = {
9062 * 100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
9065 * gtk_init (&argc, &argv);
9067 * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9068 * vbox = gtk_vbox_new (FALSE, 0);
9070 * gtk_container_add (GTK_CONTAINER (window), vbox);
9071 * fill_with_content (vbox);
9072 * gtk_widget_show_all (vbox);
9074 * gtk_window_set_geometry_hints (GTK_WINDOW (window),
9077 * GDK_HINT_MIN_SIZE |
9078 * GDK_HINT_BASE_SIZE |
9079 * GDK_HINT_RESIZE_INC);
9083 * if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
9084 * fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
9087 * gtk_widget_show_all (window);
9094 * Return value: %TRUE if string was parsed successfully
9097 gtk_window_parse_geometry (GtkWindow *window,
9098 const gchar *geometry)
9100 gint result, x = 0, y = 0;
9104 gboolean size_set, pos_set;
9107 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9108 g_return_val_if_fail (geometry != NULL, FALSE);
9110 child = gtk_bin_get_child (GTK_BIN (window));
9111 if (!child || !gtk_widget_get_visible (child))
9112 g_warning ("gtk_window_parse_geometry() called on a window with no "
9113 "visible children; the window should be set up before "
9114 "gtk_window_parse_geometry() is called.");
9116 screen = gtk_window_check_screen (window);
9118 result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
9121 if ((result & WidthValue) || (result & HeightValue))
9123 gtk_window_set_default_size_internal (window,
9124 TRUE, result & WidthValue ? w : -1,
9125 TRUE, result & HeightValue ? h : -1,
9130 gtk_window_get_size (window, (gint *)&w, (gint *)&h);
9132 grav = GDK_GRAVITY_NORTH_WEST;
9134 if ((result & XNegative) && (result & YNegative))
9135 grav = GDK_GRAVITY_SOUTH_EAST;
9136 else if (result & XNegative)
9137 grav = GDK_GRAVITY_NORTH_EAST;
9138 else if (result & YNegative)
9139 grav = GDK_GRAVITY_SOUTH_WEST;
9141 if ((result & XValue) == 0)
9144 if ((result & YValue) == 0)
9147 if (grav == GDK_GRAVITY_SOUTH_WEST ||
9148 grav == GDK_GRAVITY_SOUTH_EAST)
9149 y = gdk_screen_get_height (screen) - h + y;
9151 if (grav == GDK_GRAVITY_SOUTH_EAST ||
9152 grav == GDK_GRAVITY_NORTH_EAST)
9153 x = gdk_screen_get_width (screen) - w + x;
9155 /* we don't let you put a window offscreen; maybe some people would
9156 * prefer to be able to, but it's kind of a bogus thing to do.
9165 if ((result & XValue) || (result & YValue))
9167 gtk_window_set_gravity (window, grav);
9168 gtk_window_move (window, x, y);
9172 if (size_set || pos_set)
9174 /* Set USSize, USPosition hints */
9175 GtkWindowGeometryInfo *info;
9177 info = gtk_window_get_geometry_info (window, TRUE);
9180 info->mask |= GDK_HINT_USER_POS;
9182 info->mask |= GDK_HINT_USER_SIZE;
9189 gtk_window_mnemonic_hash_foreach (guint keyval,
9195 GtkWindowKeysForeachFunc func;
9199 (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
9203 _gtk_window_keys_foreach (GtkWindow *window,
9204 GtkWindowKeysForeachFunc func,
9208 GtkMnemonicHash *mnemonic_hash;
9212 GtkWindowKeysForeachFunc func;
9216 info.window = window;
9218 info.func_data = func_data;
9220 mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
9222 _gtk_mnemonic_hash_foreach (mnemonic_hash,
9223 gtk_window_mnemonic_hash_foreach, &info);
9225 groups = gtk_accel_groups_from_object (G_OBJECT (window));
9228 GtkAccelGroup *group = groups->data;
9231 for (i = 0; i < group->priv->n_accels; i++)
9233 GtkAccelKey *key = &group->priv->priv_accels[i].key;
9236 (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
9239 groups = groups->next;
9244 gtk_window_keys_changed (GtkWindow *window)
9246 gtk_window_free_key_hash (window);
9247 gtk_window_get_key_hash (window);
9250 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
9252 struct _GtkWindowKeyEntry
9256 guint is_mnemonic : 1;
9260 window_key_entry_destroy (gpointer data)
9262 g_slice_free (GtkWindowKeyEntry, data);
9266 add_to_key_hash (GtkWindow *window,
9268 GdkModifierType modifiers,
9269 gboolean is_mnemonic,
9272 GtkKeyHash *key_hash = data;
9274 GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
9276 entry->keyval = keyval;
9277 entry->modifiers = modifiers;
9278 entry->is_mnemonic = is_mnemonic;
9280 /* GtkAccelGroup stores lowercased accelerators. To deal
9281 * with this, if <Shift> was specified, uppercase.
9283 if (modifiers & GDK_SHIFT_MASK)
9285 if (keyval == GDK_KEY_Tab)
9286 keyval = GDK_KEY_ISO_Left_Tab;
9288 keyval = gdk_keyval_to_upper (keyval);
9291 _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
9295 gtk_window_get_key_hash (GtkWindow *window)
9297 GdkScreen *screen = gtk_window_check_screen (window);
9298 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9303 key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
9304 (GDestroyNotify)window_key_entry_destroy);
9305 _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
9306 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
9312 gtk_window_free_key_hash (GtkWindow *window)
9314 GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
9317 _gtk_key_hash_free (key_hash);
9318 g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
9323 * gtk_window_activate_key:
9324 * @window: a #GtkWindow
9325 * @event: a #GdkEventKey
9327 * Activates mnemonics and accelerators for this #GtkWindow. This is normally
9328 * called by the default ::key_press_event handler for toplevel windows,
9329 * however in some cases it may be useful to call this directly when
9330 * overriding the standard key handling for a toplevel window.
9332 * Return value: %TRUE if a mnemonic or accelerator was found and activated.
9337 gtk_window_activate_key (GtkWindow *window,
9340 GtkKeyHash *key_hash;
9341 GtkWindowKeyEntry *found_entry = NULL;
9342 gboolean enable_mnemonics;
9343 gboolean enable_accels;
9345 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9346 g_return_val_if_fail (event != NULL, FALSE);
9348 key_hash = gtk_window_get_key_hash (window);
9353 GSList *entries = _gtk_key_hash_lookup (key_hash,
9354 event->hardware_keycode,
9356 gtk_accelerator_get_default_mod_mask (),
9359 g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9360 "gtk-enable-mnemonics", &enable_mnemonics,
9361 "gtk-enable-accels", &enable_accels,
9364 for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9366 GtkWindowKeyEntry *entry = tmp_list->data;
9367 if (entry->is_mnemonic)
9369 if (enable_mnemonics)
9371 found_entry = entry;
9377 if (enable_accels && !found_entry)
9379 found_entry = entry;
9384 g_slist_free (entries);
9389 if (found_entry->is_mnemonic)
9391 if (enable_mnemonics)
9392 return gtk_window_mnemonic_activate (window, found_entry->keyval,
9393 found_entry->modifiers);
9398 return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9399 found_entry->modifiers);
9407 window_update_has_focus (GtkWindow *window)
9409 GtkWindowPrivate *priv = window->priv;
9410 GtkWidget *widget = GTK_WIDGET (window);
9411 gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9413 if (has_focus != priv->has_focus)
9415 priv->has_focus = has_focus;
9419 if (priv->focus_widget &&
9420 priv->focus_widget != widget &&
9421 !gtk_widget_has_focus (priv->focus_widget))
9422 do_focus_change (priv->focus_widget, TRUE);
9426 if (priv->focus_widget &&
9427 priv->focus_widget != widget &&
9428 gtk_widget_has_focus (priv->focus_widget))
9429 do_focus_change (priv->focus_widget, FALSE);
9435 * _gtk_window_set_is_active:
9436 * @window: a #GtkWindow
9437 * @is_active: %TRUE if the window is in the currently active toplevel
9439 * Internal function that sets whether the #GtkWindow is part
9440 * of the currently active toplevel window (taking into account inter-process
9444 _gtk_window_set_is_active (GtkWindow *window,
9447 GtkWindowPrivate *priv;
9449 g_return_if_fail (GTK_IS_WINDOW (window));
9451 priv = window->priv;
9453 is_active = is_active != FALSE;
9455 if (is_active != priv->is_active)
9457 priv->is_active = is_active;
9458 window_update_has_focus (window);
9460 g_object_notify (G_OBJECT (window), "is-active");
9465 * _gtk_window_set_is_toplevel:
9466 * @window: a #GtkWindow
9467 * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9468 * parent of the root window); %FALSE if it is not (for example, for an
9469 * in-process, parented GtkPlug)
9471 * Internal function used by #GtkPlug when it gets parented/unparented by a
9472 * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9473 * global list of toplevel windows.
9476 _gtk_window_set_is_toplevel (GtkWindow *window,
9477 gboolean is_toplevel)
9481 widget = GTK_WIDGET (window);
9483 if (gtk_widget_is_toplevel (widget))
9484 g_assert (g_slist_find (toplevel_list, window) != NULL);
9486 g_assert (g_slist_find (toplevel_list, window) == NULL);
9488 if (is_toplevel == gtk_widget_is_toplevel (widget))
9493 _gtk_widget_set_is_toplevel (widget, TRUE);
9494 toplevel_list = g_slist_prepend (toplevel_list, window);
9498 _gtk_widget_set_is_toplevel (widget, FALSE);
9499 toplevel_list = g_slist_remove (toplevel_list, window);
9504 * _gtk_window_set_has_toplevel_focus:
9505 * @window: a #GtkWindow
9506 * @has_toplevel_focus: %TRUE if the in
9508 * Internal function that sets whether the keyboard focus for the
9509 * toplevel window (taking into account inter-process embedding.)
9512 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9513 gboolean has_toplevel_focus)
9515 GtkWindowPrivate *priv;
9517 g_return_if_fail (GTK_IS_WINDOW (window));
9519 priv = window->priv;
9521 has_toplevel_focus = has_toplevel_focus != FALSE;
9523 if (has_toplevel_focus != priv->has_toplevel_focus)
9525 priv->has_toplevel_focus = has_toplevel_focus;
9526 window_update_has_focus (window);
9528 g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9533 * gtk_window_set_auto_startup_notification:
9534 * @setting: %TRUE to automatically do startup notification
9536 * By default, after showing the first #GtkWindow, GTK+ calls
9537 * gdk_notify_startup_complete(). Call this function to disable
9538 * the automatic startup notification. You might do this if your
9539 * first window is a splash screen, and you want to delay notification
9540 * until after your real main window has been shown, for example.
9542 * In that example, you would disable startup notification
9543 * temporarily, show your splash screen, then re-enable it so that
9544 * showing the main window would automatically result in notification.
9549 gtk_window_set_auto_startup_notification (gboolean setting)
9551 disable_startup_notification = !setting;
9555 * gtk_window_get_window_type:
9556 * @window: a #GtkWindow
9558 * Gets the type of the window. See #GtkWindowType.
9560 * Return value: the type of the window
9565 gtk_window_get_window_type (GtkWindow *window)
9567 g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9569 return window->priv->type;
9573 * gtk_window_get_mnemonics_visible:
9574 * @window: a #GtkWindow
9576 * Gets the value of the #GtkWindow:mnemonics-visible property.
9578 * Returns: %TRUE if mnemonics are supposed to be visible
9584 gtk_window_get_mnemonics_visible (GtkWindow *window)
9586 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9588 return window->priv->mnemonics_visible;
9592 * gtk_window_set_mnemonics_visible:
9593 * @window: a #GtkWindow
9594 * @setting: the new value
9596 * Sets the #GtkWindow:mnemonics-visible property.
9601 gtk_window_set_mnemonics_visible (GtkWindow *window,
9604 GtkWindowPrivate *priv;
9606 g_return_if_fail (GTK_IS_WINDOW (window));
9608 priv = window->priv;
9610 setting = setting != FALSE;
9612 if (priv->mnemonics_visible != setting)
9614 priv->mnemonics_visible = setting;
9615 g_object_notify (G_OBJECT (window), "mnemonics-visible");
9618 priv->mnemonics_visible_set = TRUE;
9622 _gtk_window_get_wmclass (GtkWindow *window,
9623 gchar **wmclass_name,
9624 gchar **wmclass_class)
9626 GtkWindowPrivate *priv = window->priv;
9628 *wmclass_name = priv->wmclass_name;
9629 *wmclass_class = priv->wmclass_class;